Board index FlightGear Support Hardware

Joystick xml codes Library project - open for contributions  Topic is solved

Joysticks, pedals, monitors.

Re: Joystick xml codes Library project - open for contributi

Postby Philosopher » Wed Aug 29, 2012 4:21 pm

godarklight wrote in Sat Aug 18, 2012 11:11 am: Im not sure if thats the correct way to toggle a property either but abs(value-1) does work...

Not really, the correct version is this as it doesn't get stuck if it's at 0.5:
Code: Select all
var reverser = !getprop("/controls/engines/engine[0]/reverser");
props.setAll("/controls/engines/engine", "reverser", reverser);


If the property is 0 then it gets set to 1, else it gets set to 0.

Okay, here's my first contribution from my Cyborg-X file (lots more will be coming :D):

My trigger script, adapted from the Cyborg-Evo.xml, designed for modifier combinations 0-4 that are stored in a NASAL variable (important) called "mod" whenever it's changed. If your modifier is stored exclusively in the property tree, then you need a line like: var mod = getprop("/input/joysticks/js[0]/modifier");

On the ground: Sets brakes with no mod or mod == 3 (used for differential braking on my joystick), toggles parking on release and mod == 1, toggles speedbrake/spoilers INDEPENDENTLY on mod == 2, toggle thrust reverser with mod == 4.
In the air: sets trigger0 with no mod, sets trigger1 with mod == 3, otherwise same as above.
Code: Select all
<!-- Trigger Button - Brakes, Parking Brake, Speed Brake, Thrust Reverser -->
<button n="0">
   <desc>Brakes (regular, park, speed, thrust reverser)</desc>
   <repeatable type="bool">true</repeatable>
   <binding>
      <command>nasal</command>
      <script><![CDATA[
         #if on land
         if (getprop("/gear/gear[0]/wow") or getprop("/gear/gear[1]/wow") or getprop("/gear/gear[2]/wow")) {

            #regular brakes, i was having funny effects with the interpolation on the dragonfly,
            #the left one would go quickly and the right would lag behind,
            #so I took out the interpolation
            if (mod == nil or mod == 0 or mod == 3 or mod == 1) {
               #interpolate("/controls/gear/brake-left", 1, 0.075);
               #interpolate("/controls/gear/brake-right", 1, 0.075);
               setprop("/controls/gear/brake-left", 1);
               setprop("/controls/gear/brake-right", 1);
            } elsif (mod == 2) {
            #
            } elsif (mod == 3) {
            #
            }
         } else {

            #air:
            if (mod == nil or mod == 0) {
               setprop("/controls/armament/trigger", 1);
            } elsif (mod == 1) {
            #
            } elsif (mod == 2) {
            #
            } elsif (mod == 3) { #differential braking modifier, not used in the air
               setprop("/controls/armament/trigger1", 1);
            } elsif (mod == 4) {
            #
            }
         }]]>
      </script>
   </binding>
   <mod-up>
      <repeatable type="bool">true</repeatable>
      <binding>
         <command>nasal</command>
         <script><![CDATA[
            #one if by land... oh wait, that isn't how it goes. But this is for land:
            if (getprop("/gear/gear[0]/wow") or getprop("/gear/gear[1]/wow") or getprop("/gear/gear[2]/wow")) {

               #no mod, release brakes (you can do interpolation, see above)
               if (mod == nil or mod == 0 or mod == 3) {
                  #interpolate("/controls/gear/brake-left", 0, 0.075);
                  #interpolate("/controls/gear/brake-right", 0, 0.075);
                  setprop("/controls/gear/brake-left", 0);
                  setprop("/controls/gear/brake-right", 0);

               #toggle parking brake on mod-up
               } elsif (mod == 1) {
                  var brake = !getprop("/controls/gear/brake-parking");
                  setprop("/controls/gear/brake-parking", brake);
                  if (brake) {
                     gui.popupTip("Parking Brake ON");
                  } else {
                     gui.popupTip("Parking Brake OFF");
                  }
                  setprop("/controls/gear/brake-left", 0);
                  setprop("/controls/gear/brake-right", 0);

               #toggle speedbrake and spoilers independently, and only show the speedbrake value
               } elsif (mod == 2) {
                  var speedbrake = !getprop("/controls/flight/speedbrake");
                  setprop("/controls/flight/speedbrake", speedbrake);
                  var spoilers = !getprop("/controls/flight/spoilers");
                  setprop("/controls/flight/spoilers", spoilers);
                  if (speedbrake) {
                     gui.popupTip("Speedbrake ON");
                  } else {
                     gui.popupTip("Speedbrake OFF");
                  }
               } elsif (mod == 3) {
               #
               } elsif (mod == 4) {
                  var reverser = !getprop("/controls/engines/engine[0]/reverser");
                  props.setAll("/controls/engines/engine", "reverser", reverser);
                  if (reverser) {
                     gui.popupTip("Thrust Reverser ON");
                  } else {
                     gui.popupTip("Thrust Reverser OFF");
                  }
               }

            #two if by air:
            } else {

               #the trigger up is handled at the end, regardless of mod #
               if (mod == nil or mod == 0) {
               #
               #parking brake, mod=1:
               } elsif (mod == 1) {
                  var brake = !getprop("/controls/gear/brake-parking");
                  setprop("/controls/gear/brake-parking", brake);
                  if (brake) {
                     gui.popupTip("Parking Brake ON");
                  } else {
                     gui.popupTip("Parking Brake OFF");
                  }
                  setprop("/controls/gear/brake-left", 0);
                  setprop("/controls/gear/brake-right", 0);

               #toggles independently and only shows speedbrake, not spoilers
               } elsif (mod == 2) {
                  var speedbrake = !getprop("/controls/flight/speedbrake");
                  setprop("/controls/flight/speedbrake", speedbrake);
                  var spoilers = !getprop("/controls/flight/spoilers");
                  setprop("/controls/flight/spoilers", spoilers);
                  if (getprop("/controls/flight/spoilers")) {
                     gui.popupTip("Speedbrake ON");
                  } else {
                     gui.popupTip("Speedbrake OFF");
                  }
               } elsif (mod == 3) {
               #
               } elsif (mod == 4) {
                  var reverser = !getprop("/controls/engines/engine[0]/reverser");
                  props.setAll("/controls/engines/engine", "reverser", reverser);
                  if (reverser) {
                     gui.popupTip("Thrust Reverser ON");
                  } else {
                     gui.popupTip("Thrust Reverser OFF");
                  }
               }
            }
            setprop("/controls/armament/trigger", 0); #shut down the firing, interferes with the 'e' key, but life is life and who wants to reach over there anyways?
            setprop("/controls/armament/trigger1", 0);]]>
         </script>
      </binding>
   </mod-up>
</button>


Feel free to PM me if you want anything joystick related, e.g. help on converting my code snippets, if something isn't working, or feature requests. I'll be glad to help.

P.S. @e-Tron: I have my own Cyborg-X file, but it didn't have a F.L.Y. 5 names in it, so thanks for posting and helping me ;).
Thanks,
Philosopher
(inactive but lurking occasionally...)
Philosopher
 
Posts: 1590
Joined: Sun Aug 12, 2012 6:29 pm
Location: Stuck in my head...
Callsign: AFTI
Version: Git
OS: Mac OS X 10.7.5

Re: Joystick xml codes Library project - open for contributi

Postby Philosopher » Tue Sep 04, 2012 4:13 pm

My next contribution: holding down a button.

These are some bindings for having you cake, and eating it too ;). They allow you to hold down a button and have it run a different function. The basic theory is to have a hold-down function on certain mods, and to do nothing on the initial pressing of the button on those mods, but rather, set a short timer that does the hold-down function if the button is still being pressed and does the regular function if it was released. This requires a variable for the state of the button ("/input/joysticks/js[0]/button[1]/state") and another for whether the timer was set ("/input/joysticks/js[0]/button[1]/timer"), used in releasing momentary properties (that you want to be 1 only while you're holding the button).

To use this code, and for those who aren't adventurous ;), you will have to replace all instances of the bit:
Code: Select all
Joystick ~ "
with:
Code: Select all
"input/joysticks/js[0]


For those who ARE adventurous, you can add this bit of code after the <name> tag(s) or insert the middle line if the tags (<nasal> and <script>) already exist:
Code: Select all
<nasal>
   <script>
      Joystick = "/input/joysticks/js[0]";
      var mod == 0;
   </script>
</nasal>


Here's the actual code that I use in my bindings. Make sure you change all references to "mod" to the variable used in your bindings, if it's a Nasal variable, or if it's in the property tree, add a line to the top that is something like: var mod = getprop("path/to/joystick/and/modifier"); (replacing it with the correct path of course). If the latter, make sure you add it to the <mod-up> as well!

Code: Select all
<button n="1">
   <desc>Reset view; reset trim; cockpit view; toggle tail-wheel lock; Hold (no mod): FBW-override, TWS, or NWS</desc>
   <repeatable type="bool">false</repeatable>
   <binding>
      <command>nasal</command>
      <script><![CDATA[
         #when button is first pressed
         if (mod == nil or mod == 0 or mod == 3) {
            #view.resetView();
         } elsif (mod == 1) {
            setprop("/controls/flight/elevator-trim", 0);
            setprop("/controls/flight/aileron-trim", 0);
            setprop("/controls/flight/rudder-trim", 0);
         } elsif (mod == 2) {
            setprop("/sim/current-view/view-number", 0);
            view.resetView();
         } elsif (mod == 4) {
            var twlock = !getprop("/controls/gear/tailwheel-lock");
            setprop("/controls/gear/tailwheel-lock", twlock);
            if (twlock) {
               gui.popupTip("Tail Wheel LOCKED");
            } else {
               gui.popupTip("Tail Wheel UNLOCKED");
            }
         }

         var hold = func {
            #if button is held
            if (getprop(Joystick ~ "/button[1]/state") == 1) {
               if (mod == 0) {
                  if (getprop("/fdm/jsbsim/fcs/fbw-override") != nil) {
                     setprop("/fdm/jsbsim/fcs/fbw-override", 1);
                  }
                  if (getprop("/fdm/jsbsim/systems/TWS/engaged") != nil) {
                     setprop("/fdm/jsbsim/systems/TWS/engaged", 1);
                  }
                  if (getprop("/fdm/jsbsim/systems/NWS/engaged") != nil) {
                     setprop("/fdm/jsbsim/systems/NWS/engaged", 1);
                  }
               }
               setprop(Joystick ~ "/button[1]/timer", 1);
            } else {
               #or if button is pressed quickly
               if (mod == 0) {
                  view.resetView();
               }
               setprop(Joystick ~ "/button[1]/timer", 0);
            }
         }
         #threshold for holding, 0.2 seconds
         settimer(hold, 0.2);
         setprop(Joystick ~ "/button[1]/state", 1);]]>
      </script>
   </binding>
   <mod-up>
      <binding>
      <command>nasal</command>
         <script><![CDATA[
            #if the timer was activated
            if (getprop(Joystick ~ "/button[1]/timer") == 1) {
               #and mod == 0, so we know FBW and such were set by the joystick
               if (mod == 0) {
                  if (getprop("/fdm/jsbsim/fcs/fbw-override") != nil) {
                     setprop("/fdm/jsbsim/fcs/fbw-override", 0);
                  }
                  if (getprop("/fdm/jsbsim/systems/TWS/engaged") != nil) {
                     setprop("/fdm/jsbsim/systems/TWS/engaged", 0);
                  }
                  if (getprop("/fdm/jsbsim/systems/NWS/engaged") != nil) {
                     setprop("/fdm/jsbsim/systems/NWS/engaged", 0);
                  }
               }
            }

            setprop(Joystick ~ "/button[1]/state", 0);
            setprop(Joystick ~ "/button[1]/timer", 0);]]>
         </script>
      </binding>
   </mod-up>
</button>


To modify this to suit your needs, you will need to know a couple more things than usual. First of all you, what values do you want to change and how do you want to change them. Something like "toggle this value" or "add 0.1 to this value and keep between 0 and 1". Next, you will need to know when you want to take that action, e.g. "when held for 0.1 seconds", or "when button is released but the timer was NOT activated" (or when it was), or "when the button was released and mod == 1, regardless of the timer being activated".

To simplify this, it's sometimes helpful to think of some properties as switches. In my example code, FBW-override would be a momentary, hold-down switch on mod == 0 or 3, since it waits a bit before taking action (hold-down); resets that action when the button is released and the first action has been taken (momentary); and yet only works if mod equals 0 or 3 (mod == 0 or 3). Then there's the view reset which is a fast-action push button, fast because it can't be down longer than 0.2 and still be activated; and push button because there's only one action being taken: being pushed quickly. If you can think of it as a button or switch of some sort, you're many steps closer to having it in code, you just need some thought as to how you really want it to work and how it would look in Nasal.

So let's say that when mod == 1, normally used for resetting trim, you want the hold-down to reset speedbrake and the fast-action to be the regular reset trim. Let's also say that you want to use the same amount of time (0.2) as the mod == 0 hold-down. How you would do this is add a mod == 1 section to the hold function that sets "/controls/flight/speedbrake" to 0. You will have to move the normal function script (view.resetView();) to the hold function, or just copy it and comment it out above. Here's the binding with the changes:

Code: Select all
<button n="1">
   <desc>Reset view; reset trim; cockpit view; toggle tail-wheel lock; Hold (no mod): FBW-override, TWS, or NWS</desc>
   <repeatable type="bool">false</repeatable>
   <binding>
      <command>nasal</command>
      <script><![CDATA[
         #when button is first pressed
         if (mod == nil or mod == 0 or mod == 3) {
            #view.resetView();
         } elsif (mod == 1) {
            #COMMENTED OUT FROM ABOVE
            #setprop("/controls/flight/elevator-trim", 0);
            #setprop("/controls/flight/aileron-trim", 0);
            #setprop("/controls/flight/rudder-trim", 0);
         } elsif (mod == 2) {
            setprop("/sim/current-view/view-number", 0);
            view.resetView();
         } elsif (mod == 4) {
            var twlock = !getprop("/controls/gear/tailwheel-lock");
            setprop("/controls/gear/tailwheel-lock", twlock);
            if (twlock) {
               gui.popupTip("Tail Wheel LOCKED");
            } else {
               gui.popupTip("Tail Wheel UNLOCKED");
            }
         }

         var hold = func {
            #if button is held
            if (getprop(Joystick ~ "/button[1]/state") == 1) {
               if (mod == 0) {
                  if (getprop("/fdm/jsbsim/fcs/fbw-override") != nil) {
                     setprop("/fdm/jsbsim/fcs/fbw-override", 1);
                  }
                  if (getprop("/fdm/jsbsim/systems/TWS/engaged") != nil) {
                     setprop("/fdm/jsbsim/systems/TWS/engaged", 1);
                  }
                  if (getprop("/fdm/jsbsim/systems/NWS/engaged") != nil) {
                     setprop("/fdm/jsbsim/systems/NWS/engaged", 1);
                  }
               #ADDED
               } elsif (mod == 1) {
                  setprop("/controls/flight/speedbrake", 0);
               }
               setprop(Joystick ~ "/button[1]/timer", 1);
            } else {
               #or if button is pressed quickly
               if (mod == 0) {
                  view.resetView();
               #AND ADDED
               } elsif (mod == 1) {
                  setprop("/controls/flight/elevator-trim", 0);
                  setprop("/controls/flight/aileron-trim", 0);
                  setprop("/controls/flight/rudder-trim", 0);
               }
               setprop(Joystick ~ "/button[1]/timer", 0);
            }
         }
         #threshold for holding, 0.2 seconds
         settimer(hold, 0.2);
         setprop(Joystick ~ "/button[1]/state", 1);]]>
      </script>
   </binding>
   <mod-up>
      <binding>
      <command>nasal</command>
         <script><![CDATA[
            #if the timer was activated
            if (getprop(Joystick ~ "/button[1]/timer") == 1) {
               #and mod == 0, so we know FBW and such were set by the joystick
               if (mod == 0) {
                  if (getprop("/fdm/jsbsim/fcs/fbw-override") != nil) {
                     setprop("/fdm/jsbsim/fcs/fbw-override", 0);
                  }
                  if (getprop("/fdm/jsbsim/systems/TWS/engaged") != nil) {
                     setprop("/fdm/jsbsim/systems/TWS/engaged", 0);
                  }
                  if (getprop("/fdm/jsbsim/systems/NWS/engaged") != nil) {
                     setprop("/fdm/jsbsim/systems/NWS/engaged", 0);
                  }
               #COULD ADD AN elsif IF YOU WANT A "BLIP" SWITCH EFFECT
               }
            }

            setprop(Joystick ~ "/button[1]/state", 0);
            setprop(Joystick ~ "/button[1]/timer", 0);]]>
         </script>
      </binding>
   </mod-up>
</button>


Note where I commented out the three setprops for resetting trim at the top of the binding and added the elsif (mod == 1) to both the condition where the button is still held (to set speedbrake to 0) and if it isn't held (to reset trim). If you wanted it to be like a "blip" switch, you could add a elsif (mod == 1) to the if (getprop(Joystick ~ "/button[1]/timer") == 1) inside of the <mod-up> binding and say setprop("/controls/flight/speedbrake", 1); inside of the elsif. For more information see Nasal conditionals and all the other wiki pages on Nasal, especially if you're just learning Nasal.

P.S. I hope this is what you wanted, sim! My next one's gonna be even more of an article :D.
Thanks,
Philosopher
(inactive but lurking occasionally...)
Philosopher
 
Posts: 1590
Joined: Sun Aug 12, 2012 6:29 pm
Location: Stuck in my head...
Callsign: AFTI
Version: Git
OS: Mac OS X 10.7.5

Re: Joystick xml codes Library project - open for contributi

Postby Hooray » Tue Sep 04, 2012 4:36 pm

My next one's gonna be even more of an article

You should really consider turning such essays into tutorials/howtos for the wiki - and then just post a link to the tutorial here. Especially, because you don't seem to mind writing a lot of instructional explanations - in 12+ months, it will be really hard to find this thread - if you want to provide permanent help, it's better to use the wiki and create a tutorial there.

I usually try to do the same whenever someone asks a question here that could use a real step by step tutorial- i.e. a while ago when omega95 asked about using vectors and hashes in Nasal, I created this: http://wiki.flightgear.org/Howto:Start_ ... s_in_Nasal
Please don't send support requests by PM, instead post your questions on the forum so that all users can contribute and benefit
Thanks & all the best,
Hooray
Help write next month's newsletter !
pui2canvas | MapStructure | Canvas Development | Programming resources
Hooray
 
Posts: 11191
Joined: Tue Mar 25, 2008 8:40 am

Re: Joystick xml codes Library project - open for contributi

Postby Philosopher » Thu Sep 13, 2012 12:11 am

Instead of just having separate flap and gear buttons, why not combine them? These bindings, for a pair of buttons, steps flaps, gear, and tailhook towards clean and landing configurations. The popup tips say everything else, but basically it steps flaps; lowers/raises gear; and if flaps == 1, then it lowers/raises the tailhook:

Code: Select all
<button n="4">
   <desc>Step towards clean configuration</desc>
   <repeatable type="bool">false</repeatable>
   <binding>
      <command>nasal</command>
      <script><![CDATA[
         # Step towards clean configuration:
         var popupTip = "";
         var path = getprop("/sim/model/path");
         jsbtailhook = getprop("fdm/jsbsim/systems/hook/tailhook-cmd-norm");
         tailhook = getprop("/controls/gear/tailhook");
         if (path == "Aircraft/f-14b/Models/f-14b.xml") {
            var flaps = getprop("/controls/flight/flapscommand");
            f14.raiseFlaps();
         } else {
            var flaps = getprop("/controls/flight/flaps");
         }
         gear = getprop("/controls/gear/gear-down");
         if (jsbtailhook != nil and jsbtailhook == 1) {
            setprop("fdm/jsbsim/systems/hook/tailhook-cmd-norm", 0);
            setprop("controls/gear/tailhook", 0);
            var popupTip = "Tailhook UP";
         } elsif (tailhook == 1) {
            setprop("controls/gear/tailhook", 0);
            var popupTip = "Tailhook UP";
         }
         if (flaps != 0) {
            controls.flapsDown(-1);
            if (popupTip == "") {
               var popupTip = "Flaps ";
            } else {
               var popupTip = popupTip ~ "; Flaps ";
            }
            if (path == "Aircraft/f-14b/Models/f-14b.xml") {
               var flaps = getprop("/controls/flight/flapscommand");
            } else {
               var flaps = getprop("/controls/flight/flaps");
               if (getprop("/controls/flight/aileron-droop") != nil) {
                  setprop("/controls/flight/aileron-droop", flaps);
               }
            }
            if (flaps == 0) {
               var popupTip = popupTip ~ "RETRACTED";
            } elsif (flaps == 0.25) {
               var popupTip = popupTip ~ "at 1/4";
            } elsif (int(10*flaps) == 3) {
               var popupTip = popupTip ~ "at 1/3";
            } elsif (flaps == 0.5) {
               var popupTip = popupTip ~ "at 1/2";
            } elsif (int(10*flaps) == 6) {
               var popupTip = popupTip ~ "at 2/3";
            } elsif (flaps == 0.75) {
               var popupTip = popupTip ~ "at 3/4";
            } elsif (flaps == 1) {
               var popupTip = popupTip ~ "at FULL";
            } else {
               var popupTip = popupTip ~ "at " ~ int(10*flaps)/10;
            }
         }
         if (gear != 0 and !getprop("/gear/gear[0]/wow") and !getprop("/gear/gear[1]/wow") and !getprop("/gear/gear[2]/wow")) {
            controls.gearDown(-1);
            if (popupTip == "") {
               var popupTip = "Gear UP";
            } else {
               var popupTip = popupTip ~ "; Gear UP";
            }
         }
         if (popupTip != "") {
            gui.popupTip(popupTip);
         }]]>
      </script>
   </binding>
</button>


Code: Select all
<button n="5">
   <desc>Step towards landing configuration</desc>
   <repeatable type="bool">false</repeatable>
   <binding>
      <command>nasal</command>
      <script><![CDATA[
         # Step towards landing configuration:
         var popupTip = "";
         var path = getprop("/sim/model/path");
         var jsbtailhook = getprop("fdm/jsbsim/systems/hook/tailhook-cmd-norm");
         var tailhook = getprop("/controls/gear/tailhook");
         if (path == "Aircraft/f-14b/Models/f-14b.xml") {
            var flaps = getprop("/controls/flight/flapscommand");
            f14.lowerFlaps();
            if (getprop("/controls/flight/DLC-engaged") == 0) {
               f14.toggleDLC();
               popupTip = "DLC ENGAGED";
               setprop("/controls/flight/DLC", 0);
            }
         } else {
            var flaps = getprop("/controls/flight/flaps");
         }
         var gear = getprop("/controls/gear/gear-down");
         if (jsbtailhook != nil and flaps == 1 and jsbtailhook == 0) {
            setprop("fdm/jsbsim/systems/hook/tailhook-cmd-norm", 1);
            setprop("controls/gear/tailhook", 1);
            var popupTip = "Tailhook DOWN";
         } elsif (flaps == 1 and tailhook == 0) {
            setprop("controls/gear/tailhook", 1);
            var popupTip = "Tailhook DOWN";
         }
         if (flaps != 1) {
            controls.flapsDown(1);
            if (popupTip == "") {
               var popupTip = "Flaps ";
            } else {
               var popupTip = popupTip ~ "; Flaps ";
            }
            if (path == "Aircraft/f-14b/Models/f-14b.xml") {
               var flaps = getprop("/controls/flight/flapscommand");
            } else {
               var flaps = getprop("/controls/flight/flaps");
               if (getprop("/controls/flight/aileron-droop") != nil) {
                  setprop("/controls/flight/aileron-droop", flaps);
               }
            }
            if (flaps == 0) {
               var popupTip = popupTip ~ "RETRACTED";
            } elsif (flaps == 0.25) {
               var popupTip = popupTip ~ "at 1/4";
            } elsif (int(10*flaps) == 3) {
               var popupTip = popupTip ~ "at 1/3";
            } elsif (flaps == 0.5) {
               var popupTip = popupTip ~ "at 1/2";
            } elsif (int(10*flaps) == 6) {
               var popupTip = popupTip ~ "at 2/3";
            } elsif (flaps == 0.75) {
               var popupTip = popupTip ~ "at 3/4";
            } elsif (flaps == 1) {
               var popupTip = popupTip ~ "at FULL";
            } else {
               var popupTip = popupTip ~ "at " ~ int(10*flaps)/10;
            }
         }
         if (gear != 1) {
            controls.gearDown(1);
            if (popupTip == "") {
               var popupTip = "Gear DOWN";
            } else {
               var popupTip = popupTip ~ "; and Gear DOWN";
            }
         }
         if (popupTip != "") {
            gui.popupTip(popupTip);
         }]]>
      </script>
   </binding>
</button>


P.S. This code is mostly tested, but if you find some cases where it doesn't work, feel free to (aka please) tell me. Known bugs: tailhook will "deploy" even on aircraft that don't have one. This is something that I cannot possibly work around, I'm afraid, since there is too much variation between aircraft. I did add support for David Culp's tailhook method and the "Yasim" one, "fdm/jsbsim/systems/hook/tailhook-cmd-norm" and "/controls/gear/tailhook", respectively.

EDIT: added support for aileron-droop, if the variable is already there.
Thanks,
Philosopher
(inactive but lurking occasionally...)
Philosopher
 
Posts: 1590
Joined: Sun Aug 12, 2012 6:29 pm
Location: Stuck in my head...
Callsign: AFTI
Version: Git
OS: Mac OS X 10.7.5

Re: Joystick xml codes Library project - open for contributi

Postby sim » Sat Sep 15, 2012 10:27 pm

tailhook will "deploy" even on aircraft that don't have one
Philosopher

No need for apologies! Landing 777-200 on Nimitz isn't that difficult. So if the code tells it to deploy hook and it ain't got one......just use full anchors and reversers as usual :lol: !......sim
User avatar
sim
 
Posts: 1388
Joined: Tue Jun 30, 2009 2:13 pm
Location: Shropshire England
Callsign: Fly4Fun
Version: 0.9.10 up
OS: 64 Win 10 HD6450

Re: Joystick xml codes Library project - open for contributi

Postby macnab » Thu Oct 11, 2012 9:46 am

I have a suggestion. I have posted a wiki article http://wiki.flightgear.org/Writing_Joystick_Code:_Part_1 about the basics of writing code for joysticks.

The idea is that the user knows all about selecting repeatable/non-repeatable buttons, modifier buttons, axes, etc. Having got that organised, all they have to do is get the correct code inserted between <script> and </script>. I call them snippets.

I am busy with Part 2, In which I will supply as many snippets as I can think of. In part 3 I will go into explaining how to use gui.popupTip, interpolate, perIndexAxisHandler and things like that.

Now there is no harm in duplication - some people only use the forum, some only use the wiki and a very few use both. So as soon as I have finished all my snippets I will bundle them all into a zip file called Code-Snippets and add it to the library. I will include a Read Me file that points to my article.

That way, people can either grab a quick-fix, or learn how to do it.

BTW I am busy fixing up the few current entries that are all on one line, and then I will post it back.
macnab
 
Posts: 886
Joined: Tue Aug 02, 2011 7:20 am
Location: Johannesburg, South Africa
Callsign: ZS-ILH
Version: Git
OS: Win7Pro 64bit SP1

Re: Joystick xml codes Library project - open for contributi

Postby macnab » Thu Oct 11, 2012 11:57 am

Here are the files from XML LIBRARY.ZIP that needed fixing because everything was on one line.

ADJUST XYZ VIEWPOINT SCRIPTS
Code: Select all
<!--SAMPLE A:    SIMPLE 2 BUTTON
  <button n="6">
    <desc>T3 z-offset-m Advance_View</desc>
    <repeatable>true</repeatable>
    <binding>
      <command>property-adjust</command>
      <property>/sim/current-view/z-offset-m</property>
      <step type="double">-0.5</step>
    </binding>
  </button>
 
  <button n="7">
    <desc>T4 z-offset-m Retreat_View</desc>
    <repeatable>true</repeatable>
    <binding>
      <command>property-adjust</command>
      <property>/sim/current-view/z-offset-m</property>
      <step type="double">0.5</step>
    </binding>
  </button>-->

-----------------------------------------------------------------------------

SAMPLE B:    2 BUTTON WITH TRIGGER USED AS MODIFIER. IN (M == 0) STATE TRIGGER IS OFF.

<!--
  <button n="6">
    <desc>T3 z-offset-m Advance_View</desc>
    <repeatable>true</repeatable>
    <binding>
      <command>nasal</command>
      <script>
        m = get_mode();
        if (m == 0) {
          setprop("/sim/current-view/z-offset-m", -0.1 + getprop("/sim/current-view/z-offset-m"))
        }
        elsif (m == 1) {
          setprop("/sim/current-view/y-offset-m", -0.1 + getprop("/sim/current-view/y-offset-m"))
        }
      </script>
    </binding>
  </button>

  <button n="7">
    <desc>T4 z-offset-m Retreat_View
    </desc>
    <repeatable>true</repeatable>
    <binding>
      <command>nasal</command>
      <script>
        m = get_mode();
        if (m == 0) {
          setprop("/sim/current-view/z-offset-m", 0.1 + getprop("/sim/current-view/z-offset-m"))
        }
        elsif (m == 1) {
          setprop("/sim/current-view/y-offset-m", 0.1 + getprop("/sim/current-view/y-offset-m"))
        }
      </script>
    </binding>
  </button>
-->

------------------------------------------------------------------------

YOU CAN SAFELY COPY SAMPLE A OR SAMPLE B. JUST COPY THE FIRST <!-- MARKER AND THE FINAL --> MARKER WITH THE WHOLE SCRIPT AND PASTE IT INTO YOUR OWN STICK XML BELOW THE BUTTONS YOU WISH TO USE. FIRST RENAME THE BUTTON NUMBERS TO SUIT YOUR OWN STICK. USE THE <!-- END MARKERS --> TO DISABLE ANY BUTTONS YOU WISH TO USE TO RUN THE TEST. THEN ADOPT THE SAME BUTTON NUMBERS AND REMOVE THE END MARKERS TO TEST THE SAMPLES ABOVE.     

SAMPLE A:  MOVES YOUR VIEWPOINT FORWARD OR BACKWARD

SAMPLE B:  ONLY IF YOU HAVE A MODIFIER ENABLED AND YOU MAY NEED TO ADAPT SLIGHTLY IF YOUR OWN MODIFIER SYSTEM IS WRITTEN DIFFERENTLY.(PLACING JUST THE SETPROP CODES BETWEEN YOUR OWN {  #  } BRACKETS).

           TRIGGER OFF MOVES YOUR VIEWPOINT FORWARD OR BACKWARD

           TRIGGER PRESSED MOVES YOUR VIEWPOINT UP OR DOWN

THE 0.1 AND -0.1 DETERMINE HOW QUICKLY VIEW MOVES. IDEAL FOR ADJUSTING PILOT'S VIEW JUST LIKE ADJUSTING YOUR SEAT! 0.001 -0.001 VALUES WILL BE NICE GENTLE MOVEMENT.

SET THIS TO SUIT YOURSELF BUT A VALUE OF 20 FOR EXAMPLE WILL SHOOT YOU OUT OF YOUR SEAT AT A RATE OF KNOTS. RATHER LIKE AN EJECTION SEAT!

THE X-offset-m IS SIMILAR BUT MOVES YOU LEFT OR RIGHT

FINALLY /field-of-view" CAN BE SUBSTITUTED INSTEAD OF /y-offset-m"
GIVING YOU ZOOM IN OR ZOOM OUT BUT YOU WILL GET NO GUI POP-UP TO SHOW THE VALUE LIKE YOU DO USING "X" OR "SHFT + X" ON KEYBOARD NOR WILL YOUR ZOOM BE LIMITED TO 150 DEGREES! YOU WILL KNOW WHEN YOU EXCEED 180 DEGREES AS YOUR VIEW WILL TURN UPSIDE DOWN!

PREVIOUS FORUM POST WHICH NO ONE SOLVED AT THE TIME!
http://www.flightgear.org/forums/viewtopic.php?f=17&t=5327&p=39367&hilit=magic+sim#p39367   
 



AILERON TRIM
Code: Select all
dany93 Posts: 231Joined: Mon Sep 07, 2009 3:43 pm Location: France (Paris region)Version: 200OS: Windows Vista
---------------------------------------------------------------------------------

<button n="10">
  <desc>Aileron trim left</desc>
  <repeatable type="bool">true</repeatable>
  <binding>
    <command>property-adjust</command>
    <property>/controls/flight/aileron-trim</property>
    <step type="double">-0.001</step>
    <!-- <command>nasal</command>
         <script>controls.aileronTrim(-0.5)</script> -->
  </binding>
</button>


<button n="11">
  <desc>Aileron trim right</desc>
  <repeatable type="bool">true</repeatable>
  <binding>
    <command>property-adjust</command>
    <property>/controls/flight/aileron-trim</property>
    <step type="double">0.001</step>
    <!-- <command>nasal</command>
         <script>controls.aileronTrim(0.5)</script> -->
  </binding>
</button>

------------------------------------------------------------------------------



BRAKE LEFT OR RIGHT
Code: Select all
Sim      2 buttons        Brake Left       Brake Right

<button n="1">
  <desc>Brakes</desc>
  <binding>
    <command>property-assign</command>
    <property>/controls/gear/brake-left</property>
    <value type="double">1.0</value>
  </binding>
  <mod-up>
    <binding>
      <command>nasal</command>
      <script>controls.applyBrakes(0)</script>
    </binding>
  </mod-up>
</button>

<button n="3">
  <desc>Brakes</desc>
  <binding>
    <command>property-assign</command>
    <property>/controls/gear/brake-right</property>
    <value type="double">1.0</value>
  </binding>
  <mod-up>
    <binding>
      <command>nasal</command>
      <script>controls.applyBrakes(0)</script>
    </binding>
  </mod-up>
</button>

--------------------------------------------------------------------------

Talmid          using twist axis to brake left or brake right

<axis n="0">
  <desc>Brake left</desc>
  <binding>
    <command>property-scale</command>
    <property>/controls/gear/brake-left</property>
    <factor type="double">-1.0</factor>
    <power type="double">1</power>
  </binding>
  <desc>Brake right</desc>
  <binding>
    <command>property-scale</command>
    <property>/controls/gear/brake-right</property>
    <factor type="double">1.0</factor>
    <power type="double">1</power>
  </binding>
</axis>

--------------------------------------------------------------------------

Sim    using twist axis to brake left or brake right (operates brake at full left or
right twist only!) note mod-up condition is nested within high or low extremities so
brakes release once full twist is relaxed.

<axis n="3">
  <desc>Brakes</desc>
  <high>
    <binding>
      <command>property-assign</command>
      <property>/controls/gear/brake-left</property>
      <value type="double">1.0</value>
    </binding>
    <mod-up>
      <binding>
        <command>property-assign</command>
        <property>/controls/gear/brake-left</property>
        <value type="double">0.0</value>
      </binding>
    </mod-up>
  </high>
  <low>
   <binding>
     <command>property-assign</command>
     <property>/controls/gear/brake-right</property>
     <value type="double">1.0</value>
   </binding>
   <mod-up>
     <binding>
       <command>property-assign</command>
       <property>/controls/gear/brake-right</property>
       <value type="double">0.0</value>
     </binding>
   </mod-up>
  </low>
</axis>





BRAKES
Code: Select all
dany93 Posts: 231Joined: Mon Sep 07, 2009 3:43 pm Location: France (Paris region)Version: 200OS: Windows Vista
---------------------------------------------------------------------------------

<button n="0">
  <desc>Brakes</desc>
  <binding>
    <command>nasal</command>
    <script>controls.applyBrakes(1)</script>
  </binding>
  <mod-up>
    <binding>
      <command>nasal</command>
      <script>controls.applyBrakes(0)</script>
    </binding>
   </mod-up>
</button>

----------------------------------------------------------------------------



LANDING GEAR SCRIPTS
Code: Select all
dany93 Posts: 231Joined: Mon Sep 07, 2009 3:43 pm Location: France (Paris region)Version: 200OS: Windows Vista
---------------------------------------------------------------------------------              TWO BUTTON    -1 = UP     1 = DOWN

<button n="6">
  <desc>Landing Gear Up</desc>
  <binding>
    <command>nasal</command>
    <script>controls.gearDown(-1)</script>
  </binding>
  <mod-up>
    <binding>
      <command>nasal</command>
      <script>controls.gearDown(0)</script>
    </binding>
  </mod-up>
</button>

<button n="7">
  <desc>Landing Gear Down</desc>
  <binding> <command>nasal</command>
    <script>controls.gearDown(1)</script>
  </binding>
  <mod-up>
    <binding>
      <command>nasal</command>
      <script>controls.gearDown(0)</script>
    </binding>
  </mod-up>
</button>

-------------------------------------------------------------------------------
Sim

ONE BUTTON TOGGLE GEAR UP/DOWN

<button n="10">
  <desc>Landing Gear Toggle</desc>
  <repeatable>false</repeatable>
  <binding>
    <command>nasal</command>
    <script>controls.gearToggle()</script>
  </binding>
</button>

--------------------------------------------------------------------

ONE BUTTON TOGGLE GEAR UP/DOWN WON'T PERMIT GEAR RETRACTION UNTIL ABOVE 40 FEET

if (getprop("/position/altitude-agl-ft") > 40){
  gearToggle = getprop("/controls/gear/gear-down")
}
if (gearToggle == 1){
  controls.gearDown(-1);
  gui.popupTip("Gear up!")
}
else {
  controls.gearDown(1);
  gui.popupTip("Gear down!")
}

---------------------------------------------------------------------

ONE BUTTON TOGGLE GEAR UP/DOWN WON'T PERMIT GEAR RETRACTION WHILST WHEELS ARE ON GROUND

var wow = getprop("/gear/gear[1]/wow") or getprop("/gear/gear[2]/wow")
if (wow) {
  setprop("/controls/gear/gear-down", 1)
}
else {
  gearToggle = getprop("/controls/gear/gear-down");
  if (gearToggle == 1) {
    controls.gearDown(-1);
    gui.popupTip("Gear up!")
  }
  else {
    controls.gearDown(1);
    gui.popupTip("Gear down!")
  }
}

---------------------------------------------------------------------

WRITTEN FOR TWO BUTTON OR 2 WAY TOGGLE SWITCH     ADVANTAGE - MORE CERTAINTY WHICH DIRECTION GEAR IS OPERATING!

<button n="8">
  <desc>T5 GEAR UP</desc>
  <binding>
    <command>nasal</command>
    <script>controls.gearDown(-1)</script>
  </binding>
  <mod-up>
    <binding>
      <command>nasal</command>
      <script>controls.gearDown(0)</script>
    </binding>
  </mod-up>
</button>

<button n="9">
  <desc>T6 GEAR DOWN</desc>
  <binding>
    <command>nasal</command>
    <script>controls.gearDown(1)</script>
  </binding>
  <mod-up>
    <binding>
      <command>nasal</command>
      <script>controls.gearDown(0)</script>
    </binding>
  </mod-up>
</button>

---------------------------------------------------------------------




PAN VIEW DIRECTION AND PITCH
Code: Select all
Sim     HAT    pan view    left and right      up and down

<axis n="6">
  <desc>View Horizontal</desc>
  <low>
    <repeatable>true</repeatable>
    <binding>
      <command>nasal</command>
      <script>view.panViewDir(0.5)</script>
    </binding>
  </low>
  <high>
    <repeatable>true</repeatable>
    <binding>
      <command>nasal</command>
      <script>view.panViewDir(-0.5)</script>
    </binding>
  </high>
</axis>

<axis n="7">
  <desc>View Vertical</desc>
  <low>
    <repeatable>true</repeatable>
    <binding> <command>nasal</command>
      <script>view.panViewPitch(0.5);</script>
    </binding>
  </low>
  <high>
    <repeatable>true</repeatable>
    <binding>
      <command>nasal</command>
      <script>view.panViewPitch(-0.5);</script>
    </binding>
  </high>
</axis>

-----------------------------------------------------------------------



TAIL WHEEL LOCK
Code: Select all
Gooneybird

<button n="10">
  <desc>Toggle tail-wheel lock</desc>
  <binding>
    <command>property-toggle</command>
    <property>/controls/gear/tailwheel-lock</property>
  </binding>
</button>

----------------------------------------------------
BUTTON DOWN DEPLOYS SPEEDBRAKES AND FREES TAIL-LOCK/BUTTON UP CANCELS BOTH
Sim   On some planes you need to use some functions for a short time and
cancel them rapidly or face disaster 777 speedbrakes take ages to cancel
and some tail-draggers will spin around if you leave the tail-lock free
So these scripts undo both actions as soon as you release the button !!
Taidraggers with speedbrakes are rare so keep both on one button.   
------------------
<button n="4">
  <desc>T1</desc>
  <binding>
    <command>property-assign</command>
    <property>/controls/flight/speedbrake</property>
    <value type="double">1.0</value>
  </binding>
  <binding>
    <command>property-assign</command>
    <property>/controls/gear/tailwheel-lock</property>
    <value type="double">0.0</value>
  </binding>
  <mod-up>
    <binding>
      <command>property-assign</command>
      <property>/controls/gear/tailwheel-lock</property>
      <value type="double">1.0</value>
    </binding>
    <binding>
      <command>property-assign</command>
      <property>/controls/flight/speedbrake</property>
      <value type="double">0.0</value>
    </binding>
  </mod-up>
</button>

----------------------------------------------------



ZOOM VIEW
Code: Select all
Sim      To Zoom more slowly reduce both  >1<  >-1<     to say   >0.1<  >-0.1<

----------------------------------------------------------------------

<button n="10">
  <desc>Zoom-In</desc>
  <repeatable>true</repeatable>
  <binding>
    <command>property-adjust</command>
    <property>/sim/current-view/field-of-view</property>
    <step type="double">1</step>
    <max>150</max>
  </binding>
</button>


<button n="11">
  <desc>Zoom-Out</desc>
  <repeatable>true</repeatable>
  <binding>
    <command>property-adjust</command>
    <property>/sim/current-view/field-of-view</property>
    <step type="double">-1</step>
    <min>0</min>
  </binding>
</button>



----------------------------------------------------------------------



Need a cup of tea after all that.
macnab
 
Posts: 886
Joined: Tue Aug 02, 2011 7:20 am
Location: Johannesburg, South Africa
Callsign: ZS-ILH
Version: Git
OS: Win7Pro 64bit SP1

Re: Joystick xml codes Library project - open for contributi

Postby sim » Sun Oct 14, 2012 3:43 pm

Well done Macnab! You earned that cuppa!
ADJUST XYZ VIEWPOINT SCRIPTS......done
AILERON TRIM......done
BRAKE LEFT OR RIGHT......done
BRAKES......done
LANDING GEAR SCRIPTS......done
PAN VIEW DIRECTION AND PITCH......done
TAIL WHEEL LOCK......done
ZOOM VIEW......done

Will replace other 7 with your tidy ones shortly......Cheers.....sim
ALL DONE 20.08 UTC 14 OCT
PS Like the <script>SNIPPETS</script> idea. They're really useful!
Last edited by sim on Sun Oct 14, 2012 7:19 pm, edited 2 times in total.
User avatar
sim
 
Posts: 1388
Joined: Tue Jun 30, 2009 2:13 pm
Location: Shropshire England
Callsign: Fly4Fun
Version: 0.9.10 up
OS: 64 Win 10 HD6450

Re: Joystick xml codes Library project - open for contributi

Postby macnab » Sun Oct 14, 2012 3:57 pm

You're welcome.
macnab
 
Posts: 886
Joined: Tue Aug 02, 2011 7:20 am
Location: Johannesburg, South Africa
Callsign: ZS-ILH
Version: Git
OS: Win7Pro 64bit SP1

Re: Joystick xml codes Library project - open for contributi

Postby Johan G » Wed Oct 17, 2012 7:27 pm

sim wrote in Sun Oct 14, 2012 3:43 pm:PS Like the <script>SNIPPETS</script> idea. They're really useful!

+1 on that. While I wont implement most of them (probably none), they give some insight in nasal. The wiki pages are worth a look.

http://wiki.flightgear.org/Writing_Joys ... de:_Part_1
http://wiki.flightgear.org/Writing_Joys ... de:_Part_2
http://wiki.flightgear.org/Writing_Joys ... de:_Part_3
Low-level flying — It's all fun and games till someone looses an engine. (Paraphrased from a YouTube video)
Improving the Dassault Mirage F1 (Wiki, Forum, GitLab. Work in slow progress)
Johan G
Moderator
 
Posts: 5294
Joined: Fri Aug 06, 2010 5:33 pm
Location: Sweden
Callsign: SE-JG
IRC name: Johan_G
Version: 3.0.0
OS: Windows 7, 32 bit

Re: Joystick xml codes Library project - open for contributi

Postby Sigmoid » Tue Mar 26, 2013 2:32 am

Here is my XBox 360 controller mapping for the OS X Tattiebogle driver. (It is significantly different from the Windows driver, with the axes and buttons numbered differently, etc.)
The driver can be found here: http://tattiebogle.net/index.php/ProjectRoot/Xbox360Controller/OsxDriver

Control scheme:
Left analog stick: Viewport control; click: Reset view
Right analog stick: Aileron / Elevator; click: Reset trim
Analog trigger: Rudder
D-Pad up-down: Throttle increase/decrease
D-Pad left-right: RPM decrease/increase
Trigger buttons: Ground brakes left / right (previously: Set Rudder trim)
X-Y buttons: Zoom out/in
A-B buttons: Lower/Raise Flaps
Back button: Toggle gear
Start button: Toggle parking brake
XBox button: Pause

Changelog:
v2.0:
  • I incorporated a virtual axis for rudder, controlled by the two trigger axes joined together like a pair of pedals. I decided to use the upper triggers for ground brakes instead of rudder trim, I just didn't see the reason to even have rudder trim on the controller.
  • Analog, proportional control of the viewport.
  • All analog axes have a power of 2 set, as it makes for a smoother, more natural control on thumbsticks.
v2.1:
  • Throttle control takes engine selection into account.
  • Throttle control smoother, it is ~4 seconds end to end.
  • Removed all dead-bands. The XBox 360 controller has an enormous (~15%) area on its analog sticks in the center where the elastic centering no longer applies properly, so it would require a dead-band above 10% to properly make sure there are no involuntary movements. However, such a huge deadband make some more sensitive aircraft like the Cub really hard to control (its elevator is super sensitive at low speeds). Usually you'll be holding the yoke anyway during flight, unless the autopilot is turned on. The large dead-band is okay (and in fact necessary) for the viewport adjustment, so I placed a dead-band setting in the viewport adjuster nasal code itself, to make it plainer that the deadband applies to the viewport control, not the stick itself, were it reassigned for some other function.
v3.0:
  • Had to rethink the layout after putting some hours of flight into it. Engine controls on the D-Pad. Using the XYAB buttons in critical situations is hard while holding both the yoke and the rudder.
  • Totally the best zoom algorithm ever on the XY buttons.
  • Removed the trim controls. Having them on the keyboard will be perfectly fine.
  • Stopped using controls.nas for brakes, as the brake interpolate time was too short, so I made it a bit longer.

v3.0:
Code: Select all
<?xml version="1.0"?>

<PropertyList>

  <nasal><script><![CDATA[
 
    # Common functions
    var adjustAxis = func(axis, factor, power) {
      var adjAxis = axis * factor;
      var val = math.abs(adjAxis);
      var sign = math.sgn(adjAxis);
      if (val > 0)
        return math.pow(val,power) * sign;
      else return 0;
    };
   
    # Intelligent viewport control
    # - adjustment constants
    var viewDeadBand = 0.2;
    var viewHorizontalFactor = -1.0;
    var viewVerticalFactor = 1.0;
    var viewPower = 2;
    var zoomMinFOV = 10;
    var zoomETA = 4;
    # - working code
    var viewHorizontalAxis = 0.0;
    var viewVerticalAxis = 0.0;
   var viewLoop = func {
     if (math.abs(viewHorizontalAxis) > viewDeadBand)
       view.panViewDir(adjustAxis(viewHorizontalAxis, viewHorizontalFactor, viewPower));
     if (math.abs(viewVerticalAxis) > viewDeadBand)
       view.panViewPitch(adjustAxis(viewVerticalAxis, viewVerticalFactor, viewPower));
     settimer(viewLoop, 0);
   };
   settimer(viewLoop, 0);
   var zoomIn = func {
      var zoomMaxFOV = getprop("/sim/view/config/default-field-of-view-deg");
      var zoomDiff = zoomMaxFOV - zoomMinFOV;
      interpolate("/sim/current-view/field-of-view", zoomMinFOV, (getprop("/sim/current-view/field-of-view") - zoomMinFOV) * (zoomETA / zoomDiff));
    }
    var zoomOut = func {
      var zoomMaxFOV = getprop("/sim/view/config/default-field-of-view-deg");
      var zoomDiff = zoomMaxFOV - zoomMinFOV;
      interpolate("/sim/current-view/field-of-view", zoomMaxFOV, (zoomMaxFOV - getprop("/sim/current-view/field-of-view"))  * (zoomETA / zoomDiff));
    }
    var zoomStop = func {
      interpolate("/sim/current-view/field-of-view", getprop("/sim/current-view/field-of-view"), 0);
    }
   
   # Virtual rudder pedal
    # - adjustment constants
   var pedalFactor = 0.5;
   var pedalPower = 2;
   # - working code
   var pedalLeftValue = 0.0;
   var pedalRightValue = 0.0;
   var pedalUpdate = func {
     var pedalVirtualAxis = pedalRightValue - pedalLeftValue;
     setprop("/controls/flight/rudder", adjustAxis(pedalVirtualAxis, pedalFactor, pedalPower));
   };
   
   # Brakes
   # - adjustment constants
   var brakeETA = 2;
   # - working code
   var applyLeftBrake = func(v) {
     interpolate("/controls/gear/brake-left", v, brakeETA);
   }
   var applyRightBrake = func(v) {
     interpolate("/controls/gear/brake-right", v, brakeETA);
   }
   
   
   # Engine controls
   # - adjustment constants
   var controlETA = 4;
    # - working code
    var doForSelectedEngines = func(controlName, operation) {
        foreach (var e; controls.engines) {
          if(!e.selected.getValue()) continue;
          var control = e.controls.getNode(controlName);
          operation(control);
        }
    };
    var controlUp = func(node) {
        interpolate(node, 1, (1 - node.getValue()) * controlETA);
    };
    var controlDown = func(node) {
        interpolate(node, 0, node.getValue() * controlETA);
    };
    var controlStop = func(node) {
        interpolate(node, node.getValue(), 0);
    };
   
  ]]></script></nasal>

  <axis n="0"> <!-- Left stick horizontal -->
    <desc>View Direction</desc>
    <direction>left</direction>
    <binding>
      <command>nasal</command>
      <script>var viewHorizontalAxis = cmdarg().getNode("setting").getValue()</script>
    </binding>
    <dead-band type="double">0</dead-band>
  </axis>
 
  <axis n="1"> <!-- Left stick vertical -->
    <desc>View Elevation</desc>
    <direction>upward</direction>
    <binding>
      <command>nasal</command>
      <script>var viewVerticalAxis = cmdarg().getNode("setting").getValue()</script>
    </binding>
    <dead-band type="double">0</dead-band>
  </axis>
 
  <button n="6"> <!-- Left stick click -->
    <desc>Center View</desc>
    <repeatable type="bool">false</repeatable>
    <binding>
     <command>nasal</command>
     <script>view.resetView()</script>
    </binding>
  </button>

  <axis n="2"> <!-- Right stick horizontal -->
    <desc>Aileron</desc>
    <direction>right</direction>
    <binding>
      <command>property-scale</command>
      <property>/controls/flight/aileron</property>
      <offset type="double">0</offset>
      <factor type="double">1</factor>
      <power type="int">2</power>
    </binding>
    <dead-band type="double">0</dead-band>
  </axis>
 
  <axis n="3"> <!-- Right stick vertical -->
    <desc>Elevator</desc>
    <direction>down/forward</direction>
    <binding>
      <command>property-scale</command>
      <property>/controls/flight/elevator</property>
      <factor type="double">-1</factor>
      <power type="int">2</power>
    </binding>
    <dead-band type="double">0</dead-band>
  </axis>
 
  <button n="7"> <!-- Right stick click -->
    <desc>Reset trim</desc>
    <repeatable>false</repeatable>
    <binding>
      <command>nasal</command>
      <script>
      setprop("/controls/flight/elevator-trim", 0);
      setprop("/controls/flight/aileron-trim", 0);
      setprop("/controls/flight/rudder-trim", 0);
      </script>
    </binding>
  </button>

  <axis n="4"> <!-- Left lower trigger -->
    <desc>Rudder</desc>
    <direction>left</direction>
    <binding>
      <command>nasal</command>
      <script><![CDATA[
        var pedalLeftValue = cmdarg().getNode("setting").getValue();
        pedalUpdate();
      ]]></script>
    </binding>
    <dead-band type="double">0</dead-band>
  </axis>
 
  <axis n="5"> <!-- Right lower trigger -->
    <desc>Rudder</desc>
    <direction>right</direction>
    <binding>
      <command>nasal</command>
      <script><![CDATA[
        var pedalRightValue = cmdarg().getNode("setting").getValue();
        pedalUpdate();
      ]]></script>
    </binding>
    <dead-band type="double">0</dead-band>
  </axis>

  <button n="8"> <!-- Left upper trigger -->
    <desc>Left Ground brake</desc>
    <repeatable>false</repeatable>
    <binding>
     <command>nasal</command>
     <script>applyLeftBrake(1)</script>
    </binding>
    <mod-up>
     <binding>
      <command>nasal</command>
      <script>applyLeftBrake(0)</script>
     </binding>
    </mod-up>
  </button>
 
  <button n="9"> <!--Right upper trigger -->
    <desc>Right Ground brake</desc>
    <repeatable>false</repeatable>
    <binding>
     <command>nasal</command>
     <script>applyRightBrake(1)</script>
    </binding>
    <mod-up>
     <binding>
      <command>nasal</command>
      <script>applyRightBrake(0)</script>
     </binding>
    </mod-up>
  </button>
 
  <button n="0"> <!-- D-Pad UP -->
   <desc>Throttle increase</desc>
   <repeatable type="bool">false</repeatable>
    <binding>
     <command>nasal</command>
     <script>doForSelectedEngines("throttle", controlUp)</script>
    </binding>
    <mod-up>
     <binding>
      <command>nasal</command>
      <script>doForSelectedEngines("throttle", controlStop)</script>
     </binding>
    </mod-up>
  </button>
 
  <button n="1"> <!-- D-Pad DOWN -->
    <desc>Throttle decrease</desc>
    <repeatable type="bool">false</repeatable>
    <binding>
     <command>nasal</command>
     <script>doForSelectedEngines("throttle", controlDown)</script>
    </binding>
    <mod-up>
     <binding>
      <command>nasal</command>
      <script>doForSelectedEngines("throttle", controlStop)</script>
     </binding>
    </mod-up>
  </button>
 
  <button n="2"> <!-- D-Pad LEFT -->
   <name>d</name>
   <desc>Propeller Finer</desc>
   <repeatable type="bool">false</repeatable>
   <binding>
    <command>nasal</command>
    <script>doForSelectedEngines("propeller-pitch", controlDown)</script>
   </binding>
   <mod-up>
    <binding>
     <command>nasal</command>
     <script>doForSelectedEngines("propeller-pitch", controlStop)</script>
    </binding>
   </mod-up>
  </button>
 
  <button n="3"> <!--D-Pad RIGHT -->
   <name>d</name>
   <desc>Propeller Finer</desc>
   <repeatable type="bool">false</repeatable>
   <binding>
    <command>nasal</command>
    <script>doForSelectedEngines("propeller-pitch", controlUp)</script>
   </binding>
   <mod-up>
    <binding>
     <command>nasal</command>
     <script>doForSelectedEngines("propeller-pitch", controlStop)</script>
    </binding>
   </mod-up>
  </button>

  <button n="11"> <!-- Button A -->
    <desc>Flaps Down</desc>
    <repeatable>false</repeatable>
    <binding>
     <command>nasal</command>
     <script>controls.flapsDown(1)</script>
    </binding>
  </button>

  <button n="12"> <!-- Button B -->
    <desc>Flaps Up</desc>
    <repeatable>false</repeatable>
    <binding>
      <command>nasal</command>
      <script>controls.flapsDown(-1)</script>
    </binding>
  </button>
 
  <button n="13"> <!-- Button X -->
    <desc>Zoom in</desc>
    <repeatable>false</repeatable>
    <binding>
     <command>nasal</command>
     <script>zoomIn()</script>
    </binding>
    <mod-up>
     <binding>
      <command>nasal</command>
      <script>zoomStop()</script>
     </binding>
    </mod-up>
  </button>
 
  <button n="14"> <!-- Button Y -->
    <desc>Zoom out</desc>
    <repeatable>false</repeatable>
    <binding>
     <command>nasal</command>
     <script>zoomOut()</script>
    </binding>
    <mod-up>
     <binding>
      <command>nasal</command>
      <script>zoomStop()</script>
     </binding>
    </mod-up>
  </button>

  <button n="4"> <!-- START button -->
    <desc>Parking brake</desc>
    <repeatable type="bool">false</repeatable>
    <binding>
     <command>nasal</command>
     <script>
     var pb = !getprop("/controls/gear/brake-parking");
     setprop ("/controls/gear/brake-parking",pb);
     </script>
    </binding>
  </button>
 
  <button n="5"> <!-- BACK button -->
    <desc>Landing gear toggle</desc>
    <repeatable type="bool">false</repeatable>
    <binding>
     <command>nasal</command>
     <script>controls.gearToggle()</script>
    </binding>
  </button>
 
  <button n="10"> <!-- XBox button -->
    <desc>Pause</desc>
    <repeatable type="bool">false</repeatable>
    <binding>
     <command>nasal</command>
     <script>
     var p = !getprop("/sim/freeze/master");
     setprop ("sim/freeze/master",p);
     setprop ("sim/freeze/clock",p);
     </script>
    </binding>
  </button>
 
  <name type="string">XBox 360 Controller via Tattiebogle</name>
</PropertyList>


Remarks: The controller name string is entirely arbitrary, as there is a bug either in the driver as it doesn't provide a legible vendor id, or in FlightGear that it cannot read it. Even though the pad works, it is not displayed in Help/Joystick Configuration. I get the following error message in the log that might have something to do with it:
Code: Select all
Nasal runtime error: non-objects have no members
  at /Applications/FlightGear.app/Contents/Resources/../Resources/data/Nasal/joystick.nas, line 532
  called from: __dlg:joystick-config, line 9


Also, the beginning of the log has some entries that only appear with the pad plugged in, it may shed some light on possible problems with the driver or with the FG joystick stack on OSX.
Code: Select all
WARNING: input type element has weird usage (ffffffffffffffff)
WARNING: input type element has weird usage (ffffffffffffffff)
WARNING: input type element has weird usage (ffffffffffffffff)
WARNING: input type element has weird usage (3f)
WARNING: input type element has weird usage (3b)
Sigmoid
 
Posts: 48
Joined: Tue Mar 26, 2013 12:24 am

Re: Joystick xml codes Library project - open for contributi

Postby blaster » Fri Apr 12, 2013 4:32 am

Hey guys. I want to program a single button to deploy speedbrakes and spoilers at the same time, and then retract them when I push the button again. Is there a way to do this? I've been trying to learn this xml stuff, but I'm struggling with it. Thanks.
blaster
 
Posts: 41
Joined: Sun Feb 12, 2012 4:48 am

Re: Joystick xml codes Library project - open for contributi

Postby Philosopher » Fri Apr 12, 2013 1:00 pm

Code: Select all
<binding>
    <command>nasal</command>
    <script>
        var speedbrake = getprop("/controls/flight/speedbrake");
        setprop("/controls/flight/spoilers", !speedbrake);
        setprop("/controls/flight/speedbrake", !speedbrake);
    </script>
</binding>
Thanks,
Philosopher
(inactive but lurking occasionally...)
Philosopher
 
Posts: 1590
Joined: Sun Aug 12, 2012 6:29 pm
Location: Stuck in my head...
Callsign: AFTI
Version: Git
OS: Mac OS X 10.7.5

Re: Joystick xml codes Library project - open for contributi

Postby Philosopher » Fri Apr 12, 2013 1:24 pm

One comment, Sigmoid: in controls.nas there's is a "fullBrakeTime" variable which you could change instead of creating your own functions. That would be a system-wide change, obviously, and could either be done in the file or in your bindings like so:
Code: Select all
controls.fullBrakeTime = 2;

In fact, there's a simple hack to allow you to define fullBrakeTime separately for each namespace as a local variable (i.e. «var fullBrakeTime = 2;»).
Code: Select all
##
# Brake handling.
#
var fullBrakeTime = 0.5;
var applyBrakes = func(v, which = 0) {
    var fullBrakeTime = caller(1)[0]["fullBrakeTime"] != nil ? caller(1)[0].fullBrakeTime : fullBrakeTime;
    if (which <= 0) { interpolate("/controls/gear/brake-left", v, fullBrakeTime); }
    if (which >= 0) { interpolate("/controls/gear/brake-right", v, fullBrakeTime); }
}


Note the assignment to itself: this is OK since it just recurses into the outer scope ;).
Thanks,
Philosopher
(inactive but lurking occasionally...)
Philosopher
 
Posts: 1590
Joined: Sun Aug 12, 2012 6:29 pm
Location: Stuck in my head...
Callsign: AFTI
Version: Git
OS: Mac OS X 10.7.5

Re: Joystick xml codes Library project - open for contributi

Postby sim » Fri Apr 12, 2013 2:59 pm

blaster said
I want to program a single button to deploy speedbrakes and spoilers at the same time


Try these blaster. First one operates only while button remains pressed. That's my preference as speedbrakes take time to deploy and to retract and if your flying is as hairy as mine it pays to get 'em in sharpish!

Second one is as you asked. You can delete the "gui....etc" if you dislike onscreen pop ups. But there lies uncertainty as it increases chance of accidentally leaving 'em deployed. Another reason I prefer First code!

Code: Select all
<button n="5"> <desc>speedbrake and spoilers</desc> <repeatable type="bool">false</repeatable>
 <binding> <command>nasal</command>
   <script>setprop("/controls/flight/speedbrake", 1);setprop("/controls/flight/spoilers", 1);</script>
 </binding>
<mod-up>
 <binding> <command>nasal</command>
  <script>setprop("/controls/flight/speedbrake", 0);setprop("/controls/flight/spoilers", 0);</script>
 </binding>
</mod-up> </button>


You may need to change button number from 5 to whichever number suits........

Code: Select all
<button n="5"> <desc>speedbrake and spoilers</desc> <repeatable type="bool">false</repeatable>
 <binding> <command>nasal</command>
   <script>i = !getprop("/controls/flight/speedbrake");
            setprop("/controls/flight/speedbrake", i);
            i = !getprop("/controls/flight/speedbrake");
            setprop("/controls/flight/speedbrake", i);
      gui.popupTip("AIRBRAKES" ~ (i ? "ON" : "OFF"));
   </script>
 </binding>
</button>
User avatar
sim
 
Posts: 1388
Joined: Tue Jun 30, 2009 2:13 pm
Location: Shropshire England
Callsign: Fly4Fun
Version: 0.9.10 up
OS: 64 Win 10 HD6450

PreviousNext

Return to Hardware

Who is online

Users browsing this forum: No registered users and 4 guests