2011-01-01 09:35:15 +00:00
|
|
|
var startEngine = func(v = 1, which...) {
|
|
|
|
if (!v and !size(which))
|
2009-03-14 20:56:06 +00:00
|
|
|
return props.setAll("/controls/engines/engine", "starter", 0);
|
2011-01-01 09:35:15 +00:00
|
|
|
if(size(which)) {
|
|
|
|
foreach(var i; which)
|
|
|
|
foreach(var e; engines)
|
|
|
|
if(e.index == i)
|
|
|
|
e.controls.getNode("starter").setBoolValue(v);
|
|
|
|
} else {
|
|
|
|
foreach(var e; engines)
|
|
|
|
if(e.selected.getValue())
|
|
|
|
e.controls.getNode("starter").setBoolValue(v);
|
|
|
|
}
|
2003-12-29 22:59:00 +00:00
|
|
|
}
|
|
|
|
|
2008-01-30 16:48:04 +00:00
|
|
|
var selectEngine = func(which) {
|
|
|
|
foreach(var e; engines) e.selected.setBoolValue(which == e.index);
|
2003-12-22 20:05:18 +00:00
|
|
|
}
|
|
|
|
|
2007-07-19 16:18:39 +00:00
|
|
|
# Selects (state=1) or deselects (state=0) a list of engines, or all
|
|
|
|
# engines if no list is specified. Example: selectEngines(1, 1, 3, 5);
|
|
|
|
#
|
2008-01-30 16:48:04 +00:00
|
|
|
var selectEngines = func (state, which...) {
|
|
|
|
if(size(which)) {
|
|
|
|
foreach(var i; which)
|
|
|
|
foreach(var e; engines)
|
|
|
|
if(e.index == i)
|
|
|
|
e.selected.setBoolValue(state);
|
2007-07-19 16:18:39 +00:00
|
|
|
} else {
|
2008-01-30 16:48:04 +00:00
|
|
|
foreach(var e; engines)
|
|
|
|
e.selected.setBoolValue(state);
|
2007-07-19 16:18:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-10-07 15:12:05 +00:00
|
|
|
var selectAllEngines = func {
|
2008-01-30 16:48:04 +00:00
|
|
|
foreach(var e; engines) e.selected.setBoolValue(1);
|
2003-12-22 20:05:18 +00:00
|
|
|
}
|
|
|
|
|
2008-01-30 16:48:04 +00:00
|
|
|
var stepMagnetos = func(change) {
|
2008-02-23 18:18:55 +00:00
|
|
|
if (!change)
|
|
|
|
return;
|
2008-01-30 16:48:04 +00:00
|
|
|
foreach(var e; engines) {
|
|
|
|
if(e.selected.getValue()) {
|
|
|
|
var mag = e.controls.getNode("magnetos", 1);
|
2003-12-22 20:05:18 +00:00
|
|
|
mag.setIntValue(mag.getValue() + change);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-10-07 15:12:05 +00:00
|
|
|
var centerFlightControls = func {
|
2003-12-22 20:05:18 +00:00
|
|
|
setprop("/controls/flight/elevator", 0);
|
|
|
|
setprop("/controls/flight/aileron", 0);
|
|
|
|
setprop("/controls/flight/rudder", 0);
|
|
|
|
}
|
|
|
|
|
2007-07-19 16:18:39 +00:00
|
|
|
var throttleMouse = func {
|
|
|
|
if(!getprop("/devices/status/mice/mouse[0]/button[1]")) return;
|
|
|
|
var delta = cmdarg().getNode("offset").getValue() * -4;
|
2008-01-30 16:48:04 +00:00
|
|
|
foreach(var e; engines) {
|
|
|
|
if(!e.selected.getValue()) continue;
|
|
|
|
var throttle = e.controls.getNode("throttle");
|
|
|
|
var val = throttle.getValue() + delta;
|
2007-07-19 16:18:39 +00:00
|
|
|
if(size(arg) > 0) val = -val;
|
2008-01-30 16:48:04 +00:00
|
|
|
throttle.setDoubleValue(val);
|
2007-07-19 16:18:39 +00:00
|
|
|
}
|
2003-12-22 20:05:18 +00:00
|
|
|
}
|
|
|
|
|
2018-02-16 17:43:27 +00:00
|
|
|
setprop("/controls/engines/throttle-all",0);
|
|
|
|
setprop("/controls/engines/mixture-all",0);
|
|
|
|
setprop("/controls/engines/propeller-pitch-all",0);
|
|
|
|
|
|
|
|
setForAllEnginesProperty= func(type){
|
|
|
|
var engineRoot = props.globals.getNode("/controls/engines");
|
|
|
|
var v = getprop("/controls/engines/"~type~"-all");
|
|
|
|
v = -v;
|
|
|
|
v = (v+1)*0.5; # scale from -1..1 to 0..1
|
|
|
|
foreach( var c; engineRoot.getChildren() ){
|
|
|
|
if (c.getName() =="engine"){
|
|
|
|
var n = c.getNode(type);
|
|
|
|
if(n!=nil) {
|
|
|
|
n.setValue(v);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_setlistener("/controls/engines/throttle-all", func{
|
|
|
|
setForAllEnginesProperty("throttle");
|
|
|
|
},0,0);
|
|
|
|
_setlistener("/controls/engines/mixture-all", func{
|
|
|
|
setForAllEnginesProperty("mixture");
|
|
|
|
},0,0);
|
|
|
|
_setlistener("/controls/engines/propeller-pitch-all", func{
|
|
|
|
setForAllEnginesProperty("propeller-pitch");
|
|
|
|
},0,0);
|
|
|
|
|
2008-02-23 18:18:55 +00:00
|
|
|
# Joystick axis handlers (use cmdarg). Shouldn't be called from
|
|
|
|
# other contexts. A non-null argument reverses the axis direction.
|
2008-01-30 21:52:29 +00:00
|
|
|
var axisHandler = func(pre, post) {
|
|
|
|
func(invert = 0) {
|
|
|
|
var val = cmdarg().getNode("setting").getValue();
|
|
|
|
if(invert) val = -val;
|
|
|
|
foreach(var e; engines)
|
|
|
|
if(e.selected.getValue())
|
|
|
|
setprop(pre ~ e.index ~ post, (1 - val) / 2);
|
|
|
|
}
|
2003-12-22 20:05:18 +00:00
|
|
|
}
|
2008-01-30 21:52:29 +00:00
|
|
|
var throttleAxis = axisHandler("/controls/engines/engine[", "]/throttle");
|
|
|
|
var mixtureAxis = axisHandler("/controls/engines/engine[", "]/mixture");
|
|
|
|
var propellerAxis = axisHandler("/controls/engines/engine[", "]/propeller-pitch");
|
|
|
|
var carbHeatAxis = axisHandler("/controls/anti-ice/engine[", "]/carb-heat");
|
2013-11-05 20:38:43 +00:00
|
|
|
var conditionAxis = axisHandler("/controls/engines/engine[", "]/condition");
|
2003-12-22 20:05:18 +00:00
|
|
|
|
2010-05-17 19:51:16 +00:00
|
|
|
# Joystick axis handler for controlling subsets of similar properties.
|
|
|
|
# Shouldn't be called from other contexts.
|
|
|
|
# The argument engine can be either an index number or a list of
|
|
|
|
# index numbers.
|
|
|
|
# Use only when perEngineSelectedAxisHandler() below will not do.
|
|
|
|
var perIndexAxisHandler = func(pre, post) {
|
|
|
|
return
|
|
|
|
func(index, invert = 0) {
|
|
|
|
var val = cmdarg().getNode("setting").getValue();
|
|
|
|
if(invert) val = -val;
|
|
|
|
if (typeof(index) == "scalar") {
|
|
|
|
setprop(pre ~ index ~ post, (1 - val) / 2);
|
|
|
|
} else {
|
|
|
|
foreach (var e; index) {
|
|
|
|
setprop(pre ~ e ~ post, (1 - val) / 2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
# Joystick axis handler for controlling a selected axis on specific engines.
|
|
|
|
# Shouldn't be called from other contexts.
|
|
|
|
# The argument mode can be
|
|
|
|
# 0 - throttle
|
|
|
|
# 1 - mixture
|
|
|
|
# 2 - propeller-pitch
|
|
|
|
# The argument engine to the returned function can be either an
|
|
|
|
# engine number or a list of engine numbers.
|
2017-04-20 20:06:42 +00:00
|
|
|
# Usage example (controlling the mixture of engines 0 and 1):
|
2010-05-17 19:51:16 +00:00
|
|
|
# <script>
|
2017-04-20 20:06:42 +00:00
|
|
|
# controls.perEngineSelectedAxisHandler(1)([0,1]);
|
2010-05-17 19:51:16 +00:00
|
|
|
# </script>
|
|
|
|
var _axisMode = {
|
|
|
|
0: perIndexAxisHandler("/controls/engines/engine[",
|
|
|
|
"]/throttle"),
|
|
|
|
1: perIndexAxisHandler("/controls/engines/engine[",
|
|
|
|
"]/mixture"),
|
|
|
|
2: perIndexAxisHandler("/controls/engines/engine[",
|
|
|
|
"]/propeller-pitch")
|
|
|
|
};
|
|
|
|
var perEngineSelectedAxisHandler = func(mode) {
|
|
|
|
return _axisMode[mode];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-12-22 20:05:18 +00:00
|
|
|
##
|
|
|
|
# Wrapper around stepProps() which emulates the "old" flap behavior for
|
|
|
|
# configurations that aren't using the new mechanism.
|
|
|
|
#
|
2007-11-29 13:16:13 +00:00
|
|
|
var flapsDown = func(step) {
|
|
|
|
if(step == 0) return;
|
2003-12-22 20:05:18 +00:00
|
|
|
if(props.globals.getNode("/sim/flaps") != nil) {
|
2007-11-29 13:16:13 +00:00
|
|
|
stepProps("/controls/flight/flaps", "/sim/flaps", step);
|
2003-12-22 20:05:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
# Hard-coded flaps movement in 3 equal steps:
|
2007-11-29 13:16:13 +00:00
|
|
|
var val = 0.3333334 * step + getprop("/controls/flight/flaps");
|
|
|
|
setprop("/controls/flight/flaps", val > 1 ? 1 : val < 0 ? 0 : val);
|
2003-12-22 20:05:18 +00:00
|
|
|
}
|
|
|
|
|
2007-11-29 13:16:13 +00:00
|
|
|
var wingSweep = func(step) {
|
|
|
|
if(step == 0) return;
|
|
|
|
if(props.globals.getNode("/sim/wing-sweep") != nil) {
|
|
|
|
stepProps("/controls/flight/wing-sweep", "/sim/wing-sweep", step);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
# Hard-coded wing movement in 5 equal steps:
|
|
|
|
var val = 0.20 * step + getprop("/controls/flight/wing-sweep");
|
|
|
|
setprop("/controls/flight/wing-sweep", val > 1 ? 1 : val < 0 ? 0 : val);
|
|
|
|
}
|
|
|
|
|
2008-12-17 18:42:41 +00:00
|
|
|
var wingsDown = func(v) {
|
|
|
|
if(v) setprop("/controls/flight/wing-fold", v > 0);
|
|
|
|
}
|
|
|
|
|
2007-11-29 13:16:13 +00:00
|
|
|
var stepSpoilers = func(step) {
|
2004-06-01 08:13:12 +00:00
|
|
|
if(props.globals.getNode("/sim/spoilers") != nil) {
|
2007-11-29 13:16:13 +00:00
|
|
|
stepProps("/controls/flight/spoilers", "/sim/spoilers", step);
|
2004-06-01 08:13:12 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
# Hard-coded spoilers movement in 4 equal steps:
|
2007-11-29 13:16:13 +00:00
|
|
|
var val = 0.25 * step + getprop("/controls/flight/spoilers");
|
|
|
|
setprop("/controls/flight/spoilers", val > 1 ? 1 : val < 0 ? 0 : val);
|
2004-06-01 08:13:12 +00:00
|
|
|
}
|
|
|
|
|
2007-11-29 13:16:13 +00:00
|
|
|
var stepSlats = func(step) {
|
2004-06-01 08:13:12 +00:00
|
|
|
if(props.globals.getNode("/sim/slats") != nil) {
|
2007-11-29 13:16:13 +00:00
|
|
|
stepProps("/controls/flight/slats", "/sim/slats", step);
|
2004-06-01 08:13:12 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
# Hard-coded slats movement in 4 equal steps:
|
2007-11-29 13:16:13 +00:00
|
|
|
var val = 0.25 * step + getprop("/controls/flight/slats");
|
|
|
|
setprop("/controls/flight/slats", val > 1 ? 1 : val < 0 ? 0 : val);
|
2004-06-01 08:13:12 +00:00
|
|
|
}
|
|
|
|
|
2003-12-22 20:05:18 +00:00
|
|
|
##
|
|
|
|
# Steps through an "array" of property settings. The first argument
|
|
|
|
# specifies a destination property. The second is a string containing
|
|
|
|
# a global property tree. This tree should contain an array of
|
|
|
|
# indexed <setting> children. This function will maintain a
|
|
|
|
# <current-setting> child, which contains the index of the currently
|
|
|
|
# active setting. The third argument specifies an integer delta,
|
|
|
|
# indicating how many steps to move through the setting array.
|
|
|
|
# Note that because of the magic of the property system, this
|
|
|
|
# mechanism works for all scalar property types (bool, int, double,
|
|
|
|
# string).
|
|
|
|
#
|
|
|
|
# TODO: This interface could easily be extended to allow for wrapping,
|
|
|
|
# in addition to clamping, allowing a "cycle" of settings to be
|
|
|
|
# defined. It could also be hooked up with the interpolate() call,
|
|
|
|
# which would allow the removal of the transition-time feature from
|
|
|
|
# YASim. Finally, other pre-existing features (the views and engine
|
|
|
|
# magnetos, for instance), work similarly but not compatibly, and
|
|
|
|
# could be integrated.
|
|
|
|
#
|
2013-10-20 03:34:56 +00:00
|
|
|
var stepProps = func(dst, array, delta) {
|
|
|
|
dst = props.globals.getNode(dst);
|
|
|
|
array = props.globals.getNode(array);
|
2003-12-22 20:05:18 +00:00
|
|
|
if(dst == nil or array == nil) { return; }
|
|
|
|
|
2007-10-07 15:12:05 +00:00
|
|
|
var sets = array.getChildren("setting");
|
2003-12-22 20:05:18 +00:00
|
|
|
|
2007-10-07 15:12:05 +00:00
|
|
|
var curr = array.getNode("current-setting", 1).getValue();
|
2003-12-22 20:05:18 +00:00
|
|
|
if(curr == nil) { curr = 0; }
|
|
|
|
curr = curr + delta;
|
|
|
|
if (curr < 0) { curr = 0; }
|
|
|
|
elsif(curr >= size(sets)) { curr = size(sets) - 1; }
|
|
|
|
|
|
|
|
array.getNode("current-setting").setIntValue(curr);
|
|
|
|
dst.setValue(sets[curr].getValue());
|
|
|
|
}
|
|
|
|
|
|
|
|
##
|
|
|
|
# "Slews" a property smoothly, without dependence on the simulator
|
|
|
|
# frame rate. The first argument is the property name. The second is
|
2004-02-10 18:12:09 +00:00
|
|
|
# a rate, in units per second. NOTE: this modifies the property for
|
|
|
|
# the current frame only; it is intended to be called by bindings
|
|
|
|
# which repeat each frame. If you want to cause motion over time, see
|
2008-09-30 18:11:46 +00:00
|
|
|
# interpolate(). Returns new value.
|
2003-12-22 20:05:18 +00:00
|
|
|
#
|
2007-10-07 15:12:05 +00:00
|
|
|
var slewProp = func(prop, delta) {
|
|
|
|
delta *= getprop("/sim/time/delta-realtime-sec");
|
2008-09-30 20:33:18 +00:00
|
|
|
setprop(prop, getprop(prop) + delta);
|
|
|
|
return getprop(prop); # must read again because of clamping
|
2003-12-22 20:05:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
# Standard trim rate, in units per second. Remember that the full
|
|
|
|
# range of a trim axis is 2.0. Should probably read this out of a
|
|
|
|
# property...
|
2007-10-07 15:12:05 +00:00
|
|
|
var TRIM_RATE = 0.045;
|
2018-02-16 17:43:27 +00:00
|
|
|
var setElevatorTrimToPosition_listener = nil;
|
|
|
|
setElevatorTrimToPosition = func() {
|
|
|
|
if (setElevatorTrimToPosition_listener != nil) {
|
|
|
|
removelistener(setElevatorTrimToPosition_listener);
|
|
|
|
setElevatorTrimToPosition_listener = nil;
|
|
|
|
}
|
|
|
|
var nv = getprop("/controls/flight/elevator")+getprop("/controls/flight/elevator-trim");
|
2018-07-27 22:33:19 +00:00
|
|
|
nv = math.min(math.max(-1.0,nv),1.0);
|
2018-02-16 17:43:27 +00:00
|
|
|
var lv = getprop("/controls/flight/elevator");
|
2018-07-27 22:33:19 +00:00
|
|
|
if (math.abs(lv) <= 0.001){
|
|
|
|
print("Elevator trim: centre");
|
|
|
|
setprop("/controls/flight/elevator-trim", 0);
|
|
|
|
} else {
|
|
|
|
print("Trim when centered stick");
|
|
|
|
setElevatorTrimToPosition_listener = setlistener("/controls/flight/elevator", func(v){
|
|
|
|
if (math.abs(v.getValue()) <= 0.001) {
|
|
|
|
setprop("controls/flight/elevator",0);
|
|
|
|
removelistener(setElevatorTrimToPosition_listener);
|
|
|
|
setElevatorTrimToPosition_listener = nil;
|
|
|
|
print("set trim to ",nv);
|
|
|
|
setprop("/controls/flight/elevator-trim", nv);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
print("Not trimming yet ",v.getValue());
|
|
|
|
|
|
|
|
}, 0, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-12-22 20:05:18 +00:00
|
|
|
##
|
|
|
|
# Handlers. These are suitable for binding to repeatable button press
|
|
|
|
# events. They are *not* good for binding to the keyboard, since (at
|
|
|
|
# least) X11 synthesizes its own key repeats.
|
|
|
|
#
|
2013-10-20 03:34:56 +00:00
|
|
|
var elevatorTrim = func(speed) {
|
|
|
|
slewProp("/controls/flight/elevator-trim", speed * TRIM_RATE); }
|
|
|
|
var aileronTrim = func(speed) {
|
|
|
|
slewProp("/controls/flight/aileron-trim", speed * TRIM_RATE); }
|
|
|
|
var rudderTrim = func(speed) {
|
|
|
|
slewProp("/controls/flight/rudder-trim", speed * TRIM_RATE); }
|
2003-12-22 20:05:18 +00:00
|
|
|
|
2007-10-07 15:12:05 +00:00
|
|
|
var THROTTLE_RATE = 0.33;
|
2003-12-22 20:05:18 +00:00
|
|
|
|
2013-10-20 03:34:56 +00:00
|
|
|
var adjThrottle = func(speed) {
|
|
|
|
adjEngControl("throttle", speed); }
|
|
|
|
var adjMixture = func(speed) {
|
|
|
|
adjEngControl("mixture", speed); }
|
|
|
|
var adjCondition = func(speed) {
|
|
|
|
adjEngControl("condition", speed); }
|
|
|
|
var adjPropeller = func(speed) {
|
|
|
|
adjEngControl("propeller-pitch", speed); }
|
2003-12-22 20:05:18 +00:00
|
|
|
|
2013-10-20 03:34:56 +00:00
|
|
|
var adjEngControl = func(prop, speed) {
|
|
|
|
var delta = speed * THROTTLE_RATE * getprop("/sim/time/delta-realtime-sec");
|
2008-09-30 20:33:18 +00:00
|
|
|
var (value, count) = (0, 0);
|
2008-01-30 16:48:04 +00:00
|
|
|
foreach(var e; engines) {
|
|
|
|
if(e.selected.getValue()) {
|
2013-10-20 03:34:56 +00:00
|
|
|
var node = e.controls.getNode(prop, 1);
|
2006-03-04 18:21:06 +00:00
|
|
|
node.setValue(node.getValue() + delta);
|
2008-09-30 20:33:18 +00:00
|
|
|
value += node.getValue(); # must read again because of clamping
|
|
|
|
count += 1;
|
2006-03-04 18:21:06 +00:00
|
|
|
}
|
2003-12-22 20:05:18 +00:00
|
|
|
}
|
2008-09-30 20:33:18 +00:00
|
|
|
return value / count;
|
2003-12-22 20:05:18 +00:00
|
|
|
}
|
|
|
|
|
2004-01-31 19:55:13 +00:00
|
|
|
##
|
|
|
|
# arg[0] is the throttle increment
|
|
|
|
# arg[1] is the auto-throttle target speed increment
|
2007-07-19 16:18:39 +00:00
|
|
|
var incThrottle = func {
|
2012-06-30 22:24:23 +00:00
|
|
|
var passive = getprop("/autopilot/locks/passive-mode");
|
|
|
|
var locked = getprop("/autopilot/locks/speed");
|
|
|
|
# Note: passive/locked may be nil on aircraft without A/P
|
|
|
|
if ((passive == 0) and (locked))
|
|
|
|
{
|
2007-10-07 15:12:05 +00:00
|
|
|
var node = props.globals.getNode("/autopilot/settings/target-speed-kt", 1);
|
|
|
|
if (node.getValue() == nil) {
|
|
|
|
node.setValue(0.0);
|
|
|
|
}
|
|
|
|
node.setValue(node.getValue() + arg[1]);
|
|
|
|
if (node.getValue() < 0.0) {
|
|
|
|
node.setValue(0.0);
|
|
|
|
}
|
2004-01-31 19:55:13 +00:00
|
|
|
}
|
2012-06-30 22:24:23 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
foreach(var e; engines)
|
|
|
|
{
|
|
|
|
if(e.selected.getValue())
|
|
|
|
{
|
|
|
|
var node = e.controls.getNode("throttle", 1);
|
|
|
|
var val = node.getValue() + arg[0];
|
|
|
|
node.setValue(val < -1.0 ? -1.0 : val > 1.0 ? 1.0 : val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-01-31 19:55:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
##
|
|
|
|
# arg[0] is the aileron increment
|
|
|
|
# arg[1] is the autopilot target heading increment
|
2007-10-07 15:12:05 +00:00
|
|
|
var incAileron = func {
|
2012-06-30 22:24:23 +00:00
|
|
|
var passive = getprop("/autopilot/locks/passive-mode");
|
|
|
|
var locked = getprop("/autopilot/locks/heading");
|
|
|
|
# Note: passive/locked may be nil on aircraft without A/P
|
|
|
|
if ((passive == 0) and (locked == "dg-heading-hold"))
|
|
|
|
{
|
2007-10-07 15:12:05 +00:00
|
|
|
var node = props.globals.getNode("/autopilot/settings/heading-bug-deg", 1);
|
|
|
|
if (node.getValue() == nil) {
|
|
|
|
node.setValue(0.0);
|
|
|
|
}
|
|
|
|
node.setValue(node.getValue() + arg[1]);
|
|
|
|
if (node.getValue() < 0.0) {
|
|
|
|
node.setValue(node.getValue() + 360.0);
|
|
|
|
}
|
|
|
|
if (node.getValue() > 360.0) {
|
|
|
|
node.setValue(node.getValue() - 360.0);
|
|
|
|
}
|
2004-01-31 19:55:13 +00:00
|
|
|
}
|
2012-06-30 22:24:23 +00:00
|
|
|
else if ((passive == 0) and (locked == "true-heading-hold"))
|
|
|
|
{
|
2007-10-07 15:12:05 +00:00
|
|
|
var node = props.globals.getNode("/autopilot/settings/true-heading-deg", 1);
|
|
|
|
if (node.getValue() == nil) {
|
|
|
|
node.setValue(0.0);
|
|
|
|
}
|
|
|
|
node.setValue(node.getValue() + arg[1]);
|
|
|
|
if (node.getValue() < 0.0) {
|
|
|
|
node.setValue(node.getValue() + 360.0);
|
|
|
|
}
|
|
|
|
if (node.getValue() > 360.0) {
|
|
|
|
node.setValue(node.getValue() - 360.0);
|
|
|
|
}
|
2004-01-31 19:55:13 +00:00
|
|
|
}
|
2012-06-30 22:24:23 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
var aileron = props.globals.getNode("/controls/flight/aileron");
|
|
|
|
if (aileron.getValue() == nil) {
|
|
|
|
aileron.setValue(0.0);
|
|
|
|
}
|
|
|
|
aileron.setValue(aileron.getValue() + arg[0]);
|
|
|
|
if (aileron.getValue() < -1.0) {
|
|
|
|
aileron.setValue(-1.0);
|
|
|
|
}
|
|
|
|
if (aileron.getValue() > 1.0) {
|
|
|
|
aileron.setValue(1.0);
|
|
|
|
}
|
|
|
|
}
|
2004-01-31 19:55:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
##
|
|
|
|
# arg[0] is the elevator increment
|
2007-06-22 18:49:38 +00:00
|
|
|
# arg[1] is the autopilot target altitude increment
|
2007-10-07 15:12:05 +00:00
|
|
|
var incElevator = func {
|
2012-06-30 22:24:23 +00:00
|
|
|
var passive = getprop("/autopilot/locks/passive-mode");
|
|
|
|
var locked = getprop("/autopilot/locks/altitude");
|
|
|
|
# Note: passive/locked may be nil on aircraft without A/P
|
|
|
|
if ((passive == 0) and (locked =="altitude-hold"))
|
|
|
|
{
|
|
|
|
var node = props.globals.getNode("/autopilot/settings/target-altitude-ft", 1);
|
|
|
|
if (node.getValue() == nil) {
|
|
|
|
node.setValue(0.0);
|
|
|
|
}
|
|
|
|
node.setValue(node.getValue() + arg[1]);
|
|
|
|
if (node.getValue() < 0.0) {
|
|
|
|
node.setValue(0.0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-10-07 15:12:05 +00:00
|
|
|
var elevator = props.globals.getNode("/controls/flight/elevator");
|
|
|
|
if (elevator.getValue() == nil) {
|
|
|
|
elevator.setValue(0.0);
|
|
|
|
}
|
|
|
|
elevator.setValue(elevator.getValue() + arg[0]);
|
|
|
|
if (elevator.getValue() < -1.0) {
|
|
|
|
elevator.setValue(-1.0);
|
|
|
|
}
|
|
|
|
if (elevator.getValue() > 1.0) {
|
|
|
|
elevator.setValue(1.0);
|
|
|
|
}
|
2004-01-31 19:55:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-12-22 20:05:18 +00:00
|
|
|
##
|
|
|
|
# Joystick axis handlers. Don't call from other contexts.
|
|
|
|
#
|
2010-04-25 21:05:30 +00:00
|
|
|
var elevatorTrimAxis = func { elevatorTrim(cmdarg().getNode("setting").getValue()); }
|
|
|
|
var aileronTrimAxis = func { aileronTrim(cmdarg().getNode("setting").getValue()); }
|
|
|
|
var rudderTrimAxis = func { rudderTrim(cmdarg().getNode("setting").getValue()); }
|
2003-12-22 20:05:18 +00:00
|
|
|
|
2018-02-16 17:43:27 +00:00
|
|
|
#
|
|
|
|
# to avoid clash with "gearToggle"; this will only toggle when
|
|
|
|
# given a parameter of 1; as the controls button binding will pass 0 when the button is pressed and
|
|
|
|
# 1 when the button is released.
|
|
|
|
var gearTogglePosition = func(v) {
|
|
|
|
if (v){
|
|
|
|
if (getprop("/controls/gear/gear-down"))
|
|
|
|
setprop("/controls/gear/gear-down", 0);
|
|
|
|
else
|
|
|
|
setprop("/controls/gear/gear-down", 1);
|
|
|
|
}
|
|
|
|
}
|
2006-03-04 18:21:06 +00:00
|
|
|
##
|
|
|
|
# Gear handling.
|
2018-02-16 17:43:27 +00:00
|
|
|
# - parameter v is either 1 (down), -1 up (retracted)
|
2007-10-07 15:12:05 +00:00
|
|
|
var gearDown = func(v) {
|
|
|
|
if (v < 0) {
|
2018-02-16 17:43:27 +00:00
|
|
|
setprop("/controls/gear/gear-down", 0);
|
2007-10-07 15:12:05 +00:00
|
|
|
} elsif (v > 0) {
|
2018-02-16 17:43:27 +00:00
|
|
|
setprop("/controls/gear/gear-down", 1);
|
2005-06-22 13:08:01 +00:00
|
|
|
}
|
|
|
|
}
|
2007-07-13 13:46:09 +00:00
|
|
|
var gearToggle = func { gearDown(getprop("/controls/gear/gear-down") > 0 ? -1 : 1); }
|
2005-06-22 13:08:01 +00:00
|
|
|
|
2006-03-04 18:21:06 +00:00
|
|
|
##
|
|
|
|
# Brake handling.
|
|
|
|
#
|
2007-07-13 13:46:09 +00:00
|
|
|
var fullBrakeTime = 0.5;
|
|
|
|
var applyBrakes = func(v, which = 0) {
|
2006-03-01 18:33:46 +00:00
|
|
|
if (which <= 0) { interpolate("/controls/gear/brake-left", v, fullBrakeTime); }
|
|
|
|
if (which >= 0) { interpolate("/controls/gear/brake-right", v, fullBrakeTime); }
|
2006-03-01 17:04:20 +00:00
|
|
|
}
|
2018-07-27 22:33:19 +00:00
|
|
|
var applyTrigger = func(v) {
|
|
|
|
setprop("/controls/armament/pickle", v);
|
|
|
|
}
|
2006-03-01 17:04:20 +00:00
|
|
|
|
2007-07-13 13:46:09 +00:00
|
|
|
var applyParkingBrake = func(v) {
|
2006-03-01 17:04:20 +00:00
|
|
|
if (!v) { return; }
|
|
|
|
var p = "/controls/gear/brake-parking";
|
2006-03-01 18:33:46 +00:00
|
|
|
setprop(p, var i = !getprop(p));
|
|
|
|
return i;
|
2006-03-01 17:04:20 +00:00
|
|
|
}
|
2018-02-16 17:43:27 +00:00
|
|
|
var parkingBrakeToggle = func(v) {
|
|
|
|
if (v){
|
|
|
|
if (getprop("/controls/gear/brake-parking"))
|
|
|
|
setprop("/controls/gear/brake-parking", 0);
|
|
|
|
else
|
|
|
|
setprop("/controls/gear/brake-parking", 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
var toggleNWS = func(v) {
|
|
|
|
if (v){
|
|
|
|
if (getprop("/controls/gear/nose-wheel-steering"))
|
|
|
|
setprop("/controls/gear/nose-wheel-steering", 0);
|
|
|
|
else
|
|
|
|
setprop("/controls/gear/nose-wheel-steering", 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var weAppliedSpeedBrake = 99;
|
|
|
|
var weAppliedWheelBrake = 99;
|
|
|
|
|
|
|
|
#
|
|
|
|
# allows one binding to do airbrakes and wheel brakes
|
|
|
|
var applyApplicableBrakes = func(v, which = 0) {
|
|
|
|
var wow = getprop ("/gear/gear[0]/wow")
|
|
|
|
or getprop ("/gear/gear[1]/wow")
|
|
|
|
or getprop ("/gear/gear[2]/wow")
|
|
|
|
or getprop ("/gear/gear[3]/wow")
|
|
|
|
or getprop ("/gear/gear[4]/wow")
|
|
|
|
or getprop ("/gear/gear[5]/wow")
|
|
|
|
or getprop ("/gear/gear[6]/wow")
|
|
|
|
;
|
|
|
|
|
|
|
|
if (wow) {
|
|
|
|
if (!v and weAppliedSpeedBrake != 99) {
|
|
|
|
setprop("controls/flight/speedbrake", 0);
|
|
|
|
weAppliedSpeedBrake=0;
|
|
|
|
}
|
|
|
|
if (which <= 0) {
|
|
|
|
interpolate("/controls/gear/brake-left", v, controls.fullBrakeTime);
|
|
|
|
}
|
|
|
|
if (which >= 0) {
|
|
|
|
interpolate("/controls/gear/brake-right", v, controls.fullBrakeTime);
|
|
|
|
}
|
|
|
|
weAppliedWheelBrake = which;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (!v and weAppliedWheelBrake != 99) {
|
|
|
|
if (weAppliedWheelBrake <= 0) { interpolate("/controls/gear/brake-left", 0, controls.fullBrakeTime); }
|
|
|
|
if (weAppliedWheelBrake >= 0) { interpolate("/controls/gear/brake-right", 0, controls.fullBrakeTime); }
|
|
|
|
weAppliedWheelBrake=0;
|
|
|
|
}
|
|
|
|
|
|
|
|
weAppliedSpeedBrake=which;
|
|
|
|
setprop("controls/flight/speedbrake", v);
|
|
|
|
}
|
|
|
|
}
|
2006-03-01 17:04:20 +00:00
|
|
|
|
2008-10-07 19:22:49 +00:00
|
|
|
# 1: Deploy, -1: Release
|
|
|
|
var deployChute = func(v) setprop("/controls/flight/drag-chute", v);
|
|
|
|
|
2006-06-09 20:52:03 +00:00
|
|
|
##
|
|
|
|
# Weapon handling.
|
|
|
|
#
|
2007-07-13 13:46:09 +00:00
|
|
|
var trigger = func(b) setprop("/controls/armament/trigger", b);
|
|
|
|
var weaponSelect = func(d) {
|
2006-06-24 12:31:58 +00:00
|
|
|
var ws = props.globals.getNode("/controls/armament/selected", 1);
|
|
|
|
var n = ws.getValue();
|
|
|
|
if (n == nil) { n = 0; }
|
|
|
|
ws.setIntValue(n + d);
|
|
|
|
}
|
2006-06-09 20:52:03 +00:00
|
|
|
|
2007-07-13 13:46:09 +00:00
|
|
|
##
|
|
|
|
# Communication.
|
|
|
|
#
|
|
|
|
var ptt = func(b) setprop("/instrumentation/comm/ptt", b);
|
|
|
|
|
2007-11-10 01:29:31 +00:00
|
|
|
##
|
2008-01-30 16:48:04 +00:00
|
|
|
# Lighting.
|
2007-11-10 01:29:31 +00:00
|
|
|
#
|
2007-11-20 17:02:13 +00:00
|
|
|
var toggleLights = func {
|
2007-11-10 01:29:31 +00:00
|
|
|
if (getprop("/controls/switches/panel-lights")) {
|
|
|
|
setprop("/controls/switches/panel-lights-factor", 0);
|
|
|
|
setprop("/controls/switches/panel-lights", 0);
|
|
|
|
setprop("/controls/switches/landing-light", 0);
|
|
|
|
setprop("/controls/switches/flashing-beacon", 0);
|
|
|
|
setprop("/controls/switches/strobe-lights", 0);
|
|
|
|
setprop("/controls/switches/map-lights", 0);
|
|
|
|
setprop("/controls/switches/cabin-lights", 0);
|
|
|
|
setprop("/controls/switches/nav-lights", 0);
|
|
|
|
} else {
|
|
|
|
setprop("/controls/electric/battery-switch", 1);
|
|
|
|
setprop("/controls/electric/alternator-switch", 1);
|
|
|
|
setprop("/controls/switches/panel-lights-factor", 0.1);
|
|
|
|
setprop("/controls/switches/panel-lights", 1);
|
|
|
|
setprop("/controls/switches/landing-light", 1);
|
|
|
|
setprop("/controls/switches/flashing-beacon", 1);
|
|
|
|
setprop("/controls/switches/strobe-lights", 1);
|
|
|
|
setprop("/controls/switches/map-lights", 1);
|
|
|
|
setprop("/controls/switches/cabin-lights", 1);
|
|
|
|
setprop("/controls/switches/nav-lights", 1);
|
|
|
|
}
|
|
|
|
}
|
2008-01-30 16:48:04 +00:00
|
|
|
|
|
|
|
##
|
|
|
|
# Initialization.
|
|
|
|
#
|
|
|
|
var engines = [];
|
|
|
|
_setlistener("/sim/signals/fdm-initialized", func {
|
|
|
|
var sel = props.globals.getNode("/sim/input/selected", 1);
|
|
|
|
var engs = props.globals.getNode("/controls/engines").getChildren("engine");
|
|
|
|
|
2012-03-15 19:23:45 +00:00
|
|
|
# need to reset engine list on every FDM reset
|
|
|
|
engines = [];
|
|
|
|
# process all engines
|
2008-01-30 16:48:04 +00:00
|
|
|
foreach(var e; engs) {
|
|
|
|
var index = e.getIndex();
|
|
|
|
var s = sel.getChild("engine", index, 1);
|
|
|
|
if(s.getType() == "NONE") s.setBoolValue(1);
|
|
|
|
append(engines, { index: index, controls: e, selected: s });
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2011-10-03 18:23:47 +00:00
|
|
|
var replaySkip = func(skip_time)
|
|
|
|
{
|
|
|
|
var t = getprop("/sim/replay/time");
|
|
|
|
if (t != "")
|
|
|
|
{
|
|
|
|
t+=skip_time;
|
|
|
|
if (t>getprop("/sim/replay/end-time"))
|
|
|
|
t = getprop("/sim/replay/end-time");
|
|
|
|
if (t<0)
|
|
|
|
t=0;
|
|
|
|
setprop("/sim/replay/time", t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var speedup = func(speed_up)
|
|
|
|
{
|
|
|
|
var t = getprop("/sim/speed-up");
|
|
|
|
if (speed_up < 0)
|
|
|
|
{
|
|
|
|
t = (t > 1/32) ? t/2 : 1/32;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
t = (t < 32) ? t*2 : 32;
|
|
|
|
}
|
|
|
|
setprop("/sim/speed-up", t);
|
2017-04-20 20:06:42 +00:00
|
|
|
|
2013-03-16 12:46:40 +00:00
|
|
|
# reformat as a string, this is borrowed from replay.xml
|
2017-04-20 20:06:42 +00:00
|
|
|
|
2013-03-16 12:46:40 +00:00
|
|
|
if (t<0.9)
|
|
|
|
{
|
|
|
|
t=1/t; # invert the value
|
|
|
|
t = "1/" ~ t; # convert to a string and show inverted
|
|
|
|
}
|
2017-04-20 20:06:42 +00:00
|
|
|
|
2013-03-16 12:46:40 +00:00
|
|
|
gui.popupTip("Time speed-up: " ~ t ~ "x");
|
2011-10-03 18:23:47 +00:00
|
|
|
}
|
|
|
|
|
2017-04-20 20:06:42 +00:00
|
|
|
# mouse-mode handling
|
2013-03-07 19:36:54 +00:00
|
|
|
|
|
|
|
var cycleMouseMode = func(node)
|
|
|
|
{
|
|
|
|
var reason = node.getChild("reason").getValue();
|
|
|
|
if (reason == "right-click") {
|
|
|
|
if (!getprop("/sim/mouse/right-button-mode-cycle-enabled")) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2017-04-20 20:06:42 +00:00
|
|
|
|
|
|
|
var modeNode = props.globals.getNode('/devices/status/mice/mouse[0]/mode');
|
2013-03-07 19:36:54 +00:00
|
|
|
var mode = modeNode.getValue() + 1;
|
2017-04-20 20:06:42 +00:00
|
|
|
|
2013-03-08 16:47:00 +00:00
|
|
|
if ((mode == 1) and getprop('/sim/mouse/skip-flight-controls-mode')) {
|
|
|
|
mode +=1;
|
|
|
|
}
|
2017-04-20 20:06:42 +00:00
|
|
|
|
2013-03-07 19:36:54 +00:00
|
|
|
if (mode == 3) mode = 0;
|
|
|
|
modeNode.setIntValue(mode);
|
2017-04-20 20:06:42 +00:00
|
|
|
|
2013-03-12 21:45:06 +00:00
|
|
|
# this is really a 'show on-screen hints' control
|
|
|
|
if (getprop('/sim/view-name-popup') == 0)
|
|
|
|
return;
|
2017-04-20 20:06:42 +00:00
|
|
|
|
|
|
|
# some people like popups but strongly object to this one. As you wish.
|
2013-10-25 16:22:12 +00:00
|
|
|
if (getprop('/sim/mouse/cycle-mode-popup') == 0)
|
|
|
|
return;
|
2017-04-20 20:06:42 +00:00
|
|
|
|
2013-03-16 12:46:40 +00:00
|
|
|
if (mode == 0) {
|
|
|
|
fgcommand("clear-message", props.Node.new({ "id":"mouse-mode" }));
|
|
|
|
return;
|
2013-03-07 19:36:54 +00:00
|
|
|
}
|
2017-04-20 20:06:42 +00:00
|
|
|
|
2013-03-16 12:46:40 +00:00
|
|
|
var msg = "";
|
|
|
|
if (mode == 1)
|
|
|
|
msg = "Mouse is controlling flight controls. Press TAB to change.";
|
|
|
|
else
|
|
|
|
msg = "Mouse is controlling view direction. Press TAB to change.";
|
2017-04-20 20:06:42 +00:00
|
|
|
|
2013-03-16 12:46:40 +00:00
|
|
|
fgcommand("show-message", props.Node.new({ "label": msg, "id":"mouse-mode" }));
|
2013-03-07 19:36:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
addcommand("cycle-mouse-mode", cycleMouseMode);
|