diff --git a/Aircraft/Generic/Logos/pumpkin.png b/Aircraft/Generic/Logos/pumpkin.png new file mode 100644 index 000000000..98edaa7b7 Binary files /dev/null and b/Aircraft/Generic/Logos/pumpkin.png differ diff --git a/Aircraft/Generic/Logos/pumpkin.xml b/Aircraft/Generic/Logos/pumpkin.xml new file mode 100644 index 000000000..fe685794d --- /dev/null +++ b/Aircraft/Generic/Logos/pumpkin.xml @@ -0,0 +1,12 @@ +<?xml version="1.0"?> + +<PropertyList> +<sim> + <model> + <logo> + <name type="string">Pumpkin</name> + <texture>../../Generic/Logos/pumpkin.png</texture> + </logo> + </model> +</sim> +</PropertyList> diff --git a/Aircraft/Generic/WalkView/walk-view-keys.xml b/Aircraft/Generic/WalkView/walk-view-keys.xml new file mode 100644 index 000000000..5471e9026 --- /dev/null +++ b/Aircraft/Generic/WalkView/walk-view-keys.xml @@ -0,0 +1,198 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Walk view module for FlightGear. + + Copyright (C) 2010 Anders Gidenstam (anders(at)gidenstam.org) + This file is licensed under the GPL license v2 or later. +--> +<PropertyList> + + <!-- + This module can be used to add suitable key bindings for walk views + to any aircraft. + + Usage example: + + Include it in the keybord section of the aircraft's -set file. + + <keyboard include="../Generic/WalkView/walk-view-keys.xml"> + + + Note: If the aircraft use other custom key bindings for the same keys + the walk view bindings should be merged into the aircraft specific + bindings. The walk view API commands return false if not currently + in a walk view so the other alternative action can be put in an + if statement. E.g. + if (!walkview.forward(4.0)) { + # Perform the non-walk view action of this key. + } + --> + + <!-- Keyboard commands --> + <key n="87"> + <name>W</name> + <desc>Walk view: Run forward.</desc> + <binding> + <command>nasal</command> + <script> + if (!walkview.forward(4.0)) { + } + </script> + </binding> + <mod-up> + <binding> + <command>nasal</command> + <script> + walkview.forward(0); + </script> + </binding> + </mod-up> + </key> + + <key n="119"> + <name>w</name> + <desc>Walk view: Walk forward.</desc> + <binding> + <command>nasal</command> + <script> + if (!walkview.forward(1.0)) { + } + </script> + </binding> + <mod-up> + <binding> + <command>nasal</command> + <script> + walkview.forward(0); + </script> + </binding> + </mod-up> + </key> + + <key n="100"> + <name>d</name> + <desc>Walk view: Side step right.</desc> + <repeatable type="bool">true</repeatable> + <binding> + <command>nasal</command> + <script> + if (!walkview.side_step(0.5)) { + } + </script> + </binding> + <mod-up> + <binding> + <command>nasal</command> + <script> + walkview.side_step(0); + </script> + </binding> + </mod-up> + </key> + + <key n="68"> + <name>D</name> + <desc>Walk view: Fast side step right.</desc> + <repeatable type="bool">true</repeatable> + <binding> + <command>nasal</command> + <script> + if (!walkview.side_step(1.0)) { + } + </script> + </binding> + <mod-up> + <binding> + <command>nasal</command> + <script> + walkview.side_step(0); + </script> + </binding> + </mod-up> + </key> + + <key n="97"> + <name>a</name> + <desc>Walk view: Side step left.</desc> + <repeatable type="bool">true</repeatable> + <binding> + <command>nasal</command> + <script> + if (!walkview.side_step(-0.5)) { + } + </script> + </binding> + <mod-up> + <binding> + <command>nasal</command> + <script> + walkview.side_step(0); + </script> + </binding> + </mod-up> + </key> + <key n="65"> + <name>A</name> + <desc>Walk view: Fast side step left.</desc> + <repeatable type="bool">true</repeatable> + <binding> + <command>nasal</command> + <script> + if (!walkview.side_step(-1.0)) { + } + </script> + </binding> + <mod-up> + <binding> + <command>nasal</command> + <script> + walkview.side_step(0); + </script> + </binding> + </mod-up> + </key> + + <key n="115"> + <name>s</name> + <desc>Walk view: Walk backwards.</desc> + <binding> + <command>nasal</command> + <script> + if (!walkview.forward(-1.0)) { + controls.startEngine(1); + } + </script> + </binding> + <mod-up> + <binding> + <command>nasal</command> + <script> + walkview.forward(0); + controls.startEngine(0); + </script> + </binding> + </mod-up> + </key> + <!-- Remove this if you for some reason have 2d panels and want the default + Swap panels function on 'S'. + --> + <!-- key n="83"> + <name>S</name> + <desc>Walk view: Walk backwards.</desc> + <binding> + <command>nasal</command> + <script> + walkview.forward(-1.0); + </script> + </binding> + <mod-up> + <binding> + <command>nasal</command> + <script> + walkview.forward(0); + </script> + </binding> + </mod-up> + </key --> + +</PropertyList> diff --git a/Aircraft/Generic/WalkView/walkview.nas b/Aircraft/Generic/WalkView/walkview.nas index cecd081c6..b7bad57c1 100644 --- a/Aircraft/Generic/WalkView/walkview.nas +++ b/Aircraft/Generic/WalkView/walkview.nas @@ -83,7 +83,8 @@ var active_walker = func { # speed ... speed in m/sec : double # # set_pos(pos) -# get_pos() : position +# pos ... position in meter : [double, double, double] +# get_pos() : position ([meter, meter, meter]) # # set_eye_height(h) # get_eye_height() : int (meter) @@ -97,13 +98,15 @@ var active_walker = func { # [19.5, 0.3, -8.85]); # var walker = walkview.walker.new("Passenger View", constraint); # +# See Aircraft/Nordstern, Aircraft/Short_Empire and Aircraft/ZLT-NT +# for working examples of walk views. +# # NOTES: # Currently there can only be one view manager per view so the # walk view should not have any other view manager. -# -var walker = { +var Walker = { new : func (view_name, constraints = nil, managers = nil) { - var obj = { parents : [walker] }; + var obj = { parents : [Walker] }; obj.view = view.views[view.indexof(view_name)]; obj.constraints = constraints; obj.managers = managers; @@ -124,7 +127,7 @@ var walker = { view.manager.register(view_name, obj); walkers[obj.view.getPath()] = obj; - debug.dump(obj); + #debug.dump(obj); return obj; }, active : func { @@ -216,13 +219,52 @@ var walker = { ############################################################################### # Constraint classes. Determines where the view can walk. +# + +# Convenience functions. + +# Build a UnionConstraint hierarchy from a list of constraints. +# cs - list of constraints : [constraint] +var makeUnionConstraint = func (cs) { + if (size(cs) < 2) return cs[0]; + + var ret = cs[0]; + for (var i = 1; i < size(cs); i += 1) { + ret = UnionConstraint.new(ret, cs[i]); + } + return ret; +} + +# Build a UnionConstraint hierachy that represents a polyline path +# with a certain width. Each internal point gets a circular surface. +# points - list of points : [position] ([[meter, meter, meter]]) +# width - width of the path : length (meter) +# round_ends - put a circle also on the first and last points : bool +var makePolylinePath = func (points, width, round_ends = 0) { + if (size(points) < 2) return nil; + var ret = LinePlane.new(points[0], points[1], width); + if (round_ends) { + ret = UnionConstraint.new(line, + CircularXYSurface.new(points[0], width/2)); + } + for (var i = 2; i < size(points); i += 1) { + var line = LinePlane.new(points[i-1], points[i], width); + if (i + 1 < size(points) or round_ends) { + line = UnionConstraint.new + (line, + CircularXYSurface.new(points[i], width/2)); + } + ret = UnionConstraint.new(line, ret); + } + return ret; +} # The union of two constraints. # c1, c2 - the constraints : constraint # NOTE: Assumes that the constraints are convex. -var unionConstraint = { +var UnionConstraint = { new : func (c1, c2) { - var obj = { parents : [unionConstraint] }; + var obj = { parents : [UnionConstraint] }; obj.c1 = c1; obj.c2 = c2; return obj; @@ -244,40 +286,82 @@ var unionConstraint = { } }; -# Build a unionConstraint hierarchy from a list of constraints. -# cs - list of constraints : [constraint] -var makeUnionConstraint = func (cs) { - if (size(cs) < 2) return cs[0]; - - var ret = cs[0]; - for (var i = 1; i < size(cs); i += 1) { - ret = unionConstraint.new(ret, cs[i]); - } - return ret; -} +# Rectangular plane defined by a straight line and a width. +# The line is extruded horizontally on each side by width/2 into a +# planar surface. +# p1, p2 - the line endpoints. : position ([meter, meter, meter]) +# width - total width of the plane. : length (meter) +var LinePlane = { + new : func (p1, p2, width) { + var obj = { parents : [LinePlane] }; + obj.p1 = p1; + obj.p2 = p2; + obj.halfwidth = width/2; + obj.length = vec2.length(vec2.sub(p2, p1)); + obj.e1 = vec2.normalize(vec2.sub(p2, p1)); + obj.e2 = [obj.e1[1], -obj.e1[0]]; + obj.k = (p2[2] - p1[2]) / obj.length; -# Mostly aligned plane sloping along the X axis. -# minp - the X,Y minimum point : position (meter) -# maxp - the X,Y maximum point : position (meter) -var slopingYAlignedPlane = { - new : func (minp, maxp) { - var obj = { parents : [slopingYAlignedPlane] }; - obj.minp = minp; - obj.maxp = maxp; - obj.kxz = (maxp[2] - minp[2])/(maxp[0] - minp[0]); return obj; }, constrain : func (pos) { - var p = [pos[0], pos[1], pos[2]]; - if (pos[0] < me.minp[0]) p[0] = me.minp[0]; - if (pos[0] > me.maxp[0]) p[0] = me.maxp[0]; - if (pos[1] < me.minp[1]) p[1] = me.minp[1]; - if (pos[1] > me.maxp[1]) p[1] = me.maxp[1]; - p[2] = me.minp[2] + me.kxz * (pos[0] - me.minp[0]); + var p = [pos[0], pos[1], pos[2]]; + var pXY = vec2.sub(pos, me.p1); + var along = vec2.dot(pXY, me.e1); + var across = vec2.dot(pXY, me.e2); + + var along2 = max(0, min(along, me.length)); + var across2 = max(-me.halfwidth, min(across, me.halfwidth)); + if (along2 != along or across2 != across) { + # Compute new XY position. + var t = vec2.add(vec2.mul(along2, me.e1), vec2.mul(across2, me.e2)); + p[0] = me.p1[0] + t[0]; + p[1] = me.p1[1] + t[1]; + } + + # Compute Z positition. + p[2] = me.p1[2] + me.k * along2; + return p; + } +}; + +# Circular surface aligned with the XY plane +# center - the center point : position ([meter, meter, meter]) +# radius - radius in the XY plane : length (meter) +var CircularXYSurface = { + new : func (center, radius) { + var obj = { parents : [CircularXYSurface] }; + obj.center = center; + obj.radius = radius; + + return obj; + }, + constrain : func (pos) { + var p = [pos[0], pos[1], me.center[2]]; + var pXY = vec2.sub(pos, me.center); + var lXY = vec2.length(pXY); + + if (lXY > me.radius) { + var t = vec2.add(me.center, vec2.mul(me.radius/lXY, pXY)); + p[0] = t[0]; + p[1] = t[1]; + } return p; }, }; +# Mostly aligned plane sloping along the X axis. +# NOTE: Obsolete. Use linePlane instead. +# minp - the X,Y minimum point : position ([meter, meter, meter]) +# maxp - the X,Y maximum point : position ([meter, meter, meter]) +var SlopingYAlignedPlane = { + new : func (minp, maxp) { + return LinePlane.new([minp[0], (minp[1] + maxp[1])/2, minp[2]], + [maxp[0], (minp[1] + maxp[1])/2, maxp[2]], + (maxp[1] - minp[1])); + } +}; + # Action constraint # Triggers an action when entering or exiting the constraint. # constraint - the area in question : constraint @@ -285,9 +369,9 @@ var slopingYAlignedPlane = { # on_exit(x, y) - function that is called when the walker leaves the area. # x and y are <0, 0 or >0 depending on in which direction(s) # the walker left the constraint. -var actionConstraint = { +var ActionConstraint = { new : func (constraint, on_enter = nil, on_exit = nil) { - var obj = { parents : [actionConstraint] }; + var obj = { parents : [ActionConstraint] }; obj.constraint = constraint; obj.on_enter = on_enter; obj.on_exit = on_exit; @@ -366,3 +450,33 @@ var closerXY = func (pos, p1, p2) { var l2 = [p2[0] - pos[0], p2[1] - pos[1]]; return (l1[0]*l1[0] + l1[1]*l1[1]) - (l2[0]*l2[0] + l2[1]*l2[1]); } + +var max = func (a, b) { + return b > a ? b : a; +} +var min = func (a, b) { + return a > b ? b : a; +} + +# 2D vector math. +var vec2 = { + add : func (a, b) { + return [a[0] + b[0], a[1] + b[1]]; + }, + sub : func (a, b) { + return [a[0] - b[0], a[1] - b[1]]; + }, + mul : func (k, a) { + return [k * a[0], k * a[1]]; + }, + length : func (a) { + return math.sqrt(a[0]*a[0] + a[1]*a[1]); + }, + dot : func (a, b) { + return a[0]*b[0] + a[1]*b[1]; + }, + normalize : func (a) { + var s = 1/vec2.length(a); + return [s * a[0], s * a[1]]; + } +} diff --git a/Input/Joysticks/Saitek/Aviator.xml b/Input/Joysticks/Saitek/Aviator.xml index 4d3febc29..1f0e6b23b 100644 --- a/Input/Joysticks/Saitek/Aviator.xml +++ b/Input/Joysticks/Saitek/Aviator.xml @@ -1,9 +1,8 @@ <?xml version="1.0" ?> <?xml-stylesheet type="text/xsl" href="joystick.xsl"?> -<!-- $Id$ --> <!-- Saitek AV8R/Aviator - Copyright (C) 2007 - 2009 Anders Gidenstam (anders(at)gidenstam.org) + Copyright (C) 2007 - 2010 Anders Gidenstam (anders(at)gidenstam.org) This file is released under the GPL license v2 or later. --> <PropertyList> @@ -21,18 +20,27 @@ # TM0: All selected; TM1: #1 & #2; TM2: #3 & #4 var engine_axis_mode = 0; # Valid only in TM1 and TM2. - # EA0: throttle, +mod: propeller - # EA1: propeller, +mod: throttle + # EA0: throttle + # EA1: mixture + # EA2: propeller var quick_view_active = 0; var old_view = view.point.save(); var pressed = [0,0,0,0,0,0,0,0,0,0,0,0]; + # Map engines to throttles for TM1 (0, 1) and TM2 (2, 3) var engine = [0, 1, 2, 3]; - # Do per-aircraft modifications - if (getprop("/sim/model/path") == - "Aircraft/Short_Empire/Models/Short_Empire-model.xml") { + # Do per-aircraft modifications + if (contains({"Aircraft/Short_Empire/Models/Short_Empire-model.xml" : 0, + "Aircraft/Lockheed1049/Models/Lockheed1049_twa.xml" : 0}, + getprop("/sim/model/path"))) { + # TM1: the outer engines, TM2: the inner engines engine = [0, 3, 1, 2]; } + if (contains({"Aircraft/DO-X/Models/dox.xml" : 0}, + getprop("/sim/model/path"))) { + engine = [[0, 1, 2, 3, 4, 5], [6, 7, 8, 9, 10, 11], + [0, 1, 2, 3, 4, 5], [6, 7, 8, 9, 10, 11]]; + } var goal_heading_offset = @@ -46,7 +54,7 @@ var kbdalt = props.globals.getNode("/devices/status/keyboard/alt", 1); var quick_view = func { - dir = arg[0]; + var dir = arg[0]; if (dir == 0) { quick_view_active = 0; view.point.move(old_view, 0.1); @@ -99,7 +107,13 @@ </nasal> <!-- Analog axis 0. Aileron --> - <axis n="0"> + <axis> + <name>Stick left/right</name> + <number> + <unix>0</unix> + <mac>0</mac> + <windows>0</windows> + </number> <desc>aileron</desc> <binding> <command>property-scale</command> @@ -111,7 +125,13 @@ </axis> <!-- Analog axis 1. Elevator --> - <axis n="1"> + <axis> + <name>Stick forward/back</name> + <number> + <unix>1</unix> + <mac>1</mac> + <windows>1</windows> + </number> <desc>elevator</desc> <binding> <command>property-scale</command> @@ -125,6 +145,7 @@ <!-- Analog axis 3. Rudder --> <axis> + <name>Stick twist</name> <number> <unix>3</unix> <mac>2</mac> @@ -139,10 +160,18 @@ <factor type="double">1.0</factor> <squared type="bool">true</squared> </binding> + <!-- binding> + <command>nasal</command> + <script> + setprop("sim/current-view/goal-heading-offset-deg", + -90.0*cmdarg().getNode("setting").getValue()); + </script> + </binding --> </axis> <!-- Analog axis 2. Throttle 1 --> <axis> + <name>Left throttle</name> <number> <unix>2</unix> <mac>3</mac> @@ -155,43 +184,43 @@ if (engine_select_mode == 0) { controls.throttleAxis(); } else { - var val = cmdarg().getNode("setting").getValue(); - var ctrl_pp = - "/controls/engines/engine[" ~ - ((engine_select_mode == 1) ? engine[0] : engine[2]) ~ "]/" ~ - (engine_axis_mode ? "propeller-pitch" : "throttle"); - setprop(ctrl_pp, (1 - val)/2); + controls.perEngineSelectedAxisHandler(engine_axis_mode) + ((engine_select_mode == 1) ? engine[0] : engine[2]); } </script> </binding> </axis> <!-- Analog axis 4. Throttle 2 --> - <axis n="4"> - <desc>TM0: mixture, +mod: propeller pitch, TM1: throttle/propeller 2, TM2: throttle/propeller 4</desc> + <axis> + <name>Right throttle</name> + <number> + <unix>4</unix> + <mac>4</mac> + <windows>4</windows> + </number> + <desc>TM0: mixture, TM1: throttle/propeller 2, TM2: throttle/propeller 4</desc> <binding> <command>nasal</command> <script> if (engine_select_mode == 0) { - if (!modifier) { - controls.mixtureAxis(); - } else { - controls.propellerAxis(); - } + controls.mixtureAxis(); } else { - var val = cmdarg().getNode("setting").getValue(); - var ctrl_pp = - "/controls/engines/engine[" ~ - ((engine_select_mode == 1) ? engine[1] : engine[3]) ~ "]/" ~ - (engine_axis_mode ? "propeller-pitch" : "throttle"); - setprop(ctrl_pp, (1 - val)/2); + controls.perEngineSelectedAxisHandler(engine_axis_mode) + ((engine_select_mode == 1) ? engine[1] : engine[3]); } </script> </binding> </axis> <!-- Axis 5. Hat left/right --> - <axis n="5"> + <axis> + <name>Hat left/right</name> + <number> + <unix>5</unix> + <mac>5</mac> + <windows>5</windows> + </number> <desc>quick view left/right, +mod: horizontal view pan</desc> <low> <repeatable type="bool">true</repeatable> @@ -238,10 +267,12 @@ <binding> <command>nasal</command> <script> + <![CDATA[ trace("Axis 5, Hat: low released!"); if (!modifier) { quick_view(0); } + ]]> </script> </binding> </mod-up> @@ -249,7 +280,13 @@ </axis> <!-- Axis 6. Hat up/down --> - <axis n="6"> + <axis> + <name>Hat up/down</name> + <number> + <unix>6</unix> + <mac>6</mac> + <windows>6</windows> + </number> <desc>view reset/quick view front, +mod: vertical view pan</desc> <low> <repeatable type="bool">true</repeatable> @@ -270,9 +307,11 @@ <binding> <command>nasal</command> <script> + <![CDATA[ if (!modifier) { #quick_view(0); } + ]]> </script> </binding> </mod-up> @@ -296,9 +335,11 @@ <binding> <command>nasal</command> <script> + <![CDATA[ if (!modifier) { quick_view(0); } + ]]> </script> </binding> </mod-up> @@ -306,8 +347,13 @@ </axis> <!-- Trigger Button --> - <button n="0"> + <button> <name>Trigger</name> + <number> + <unix>0</unix> + <mac>0</mac> + <windows>0</windows> + </number> <desc>function modifier (mod)</desc> <binding> <command>nasal</command> @@ -327,8 +373,13 @@ </button> <!-- Center Button --> - <button n="2"> + <button> <name>Center button</name> + <number> + <unix>2</unix> + <mac>2</mac> + <windows>2</windows> + </number> <desc>brakes, +mod: Toggle parking brake</desc> <binding> <command>nasal</command> @@ -352,8 +403,13 @@ </button> <!-- Left Button --> - <button n="1"> + <button> <name>Left button</name> + <number> + <unix>1</unix> + <mac>1</mac> + <windows>1</windows> + </number> <desc>left brake, +mod: PTT</desc> <binding> <command>nasal</command> @@ -378,8 +434,13 @@ </button> <!-- Right Button --> - <button n="3"> + <button> <name>Right button</name> + <number> + <unix>3</unix> + <mac>3</mac> + <windows>3</windows> + </number> <desc>right brake, +mod: trigger</desc> <binding> <command>nasal</command> @@ -404,8 +465,13 @@ </button> <!-- Button: T1 --> - <button n="4"> + <button> <name>T1</name> + <number> + <unix>4</unix> + <mac>4</mac> + <windows>4</windows> + </number> <desc>next view, +mod: zoom in +Shift: next weapon</desc> <repeatable type="bool">true</repeatable> <binding> @@ -442,8 +508,13 @@ </button> <!-- Button: T2 --> - <button n="5"> + <button> <name>T2</name> + <number> + <unix>5</unix> + <mac>5</mac> + <windows>5</windows> + </number> <desc>previous view, +mod: zoom out, +Shift: previous weapon</desc> <repeatable type="bool">true</repeatable> <binding> @@ -480,8 +551,13 @@ </button> <!-- Button: T3 --> - <button n="6"> + <button> <name>T3</name> + <number> + <unix>6</unix> + <mac>6</mac> + <windows>6</windows> + </number> <desc>trim nose down, +mod: disarm speed brakes</desc> <repeatable type="bool">true</repeatable> <binding> @@ -498,8 +574,13 @@ </button> <!-- Button: T4 --> - <button n="7"> + <button> <name>T4</name> + <number> + <unix>7</unix> + <mac>7</mac> + <windows>7</windows> + </number> <desc>trim nose up, +mod: deploy speed brakes</desc> <repeatable type="bool">true</repeatable> <binding> @@ -516,8 +597,13 @@ </button> <!-- Button: T5 --> - <button n="8"> + <button> <name>T5</name> + <number> + <unix>8</unix> + <mac>8</mac> + <windows>8</windows> + </number> <desc>retract flaps one step, +mod: gear up</desc> <binding> <command>nasal</command> @@ -542,8 +628,13 @@ </button> <!-- Button: T6 --> - <button n="9"> + <button> <name>T6</name> + <number> + <unix>9</unix> + <mac>9</mac> + <windows>9</windows> + </number> <desc>deploy flaps one step, +mod: gear down</desc> <binding> <command>nasal</command> @@ -568,8 +659,13 @@ </button> <!-- Button: T7 --> - <button n="10"> + <button> <name>T7</name> + <number> + <unix>10</unix> + <mac>10</mac> + <windows>10</windows> + </number> <desc>Increase magnetos, +mod: Engine throttle/propeller axis swap</desc> <binding> <command>nasal</command> @@ -578,14 +674,19 @@ if (!modifier) { controls.stepMagnetos(1); } else { - engine_axis_mode = !engine_axis_mode; + engine_axis_mode = 2*!engine_axis_mode; } </script> </binding> </button> <!-- Button: T8 --> - <button n="11"> + <button> + <number> + <unix>11</unix> + <mac>11</mac> + <windows>11</windows> + </number> <name>T8</name> <desc>Decrease magnetos, +mod: Engine throttle/propeller axis swap</desc> <binding> @@ -595,15 +696,20 @@ if (!modifier) { controls.stepMagnetos(-1); } else { - engine_axis_mode = !engine_axis_mode; + engine_axis_mode = 2*!engine_axis_mode; } </script> </binding> </button> <!-- Button: 3-way Mode switch --> - <button n="12"> + <button> <name>Mode 1</name> + <number> + <unix>12</unix> + <mac>12</mac> + <windows>12</windows> + </number> <desc>Engine 0/1 throttle mode</desc> <binding> <command>nasal</command> @@ -622,7 +728,13 @@ </binding> </mod-up> </button> - <button n="13"> + <button> + <name>Mode 2</name> + <number> + <unix>13</unix> + <mac>13</mac> + <windows>13</windows> + </number> <name>Mode 2</name> <desc>Engine 2/3 throttle mode</desc> <binding> diff --git a/Input/Joysticks/Saitek/Pro-Flight-Quadrant.xml b/Input/Joysticks/Saitek/Pro-Flight-Quadrant.xml index a0ba91fee..bb9ac4ccd 100644 --- a/Input/Joysticks/Saitek/Pro-Flight-Quadrant.xml +++ b/Input/Joysticks/Saitek/Pro-Flight-Quadrant.xml @@ -1,35 +1,122 @@ <?xml version="1.0"?> <!-- Saitek Pro Flight Quadrant - Copyright (C) 2008 Ronald Jensen (wino(at)jentronics.com) - This file is released under the GPL license. + Copyright (C) 2008 Ronald Jensen (wino(at)jentronics.com) + Copyright (C) 2009 - 2010 Anders Gidenstam (anders(at)gidenstam.org) + This file is released under the GPL license version 2. --> <PropertyList> <name>Saitek Saitek Pro Flight Quadrant</name> <name>Saitek Pro Flight Quadrant</name> <name>Saitek Pro Flight Throttle Quadrant</name> - <axis n="0"> - <desc>Throttle</desc> + + <nasal> + <script> + <![CDATA[ + var self = cmdarg().getParent(); + var data = self.getNode("data"); + var engine_select_mode = 0; + # TM0: All selected; TM1: #1-#3; TM2: #3-#6 + var engine_axis_mode = 0; + # Valid only in TM1 and TM2. + # EA0: throttle + # EA1: mixure + # EA2: propeller + var pressed = [0,0,0,0,0,0]; + var engine = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + + # Do per-aircraft modifications + if (contains({"Aircraft/Short_Empire/Models/Short_Empire-model.xml" : 0, + "Aircraft/Lockheed1049/Models/Lockheed1049_twa.xml" : 0}, + getprop("/sim/model/path"))) { + # Map port outer to axis 0, starboard outer to axis 2 and + # the inner engines to axis 1. + engine = [0, [1, 2], 3]; + } + if (contains({"Aircraft/DO-X/Models/dox.xml" : 0}, + getprop("/sim/model/path"))) { + engine = [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]]; + } + if (contains({"Aircraft/Nordstern/Models/Nordstern.xml" : 0}, + getprop("/sim/model/path"))) { + engine = [0, 1, [2, 3]]; + } + + var kbdctrl = props.globals.getNode("/devices/status/keyboard/ctrl", 1); + var kbdalt = props.globals.getNode("/devices/status/keyboard/alt", 1); + + var axis_handler = func(axis) { + if (engine_select_mode == 0) { + if (axis == 0) { + controls.throttleAxis(); + } elsif (axis == 1) { + controls.propellerAxis(); + } elsif (axis == 2) { + controls.mixtureAxis(); + } + } else { + controls.perEngineSelectedAxisHandler(engine_axis_mode) + (engine[axis + 3*(engine_select_mode - 1)]); + } + } + + var trace = func(str) { + # Uncomment the line below to trace button presses. + #print("Pro-Flight-Quadrant.xml: " ~ str); + } + ]]> + </script> + </nasal> + + <!-- Levers left to right. --> + <axis> + <name>Left lever</name> + <number> + <unix>0</unix> + <mac>0</mac> + <windows>0</windows> + </number> + <desc>TM0: throttle, TM1: throttle/propeller 1, TM2: throttle/propeller 4</desc> <binding> <command>nasal</command> - <script>controls.throttleAxis()</script> + <script>axis_handler(0)</script> </binding> </axis> - <axis n="1"> - <desc>Prop Pitch</desc> + <axis> + <name>Middle lever</name> + <number> + <unix>1</unix> + <mac>1</mac> + <windows>1</windows> + </number> + <desc>TM0: propeller, TM1: throttle/propeller 2, TM2: throttle/propeller 5</desc> <binding> <command>nasal</command> - <script>controls.propellerAxis()</script> + <script>axis_handler(1)</script> </binding> </axis> - <axis n="2"> - <desc>Mixture </desc> + <axis> + <name>Right lever</name> + <number> + <unix>2</unix> + <mac>2</mac> + <windows>2</windows> + </number> + <desc>TM0: mixture, TM1: throttle/propeller 3, TM2: throttle/propeller 6</desc> <binding> <command>nasal</command> - <script>controls.mixtureAxis()</script> + <script>axis_handler(2)</script> </binding> </axis> - <button n="0"> + + <!-- 2-way rocker switches. Left to right. --> + <button> + <name>Left button up</name> + <number> + <unix>0</unix> + <mac>0</mac> + <windows>0</windows> + </number> <desc>Flaps up</desc> <repeatable>false</repeatable> <binding> @@ -42,14 +129,40 @@ <script>controls.flapsDown(0)</script> </binding> </mod-up> + <mod-shift> + <binding> + <command>nasal</command> + <script> + trace("Button 0 + shift pressed!"); + gui.popupTip("Saitek Quadrant: Throttle Mode 1"); + engine_select_mode = 1; + </script> + </binding> + </mod-shift> </button> <button n="1"> + <name>Left button down</name> + <number> + <unix>1</unix> + <mac>1</mac> + <windows>1</windows> + </number> <desc>Flaps down</desc> <repeatable>false</repeatable> <binding> <command>nasal</command> <script>controls.flapsDown(1)</script> </binding> + <mod-shift> + <binding> + <command>nasal</command> + <script> + trace("Button 1 + shift pressed!"); + gui.popupTip("Saitek Quadrant: Throttle Mode 0"); + engine_select_mode = 0; + </script> + </binding> + </mod-shift> <mod-up> <binding> <command>nasal</command> @@ -57,23 +170,64 @@ </binding> </mod-up> </button> - <button n="2"> + + <button> + <name>Middle button up</name> + <number> + <unix>2</unix> + <mac>2</mac> + <windows>2</windows> + </number> <desc>Elevator trim up</desc> <repeatable>true</repeatable> <binding> <command>nasal</command> <script>controls.elevatorTrim(-0.75)</script> </binding> + <mod-shift> + <binding> + <command>nasal</command> + <script> + trace("Button 2 + shift pressed!"); + if (engine_select_mode) gui.popupTip("Saitek Quadrant: Throttle control"); + engine_axis_mode = 0; + </script> + </binding> + </mod-shift> </button> - <button n="3"> + <button> + <name>Middle button down</name> + <number> + <unix>3</unix> + <mac>3</mac> + <windows>3</windows> + </number> <desc>Elevator trim down</desc> <repeatable>true</repeatable> <binding> <command>nasal</command> <script>controls.elevatorTrim(0.75)</script> </binding> + <mod-shift> + <binding> + <command>nasal</command> + <script> + trace("Button 3 + shift pressed!"); + if (engine_select_mode) + gui.popupTip("Saitek Quadrant: Propeller control"); + engine_axis_mode = 2; + </script> + </binding> + </mod-shift> </button> - <button n="4"> + + <button> + <name>Right button up</name> + <number> + <unix>4</unix> + <mac>4</mac> + <windows>4</windows> + </number> <desc>Gear up</desc> <repeatable>false</repeatable> <binding> @@ -81,7 +235,13 @@ <script>controls.gearDown(-1)</script> </binding> </button> - <button n="5"> + <button> + <name>Right button down</name> + <number> + <unix>5</unix> + <mac>5</mac> + <windows>5</windows> + </number> <desc>Gear down</desc> <repeatable>false</repeatable> <binding> @@ -89,4 +249,49 @@ <script>controls.gearDown(1)</script> </binding> </button> + + <!-- Axis reverse area switches. --> + <button> + <name>Left lever reverse</name> + <number> + <unix>6</unix> + <mac>6</mac> + <windows>6</windows> + </number> + <desc></desc> + <repeatable>false</repeatable> + <binding> + <command>nasal</command> + <script></script> + </binding> + </button> + <button> + <name>Middle lever reverse</name> + <number> + <unix>7</unix> + <mac>7</mac> + <windows>7</windows> + </number> + <desc></desc> + <repeatable>false</repeatable> + <binding> + <command>nasal</command> + <script></script> + </binding> + </button> + <button> + <name>Right lever reverse</name> + <number> + <unix>8</unix> + <mac>8</mac> + <windows>8</windows> + </number> + <desc></desc> + <repeatable>false</repeatable> + <binding> + <command>nasal</command> + <script></script> + </binding> + </button> + </PropertyList> diff --git a/Nasal/controls.nas b/Nasal/controls.nas index 016a35402..2d3f41441 100644 --- a/Nasal/controls.nas +++ b/Nasal/controls.nas @@ -74,6 +74,51 @@ var mixtureAxis = axisHandler("/controls/engines/engine[", "]/mixture"); var propellerAxis = axisHandler("/controls/engines/engine[", "]/propeller-pitch"); var carbHeatAxis = axisHandler("/controls/anti-ice/engine[", "]/carb-heat"); +# 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. +# Usage example (controlling the mixture of engines 1 and 2): +# <script> +# controls.perEngineSelectedAxisHandler(1)([1,2]); +# </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]; +} + + ## # Wrapper around stepProps() which emulates the "old" flap behavior for # configurations that aren't using the new mechanism. diff --git a/gui/dialogs/ai.xml b/gui/dialogs/ai.xml index bba1c22eb..56898b8c9 100644 --- a/gui/dialogs/ai.xml +++ b/gui/dialogs/ai.xml @@ -71,4 +71,54 @@ <stretch>true</stretch> </empty> </group> -</PropertyList> \ No newline at end of file + + <group> + <layout>hbox</layout> + <default-padding>6</default-padding> + <empty> + <stretch>true</stretch> + </empty> + + <button> + <legend>OK</legend> + <default>true</default> + <equal>true</equal> + <binding> + <command>dialog-apply</command> + </binding> + <binding> + <command>dialog-close</command> + </binding> + </button> + + <button> + <legend>Apply</legend> + <equal>true</equal> + <binding> + <command>dialog-apply</command> + </binding> + </button> + + <button> + <legend>Reset</legend> + <equal>true</equal> + <binding> + <command>dialog-update</command> + </binding> + </button> + + <button> + <legend>Cancel</legend> + <equal>true</equal> + <key>Esc</key> + <binding> + <command>dialog-close</command> + </binding> + </button> + + <empty> + <stretch>true</stretch> + </empty> + </group> + +</PropertyList> diff --git a/gui/dialogs/location-in-air.xml b/gui/dialogs/location-in-air.xml index 4e2fa953a..ce16f3fae 100644 --- a/gui/dialogs/location-in-air.xml +++ b/gui/dialogs/location-in-air.xml @@ -261,7 +261,7 @@ <command>nasal</command> <script> setprop("/sim/presets/parkpos", ""); - + if (!mode.airport.getBoolValue()) { setprop("/sim/presets/airport-id", ""); setprop("/sim/presets/runway", ""); diff --git a/gui/menubar.xml b/gui/menubar.xml index 39045e82f..29295d576 100644 --- a/gui/menubar.xml +++ b/gui/menubar.xml @@ -457,9 +457,9 @@ </menu> <menu> - <label>ATC/AI</label> + <label>AI</label> <item> - <label>ATC Options</label> + <label>AI Options</label> <binding> <command>dialog-show</command> <dialog-name>ai</dialog-name> diff --git a/materials.xml b/materials.xml index e3f79bf99..828bc5cdf 100644 --- a/materials.xml +++ b/materials.xml @@ -1320,6 +1320,9 @@ Shared parameters for various materials. <heading-type>random</heading-type> </object> </object-group> + <!-- Disabled to avoid a tremendous osg performance penalty when + deleting scenery tiles, caused by tens of thousands of shared + horse/cow objects. Need a better implementation! <object-group> <range-m>1000</range-m> <object> @@ -1332,7 +1335,7 @@ Shared parameters for various materials. <coverage-m2>300000</coverage-m2> <heading-type>random</heading-type> </object> - </object-group> + </object-group> --> <wood-coverage>1000000.0</wood-coverage> <wood-size>20000.0</wood-size> <tree-density>4000.0</tree-density> @@ -1383,6 +1386,9 @@ Shared parameters for various materials. <heading-type>random</heading-type> </object> </object-group> + <!-- Disabled to avoid a tremendous osg performance penalty when + deleting scenery tiles, caused by tens of thousands of shared + horse/cow objects. Need a better implementation! <object-group> <range-m>1000</range-m> <object> @@ -1395,7 +1401,7 @@ Shared parameters for various materials. <coverage-m2>300000</coverage-m2> <heading-type>random</heading-type> </object> - </object-group> + </object-group> --> <wood-coverage>500000.0</wood-coverage> <tree-texture>Textures/Trees/mixed-summer.png</tree-texture> <tree-varieties>8</tree-varieties> @@ -1444,6 +1450,9 @@ Shared parameters for various materials. <heading-type>random</heading-type> </object> </object-group> + <!-- Disabled to avoid a tremendous osg performance penalty when + deleting scenery tiles, caused by tens of thousands of shared + horse/cow objects. Need a better implementation! <object-group> <range-m>1000</range-m> <object> @@ -1456,7 +1465,7 @@ Shared parameters for various materials. <coverage-m2>300000</coverage-m2> <heading-type>random</heading-type> </object> - </object-group> + </object-group> --> <wood-coverage>500000.0</wood-coverage> <wood-size>20000.0</wood-size> <tree-density>5000.0</tree-density> @@ -2140,6 +2149,9 @@ Shared parameters for various materials. <heading-type>random</heading-type> </object> </object-group> + <!-- Disabled to avoid a tremendous osg performance penalty when + deleting scenery tiles, caused by tens of thousands of shared + horse/cow objects. Need a better implementation! <object-group> <range-m>1000</range-m> <object> @@ -2152,7 +2164,7 @@ Shared parameters for various materials. <coverage-m2>300000</coverage-m2> <heading-type>random</heading-type> </object> - </object-group> + </object-group> --> <wood-coverage>1000000.0</wood-coverage> <wood-size>20000.0</wood-size> <tree-density>4000.0</tree-density> @@ -2202,6 +2214,9 @@ Shared parameters for various materials. <heading-type>random</heading-type> </object> </object-group> + <!-- Disabled to avoid a tremendous osg performance penalty when + deleting scenery tiles, caused by tens of thousands of shared + horse/cow objects. Need a better implementation! <object-group> <range-m>1000</range-m> <object> @@ -2214,7 +2229,7 @@ Shared parameters for various materials. <coverage-m2>300000</coverage-m2> <heading-type>random</heading-type> </object> - </object-group> + </object-group> --> <wood-coverage>150000.0</wood-coverage> <wood-size>10000.0</wood-size> <tree-density>5000.0</tree-density> @@ -2264,6 +2279,9 @@ Shared parameters for various materials. <heading-type>random</heading-type> </object> </object-group> + <!-- Disabled to avoid a tremendous osg performance penalty when + deleting scenery tiles, caused by tens of thousands of shared + horse/cow objects. Need a better implementation! <object-group> <range-m>1000</range-m> <object> @@ -2276,7 +2294,7 @@ Shared parameters for various materials. <coverage-m2>300000</coverage-m2> <heading-type>random</heading-type> </object> - </object-group> + </object-group> --> <wood-coverage>150000.0</wood-coverage> <wood-size>10000.0</wood-size> <tree-density>5000.0</tree-density> diff --git a/preferences.xml b/preferences.xml index 940cbd3bc..334cfa354 100644 --- a/preferences.xml +++ b/preferences.xml @@ -54,7 +54,7 @@ Started September 2000 by David Megginson, david@megginson.com <terminal-ansi-colors type="bool">true</terminal-ansi-colors> <season type="string">summer</season> </startup> - <rendering> <multithreading-mode>AutomaticSelection</multithreading-mode> + <rendering> <debug type="bool">false</debug> <realism>5</realism> <filtering>8</filtering> @@ -281,12 +281,11 @@ Started September 2000 by David Megginson, david@megginson.com <systems> <path>Aircraft/Generic/generic-systems.xml</path> <autopilot> + <name>generic autopilot</name> <path>Aircraft/Generic/generic-autopilot.xml</path> </autopilot> - <!-- - replace the hard coded helpers, which are gone now - --> <autopilot> + <name>autopilot helpers</name> <path>Aircraft/Generic/generic-autopilot-helper.xml</path> </autopilot> <property-rule> @@ -593,7 +592,7 @@ Started September 2000 by David Megginson, david@megginson.com </airport> <atc> - <enabled type="bool">false</enabled> + <enabled type="bool">true</enabled> </atc> <ai-traffic> @@ -602,7 +601,7 @@ Started September 2000 by David Megginson, david@megginson.com </ai-traffic> <traffic-manager> - <enabled type="bool">false</enabled> + <enabled type="bool">true</enabled> <heuristics type="bool">true</heuristics> <datafile type="string"></datafile> <instantaneous-action type="bool">false</instantaneous-action> @@ -612,13 +611,12 @@ Started September 2000 by David Megginson, david@megginson.com <ai> <enabled type="bool">true</enabled> - <!-- <scenario>nimitz_demo</scenario> --> + <scenario>nimitz_demo</scenario> <!-- <scenario>balloon_demo</scenario> --> <!-- <scenario>aircraft_demo</scenario> --> <!-- <scenario>refueling_demo</scenario> --> <!-- <scenario>lead_aircraft</scenario> --> <!-- <scenario>vinson_demo</scenario> --> - <!-- <scenario>mp-carriers</scenario> --> </ai> <multiplay>