1
0
Fork 0

Merge branch 'work' of D:\Git_New\fgdata

This commit is contained in:
Vivian Meazza 2012-08-27 09:17:09 +01:00
commit 36a10e0670
14 changed files with 1898 additions and 62 deletions

View file

@ -51,7 +51,7 @@
</marker-beacon>
<heading-indicator>
<name>heading-indicator</name>
<name>heading-indicator-dg</name>
<number>0</number>
<suction>/systems/vacuum/suction-inhg</suction>
</heading-indicator>

View file

@ -335,9 +335,6 @@ electrical_bus_2 = func() {
var bus_volts = vbus_volts;
var load = 0.0;
# Turn Coordinator Power
setprop("/systems/electrical/outputs/turn-coordinator", bus_volts);
# Map Lights Power
if ( getprop("/controls/switches/nav-lights" ) ) {
setprop("/systems/electrical/outputs/map-lights", bus_volts);
@ -404,6 +401,12 @@ avionics_bus_1 = func() {
bus_volts = ebus1_volts;
}
# Turn Coordinator Power
setprop("/systems/electrical/outputs/turn-coordinator", bus_volts);
# Directional Gyro Power
setprop("/systems/electrical/outputs/DG", bus_volts);
# Avionics Fan Power
setprop("/systems/electrical/outputs/avionics-fan", bus_volts);

View file

@ -0,0 +1,125 @@
<?xml version="1.0"?>
<!--
**********************************************************************
instrumentation.xml
c172p instrumentation configuration. This file selects the
instrumentation modules that should be available.
You can have several instances of the same instrument type.
The value inside the name tag becomes the node in the property tree.
If two instruments have the same name you must use the number tag
to separate them. They become name[number] in the property tree.
Some instruments have additional configuration tags like static-port
and pitot-port. The static- and pitot-ports (and any other system that
an instrument depend on) have to be configured in the systems
configuration file: generic-systems.xml
The values in this file are the default values. If any configuration
tags are omitted in an aircraft specific version of this configuration
file, these values will be used (they are hardcoded).
**********************************************************************
-->
<PropertyList>
<adf>
<name>adf</name>
<number>0</number>
</adf>
<airspeed-indicator>
<name>airspeed-indicator</name>
<number>0</number>
<total-pressure>/systems/pitot/total-pressure-inhg</total-pressure>
<static-pressure>/systems/static/pressure-inhg</static-pressure>
</airspeed-indicator>
<altimeter>
<name>altimeter</name>
<number>0</number>
<static-pressure>/systems/static/pressure-inhg</static-pressure>
<quantum>0</quantum>
<tau>0</tau>
</altimeter>
<attitude-indicator>
<name>attitude-indicator</name>
<number>0</number>
<suction>/systems/vacuum/suction-inhg</suction>
</attitude-indicator>
<clock>
<name>clock</name>
<number>0</number>
</clock>
<dme>
<name>dme</name>
<number>0</number>
</dme>
<altimeter>
<name>encoder</name>
<number>0</number>
<static-pressure>/systems/static/pressure-inhg</static-pressure>
<quantum>10</quantum>
<tau>0.1</tau>
</altimeter>
<marker-beacon>
<name>marker-beacon</name>
<number>0</number>
</marker-beacon>
<heading-indicator-dg>
<name>heading-indicator</name>
<number>0</number>
<suction>/systems/vacuum/suction-inhg</suction>
</heading-indicator-dg>
<KT-70>
<name>kt-70</name>
<number>0</number>
</KT-70>
<magnetic-compass>
<name>magnetic-compass</name>
<number>0</number>
</magnetic-compass>
<nav-radio>
<name>nav</name>
<number>0</number>
</nav-radio>
<nav-radio>
<name>nav</name>
<number>1</number>
</nav-radio>
<slip-skid-ball>
<name>slip-skid-ball</name>
<number>0</number>
</slip-skid-ball>
<transponder>
<name>transponder</name>
<number>0</number>
<mode-c-altitude>/instrumentation/encoder/mode-c-alt-ft</mode-c-altitude>
</transponder>
<turn-indicator>
<name>turn-indicator</name>
<number>0</number>
</turn-indicator>
<vertical-speed-indicator>
<name>vertical-speed-indicator</name>
<number>0</number>
<static-pressure>/systems/static/pressure-inhg</static-pressure>
</vertical-speed-indicator>
</PropertyList>

View file

@ -104,6 +104,11 @@
<!-- Electrical Bus 2 Outputs -->
<output>
<name>Directional Gyro</name>
<prop>/systems/electrical/outputs/DG</prop>
</output>
<output>
<name>Turn Coordinator Power</name>
<prop>/systems/electrical/outputs/turn-coordinator</prop>
@ -341,6 +346,14 @@
<!-- connect bus 2 outputs -->
<connector>
<input>Electrical Bus 2</input>
<output>Directional Gyro</output>
<switch>
<prop>/controls/circuit-breakers/directional-gyro</prop>
</switch>
</connector>
<connector>
<input>Electrical Bus 2</input>
<output>Turn Coordinator Power</output>

View file

@ -128,7 +128,9 @@ Started October 23 2001 by John Check, fgpanels@rockfish.net
</flight-recorder>
<menubar include="Dialogs/c172p-menu.xml"/>
<instrumentation n="0">
<path>Aircraft/c172p/Systems/instrumentation.xml</path>
</instrumentation>
</sim>
<!-- trim for level cruise -->

View file

@ -38,3 +38,5 @@ WRITE ALLOW $FG_HOME/state/*.xml
WRITE ALLOW $FG_HOME/aircraft-data/*.xml
WRITE ALLOW $FG_HOME/Wildfire/*.xml
WRITE ALLOW $FG_HOME/runtime-jetways/*.xml
WRITE ALLOW $FG_HOME/Input/Joysticks/*.xml

View file

@ -53,6 +53,31 @@ var _setColorNodes = func(nodes, color)
nodes[3].setDoubleValue(1);
};
var _getColor = func(color)
{
if( size(color) == 1 )
var color = color[0];
if( typeof(color) == 'scalar' )
return color;
if( typeof(color) != "vector" )
return debug.warn("Wrong type for color");
if( size(color) < 3 or size(color) > 4 )
return debug.warn("Color needs 3 or 4 values (RGB or RGBA)");
var str = 'rgb';
if( size(color) == 4 )
str ~= 'a';
str ~= '(';
# rgb = [0,255], a = [0,1]
for(var i = 0; i < size(color); i += 1)
str ~= (i > 0 ? ',' : '') ~ (i < 3 ? int(color[i] * 255) : color[i]);
return str ~ ')';
};
var _arg2valarray = func
{
var ret = arg;
@ -233,14 +258,10 @@ var Element = {
setScale: func { me._getTf().setScale(arg); return me; },
# Shortcut for getting scale
getScale: func me._getTf().getScale(),
# Set the line/text color
#
# @param color Vector of 3 or 4 values in [0, 1]
setColor: func { _setColorNodes(me.color, arg); return me; },
# Set the fill/background/boundingbox color
#
# @param color Vector of 3 or 4 values in [0, 1]
setColorFill: func { _setColorNodes(me.color_fill, arg); return me; },
setColorFill: func me.set('fill', _getColor(arg)),
#
getBoundingBox: func()
{
@ -381,10 +402,7 @@ var Map = {
var Text = {
new: func(node, id)
{
var m = { parents: [Text, Element.new(node, id)] };
m.color = _createColorNodes(m._node, "color");
m.color_fill = _createColorNodes(m._node, "color-fill");
return m;
return { parents: [Text, Element.new(node, id)] };
},
# Set the text
setText: func(text)
@ -447,7 +465,9 @@ var Text = {
setMaxWidth: func(w)
{
me.setDouble("max-width", w);
}
},
setColor: func me.set('fill', _getColor(arg)),
setColorFill: func me.set('background', _getColor(arg))
};
# Path
@ -514,14 +534,11 @@ var Path = {
#
new: func(node, id)
{
var m = {
return {
parents: [Path, Element.new(node, id)],
_num_cmds: 0,
_num_coords: 0
};
m.color = _createColorNodes(m._node, "color");
m.color_fill = _createColorNodes(m._node, "color-fill");
return m;
},
# Remove all existing path data
reset: func
@ -608,6 +625,17 @@ var Path = {
# Close the path (implicit lineTo to first point of path)
close: func me.addSegment(me.VG_CLOSE_PATH),
setColor: func me.setStroke(_getColor(arg)),
setColorFill: func me.setFill(_getColor(arg)),
setFill: func(fill)
{
me.set('fill', fill);
},
setStroke: func(stroke)
{
me.set('stroke', stroke);
},
setStrokeLineWidth: func(width)
{
me.setDouble('stroke-width', width);
@ -627,23 +655,12 @@ var Path = {
# [on1, off1, on2, ...]
setStrokeDashArray: func(pattern)
{
me._node.removeChildren('stroke-dasharray');
if( typeof(pattern) == 'vector' )
me._node.setValues({'stroke-dasharray': pattern});
me.set('stroke-dasharray', string.join(',', pattern));
else
debug.warn("setStrokeDashArray: vector expected!");
return me;
},
# Set the fill color and enable filling this path
#
# @param color Vector of 3 or 4 values in [0, 1]
setColorFill: func { _setColorNodes(me.color_fill, arg); me.setFill(1); },
# Enable/disable filling this path
setFill: func(fill)
{
me.setBool("fill", fill);
}
};

View file

@ -341,19 +341,17 @@ var parsesvg = func(group, path, options = nil)
}
parsePath(d);
stack[-1].set('fill', style['fill']);
var w = style['stroke-width'];
stack[-1].setStrokeLineWidth( w != nil ? w : 1 );
stack[-1].setColor(parseColor(style['stroke']));
stack[-1].set('stroke', style['stroke'] or "none");
var linecap = style['stroke-linecap'];
if( linecap != nil )
stack[-1].setStrokeLineCap(style['stroke-linecap']);
var fill = style['fill'];
if( fill != nil and fill != "none" )
stack[-1].setColorFill(parseColor(fill));
# http://www.w3.org/TR/SVG/painting.html#StrokeDasharrayProperty
var dash = style['stroke-dasharray'];
if( dash and size(dash) > 3 )

693
Nasal/joystick.nas Normal file
View file

@ -0,0 +1,693 @@
# Joystick configuration library.
var DIALOGROOT = "/sim/gui/dialogs/joystick-config";
var MAX_AXES = 8;
var MAX_BUTTONS = 24;
# Hash of the custom axis/buttons
var custom_bindings = {};
# Class for an individual joystick axis binding
var Axis = {
new: func(name, prop, invertable) {
var m = { parents: [Axis] };
m.name = name;
m.prop = prop;
m.invertable = invertable;
m.inverted = 0;
return m;
},
clone: func() {
var m = { parents: [Axis] };
m.name = me.name;
m.prop = me.prop;
m.invertable = me.invertable;
m.inverted = me.inverted;
return m;
},
match: func(prop) {
return 0;
},
parse: func(prop) { },
readProps: func(props) {},
getName: func() { return me.name; },
getBinding: func(axis) { return props.Node.new(); },
isInvertable: func() { return me.invertable; },
isInverted: func() { return me.inverted; },
setInverted: func(b) {
if (me.invertable) me.inverted = b;
},
};
var CustomAxis = {
new: func() {
var m = { parents: [CustomAxis, Axis.new("Custom", "", 0) ] };
me.custom_binding = nil;
return m;
},
clone: func() {
var m = { parents: [CustomAxis, Axis.new("Custom", "", 0) ] };
m.custom_binding = me.custom_binding;
return m;
},
match: func(prop) {
var p = props.Node.new();
if (prop.getNode("binding") != nil) {
props.copy(prop.getNode("binding"), p);
me.custom_binding = p;
return 1;
} else {
return 0;
}
},
getBinding: func(axis) {
var p = props.Node.new().getNode("axis[" ~ axis ~ "]", 1);
p.getNode("desc", 1).setValue(me.name);
props.copy(me.custom_binding, p.getNode("binding", 1));
return p;
},
};
var UnboundAxis = {
new: func() {
var m = { parents: [UnboundAxis, Axis.new("None", "", 0) ] };
return m;
},
clone: func() {
var m = { parents: [UnboundAxis, Axis.new("None", "", 0) ] };
return m;
},
match: func(prop) {
return 1;
},
getBinding: func(axis) {
return nil;
},
};
var PropertyScaleAxis = {
new: func(name, prop, deadband=0, factor=1, offset=0) {
var m = { parents: [PropertyScaleAxis, Axis.new(name, prop, 1) ] };
m.prop=prop;
m.deadband = deadband;
m.factor = factor;
m.offset = offset;
return m;
},
clone: func() {
var m = { parents: [PropertyScaleAxis, Axis.new(me.name, me.prop, 1) ] };
m.inverted = me.inverted;
m.prop= me.prop;
m.deadband = me.deadband;
m.factor = me.factor;
m.offset = me.offset;
return m;
},
match: func(prop) {
var cmd = prop.getNode("binding", 1).getNode("command", 1).getValue();
var p = prop.getNode("binding", 1).getNode("property", 1).getValue();
return ((cmd == "property-scale") and (p == me.prop));
},
parse: func(p) {
me.deadband = p.getNode("binding", 1).getNode("dead-band", 1).getValue();
if (p.getNode("binding", 1).getNode("factor", 1).getValue() != nil) {
me.inverted = (p.getNode("binding", 1).getNode("factor", 1).getValue() < 0);
}
me.offset = p.getNode("binding", 1).getNode("offset", 1).getValue();
},
getBinding: func(axis) {
var p = props.Node.new();
p = p.getNode("axis[" ~ axis ~ "]", 1);
p.getNode("desc", 1).setValue(me.name);
p.getNode("binding", 1).getNode("command", 1).setValue("property-scale");
p.getNode("binding", 1).getNode("property", 1).setValue(me.prop);
p.getNode("binding", 1).getNode("dead-band", 1).setValue(me.deadband);
if (me.inverted) {
p.getNode("binding", 1).getNode("factor", 1).setValue(0 - me.factor);
} else {
p.getNode("binding", 1).getNode("factor", 1).setValue(me.factor);
}
p.getNode("binding", 1).getNode("offset", 1).setValue(me.offset);
return p;
},
};
var NasalScaleAxis = {
new: func(name, script, prop) {
var m = { parents: [NasalScaleAxis, Axis.new(name, prop, 0) ] };
m.script = script;
m.prop = prop;
return m;
},
clone: func() {
var m = { parents: [NasalScaleAxis, Axis.new(me.name, me.prop, 0) ] };
m.script = me.script;
m.prop = me.prop;
return m;
},
match: func(prop) {
var cmd = prop.getNode("binding", 1).getNode("command", 1).getValue();
var p = prop.getNode("binding", 1).getNode("script", 1).getValue();
if ((p != nil) and (cmd == "nasal")) {
p = string.trim(p);
p = string.replace(p, ";", "");
p = p ~ ";";
return (p == me.script);
} else {
return 0;
}
},
getBinding: func(axis) {
var p = props.Node.new().getNode("axis[" ~ axis ~ "]", 1);
p.getNode("desc", 1).setValue(me.name);
p.getNode("binding", 1).getNode("command", 1).setValue("nasal");
p.getNode("binding", 1).getNode("script", 1).setValue(me.script);
return p;
},
};
var NasalLowHighAxis = {
new: func(name, lowscript, highscript, prop) {
var m = { parents: [NasalLowHighAxis, Axis.new(name, prop, 1) ] };
m.lowscript = lowscript;
m.highscript = highscript;
return m;
},
clone: func() {
var m = { parents: [NasalLowHighAxis, Axis.new(me.name, me.prop, 1) ] };
m.inverted = me.inverted;
m.lowscript = me.lowscript;
m.highscript = me.highscript;
return m;
},
match: func(prop) {
var cmd = prop.getNode("low", 1).getNode("binding", 1).getNode("command", 1).getValue();
var p = prop.getNode("low", 1).getNode("binding", 1).getNode("script", 1).getValue();
if ((p == nil) or (cmd != "nasal")) return 0;
p = string.trim(p);
p = string.replace(p, ";", "");
p = p ~ ";";
if (p == me.lowscript) {
return 1;
}
if (p == me.highscript) {
me.inverted = 1;
return 1;
}
return 0;
},
getBinding: func(axis) {
var p = props.Node.new().getNode("axis[" ~ axis ~ "]", 1);
p.getNode("desc", 1).setValue(me.name);
p.getNode("low", 1).getNode("binding", 1).getNode("command", 1).setValue("nasal");
p.getNode("high", 1).getNode("binding", 1).getNode("command", 1).setValue("nasal");
if (me.inverted) {
p.getNode("low", 1).getNode("binding", 1).getNode("script", 1).setValue(me.highscript);
p.getNode("high", 1).getNode("binding", 1).getNode("script", 1).setValue(me.lowscript);
} else {
p.getNode("low", 1).getNode("binding", 1).getNode("script", 1).setValue(me.lowscript);
p.getNode("high", 1).getNode("binding", 1).getNode("script", 1).setValue(me.highscript);
}
return p;
},
};
var axisBindings = [
PropertyScaleAxis.new("Aileron", "/controls/flight/aileron"),
PropertyScaleAxis.new("Elevator", "/controls/flight/elevator"),
PropertyScaleAxis.new("Rudder", "/controls/flight/rudder"),
NasalScaleAxis.new("Throttle", "controls.throttleAxis();", "/controls/engines/engine[0]/throttle") ,
NasalScaleAxis.new("Mixture", "controls.mixtureAxis();", "/controls/engines/engine[0]/mixture") ,
NasalScaleAxis.new("Propeller", "controls.propellerAxis();", "/controls/engines/engine[0]/propeller-pitch") ,
NasalLowHighAxis.new("View (horizontal)",
"setprop(\"/sim/current-view/goal-heading-offset-deg\", getprop(\"/sim/current-view/goal-heading-offset-deg\") + 30);",
"setprop(\"/sim/current-view/goal-heading-offset-deg\", getprop(\"/sim/current-view/goal-heading-offset-deg\") - 30);",
"/sim/current-view/goal-heading-offset-deg"),
NasalLowHighAxis.new("View (vertical)",
"setprop(\"/sim/current-view/goal-pitch-offset-deg\", getprop(\"/sim/current-view/goal-pitch-offset-deg\") - 20);",
"setprop(\"/sim/current-view/goal-pitch-offset-deg\", getprop(\"/sim/current-view/goal-pitch-offset-deg\") + 20);",
"/sim/current-view/goal-heading-offset-deg"),
# PropertyScaleAxis.new("Aileron Trim", "/controls/flight/aileron-trim"),
# PropertyScaleAxis.new("Elevator Trim", "/controls/flight/elevator-trim"),
# PropertyScaleAxis.new("Rudder Trim", "/controls/flight/rudder-trim"),
PropertyScaleAxis.new("Brake Left", "/controls/gear/brake-left", 0, 0.5, 1.0),
PropertyScaleAxis.new("Brake Right", "/controls/gear/brake-right", 0, 0.5, 1.0),
NasalLowHighAxis.new("Aileron Trim", "controls.aileronTrim(-1);", "controls.aileronTrim(1);", "/controls/flight/aileron-trim"),
NasalLowHighAxis.new("Elevator Trim", "controls.elevatorTrim(-1);", "controls.elevatorTrim(1);", "/controls/flight/elevator-trim"),
NasalLowHighAxis.new("Rudder Trim", "controls.rudderTrim(-1);", "controls.rudderTrim(1);", "/controls/flight/rudder-trim"),
CustomAxis.new(),
UnboundAxis.new(),
];
# Button bindings
var ButtonBinding = {
new: func(name, binding, repeatable) {
var m = { parents: [ButtonBinding] };
m.name = name;
m.binding = binding;
m.repeatable = repeatable;
return m;
},
clone: func() {
var m = { parents: [ButtonBinding] };
m.name = me.name;
m.binding= me.binding;
m.repeatable = me.repeatable;
return m;
},
match: func(prop) {
return 0;
},
getName: func() { return me.name; },
getBinding: func(button) { return nil; },
isRepeatable: func() { return me.repeatable; }
};
var CustomButton = {
new: func() {
var m = { parents: [CustomButton, ButtonBinding.new("Custom", "", 0) ] };
m.custom_binding = nil;
return m;
},
clone: func() {
var m = { parents: [CustomButton, ButtonBinding.new("Custom", "", 0) ] };
m.custom_binding = me.custom_binding;
return m;
},
match: func(prop) {
if (prop.getNode("binding") != nil) {
var p = props.Node.new();
props.copy(prop.getNode("binding"), p);
me.custom_binding = p;
return 1;
} else {
return 0;
}
},
getBinding: func(button) {
var p = props.Node.new().getNode("button[" ~ button ~ "]", 1);
p.getNode("desc", 1).setValue(me.name);
props.copy(me.custom_binding, p.getNode("binding", 1));
return p;
},
};
var UnboundButton = {
new: func() {
var m = { parents: [UnboundButton, ButtonBinding.new("None", "", 0) ] };
return m;
},
clone: func() {
var m = { parents: [UnboundButton, ButtonBinding.new("None", "", 0) ] };
return m;
},
match: func(prop) {
return (prop.getNode("binding") != nil);
},
getBinding: func(button) {
var p = props.Node.new().getNode("button[" ~ button ~ "]", 1);
p.getNode("desc", 1).setValue(me.name);
return p;
},
};
var PropertyToggleButton = {
new: func(name, prop) {
var m = { parents: [PropertyToggleButton, ButtonBinding.new(name, prop, 0) ] };
return m;
},
clone: func() {
var m = { parents: [PropertyToggleButton, ButtonBinding.new(me.name, me.binding, 0) ] };
return m;
},
match: func(prop) {
var c = prop.getNode("binding", 1).getNode("command", 1).getValue();
var p = prop.getNode("binding", 1).getNode("property", 1).getValue();
return ((c == "property-toggle") and (p == me.prop));
},
getBinding: func(button) {
var p = props.Node.new().getNode("button[" ~ button ~ "]", 1);
p.getNode("desc", 1).setValue(me.name);
p.getNode("binding", 1).getNode("command", 1).setValue("property-toggle");
p.getNode("binding", 1).getNode("property", 1).setValue(me.binding);
return p;
},
};
var PropertyAdjustButton = {
new: func(name, prop, step) {
var m = { parents: [PropertyAdjustButton, ButtonBinding.new(name, prop, 0) ] };
m.step = step;
return m;
},
clone: func() {
var m = { parents: [PropertyAdjustButton, ButtonBinding.new(me.name, me.binding, 0) ] };
m.step = me.step;
return m;
},
match: func(prop) {
var c = prop.getNode("binding", 1).getNode("command", 1).getValue();
var p = prop.getNode("binding", 1).getNode("property", 1).getValue();
var s = prop.getNode("binding", 1).getNode("step", 1).getValue();
return ((c == "property-adjust") and (p == me.binding) and (s == me.step));
},
getBinding: func(button) {
var p = props.Node.new().getNode("button[" ~ button ~ "]", 1);
p.getNode("desc", 1).setValue(me.name);
p.getNode("binding", 1).getNode("command", 1).setValue("property-adjust");
p.getNode("binding", 1).getNode("property", 1).setValue(me.binding);
p.getNode("binding", 1).getNode("step", 1).setValue(me.step);
return p;
},
};
var NasalButton = {
new: func(name, script, repeatable) {
var m = { parents: [NasalButton, ButtonBinding.new(name, script, repeatable) ] };
return m;
},
clone: func() {
var m = { parents: [NasalButton, ButtonBinding.new(me.name, me.binding, me.repeatable) ] };
return m;
},
match: func(prop) {
var c = prop.getNode("binding", 1).getNode("command", 1).getValue();
var p = prop.getNode("binding", 1).getNode("script", 1).getValue();
if (p == nil) { return 0; }
p = string.trim(p);
p = string.replace(p, ";", "");
p = p ~ ";";
return ((c == "nasal") and (p == me.binding));
},
getBinding: func(button) {
var p = props.Node.new().getNode("button[" ~ button ~ "]", 1);
p.getNode("desc", 1).setValue(me.name);
p.getNode("binding", 1).getNode("command", 1).setValue("nasal");
p.getNode("binding", 1).getNode("script", 1).setValue(me.binding);
p.getNode("repeatable", 1).setValue(me.repeatable);
return p;
},
};
var NasalHoldButton = {
new: func(name, script, scriptUp) {
var m = { parents: [NasalHoldButton, ButtonBinding.new(name, script, 0) ] };
m.scriptUp = scriptUp;
return m;
},
clone: func() {
var m = { parents: [NasalHoldButton, ButtonBinding.new(me.name, me.binding, 0) ] };
m.scriptUp = me.scriptUp;
return m;
},
match: func(prop) {
var c = prop.getNode("mod-up", 1).getNode("binding", 1).getNode("command", 1).getValue();
var p1 = prop.getNode("binding", 1).getNode("script", 1).getValue();
var p2 = prop.getNode("mod-up", 1).getNode("binding", 1).getNode("script", 1).getValue();
if (p2 == nil) { return 0; }
p1 = string.trim(p1);
p1 = string.replace(p1, ";", "");
p1 = p1 ~ ";";
return ((c == "nasal") and (p1 == me.binding));
},
getBinding: func(button) {
var p = props.Node.new().getNode("button[" ~ button ~ "]", 1);
p.getNode("desc", 1).setValue(me.name);
p.getNode("repeatable", 1).setValue("false");
p.getNode("binding", 1).getNode("command", 1).setValue("nasal");
p.getNode("binding", 1).getNode("script", 1).setValue(me.binding);
p.getNode("mod-up", 1).getNode("binding", 1).getNode("command", 1).setValue("nasal");
p.getNode("mod-up", 1).getNode("binding", 1).getNode("script", 1).setValue(me.scriptUp);
return p;
},
};
var buttonBindings = [
NasalButton.new("Elevator Trim Up", "controls.elevatorTrim(-1);", 1),
NasalButton.new("Elevator Trim Down", "controls.elevatorTrim(1);", 1),
NasalButton.new("Rudder Trim Left", "controls.rudderTrim(-1);", 1),
NasalButton.new("Rudder Trim Right", "controls.rudderTrim(1);", 1),
NasalButton.new("Aileron Trim Left", "controls.aileronTrim(-1);", 1),
NasalButton.new("Aileron Trim Right", "controls.aileronTrim(1);", 1),
NasalHoldButton.new("FGCom PTT", "controls.ptt(1);", "controls.ptt(-1);"),
NasalHoldButton.new("Trigger", "controls.trigger(1);", "controls.trigger(0);"),
NasalHoldButton.new("Flaps Up", "controls.flapsDown(-1);", "controls.flapsDown(0);"),
NasalHoldButton.new("Flaps Down", "controls.flapsDown(1);", "controls.flapsDown(0);"),
NasalHoldButton.new("Gear Up", "controls.gearDown(-1);", "controls.gearDown(0);"),
NasalHoldButton.new("Gear Down", "controls.gearDown(1);", "controls.gearDown(0);"),
NasalHoldButton.new("Spoilers Retract", "controls.stepSpoilers(-1);", "controls.stepSpoilers(0);"),
NasalHoldButton.new("Spoilers Deploy", "controls.stepSpoilers(1);", "controls.stepSpoilers(0);"),
NasalHoldButton.new("Brakes", "controls.applyBrakes(1);", "controls.applyBrakes(0);"),
NasalButton.new("View Decrease", "view.decrease(0.75);", 1),
NasalButton.new("View Increase", "view.increase(0.75);", 1),
NasalButton.new("View Cycle Forwards", "view.stepView(1);", 0),
NasalButton.new("View Cycle Backwards", "view.stepView(-1);", 0),
PropertyAdjustButton.new("View Left", "/sim/current-view/goal-heading-offset-deg", "30.0"),
PropertyAdjustButton.new("View Right", "/sim/current-view/goal-heading-offset-deg", "-30.0"),
PropertyAdjustButton.new("View Up", "/sim/current-view/goal-pitch-offset-deg", "20.0"),
PropertyAdjustButton.new("View Down", "/sim/current-view/goal-pitch-offset-deg", "-20.0"),
CustomButton.new(),
];
# Parse config from the /input tree and write it to the
# dialog_root.
var readConfig = func(dialog_root="/sim/gui/dialogs/joystick-config") {
var js_name = getprop(dialog_root ~ "/selected-joystick");
var joysticks = props.globals.getNode("/input/joysticks").getChildren("js");
if (size(joysticks) == 0) { return 0; }
if (js_name == nil) {
js_name = joysticks[0].getNode("id").getValue();
}
var js = nil;
forindex (var i; joysticks) {
if ((joysticks[i].getNode("id") != nil) and
(joysticks[i].getNode("id").getValue() == js_name))
{
js = joysticks[i];
setprop(dialog_root ~ "/selected-joystick", js_name);
setprop(dialog_root ~ "/selected-joystick-index", i);
setprop(dialog_root ~ "/selected-joystick-config", joysticks[i].getNode("source").getValue());
}
}
if (js == nil) {
# We didn't find the joystick we expected - default to the first
setprop(dialog_root ~ "/selected-joystick", joysticks[0].getNode("id").getValue());
setprop(dialog_root ~ "/selected-joystick-index", 0);
setprop(dialog_root ~ "/selected-joystick-config", joysticks[0].getNode("source").getValue());
}
# Set up the axes assignments
var axes = js.getChildren("axis");
for (var axis = 0; axis < MAX_AXES; axis = axis +1) {
var p = props.globals.getNode(dialog_root ~ "/axis[" ~ axis ~ "]", 1);
p.remove();
p = props.globals.getNode(dialog_root ~ "/axis[" ~ axis ~ "]", 1);
# Note that we can't simply use an index into the axes array
# as that doesn't work for a sparsley populated set of axes.
# E.g. one with n="3"
var a = js.getNode("axis[" ~ axis ~ "]");
if (a != nil) {
# Read properties from bindings
props.copy(a, p.getNode("original_binding", 1));
var binding = nil;
foreach (var b; joystick.axisBindings) {
if ((binding == nil) and (a != nil) and b.match(a)) {
binding = b.clone();
binding.parse(a);
p.getNode("binding", 1).setValue(binding.getName());
p.getNode("invertable", 1).setValue(binding.isInvertable());
p.getNode("inverted", 1).setValue(binding.isInverted());
}
}
if (binding == nil) {
# No binding for this axis
p.getNode("binding", 1).setValue("None");
p.getNode("invertable", 1).setValue(0);
p.getNode("inverted", 1).setValue(0);
p.removeChild("original_binding");
}
} else {
p.getNode("binding", 1).setValue("None");
p.getNode("invertable", 1).setValue(0);
p.getNode("inverted", 1).setValue(0);
p.removeChild("original_binding");
}
}
# Set up button assignment.
var buttons = js.getChildren("button");
for (var button = 0; button < MAX_BUTTONS; button = button + 1) {
var btn = props.globals.getNode(dialog_root ~ "/button[" ~ button ~ "]", 1);
btn.remove();
btn = props.globals.getNode(dialog_root ~ "/button[" ~ button ~ "]", 1);
# Note that we can't simply use an index into the buttons array
# as that doesn't work for a sparsley populated set of buttons.
# E.g. one with n="3"
var a = js.getNode("button[" ~ button ~ "]");
if (a != nil) {
# Read properties from bindings
props.copy(a, p.getNode("original_binding", 1));
var binding = nil;
foreach (var b; joystick.buttonBindings) {
if ((binding == nil) and (a != nil) and b.match(a)) {
binding = b.clone();
btn.getNode("binding", 1).setValue(binding.getName());
props.copy(b.getBinding(button), btn.getNode("original_binding", 1));
}
}
if (b == nil) {
btn.getNode("binding", 1).setValue("None");
btn.removeChild("original_binding");
}
} else {
btn.getNode("binding", 1).setValue("None");
btn.removeChild("original_binding");
}
}
}
var writeConfig = func(dialog_root="/sim/gui/dialogs/joystick-config") {
# Write out the joystick file.
var config = props.Node.new();
var id = getprop(dialog_root ~ "/selected-joystick");
config.getNode("name", 1).setValue(id);
var axes = props.globals.getNode(dialog_root).getChildren("axis");
forindex (var axis; axes) {
var name = getprop(dialog_root ~ "/axis[" ~ axis ~ "]/binding");
if (name != "None") {
foreach (var binding; axisBindings) {
if (binding.getName() == name) {
var b = binding.clone();
b.setInverted(getprop(dialog_root ~ "/axis[" ~ axis ~ "]/inverted"));
# Generate the axis and binding
var axisnode = config.getNode("axis[" ~ axis ~ "]", 1);
if (name == "Custom") {
props.copy(props.globals.getNode(dialog_root ~ "/axis[" ~ axis ~ "]/original_binding", 1), axisnode);
} else {
props.copy(b.getBinding(axis), axisnode);
}
}
}
}
}
var buttons = props.globals.getNode(dialog_root).getChildren("button");
forindex (var btn; buttons) {
var name = getprop(dialog_root ~ "/button[" ~ btn ~ "]/binding");
if (name != "None") {
foreach (var binding; buttonBindings) {
if (binding.getName() == name) {
var b = binding.clone();
# Generate the axis and binding
var buttonprop = config.getNode("button[" ~ btn ~ "]", 1);
if (name == "Custom") {
props.copy(props.globals.getNode(dialog_root ~ "/button[" ~ btn ~ "]/original_binding", 1), buttonprop);
} else {
props.copy(b.getBinding(btn), buttonprop);
}
}
}
}
}
var filename = id;
filename = string.replace(filename, " ", "-");
filename = string.replace(filename, ".", "");
filename = string.replace(filename, "/", "");
# Write out the file
io.write_properties(getprop("/sim/fg-home") ~ "/Input/Joysticks/" ~ filename ~ ".xml", config);
}

View file

@ -95,7 +95,7 @@ var resolve_foam_drop = func (pos, radius, volume, source=1) {
# x < last event - fast forward all the way to current time (use 0).
# NOTE: Can be VERY time consuming.
# -1 - skip to current time.
var load_event_log = func (filename, skip_ahead_until=-1) {
var load_event_log = func (filename, skip_ahead_until) {
CAFire.load_event_log(filename, skip_ahead_until);
}
@ -129,6 +129,9 @@ var restore_on_startup_pp = "environment/wildfire/restore-on-startup";
var crash_fire_pp = "environment/wildfire/fire-on-crash";
var impact_fire_pp = "environment/wildfire/fire-on-impact";
var report_score_pp = "environment/wildfire/report-score";
var event_file_pp = "environment/wildfire/events-file";
var time_hack_pp = "environment/wildfire/time-hack-gmt";
# Format: "yyyy:mm:dd:hh:mm:ss"
# Internal properties to control the models
var models_enabled_pp = "environment/wildfire/models/enabled";
var fire_LOD_pp = "environment/wildfire/models/fire-lod";
@ -788,7 +791,7 @@ CAFire.save_event_log = func (filename) {
# to current time.
# x < last event - fast forward all the way to current time (use 0).
# -1 - skip to current time.
CAFire.load_event_log = func (filename, skip_ahead_until=-1) {
CAFire.load_event_log = func (filename, skip_ahead_until) {
me.load_count += 1;
var logbase = "/tmp/wildfire-load-log[" ~ me.load_count ~ "]";
if (!fgcommand("loadxml",
@ -814,7 +817,7 @@ CAFire.load_event_log = func (filename, skip_ahead_until=-1) {
event.getNode("type").getValue()];
# Fast forward state.
while (me.generation * me.GENERATION_DURATION <= e[0]) {
while (me.generation * me.GENERATION_DURATION < e[0]) {
# print("between event ff " ~ me.generation);
me.update();
}
@ -958,6 +961,8 @@ _setlistener("/sim/signals/nasal-dir-initialized", func {
props.globals.initNode(restore_on_startup_pp, 0, "BOOL");
props.globals.initNode(models_enabled_pp, 1, "BOOL");
props.globals.initNode(report_score_pp, 1, "BOOL");
props.globals.initNode(event_file_pp, "", "STRING");
props.globals.initNode(time_hack_pp, "", "STRING");
props.globals.initNode(fire_LOD_pp, 10, "INT");
props.globals.initNode(smoke_LOD_pp, 10, "INT");
@ -977,10 +982,35 @@ _setlistener("/sim/signals/nasal-dir-initialized", func {
CAFire.save_event_log(SAVEDIR ~ "fire_log.xml");
});
if (getprop(restore_on_startup_pp)) {
# Determine the skip-ahead-to time, if any.
var time_hack = time_string_to_epoch(getprop(time_hack_pp));
if (time_hack > SimTime.current_time()) {
printlog("alert",
"wildfire.nas: Ignored time hack " ~
(SimTime.current_time() - time_hack) ~
" seconds into the future.");
# Skip ahead to current time instead.
time_hack = -1;
} elsif (time_hack > 0) {
printlog("alert",
"wildfire.nas: Time hack " ~
(SimTime.current_time() - time_hack) ~
" seconds ago.");
} else {
# Skip ahead to current time instead.
time_hack = -1;
}
if (getprop(event_file_pp) != "") {
settimer(func {
# Delay loading the log until the terrain is there. Note: hack.
CAFire.load_event_log(SAVEDIR ~ "fire_log.xml", 1);
CAFire.load_event_log(getprop(event_file_pp), time_hack);
}, 3);
} elsif (getprop(restore_on_startup_pp)) {
settimer(func {
# Delay loading the log until the terrain is there. Note: hack.
# Restore skips ahead to current time.
CAFire.load_event_log(SAVEDIR ~ "fire_log.xml", -1);
}, 3);
}
@ -990,19 +1020,18 @@ _setlistener("/sim/signals/nasal-dir-initialized", func {
wildfire.ignite(geo.aircraft_position());
});
# Detect impact
# Detect impact.
var impact_node = props.globals.getNode("sim/ai/aircraft/impact/bomb", 1);
setlistener("sim/ai/aircraft/impact/bomb", func(n) {
if (getprop(impact_fire_pp) and n.getBoolValue()){
var node = props.globals.getNode(n.getValue(), 1);
var impactpos = geo.Coord.new();
impactpos.set_latlon(
node.getNode("impact/latitude-deg").getValue(),
node.getNode("impact/longitude-deg").getValue()
);
wildfire.ignite(impactpos);
}
if (getprop(impact_fire_pp) and n.getBoolValue()){
var node = props.globals.getNode(n.getValue(), 1);
var impactpos = geo.Coord.new();
impactpos.set_latlon
(node.getNode("impact/latitude-deg").getValue(),
node.getNode("impact/longitude-deg").getValue());
wildfire.ignite(impactpos);
}
});
@ -1010,6 +1039,40 @@ _setlistener("/sim/signals/nasal-dir-initialized", func {
});
###############################################################################
###############################################################################
# Utility functions
# Convert a time string in the format yyyy[:mm[:dd[:hh[:mm[:ss]]]]]
# to seconds since 1970:01:01:00:00:00.
#
# Note: This is an over simplified approximation.
var time_string_to_epoch = func (time) {
var res = [];
if (string.scanf(time, "%d:%d:%d:%d:%d:%d", var res1 = []) != 0) {
res = res1;
} elsif (string.scanf(time, "%d:%d:%d:%d:%d", var res2 = []) != 0) {
res = res2 ~ [0];
} elsif (string.scanf(time, "%d:%d:%d:%d", var res3 = []) != 0) {
res = res3 ~ [0, 0];
} elsif (string.scanf(time, "%d:%d:%d", var res4 = []) != 0) {
res = res4 ~ [0, 0, 0];
} elsif (string.scanf(time, "%d:%d", var res5 = []) != 0) {
res = res5 ~ [0, 0, 0, 0];
} elsif (string.scanf(time, "%d", var res6 = []) != 0) {
res = res6 ~ [0, 0, 0, 0, 0];
} else {
return -1;
}
return
(res[0] - 1970) * 3.15569e7 +
(res[1] - 1) * 2.63e+6 +
(res[2] - 1) * 86400 +
res[3] * 3600 +
res[4] * 60 +
res[5];
}
###############################################################################
## WildFire configuration dialog.
## Partly based on Till Bush's multiplayer dialog
@ -1126,7 +1189,7 @@ var dialog = {
#################################################################
select_and_load : func {
var selector = gui.FileSelector.new
(func (n) { CAFire.load_event_log(n.getValue()); },
(func (n) { load_event_log(n.getValue(), -1); },
"Load Wildfire log", # dialog title
"Load", # button text
["*.xml"], # pattern for files

View file

@ -3,8 +3,6 @@
// based on earlier work by Frederic Bouvier, Tim Moore, and Yves Sablonier.
// © Emilian Huminiuc 2011
// Ambient term comes in gl_Color.rgb.
#version 120
varying vec4 RawPos;
@ -69,19 +67,12 @@ void main()
if (gl_FrontMaterial.shininess > 0.0)
specular = gl_FrontMaterial.specular * gl_LightSource[0].specular * pf;
<<<<<<< HEAD
vec4 diffuseColor = gl_FrontMaterial.emission +
vec4(1.0) * (gl_LightModel.ambient + gl_LightSource[0].ambient) +
Diffuse * gl_FrontMaterial.diffuse;
=======
// vec4 diffuseColor = gl_FrontMaterial.emission +
// vec4(1.0) * (gl_LightModel.ambient + gl_LightSource[0].ambient) +
// Diffuse * gl_FrontMaterial.diffuse;
vec4 ambientColor = gl_LightModel.ambient + gl_LightSource[0].ambient;
//vec4 diffuseColor = gl_Color + Diffuse * gl_FrontMaterial.diffuse + ambientColor;
vec4 diffuseColor = vec4(Diffuse) + ambientColor; //ATI workaround
>>>>>>> 458720af8eb7ffa022b5b8dcc51d3cde60e5dded
diffuseColor += specular * gl_FrontMaterial.specular;
// This shouldn't be necessary, but our lighting becomes very

View file

@ -112,6 +112,7 @@
<aircraft-keys>Aircraft Help</aircraft-keys>
<common-keys>Common Aircraft Keys</common-keys>
<basic-keys>Basic Simulator Keys</basic-keys>
<joystick-config>Joystick Configuration</joystick-config>
<joystick-info>Joystick Information</joystick-info>
<tutorial-start>Tutorials</tutorial-start>
<menu-about>About</menu-about>

View file

@ -0,0 +1,437 @@
<?xml version="1.0"?>
<PropertyList>
<nasal>
<open><![CDATA[
var assignButton = func(cmd) {
var i = getprop("/sim/gui/dialogs/joystick-config/current-button");
setprop("/sim/gui/dialogs/joystick-config/button[" ~ i ~ "]/binding", cmd);
joystick.writeConfig();
fgcommand("reinit", props.Node.new({"subsystem": "input"}));
fgcommand("dialog-close", props.Node.new({"dialog-name": "button-config"}));
fgcommand("dialog-close", props.Node.new({"dialog-name": "joystick-config"}));
fgcommand("dialog-show", props.Node.new({"dialog-name": "joystick-config"}));
}
]]></open>
<close><![CDATA[
]]></close>
</nasal>
<name>button-config</name>
<layout>vbox</layout>
<resizable>true</resizable>
<modal>true</modal>
<default-padding>3</default-padding>
<group>
<layout>hbox</layout>
<default-padding>1</default-padding>
<empty><stretch>true</stretch></empty>
<text>
<label>Button Configuration</label>
</text>
<empty><stretch>true</stretch></empty>
<button>
<legend></legend>
<key>Esc</key>
<pref-width>16</pref-width>
<pref-height>16</pref-height>
<border>2</border>
<binding>
<command>dialog-close</command>
</binding>
</button>
</group>
<hrule/>
<text>
<halign>left</halign>
<label>Select the command you wish to assign to this button</label>
</text>
<hrule/>
<group>
<layout>table</layout>
<text>
<row>0</row>
<col>0</col>
<label>Flight surface trim</label>
</text>
<button>
<row>1</row>
<col>0</col>
<halign>fill</halign>
<legend>Elevator Trim Up</legend>
<binding>
<command>nasal</command>
<script>
assignButton("Elevator Trim Up");
</script>
</binding>
</button>
<button>
<row>2</row>
<col>0</col>
<halign>fill</halign>
<legend>Elevator Trim Down</legend>
<binding>
<command>nasal</command>
<script>
assignButton("Elevator Trim Down");
</script>
</binding>
</button>
<button>
<row>3</row>
<col>0</col>
<halign>fill</halign>
<legend>Rudder Trim Left</legend>
<binding>
<command>nasal</command>
<script>
assignButton("Rudder Trim Left");
</script>
</binding>
</button>
<button>
<row>4</row>
<col>0</col>
<halign>fill</halign>
<legend>Rudder Trim Right</legend>
<binding>
<command>nasal</command>
<script>
assignButton("Rudder Trim Right");
</script>
</binding>
</button>
<button>
<row>5</row>
<col>0</col>
<halign>fill</halign>
<legend>Aileron Trim Left</legend>
<binding>
<command>nasal</command>
<script>
assignButton("Aileron Trim Left");
</script>
</binding>
</button>
<button>
<row>6</row>
<col>0</col>
<halign>fill</halign>
<legend>Aileron Trim Right</legend>
<binding>
<command>nasal</command>
<script>
assignButton("Aileron Trim Right");
</script>
</binding>
</button>
<text>
<row>0</row>
<col>1</col>
<label>Control Surfaces</label>
</text>
<button>
<row>1</row>
<col>1</col>
<halign>fill</halign>
<legend>Flaps Up</legend>
<binding>
<command>nasal</command>
<script>
assignButton("Flaps Up");
</script>
</binding>
</button>
<button>
<row>2</row>
<col>1</col>
<halign>fill</halign>
<legend>Flaps Down</legend>
<binding>
<command>nasal</command>
<script>
assignButton("Flaps Down");
</script>
</binding>
</button>
<button>
<row>3</row>
<col>1</col>
<halign>fill</halign>
<legend>Gear Up</legend>
<binding>
<command>nasal</command>
<script>
assignButton("Gear Up");
</script>
</binding>
</button>
<button>
<row>4</row>
<col>1</col>
<halign>fill</halign>
<legend>Gear Down</legend>
<binding>
<command>nasal</command>
<script>
assignButton("Gear Down");
</script>
</binding>
</button>
<button>
<row>5</row>
<col>1</col>
<halign>fill</halign>
<legend>Spoilers Retract</legend>
<binding>
<command>nasal</command>
<script>
assignButton("Spoilers Retract");
</script>
</binding>
</button>
<button>
<row>6</row>
<col>1</col>
<halign>fill</halign>
<legend>Spoilers Deploy</legend>
<binding>
<command>nasal</command>
<script>
assignButton("Spoilers Deploy");
</script>
</binding>
</button>
<text>
<row>0</row>
<col>2</col>
<label>Other Aircraft Controls</label>
</text>
<button>
<row>1</row>
<col>2</col>
<halign>fill</halign>
<legend>Brakes</legend>
<binding>
<command>nasal</command>
<script>
assignButton("Brakes");
</script>
</binding>
</button>
<button>
<row>2</row>
<col>2</col>
<halign>fill</halign>
<legend>FGCom PTT</legend>
<binding>
<command>nasal</command>
<script>
assignButton("FGCom PTT");
</script>
</binding>
</button>
<button>
<row>3</row>
<col>2</col>
<halign>fill</halign>
<legend>Trigger</legend>
<binding>
<command>nasal</command>
<script>
assignButton("Trigger");
</script>
</binding>
</button>
<button>
<row>4</row>
<col>2</col>
<halign>fill</halign>
<legend>Custom</legend>
<binding>
<command>nasal</command>
<script>
assignButton("Custom");
</script>
</binding>
</button>
<button>
<row>5</row>
<col>2</col>
<halign>fill</halign>
<legend>None</legend>
<binding>
<command>nasal</command>
<script>
assignButton("None");
</script>
</binding>
</button>
<text>
<row>0</row>
<col>3</col>
<label>View</label>
</text>
<button>
<row>1</row>
<col>3</col>
<halign>fill</halign>
<legend>View Decrease</legend>
<binding>
<command>nasal</command>
<script>
assignButton("View Decrease");
</script>
</binding>
</button>
<button>
<row>2</row>
<col>3</col>
<halign>fill</halign>
<legend>View Increase</legend>
<binding>
<command>nasal</command>
<script>
assignButton("View Increase");
</script>
</binding>
</button>
<button>
<row>3</row>
<col>3</col>
<halign>fill</halign>
<legend>View Cycle Forwards</legend>
<binding>
<command>nasal</command>
<script>
assignButton("View Cycle Forwards");
</script>
</binding>
</button>
<button>
<row>4</row>
<col>3</col>
<halign>fill</halign>
<legend>View Cycle Backwards</legend>
<binding>
<command>nasal</command>
<script>
assignButton("View Cycle Backwards");
</script>
</binding>
</button>
<button>
<row>5</row>
<col>3</col>
<halign>fill</halign>
<legend>View Left</legend>
<binding>
<command>nasal</command>
<script>
assignButton("View Left");
</script>
</binding>
</button>
<button>
<row>6</row>
<col>3</col>
<halign>fill</halign>
<legend>View Right</legend>
<binding>
<command>nasal</command>
<script>
assignButton("View Right");
</script>
</binding>
</button>
<button>
<row>7</row>
<col>3</col>
<halign>fill</halign>
<legend>View Up</legend>
<binding>
<command>nasal</command>
<script>
assignButton("View Up");
</script>
</binding>
</button>
<button>
<row>8</row>
<col>3</col>
<halign>fill</halign>
<legend>View Down</legend>
<binding>
<command>nasal</command>
<script>
assignButton("View Down");
</script>
</binding>
</button>
</group>
<group>
<empty>
<stretch>true</stretch>
</empty>
<layout>hbox</layout>
<button>
<legend>Close</legend>
<default>true</default>
<key>Esc</key>
<binding>
<command>dialog-close</command>
</binding>
</button>
<empty>
<stretch>true</stretch>
</empty>
</group>
</PropertyList>

View file

@ -0,0 +1,491 @@
<?xml version="1.0"?>
<PropertyList>
<nasal>
<open><![CDATA[
var dlgRoot = cmdarg();
var DIALOG_ROOT = "/sim/gui/dialogs/joystick-config";
# Read the current bindings
joystick.readConfig();
# Fill in the joystick names combo box.
var joysticks = props.globals.getNode("/input/joysticks").getChildren("js");
if (size(joysticks) == 0) {
# No joysticks found - no point filling in rest of dialog
setprop(DIALOG_ROOT ~ "joystick-count", 0);
} else {
var jsselect = gui.findElementByName(dlgRoot, "jsselect" );
forindex (var joystick_index; joysticks) {
var js = joysticks[joystick_index];
var js_id = "unknown";
if ((js.getNode("id") != nil) and (js.getNode("id").getValue() != nil))
{
js_id = js.getNode("id").getValue();
}
jsselect.getNode("value[" ~ joystick_index ~ "]", 1).setValue(js_id);
}
var joystick_index = getprop(DIALOG_ROOT ~ "/selected-joystick-index");
var table = gui.findElementByName(dlgRoot, "axistable");
table.removeChildren("checkbox");
table.removeChildren("combo");
# Fill in the valid axis bindings
for (var i = 0; i < joystick.MAX_AXES; i = i + 1) {
# Label
var t = table.getChild("text", 2*i + 4, 1);
t.getNode("row", 1).setValue(i + 1);
t.getNode("col", 1).setValue(0);
t.getNode("label", 1).setValue("Axis " ~ i);
# Raw data
t = table.getChild("text", 2*i + 5, 1);
t.getNode("property", 1).setValue("/devices/status/joysticks/joystick[" ~ joystick_index ~ "]/axis[" ~ i ~ "]");
t.getNode("row", 1).setValue(i +1 );
t.getNode("col", 1).setValue(1);
t.getNode("label", 1).setValue("01234");
t.getNode("format", 1).setValue("%2.2f");
t.getNode("halign", 1).setValue("right");
t.getNode("live", 1).setValue(1);
# Binding
t = table.getChild("combo", i, 1);
t.getNode("name", 1).setValue("axis" ~ i ~ "binding");
t.getNode("row", 1).setValue(i + 1);
t.getNode("col", 1).setValue("2");
t.getNode("halign", 1).setValue("fill");
t.getNode("pref-width", 1).setValue("150");
t.getNode("live", 1).setValue(1);
t.getNode("property", 1).setValue(DIALOG_ROOT ~ "/axis[" ~ i ~ "]/binding");
forindex (var idx; joystick.axisBindings) {
t.getChild("value", idx, 1).setValue(joystick.axisBindings[idx].getName());
}
var b = t.getChild("binding", 0, 1);
b.getNode("command", 1).setValue("dialog-apply");
b.getNode("object-name", 1).setValue("axis" ~ i ~ "binding");
b = t.getChild("binding", 1, 1);
b.getNode("command", 1).setValue("nasal");
b.getNode("script", 1).setValue("updateConfig();");
# Inverted
t = table.getChild("checkbox", i, 1);
t.getNode("name", 1).setValue("axis" ~ i ~ "inverted");
t.getNode("property", 1).setValue(DIALOG_ROOT ~ "/axis[" ~ i ~ "]/inverted");
t.getNode("row", 1).setValue(i +1 );
t.getNode("col", 1).setValue(3);
t.getNode("visible", 1).getNode("property", 1).setValue(DIALOG_ROOT ~ "/axis[" ~ i ~ "]/invertable");
t.getNode("live", 1).setValue(1);
var b = t.getChild("binding", 0, 1);
b.getNode("command", 1).setValue("dialog-apply");
b.getNode("object-name", 1).setValue("axis" ~ i ~ "inverted");
b = t.getChild("binding", 1, 1);
b.getNode("command", 1).setValue("nasal");
b.getNode("script", 1).setValue("updateConfig();");
}
# Set up the buttons.
table = gui.findElementByName(dlgRoot, "buttontable");
table.removeChildren("checkbox");
table.removeChildren("button");
var row = 1;
var col = 0;
for (var button = 0; button < joystick.MAX_BUTTONS; button = button + 1) {
t = table.getChild("checkbox", button, 1);
t.getNode("property", 1).setValue("/devices/status/joysticks/joystick[" ~ joystick_index ~ "]/button[" ~ button ~ "]");
t.getNode("row", 1).setValue(row );
t.getNode("col", 1).setValue(col);
t.getNode("live", 1).setValue(1);
t = table.getChild("button", button, 1);
t.getNode("name", 1).setValue("button" ~ button);
t.getNode("pref-width", 1).setValue(140);
t.getNode("halign", 1).setValue("fill");
t.getNode("live", 1).setValue("fill");
t.getNode("row", 1).setValue(row );
t.getNode("col", 1).setValue(col +1);
t.getNode("legend", 1).setValue(getprop(DIALOG_ROOT ~ "/button[" ~ button ~ "]/binding"));
var b = t.getChild("binding", 0, 1);
b.getNode("command", 1).setValue("property-assign");
b.getNode("property", 1).setValue("/sim/gui/dialogs/joystick-config/current-button");
b.getNode("value", 1).setValue(button);
b = t.getChild("binding", 1, 1);
b.getNode("command", 1).setValue("dialog-show");
b.getNode("dialog-name", 1).setValue("button-config");
col = col + 2;
if (col > 5) {
row = row +1;
col = 0;
}
}
}
var updateConfig = func() {
joystick.writeConfig();
fgcommand("reinit", props.Node.new({"subsystem": "input"}));
fgcommand("dialog-close", props.Node.new({"dialog-name": "joystick-config"}));
fgcommand("dialog-show", props.Node.new({"dialog-name": "joystick-config"}));
}
]]></open>
<close><![CDATA[
]]></close>
</nasal>
<name>joystick-config</name>
<layout>vbox</layout>
<resizable>true</resizable>
<default-padding>3</default-padding>
<group>
<layout>hbox</layout>
<default-padding>1</default-padding>
<empty><stretch>true</stretch></empty>
<text>
<label>Joystick Configuration</label>
</text>
<empty><stretch>true</stretch></empty>
<button>
<legend></legend>
<key>Esc</key>
<pref-width>16</pref-width>
<pref-height>16</pref-height>
<border>2</border>
<binding>
<command>dialog-close</command>
</binding>
</button>
</group>
<hrule/>
<text>
<halign>left</halign>
<label>To configure your joystick(s):</label>
</text>
<text>
<halign>left</halign>
<label> 1) Select the joystick your wish to configure below.</label>
</text>
<text>
<halign>left</halign>
<label> 2) Identify the control you wish to configure by moving the joystick or pressing the button. The result is shown in the Input column.</label>
</text>
<text>
<halign>left</halign>
<label> 3) Using the drop down or dialog button, select what you want the control to do. "Custom" indicates a manually configured command.</label>
</text>
<text>
<halign>left</halign>
<label> Your selection will take effect immediately.</label>
</text>
<text>
<halign>left</halign>
<label> 4) Test your control. Some joystick controls can be "inverted" if you wish the control to take effect in the opposite direction.</label>
</text>
<text>
<halign>left</halign>
<label>Your modified joystick configuration is saved automatically to a new configuration file.</label>
</text>
<hrule/>
<!-- Joystick selector -->
<group>
<layout>table</layout>
<halign>left</halign>
<text>
<row>0</row>
<col>0</col>
<halign>right</halign>
<label>Joystick:</label>
</text>
<combo>
<name>jsselect</name>
<row>0</row>
<col>1</col>
<halign>left</halign>
<property>/sim/gui/dialogs/joystick-config/selected-joystick</property>
<pref-width>350</pref-width>
<binding>
<command>dialog-apply</command>
<object-name>jsselect</object-name>
</binding>
<binding>
<command>nasal</command>
<script>
fgcommand("dialog-close", props.Node.new({"dialog-name": "joystick-config"}));
fgcommand("dialog-show", props.Node.new({"dialog-name": "joystick-config"}));
</script>
</binding>
</combo>
<button>
<row>0</row>
<col>2</col>
<halign>center</halign>
<legend>Refresh Joysticks</legend>
<binding>
<command>nasal</command>
<script>
fgcommand("reinit", props.Node.new({"subsystem": "input"}));
fgcommand("dialog-close", props.Node.new({"dialog-name": "joystick-config"}));
fgcommand("dialog-show", props.Node.new({"dialog-name": "joystick-config"}));
</script>
</binding>
</button>
<text>
<row>1</row>
<col>0</col>
<halign>right</halign>
<label>Configuration File:</label>
</text>
<text>
<row>1</row>
<col>1</col>
<colspan>2</colspan>
<halign>left</halign>
<label>Joystick Confgig</label>
<property>/sim/gui/dialogs/joystick-config/selected-joystick-config</property>
</text>
</group>
<hrule/>
<group>
<layout>hbox</layout>
<valign>top</valign>
<halign>fill</halign>
<!-- Axis list -->
<group>
<layout>table</layout>
<valign>top</valign>
<name>axistable</name>
<!-- Header Row -->
<text>
<row>0</row>
<col>0</col>
<label>Axis</label>
</text>
<text>
<row>0</row>
<col>1</col>
<label>Input</label>
</text>
<text>
<row>0</row>
<col>2</col>
<label>Control</label>
</text>
<text>
<row>0</row>
<col>3</col>
<label>Inverted?</label>
</text>
<!-- Axes get added here -->
</group>
<vrule/>
<!-- Buttons -->
<group>
<layout>table</layout>
<valign>top</valign>
<name>buttontable</name>
<!-- Header row-->
<text>
<row>0</row><col>0</col>
<label>Input</label>
</text>
<text>
<row>0</row><col>1</col>
<label>Control</label>
</text>
<text>
<row>0</row><col>2</col>
<label>Input</label>
</text>
<text>
<row>0</row><col>3</col>
<label>Control</label>
</text>
<text>
<row>0</row><col>4</col>
<label>Input</label>
</text>
<text>
<row>0</row><col>5</col>
<label>Control</label>
</text>
<!-- Buttons get added here -->
</group>
</group>
<hrule/>
<group>
<layout>table</layout>
<default-padding>2</default-padding>
<empty>
<width>150</width>
<col>0</col>
<row>0</row>
</empty>
<text>
<label>Aileron: </label>
<halign>right</halign>
<col>1</col>
<row>0</row>
</text>
<text>
<label>-0.00000</label>
<halign>left</halign>
<format>%.5f</format>
<property>/controls/flight/aileron</property>
<live>1</live>
<col>2</col>
<row>0</row>
</text>
<text>
<label>Elevator: </label>
<halign>right</halign>
<col>1</col>
<row>1</row>
</text>
<text>
<label>-0.00000</label>
<halign>left</halign>
<format>%.5f</format>
<property>/controls/flight/elevator</property>
<live>1</live>
<col>2</col>
<row>1</row>
</text>
<text>
<label>Rudder: </label>
<halign>right</halign>
<col>3</col>
<row>0</row>
</text>
<text>
<label>-0.00000</label>
<halign>left</halign>
<format>%.5f</format>
<property>/controls/flight/rudder</property>
<live>1</live>
<col>4</col>
<row>0</row>
</text>
<text>
<label>Throttle: </label>
<halign>right</halign>
<col>3</col>
<row>1</row>
</text>
<text>
<label>-0.00000</label>
<halign>left</halign>
<format>%.5f</format>
<property>/controls/engines/engine/throttle</property>
<live>1</live>
<col>4</col>
<row>1</row>
</text>
<empty>
<width>150</width>
<col>5</col>
<row>0</row>
</empty>
</group>
<hrule/>
<!-- Button bar -->
<group>
<layout>hbox</layout>
<empty>
<stretch>true</stretch>
</empty>
<button>
<legend>Close</legend>
<binding>
<command>dialog-close</command>
</binding>
</button>
<empty>
<stretch>true</stretch>
</empty>
</group>
</PropertyList>