diff --git a/Nasal/gui.nas b/Nasal/gui.nas index 2a5c74414..e0fa55d68 100644 --- a/Nasal/gui.nas +++ b/Nasal/gui.nas @@ -1265,3 +1265,12 @@ _setlistener("/sim/signals/screenshot", func { } }); +var do_welcome = 1; +_setlistener("/sim/signals/fdm-initialized", func { + var haveTutorials = size(props.globals.getNode("/sim/tutorials", 1).getChildren("tutorial")); + gui.menuEnable("tutorial-start", haveTutorials); + if (do_welcome and haveTutorials) + settimer(func { setprop("/sim/messages/copilot", "Welcome aboard! Need help? Use 'Help -> Tutorials'.");}, 5.0); + do_welcome = 0; +}); + diff --git a/Nasal/jetways.nas b/Nasal/jetways.nas deleted file mode 100644 index 68d0b68fa..000000000 --- a/Nasal/jetways.nas +++ /dev/null @@ -1,889 +0,0 @@ -############################################################################### -## -## Animated Jetway System. Spawns and manages interactive jetway models. -## -## Copyright (C) 2011 Ryan Miller -## This file is licensed under the GPL license version 2 or later. -## -############################################################################### - -############################################################################### -# (See http://wiki.flightgear.org/Howto:_Animated_jetways) -# -# Special jetway definition files located in $FG_ROOT/Airports/Jetways/XXXX.xml -# for each airport are loaded when the user's aircraft is within 50 nm of the -# airport. The script dynamically generates runtime model files, writes them to -# $FG_ROOT/Models/Airport/Jetway/runtimeX.xml, and places them into the -# simulator using the model manager. -# -# Different jetway models can be defined and are placed under -# $FG_ROOT/Models/Airport/Jetway/XXX.xml. -# -# Jetways can be extended/retracted independently either by user operation or -# by automatic extension for AI models and multiplayer aircraft. -# -# UTILITY FUNCTIONS -# ----------------- -# -# print_debug() - prints debug messages -# - message to print -# -# print_error() - prints error messages -# - error to print -# -# alert() - displays an alert message in-sim -# - the message -# -# normdeg() - normalizes angle measures between -180° and 180° -# - angle to normalize -# -# remove(, ) - removes an element from a vector -# - vector -# - item -# -# isin(, ) - checks if an item exists in a vector -# - vector -# - item -# -# putmodel(, , , , ) - add a model to the scene graph (unlike geo.put_model(), models added with this function can be adjusted) -# - model path -# - latitude -# - longitude -# - altitude in m -# - heading -# -# interpolate_table(, ) - interpolates a value within a table -#
- interpolation table/vector, in the format of [[, ], [, ], ... ] -# - value -# -# get_relative_filepath(, ) - gets a relative file path from a directory -# - directory path should be relative to -# - target directory -# -# find_airports() - gets a list of nearest airports -# - maximum search distance in nm (currently unused) -# -# JETWAY CLASS -# ------------ -# -# Jetway. - creates a new jetway object/model -# new(, , , , -# , , , , -# , [, ] -# [, ] [, ] -# [, ]) -# - ICAO of associated airport -# - jetway model definition (i.e. Models/Airport/Jetway/generic.xml) -# - gate number (i.e. "A1") -# - door number (i.e. 0) -# - airline code (i.e. "AAL") -# - latitude location of model -# - longitude location of model -# - elevation of model in m -# - (optional) heading of model -# - (optional) initial extension of tunnel in m -# - (optional) initial rotation of tunnel along the Z axis -# - (optional) initial pitch of tunnel (rotation along Y axis) -# - (optional) initial rotation of entrance along the Z axis -# -# toggle(, , - extends/retracts a jetway -# [, ]) -# - whether or not jetway is toggled by user command (0/1) -# - heading of aircraft to connect to -# - a geo.Coord of the target aircraft's door -# - (optional) amount to rotate jetway hood (only required when != 1) -# -# extend(, , - extends a jetway (should be called by Jetway.toggle()) -# [, ]) -# - whether or not jetway is toggled by user command (0/1) -# - heading of aircraft to connect to -# - a geo.Coord of the target aircraft's door -# - (optional) amount to rotate jetway hood (only required when != 1) -# -# retract() - retracts a jetway (should be called by Jetway.toggle()) -# - whether or not a jetway is toggled by user command (0/1) -# -# remove() - removes a jetway object and its model -# -# reload() - reloads a jetway object and its model -# -# setpos(, , , ) - moves a jetway to a new location -# - new latitude -# - new longitude -# - new heading -# - new altitude in m -# -# setmodel(, , ) - changes the jetway model -# - new model -# - new airline sign code -# - new gate number -# -# INTERACTION FUNCTIONS -# --------------------- -# -# dialog() - open settings dialog -# -# toggle_jetway() - toggles a jetway by user command (should be called by a pick animation in a jetway model) -# - id number of jetway to toggle -# -# toggle_jetway_from_coord(, , - toggles a jetway with the target door at the specified coordinates -# , [, -# ] []) -# - door number (i.e. 0) -# - amount to rotate jetway hood -# - (required or ) latitude location of door -# - (required or ) longitude location of door -# - (required or , ) a geo.Coord of the door -# -# toggle_jetway_from_model() - toggles a jetway using an AI model instead of the user's aircraft -# - path of AI model (i.e. /ai/models/aircraft[0])- can be the path in a string or a props.Node -# -# INTERNAL FUNCTIONS -# ------------------ -# -# load_airport_jetways() - loads jetways at an airport -# - ICAO of airport -# -# unload_airport_jetways() - unloads jetways at an airport -# - ICAO of airport -# -# update_jetways() - interpolates model animation values and keeps the system tidy -# -# load_jetways() - loads new jetway models and unloads out-of-range models every 30 seconds -# - -## Utility functions -#################### - -# prints debug messages -var print_debug = func(msg) - { - if (debug_switch.getBoolValue()) - { - print(msg); - } - }; -# prints error messages -var print_error = func(msg) - { - print("\x1b[31m" ~ msg ~ "\x1b[m"); - }; -# alerts the user -var alert = func(msg) - { - setprop("/sim/messages/ground", msg); - }; -# normalizes headings between -180 and 180 -var normdeg = func(x) - { - while (x >= 180) - { - x -= 360; - } - while (x <= -180) - { - x += 360; - } - return x; - }; -# deletes an item in a vector -var remove = func(vector, item) - { - var s = size(vector); - var found = 0; - for (var i = 0; i < s; i += 1) - { - if (found) - { - vector[i - 1] = vector[i]; - } - elsif (vector[i] == item) - { - found = 1; - } - } - if (found) setsize(vector, s - 1); - return vector; - }; -# checks if an item is in a vector -var isin = func(vector, v) - { - for (var i = 0; i < size(vector); i += 1) - { - if (vector[i] == v) return 1; - } - return 0; - }; -# adds a model -var putmodel = func(path, lat, lon, alt, hdg) - { - var models = props.globals.getNode("/models"); - var model = nil; - for (var i = 0; 1; i += 1) - { - if (models.getChild("model", i, 0) == nil) - { - model = models.getChild("model", i, 1); - break; - } - } - var model_path = model.getPath(); - model.getNode("path", 1).setValue(path); - model.getNode("latitude-deg", 1).setDoubleValue(lat); - model.getNode("latitude-deg-prop", 1).setValue(model_path ~ "/latitude-deg"); - model.getNode("longitude-deg", 1).setDoubleValue(lon); - model.getNode("longitude-deg-prop", 1).setValue(model_path ~ "/longitude-deg"); - model.getNode("elevation-ft", 1).setDoubleValue(alt * M2FT); - model.getNode("elevation-ft-prop", 1).setValue(model_path ~ "/elevation-ft"); - model.getNode("heading-deg", 1).setDoubleValue(hdg); - model.getNode("heading-deg-prop", 1).setValue(model_path ~ "/heading-deg"); - model.getNode("pitch-deg", 1).setDoubleValue(0); - model.getNode("pitch-deg-prop", 1).setValue(model_path ~ "/pitch-deg"); - model.getNode("roll-deg", 1).setDoubleValue(0); - model.getNode("roll-deg-prop", 1).setValue(model_path ~ "/roll-deg"); - model.getNode("load", 1).remove(); - return model; - }; - -# interpolates a value -var interpolate_table = func(table, v) - { - var x = 0; - forindex (i; table) - { - if (v >= table[i][0]) - { - x = i + 1 < size(table) ? (v - table[i][0]) / (table[i + 1][0] - table[i][0]) * (table[i + 1][1] - table[i][1]) + table[i][1] : table[i][1]; - } - } - return x; - }; -# gets a relative file path -var get_relative_filepath = func(path, target) - { - var newpath = ""; - for (var i = size(path) - 1; i >= 0; i -= 1) - { - var char = substr(path, i, 1); - if (char == "/") newpath ~= "../"; - } - # we can just append the target path for UNIX systems, but we need to remove the drive letter prefix for DOS systems - return newpath ~ (string.match(substr(target, 0, 3), "?:/") ? substr(target, 2, size(target) - 2) : target); - }; -# gets a list of nearest airports -# TODO: Don't use /sim/airport/nearest-airport-id, which restricts the list to 1 airport -var find_airports = func(max_distance) - { - var apt = getprop("/sim/airport/closest-airport-id"); - return apt == "" ? nil : [apt]; - }; - -## Global variables -################### - -var root = nil; -var home = nil; -var scenery = []; - -var UPDATE_PERIOD = 1 / 30; -var LOAD_PERIOD = 30; -var LOAD_DISTANCE = 50; # in nautical miles -var LOAD_JETWAY_PERIOD = 0.05; -var NUMBER_OF_JETWAYS = 2000; # approx max number of jetways loadable in FG -var runtime_files = NUMBER_OF_JETWAYS / LOAD_PERIOD * LOAD_JETWAY_PERIOD; -runtime_files = int(runtime_files) == runtime_files ? runtime_files : int(runtime_files) + 1; -var runtime_file = 0; -var update_loopid = -1; -var load_loopid = -1; -var load_listenerid = nil; -var loadids = {}; -var dialog_object = nil; -var loaded_airports = []; -var jetways = []; - -# properties -var on_switch = "/sim/jetways/enabled"; -var debug_switch = "/sim/jetways/debug"; -var mp_switch = "/sim/jetways/interact-with-multiplay"; -var jetway_id_prop = "/sim/jetways/last-loaded-jetway"; - -# interpolation tables -var extend_rate = 0.5; -var extend_table = [ - [0.0, 0.0], - [0.2, 0.3], - [0.6, 0.3], - [0.8, 1.0], - [1.0, 1.0] - ]; -var pitch_rate = 1; -var pitch_table = [ - [0.0, 0.0], - [0.4, 0.7], - [0.7, 1.0], - [1.0, 1.0] - ]; -var heading_rate = 1; -var heading_table = [ - [0.0, 0.0], - [0.2, 0.0], - [0.6, 0.7], - [0.9, 1.0], - [1.0, 1.0] - ]; -var heading_entrance_rate = 5; -var heading_entrance_table = [ - [0.0, 0.0], - [0.3, 0.0], - [0.6, 0.7], - [0.8, 1.0], - [1.0, 1.0] - ]; -var hood_rate = 1; -var hood_table = [ - [0.0, 0.0], - [0.9, 0.0], - [1.0, 1.0] - ]; - -## Classes -########## - -# main jetway class -var Jetway = - { - new: func(airport, model, gate, door, airline, lat, lon, elev, heading, init_extend = 0, init_heading = 0, init_pitch = 0, init_ent_heading = 0) - { - var id = 0; - for (var i = 0; 1; i += 1) - { - if (i == size(jetways)) - { - setsize(jetways, i + 1); - id = i; - break; - } - elsif (jetways[i] == nil) - { - id = i; - } - } - # locate the jetway model directory and load the model tree - var model_tree = nil; - var model_file = ""; - var model_dir = ""; - var airline_file = ""; - if (props.globals.getNode("/sim/paths/use-custom-scenery-data", 1).getBoolValue()) - { - # search in scenery directories - foreach (var scenery_path; scenery) - { - model_dir = scenery_path ~ "/Models/Airport/Jetway"; - model_file = model_dir ~ "/" ~ model ~ ".xml"; - print_debug("Trying to load a jetway model from " ~ model_file); - if (io.stat(model_file) == nil) continue; - model_tree = io.read_properties(model_file); - airline_file = get_relative_filepath(home ~ "/runtime-jetways", model_dir ~ "/Airlines/" ~ airline ~ ".png"); - if (io.stat(airline_file) == nil) airline_file = get_relative_filepath(home ~ "/runtime-jetways", model_dir ~ "/Airlines/None.png"); - break; - } - } - if (model_tree == nil) - { - model_dir = root ~ "/Models/Airport/Jetway"; - model_file = model_dir ~ "/" ~ model ~ ".xml"; - print_debug("Falling back to " ~ model_file); - if (io.stat(model_file) == nil) - { - print_error("Failed to load jetway model: " ~ model); - return; - } - model_tree = io.read_properties(model_file); - airline_file = get_relative_filepath(home ~ "/runtime-jetways", model_dir ~ "/Airlines/" ~ airline ~ ".png"); - if (io.stat(airline_file) == nil) airline_file = get_relative_filepath(home ~ "/runtime-jetways", model_dir ~ "/Airlines/None.png"); - } - - var m = - { - parents: [Jetway] - }; - m.airport = airport; - m.gate = gate; - m.airline = airline; - m.id = id; - m.model = model; - m.extended = 0; - m.door = door; - m.lat = lat; - m.lon = lon; - m.elev = elev; - m.heading = geo.normdeg(180 - heading); - m.init_extend = init_extend; - m.init_heading = init_heading; - m.init_pitch = init_pitch; - m.init_ent_heading = init_ent_heading; - m.target_extend = 0; - m.target_pitch = 0; - m.target_heading = 0; - m.target_ent_heading = 0; - m.target_hood = 0; - m.rotunda_x = model_tree.getNode("rotunda/x-m").getValue(); - m.rotunda_y = model_tree.getNode("rotunda/y-m").getValue(); - m.rotunda_z = model_tree.getNode("rotunda/z-m").getValue(); - m.offset_extend = model_tree.getNode("extend-offset-m").getValue(); - m.offset_entrance = model_tree.getNode("entrance-offset-m").getValue(); - m.min_extend = model_tree.getNode("min-extend-m").getValue(); - m.max_extend = model_tree.getNode("max-extend-m").getValue(); - - # get the runtime file path - if (runtime_file == runtime_files) - { - runtime_file = 0; - } - var runtime_file_path = home ~ "/runtime-jetways/" ~ runtime_file ~ ".xml"; - runtime_file += 1; - - # create the model node and the door object - m.node = putmodel(runtime_file_path, lat, lon, elev, geo.normdeg(360 - heading)); - var node_path = m.node.getPath(); - m.door_object = aircraft.door.new(node_path ~ "/jetway-position", 0); - - # manipulate the model tree - model_tree.getNode("path").setValue(model_dir ~ "/" ~ model_tree.getNode("path").getValue()); - model_tree.getNode("toggle-action-script").setValue("jetways.toggle_jetway(" ~ id ~ ");"); - model_tree.getNode("gate").setValue(m.gate); - model_tree.getNode("airline-code").setValue(airline_file); - model_tree.getNode("extend-m").setValue(props.globals.initNode(node_path ~ "/jetway-position/extend-m", 0, "DOUBLE").getPath()); - model_tree.getNode("pitch-deg").setValue(props.globals.initNode(node_path ~ "/jetway-position/pitch-deg", 0, "DOUBLE").getPath()); - model_tree.getNode("heading-deg").setValue(props.globals.initNode(node_path ~ "/jetway-position/heading-deg", 0, "DOUBLE").getPath()); - model_tree.getNode("entrance-heading-deg").setValue(props.globals.initNode(node_path ~ "/jetway-position/entrance-heading-deg", 0, "DOUBLE").getPath()); - model_tree.getNode("hood-deg").setValue(props.globals.initNode(node_path ~ "/jetway-position/hood-deg", 0, "DOUBLE").getPath()); - # write the model tree - io.write_properties(runtime_file_path, model_tree); - - jetways[id] = m; - print_debug("Loaded jetway #" ~ id); - jetway_id_prop.setValue(id); - return m; - }, - toggle: func(user, heading, coord, hood = 0) - { - if (me.extended) - { - me.retract(user, heading, coord); - } - else - { - me.extend(user, heading, coord, hood); - } - }, - extend: func(user, heading, door_coord, hood = 0) - { - me.extended = 1; - - # get the coordinates of the jetway and offset for the rotunda position - var jetway_coord = geo.Coord.new(); - jetway_coord.set_latlon(me.lat, me.lon); - jetway_coord.apply_course_distance(me.heading, me.rotunda_x); - jetway_coord.apply_course_distance(me.heading - 90, me.rotunda_y); - jetway_coord.set_alt(me.elev + me.rotunda_z); - - if (debug_switch.getBoolValue()) - { - # place UFO cursors at the calculated door and jetway positions for debugging purposes - geo.put_model("Aircraft/ufo/Models/cursor.ac", door_coord); - geo.put_model("Aircraft/ufo/Models/cursor.ac", jetway_coord); - } - - # offset the door for the length of the jetway entrance - door_coord.apply_course_distance(heading - 90, me.offset_entrance); - - # calculate the bearing to the aircraft and the distance from the door - me.target_heading = normdeg(jetway_coord.course_to(door_coord) - me.heading - me.init_heading); - me.target_extend = jetway_coord.distance_to(door_coord) - me.offset_extend - me.init_extend; - - # check if distance exceeds maximum jetway extension length - if (me.target_extend + me.init_extend > me.max_extend) - { - me.extended = 0; - me.target_extend = 0; - me.target_heading = 0; - if (user) alert("Your aircraft is too far from this jetway."); - print_debug("Jetway #" ~ me.id ~ " is too far from the door"); - return; - } - # check if distance fails to meet minimum jetway extension length - if (me.target_extend + me.init_extend < me.min_extend) - { - me.extended = 0; - me.target_extend = 0; - me.target_heading = 0; - if (user) alert("Your aircraft is too close to this jetway."); - print_debug("Jetway #" ~ me.id ~ " is too close to the door"); - return; - } - - # calculate the jetway pitch, entrance heading, and hood - me.target_pitch = math.atan2((door_coord.alt() - jetway_coord.alt()) / (me.target_extend + me.offset_extend + me.init_extend), 1) * R2D - me.init_pitch; - me.target_ent_heading = normdeg((heading + 90) - (me.heading + (me.target_heading + me.init_heading) + me.init_ent_heading)); - me.target_hood = user ? getprop("/sim/model/door[" ~ me.door ~ "]/jetway-hood-deg") : hood; - - # fire up the animation - if (user) alert("Extending jetway."); - var animation_time = math.abs(me.target_extend / extend_rate) + math.abs(me.target_pitch / pitch_rate) + math.abs(me.target_heading / heading_rate) + math.abs(me.target_ent_heading / heading_entrance_rate) + math.abs(me.target_hood / hood_rate); - me.door_object.swingtime = animation_time; - me.door_object.open(); - - print_debug("************************************************"); - print_debug("Activated jetway #" ~ me.id); - print_debug("Using door #" ~ me.door); - print_debug("Jetway heading: " ~ me.heading ~ " deg"); - print_debug("Extension: " ~ me.target_extend ~ " m"); - print_debug("Pitch: " ~ me.target_pitch ~ " deg"); - print_debug("Heading: " ~ me.target_heading ~ " deg"); - print_debug("Entrance heading: " ~ me.target_ent_heading ~ " deg"); - print_debug("Hood: " ~ me.target_hood ~ " deg"); - print_debug("Total animation time: " ~ animation_time ~ " sec"); - print_debug("Jetway extending"); - print_debug("************************************************"); - }, - retract: func(user) - { - if (user) alert("Retracting jetway."); - me.door_object.close(); - me.extended = 0; - - print_debug("************************************************"); - print_debug("Activated jetway #" ~ me.id); - print_debug("Total animation time: " ~ me.door_object.swingtime ~ " sec"); - print_debug("Jetway retracting"); - print_debug("************************************************"); - }, - remove: func - { - me.node.remove(); - var id = me.id; - jetways[me.id] = nil; - print_debug("Unloaded jetway #" ~ id); - }, - reload: func - { - var airport = me.airport; - var model = me.model; - var gate = me.gate; - var door = me.door; - var airline = me.airline; - var lat = me.lat; - var lon = me.lon; - var elev = me.elev; - var heading = geo.normdeg(180 - (me.heading - 360)); - var init_extend = me.init_extend; - var init_heading = me.init_heading; - var init_pitch = me.init_pitch; - var init_ent_heading = me.init_ent_heading; - me.remove(); - Jetway.new(airport, model, gate, door, airline, lat, lon, elev, heading, init_extend, init_heading, init_pitch, init_ent_heading); - }, - setpos: func(lat, lon, hdg, alt) - { - me.node.getNode("latitude-deg").setValue(lat); - me.lat = lat; - me.node.getNode("longitude-deg").setValue(lon); - me.lon = lon; - me.node.getNode("heading-deg").setValue(geo.normdeg(hdg - 180)); - me.heading = hdg; - me.node.getNode("elevation-ft").setValue(alt * M2FT); - me.elev = alt; - }, - setmodel: func(model, airline, gate) - { - me.airline = airline; - me.gate = gate; - me.model = model; - me.extended = 0; - me.target_extend = 0; - me.target_pitch = 0; - me.target_heading = 0; - me.target_ent_heading = 0; - me.target_hood = 0; - me.door_object.setpos(0); - me.reload(); - } - }; - -## Interaction functions -######################## - -var dialog = func - { - if (dialog_object == nil) dialog_object = gui.Dialog.new("/sim/gui/dialogs/jetways/dialog", "gui/dialogs/jetways.xml"); - dialog_object.open(); - }; - -var toggle_jetway = func(n) - { - var jetway = jetways[n]; - if (jetway == nil) return; - var door = props.globals.getNode("/sim/model/door[" ~ jetway.door ~ "]"); - if (door == nil) - { - alert("Your aircraft does not define the location of door " ~ (jetway.door + 1) ~ ", cannot extend this jetway."); - return; - } - - # get the coordinates of the user's aircraft and offset for the door position and aircraft pitch - var coord = geo.aircraft_position(); - var heading = getprop("/orientation/heading-deg"); - var pitch = getprop("/orientation/pitch-deg"); - coord.apply_course_distance(heading, -door.getChild("position-x-m").getValue()); - coord.apply_course_distance(heading + 90, door.getChild("position-y-m").getValue()); - coord.set_alt(coord.alt() + door.getChild("position-z-m").getValue()); - coord.set_alt(coord.alt() + math.tan(pitch * D2R) * -door.getChild("position-x-m").getValue()); - - jetway.toggle(1, heading, coord); - }; -var toggle_jetway_from_coord = func(door, hood, heading, lat, lon = nil) - { - if (isa(lat, geo.Coord)) - { - var coord = lat; - } - else - { - var coord = geo.Coord.new(); - coord.set_latlon(lat, lon); - } - var closest_jetway = nil; - var closest_jetway_dist = nil; - var closest_jetway_coord = nil; - for (var i = 0; i < size(jetways); i += 1) - { - if (jetways[i] == nil) continue; - var jetway = jetways[i]; - var jetway_coord = geo.Coord.new(); - jetway_coord.set_latlon(jetway.lat, jetway.lon); - - var distance = jetway_coord.distance_to(coord); - if ((closest_jetway_dist == nil or distance < closest_jetway_dist) and jetway.door == door) - { - closest_jetway = jetway; - closest_jetway_dist = distance; - closest_jetway_coord = jetway_coord; - } - } - if (closest_jetway == nil) - { - print_debug("No jetways available"); - } - elsif (!closest_jetway.extended) - { - closest_jetway.toggle(0, heading, coord, hood); - } - }; -var toggle_jetway_from_model = func(model) - { - model = aircraft.makeNode(model); - var doors = model.getChildren("door"); - if (doors == nil or size(doors) == 0) return; - for (var i = 0; i < size(doors); i += 1) - { - var coord = geo.Coord.new(); - var hdg = model.getNode("orientation/true-heading-deg").getValue(); - var lat = model.getNode("position/latitude-deg").getValue(); - var lon = model.getNode("position/longitude-deg").getValue(); - var alt = model.getNode("position/altitude-ft").getValue() * FT2M + doors[i].getNode("position-z-m").getValue(); - coord.set_latlon(lat, lon, alt); - coord.apply_course_distance(hdg, -doors[i].getNode("position-x-m").getValue()); - coord.apply_course_distance(hdg + 90, doors[i].getNode("position-y-m").getValue()); - print_debug("Connecting a jetway to door #" ~ i ~ " for model " ~ model.getPath()); - toggle_jetway_from_coord(i, doors[i].getNode("jetway-hood-deg").getValue(), hdg, coord); - } - }; - -## Internal functions -##################### - -# loads jetways at an airport -var load_airport_jetways = func(airport) - { - if (isin(loaded_airports, airport)) return; - var tree = props.globals.getNode("/sim/paths/use-custom-scenery-data", 1).getBoolValue() ? io.read_airport_properties(airport, "jetways") : (io.stat(root ~ "/AI/Airports/" ~ airport ~ "/jetways.xml") == nil ? nil : io.read_properties(root ~ "/AI/Airports/" ~ airport ~ "/jetways.xml")); - if (tree == nil) return; - print_debug("Loading jetways for airport " ~ airport); - var nodes = tree.getChildren("jetway"); - - loadids[airport] = loadids[airport] == nil ? 0 : loadids[airport] + 1; - var i = 0; - var loop = func(id) - { - if (id != loadids[airport]) return; - if (i >= size(nodes)) - { - append(loaded_airports, airport); - return; - } - var jetway = nodes[i]; - var model = jetway.getNode("model", 1).getValue() or return; - var gate = jetway.getNode("gate", 1).getValue() or ""; - var door = jetway.getNode("door", 1).getValue() or 0; - var airline = jetway.getNode("airline", 1).getValue() or "None"; - var lat = jetway.getNode("latitude-deg", 1).getValue() or return; - var lon = jetway.getNode("longitude-deg", 1).getValue() or return; - var elev = jetway.getNode("elevation-m", 1).getValue() or 0; - var heading = jetway.getNode("heading-deg", 1).getValue() or 0; - var init_extend = jetway.getNode("initial-position/jetway-extension-m", 1).getValue() or 0; - var init_heading = jetway.getNode("initial-position/jetway-heading-deg", 1).getValue() or 0; - var init_pitch = jetway.getNode("initial-position/jetway-pitch-deg", 1).getValue() or 0; - var init_ent_heading = jetway.getNode("initial-position/entrance-heading-deg", 1).getValue() or 0; - Jetway.new(airport, model, gate, door, airline, lat, lon, elev, heading, init_extend, init_heading, init_pitch, init_ent_heading); - - i += 1; - settimer(func loop(id), LOAD_JETWAY_PERIOD); - }; - settimer(func loop(loadids[airport]), 0); - }; -# unloads jetways at an airport -var unload_airport_jetways = func(airport) - { - print_debug("Unloading jetways for airport " ~ airport); - foreach (var jetway; jetways) - { - if (jetway != nil and jetway.airport == airport) jetway.remove(); - } - remove(loaded_airports, airport); - }; - -# restarts the main update loop -var restart = func(node) - { - if (!node.getBoolValue()) return; - update_loopid += 1; - update_jetways(update_loopid); - settimer(func - { - load_loopid += 1; - load_jetways(load_loopid); - }, 2); - print("Animated jetways ... initialized"); - }; -# main update loop (runs when jetways are enabled) -var update_jetways = func(loopid) - { - # terminate if loopid does not match - if (loopid != update_loopid) return; - # if jetways disabled, unload jetways and terminate - if (!on_switch.getBoolValue()) - { - for (var i = 0; i < size(jetways); i += 1) - { - if (jetways[i] != nil) jetways[i].remove(); - } - setsize(jetways, 0); - setsize(loaded_airports, 0); - return; - } - - var nearest_airport = airportinfo(); - nearest_airport = nearest_airport == nil ? nil : nearest_airport.id; - if (isin(loaded_airports, nearest_airport)) - { - # loop through the AI aircraft and extend/retract jetways - var ai_aircraft = props.globals.getNode("ai/models").getChildren("aircraft"); - foreach (var aircraft; ai_aircraft) - { - if (!aircraft.getNode("valid", 1).getBoolValue()) continue; - var connected = aircraft.getNode("connected-to-jetways", 1); - var velocity = aircraft.getNode("velocities/true-airspeed-kt").getValue(); - # TODO: Find a better way to know when the aircraft is "parked" - if (velocity > -1 and velocity < 1) - { - if (!connected.getBoolValue()) toggle_jetway_from_model(aircraft); - connected.setBoolValue(1); - } - else - { - if (connected.getBoolValue()) toggle_jetway_from_model(aircraft); - connected.setBoolValue(0); - } - } - # loop through the multiplayer aircraft and extend/retract jetways - # TODO: In the future, broadcast jetway properties over MP, making this part obselete - if (mp_switch.getBoolValue()) - { - var multiplayers = props.globals.getNode("ai/models").getChildren("multiplayer"); - foreach (var aircraft; multiplayers) - { - if (!aircraft.getNode("valid", 1).getBoolValue()) continue; - var connected = aircraft.getNode("connected-to-jetways", 1); - var velocity = aircraft.getNode("velocities/true-airspeed-kt").getValue(); - if (velocity > -1 and velocity < 1) - { - if (!connected.getBoolValue()) toggle_jetway_from_model(aircraft); - connected.setBoolValue(1); - } - else - { - if (connected.getBoolValue()) toggle_jetway_from_model(aircraft); - connected.setBoolValue(0); - } - } - } - } - # interpolate jetway values - for (var i = 0; i < size(jetways); i += 1) - { - if (jetways[i] == nil) continue; - var jetway = jetways[i]; - var position = jetway.door_object.getpos(); - jetway.node.getNode("jetway-position/extend-m").setValue(interpolate_table(extend_table, position) * jetway.target_extend + jetway.init_extend); - jetway.node.getNode("jetway-position/pitch-deg").setValue(interpolate_table(pitch_table, position) * jetway.target_pitch + jetway.init_pitch); - jetway.node.getNode("jetway-position/heading-deg").setValue(interpolate_table(heading_table, position) * jetway.target_heading + jetway.init_heading); - jetway.node.getNode("jetway-position/entrance-heading-deg").setValue(interpolate_table(heading_entrance_table, position) * jetway.target_ent_heading + jetway.init_ent_heading); - jetway.node.getNode("jetway-position/hood-deg").setValue(interpolate_table(hood_table, position) * jetway.target_hood); - } - settimer(func update_jetways(loopid), UPDATE_PERIOD); - }; -# loading/unloading loop (runs continuously) -var load_jetways = func(loopid) - { - if (load_listenerid != nil) removelistener(load_listenerid); - # terminate if loopid does not match - # unloading jetways if jetways are disabled is handled by update loop - if (loopid != load_loopid or !on_switch.getBoolValue()) return; - var airports = find_airports(LOAD_DISTANCE); - if (airports == nil) return; - # search for any airports out of range and unload their jetways - foreach (var airport; loaded_airports) - { - if (!isin(airports, airport)) - { - unload_airport_jetways(airport); - } - } - # load any airports in range - foreach (var airport; airports) - { - load_airport_jetways(airport); - } - settimer(func load_jetways(loopid), LOAD_PERIOD); - }; -## fire it up -_setlistener("/sim/signals/fdm-initialized", func - { - # global variables - root = string.normpath(getprop("/sim/fg-root")); - home = string.normpath(getprop("/sim/fg-home")); - foreach (var scenery_path; props.globals.getNode("/sim").getChildren("fg-scenery")) - { - append(scenery, string.normpath(scenery_path.getValue())); - } - if (size(scenery) == 0) append(scenery, root ~ "/Scenery"); - - # properties - on_switch = props.globals.getNode(on_switch, 1); - debug_switch = props.globals.getNode(debug_switch, 1); - mp_switch = props.globals.getNode(mp_switch, 1); - - jetway_id_prop = props.globals.getNode(jetway_id_prop, 1); - setlistener(on_switch, restart, 1, 0); - }); diff --git a/Nasal/jetways_edit.nas b/Nasal/jetways_edit.nas deleted file mode 100644 index 1b16925c7..000000000 --- a/Nasal/jetways_edit.nas +++ /dev/null @@ -1,593 +0,0 @@ -############################################################################### -## -## Animated Jetway System. Allows the user to edit jetways during runtime. -## -## Copyright (C) 2011 Ryan Miller -## This file is licensed under the GPL license version 2 or later. -## -############################################################################### - -############################################################################### -# (See http://wiki.flightgear.org/Howto:_Animated_jetways) -# - -### Static jetway model profiles ### -### This class specifies the offsets used when converting static jetways using the STG converter ### -var Static_jetway = - [ - # Models/Airport/jetway-movable.ac - # Models/Airport/jetway-movable.xml - # Models/Airport/jetway-movable-2.ac - # Models/Airport/jetway-movable-2.xml - # Models/Airport/jetway-movable-3.ac - # Models/Airport/jetway-movable-3.xml - { - models: - [ - "Models/Airport/jetway-movable.ac", - "Models/Airport/jetway-movable.xml", - "Models/Airport/jetway-movable-2.ac", - "Models/Airport/jetway-movable-2.xml", - "Models/Airport/jetway-movable-3.ac", - "Models/Airport/jetway-movable-3.xml" - ], - offsets: - { - x: -2.042, - y: 0, - z: 0, - heading: 0 - }, - init_pos: - { - extend: 7.24, - heading: 0, - pitch: 0, - ent_heading: -90 - }, - model: "generic", - airline: "None" - }, - # Models/Airport/jetway.xml - # Models/Airport/jetway-ba.ac - # Models/Airport/jetway-ba.xml - { - models: - [ - "Models/Airport/jetway.xml", - "Models/Airport/jetway-ba.ac", - "Models/Airport/jetway-ba.xml" - ], - offsets: - { - x: 0, - y: 0, - z: -0.25, - heading: 0 - }, - init_pos: - { - extend: 7.24, - heading: -6.7, - pitch: -3.6, - ent_heading: -83.3 - }, - model: "generic", - airline: "None" - }, - # Models/Airport/jetway-737-ba.ac - # Models/Airport/jetway-737-ba.xml - { - models: - [ - "Models/Airport/jetway-737-ba.ac", - "Models/Airport/jetway-737-ba.xml" - ], - offsets: - { - x: 0, - y: 0, - z: -0.25, - heading: 0 - }, - init_pos: - { - extend: 7.24, - heading: -6.7, - pitch: -4, - ent_heading: -83.3 - }, - model: "generic", - airline: "None" - }, - # Models/Airport/jetway-747-ba.ac - # Models/Airport/jetway-747-ba.xml - { - models: - [ - "Models/Airport/jetway-747-ba.ac", - "Models/Airport/jetway-747-ba.xml" - ], - offsets: - { - x: 0, - y: 0, - z: -0.25, - heading: 0 - }, - init_pos: - { - extend: 7.24, - heading: -6.7, - pitch: 2, - ent_heading: -83.3 - }, - model: "generic", - airline: "None" - }, - # Models/Airport/jetway-a320-ba.ac - # Models/Airport/jetway-a320-ba.xml - { - models: - [ - "Models/Airport/jetway-a320-ba.ac", - "Models/Airport/jetway-a320-ba.xml" - ], - offsets: - { - x: 0, - y: 0, - z: -0.25, - heading: 0 - }, - init_pos: - { - extend: 7.24, - heading: -6.7, - pitch: -1.6, - ent_heading: -83.3 - }, - model: "generic", - airline: "None" - }, - # Models/Airport/AutoGate-ba.ac - # Models/Airport/AutoGate.xml - { - models: - [ - "Models/Airport/AutoGate-ba.ac", - "Models/Airport/AutoGate.xml" - ], - offsets: - { - x: -10, - y: 25, - z: 0, - heading: -90 - }, - init_pos: - { - extend: 7.68, - heading: 0, - pitch: 0, - ent_heading: -90 - }, - model: "generic", - airline: "None" - }, - # Models/Airport/DockingGate-ba.ac - # Models/Airport/DockingGate.xml - { - models: - [ - "Models/Airport/DockingGate-ba.ac", - "Models/Airport/DockingGate.xml" - ], - offsets: - { - x: -10, - y: 5, - z: 0, - heading: -90 - }, - init_pos: - { - extend: 7.68, - heading: 0, - pitch: 0, - ent_heading: -90 - }, - model: "generic", - airline: "None" - } - ]; - -### Rest of script follows below ### -### Watch your step! :) ### -var dialog_object = nil; -var selected_jetway = nil; -var mouse_mmb = 0; -var kbd_shift = nil; -var kbd_ctrl = nil; -var kbd_alt = nil; -var enabled = nil; -var FLASH_PERIOD = 0.3; -var FLASH_NUM = 3; -var filedialog_listener = 0; - -var click = func(pos) - { - if (kbd_alt.getBoolValue()) - { - if (selected_jetway == nil) return; - selected_jetway.setpos(pos.lat(), pos.lon(), selected_jetway.heading, pos.alt()); - } - elsif (kbd_shift.getBoolValue()) - { - selected_jetway = nil; - } - elsif (kbd_ctrl.getBoolValue()) - { - var nearest_jetway = nil; - var min_dist = geo.ERAD; - for (var i = 0; i < size(jetways.jetways); i += 1) - { - var jetway = jetways.jetways[i]; - if (jetway == nil) continue; - var dist = geo.Coord.new().set_latlon(jetway.lat, jetway.lon, jetway.elev).direct_distance_to(pos); - if (dist < min_dist) - { - min_dist = dist; - nearest_jetway = jetway; - } - } - if (nearest_jetway != nil) - { - selected_jetway = nearest_jetway; - setprop("/sim/jetways/adjust/model", selected_jetway.model); - setprop("/sim/jetways/adjust/door", selected_jetway.door); - setprop("/sim/jetways/adjust/airline", selected_jetway.airline); - setprop("/sim/jetways/adjust/gate", selected_jetway.gate); - flash(nearest_jetway); - } - } - else - { - var airport = getprop("/sim/airport/closest-airport-id"); - if (airport == "") return; - selected_jetway = jetways.Jetway.new(airport, "generic", "FG", 0, "FGFS", pos.lat(), pos.lon(), pos.alt(), 0); - if (!jetways.isin(jetways.loaded_airports, airport)) append(jetways.loaded_airports, airport); - setprop("/sim/jetways/adjust/model", selected_jetway.model); - setprop("/sim/jetways/adjust/door", selected_jetway.door); - setprop("/sim/jetways/adjust/airline", selected_jetway.airline); - setprop("/sim/jetways/adjust/gate", selected_jetway.gate); - flash(selected_jetway); - } - }; -var delete = func - { - if (selected_jetway == nil) return; - selected_jetway.remove(); - selected_jetway = nil; - }; -var adjust = func(name, value) - { - if (selected_jetway == nil) return; - if (name == "longitudinal") - { - var jetway_pos = geo.Coord.new(); - jetway_pos.set_latlon(selected_jetway.lat, selected_jetway.lon, selected_jetway.elev); - var dir = geo.aircraft_position().course_to(jetway_pos); - jetway_pos.apply_course_distance(dir, value); - selected_jetway.setpos(jetway_pos.lat(), jetway_pos.lon(), selected_jetway.heading, selected_jetway.elev); - } - elsif (name == "transversal") - { - var jetway_pos = geo.Coord.new(); - jetway_pos.set_latlon(selected_jetway.lat, selected_jetway.lon, selected_jetway.elev); - var dir = geo.aircraft_position().course_to(jetway_pos) + 90; - jetway_pos.apply_course_distance(dir, value); - selected_jetway.setpos(jetway_pos.lat(), jetway_pos.lon(), selected_jetway.heading, selected_jetway.elev); - } - elsif (name == "altitude") - { - var elev = selected_jetway.elev + value * 0.4; - selected_jetway.setpos(selected_jetway.lat, selected_jetway.lon, selected_jetway.heading, elev); - } - elsif (name == "heading") - { - var hdg = geo.normdeg(selected_jetway.heading + value * 4); - selected_jetway.setpos(selected_jetway.lat, selected_jetway.lon, hdg, selected_jetway.elev); - } - elsif (name == "initial-extension") - { - var newvalue = selected_jetway.init_extend + value; - if (newvalue > selected_jetway.max_extend) - { - gui.popupTip("Value exceeds maximum jetway extension limit"); - } - elsif (newvalue < selected_jetway.min_extend) - { - gui.popupTip("Value lower than minimum jetway extension limit"); - } - else - { - selected_jetway.init_extend = newvalue; - } - } - elsif (name == "initial-pitch") - { - selected_jetway.init_pitch += value; - } - elsif (name == "initial-heading") - { - selected_jetway.init_heading += value; - } - elsif (name == "initial-entrance-heading") - { - selected_jetway.init_ent_heading += value; - } - elsif (name == "model") - { - selected_jetway.setmodel(value, selected_jetway.airline, selected_jetway.gate); - selected_jetway = jetways.jetways[getprop("/sim/jetways/last-loaded-jetway")]; - } - elsif (name == "door") - { - selected_jetway.door = value; - } - elsif (name == "airline") - { - selected_jetway.setmodel(selected_jetway.model, value, selected_jetway.gate); - selected_jetway = jetways.jetways[getprop("/sim/jetways/last-loaded-jetway")]; - } - elsif (name == "gate") - { - selected_jetway.setmodel(selected_jetway.model, selected_jetway.airline, value); - selected_jetway = jetways.jetways[getprop("/sim/jetways/last-loaded-jetway")]; - } - }; -var export = func - { - var path = getprop("/sim/fg-home") ~ "/Export/"; - var airports = {}; - var airportarray = []; - foreach (var jetway; jetways.jetways) - { - if (jetway == nil) continue; - if (airports[jetway.airport] == nil) - { - airports[jetway.airport] = []; - append(airportarray, jetway.airport); - } - var node = props.Node.new(); - node.getNode("model", 1).setValue(jetway.model); - node.getNode("gate", 1).setValue(jetway.gate); - node.getNode("door", 1).setIntValue(jetway.door); - node.getNode("airline", 1).setValue(jetway.airline); - node.getNode("latitude-deg", 1).setDoubleValue(jetway.lat); - node.getNode("longitude-deg", 1).setDoubleValue(jetway.lon); - node.getNode("elevation-m", 1).setDoubleValue(jetway.elev); - node.getNode("heading-deg", 1).setDoubleValue(geo.normdeg(180 - jetway.heading)); - node.getNode("initial-position/jetway-extension-m", 1).setDoubleValue(jetway.init_extend); - node.getNode("initial-position/jetway-heading-deg", 1).setDoubleValue(jetway.init_heading); - node.getNode("initial-position/jetway-pitch-deg", 1).setDoubleValue(jetway.init_pitch); - node.getNode("initial-position/entrance-heading-deg", 1).setDoubleValue(jetway.init_ent_heading); - append(airports[jetway.airport], node); - } - foreach (var airport; airportarray) - { - var file = path ~ airport ~ ".xml"; - var args = props.Node.new({ filename: file }); - var nodes = airports[airport]; - foreach (var node; nodes) - { - var data = args.getNode("data", 1); - for (var i = 0; 1; i += 1) - { - if (data.getChild("jetway", i, 0) == nil) - { - props.copy(node, data.getChild("jetway", i, 1)); - break; - } - } - } - fgcommand("savexml", args); - print("jetway definitions for airport " ~ airport ~ " exported to " ~ file); - } - }; -var convert_stg = func - { - fgcommand("dialog-show", props.Node.new({ "dialog-name": "file-select" })); - setprop("/sim/gui/dialogs/file-select/path", ""); - filedialog_listener = setlistener("/sim/gui/dialogs/file-select/path", func(n) - { - removelistener(filedialog_listener); - var path = n.getValue(); - if (path == "") return; - var stg = io.readfile(path); - var stg_lines = [[]]; - var current_word = ""; - for (var i = 0; i < size(stg); i += 1) - { - var char = substr(stg, i, 1); - if (char == " " or char == "\n") - { - append(stg_lines[size(stg_lines) - 1], current_word); - current_word = ""; - if (char == "\n") append(stg_lines, []); - } - else - { - current_word ~= char; - } - } - - var jetway_array = []; - foreach (var line; stg_lines) - { - if (size(line) < 6 or line[0] != "OBJECT_SHARED") continue; - var foundmodel = 0; - var jetway = nil; - foreach (var profile; Static_jetway) - { - foreach (var model; profile.models) - { - if (model == line[1]) foundmodel = 1; - } - if (foundmodel) - { - jetway = profile; - break; - } - } - if (jetway == nil) continue; - var heading = num(line[5]); - var coord = geo.Coord.new(); - coord.set_latlon(line[3], line[2], line[4]); - coord.apply_course_distance(360 - heading, -jetway.offsets.x); - coord.apply_course_distance(360 - heading + 90, jetway.offsets.y); - coord.set_alt(coord.alt() + jetway.offsets.z); - var hash = {}; - hash.coord = coord; - hash.heading = heading + jetway.offsets.heading; - hash.init_extend = jetway.init_pos.extend; - hash.init_heading = jetway.init_pos.heading; - hash.init_pitch = jetway.init_pos.pitch; - hash.init_ent_heading = jetway.init_pos.ent_heading; - hash.model = jetway.model; - hash.airline = jetway.airline; - append(jetway_array, hash); - } - - var airport = getprop("/sim/jetways/closest-airport-id"); - if (airport == "") return; - var i = 0; - var loop = func - { - if (i >= size(jetway_array)) return; - var jetway = jetway_array[i]; - jetways.Jetway.new(airport, jetway.model, "", 0, jetway.airline, jetway.coord.lat(), jetway.coord.lon(), jetway.coord.alt(), jetway.heading, jetway.init_extend, jetway.init_heading, jetway.init_pitch, jetway.init_ent_heading); - if (!jetways.isin(jetways.loaded_airports, airport)) append(jetways.loaded_airports, airport); - i += 1; - settimer(loop, jetways.LOAD_JETWAY_PERIOD); - }; - settimer(loop, 0); - jetways.alert("Creating " ~ size(jetway_array) ~ " jetways for airport " ~ airport); - }, 0, 1); - }; -var flash = func(jetway) - { - if (!contains(jetway, "_flashnum") or jetway._flashnum == -1) - { - jetway._elev = jetway.elev; - jetway.setpos(jetway.lat, jetway.lon, jetway.heading, -geo.ERAD); - jetway._flashnum = 0; - settimer(func flash(jetway), FLASH_PERIOD); - } - elsif (!contains(jetway, "_elev")) - { - jetway._flashnum = -1; - jetway.setpos(jetway.lat, jetway.lon, geo.elevation(jetway.lat, jetway.lon)); - return; - } - elsif (jetway._flashnum == FLASH_NUM + 1) - { - jetway.setpos(jetway.lat, jetway.lon, jetway.heading, jetway._elev); - jetway._elev = nil; - jetway._flashnum = -1; - } - else - { - if (jetway.elev == -geo.ERAD) - { - jetway.setpos(jetway.lat, jetway.lon, jetway.heading, jetway._elev); - } - else - { - jetway.setpos(jetway.lat, jetway.lon, jetway.heading, -geo.ERAD); - } - jetway._flashnum += 1; - settimer(func flash(jetway), FLASH_PERIOD); - } - }; - -var dialog = func - { - if (dialog_object == nil) dialog_object = gui.Dialog.new("/sim/gui/dialogs/jetways-adjust/dialog", "gui/dialogs/jetways-adjust.xml"); - dialog_object.open(); - }; -var print_help = func - { - print("JETWAY EDITOR HELP"); - print("*******************************************************"); - print("See: http://wiki.flightgear.org/Howto:_Animated_jetways"); - print(""); - print("Adjust position, heading, and altitude with top sliders"); - print("Adjust initial jetway positions with bottom sliders"); - print(""); - print(" model of selected jetway"); - print(" aircraft door number of selected jetway"); - print(" airline sign code of selected jetway"); - print(" gate number of selected jetway"); - print(""); - print("[Center sliders] apply slider offsets and return sliders to 0"); - print("[Export] export jetway definition file(s)"); - print("[STG converter] convert static jetways in STG files to animated jetways"); - print("[?] show this help text"); - print(""); - print("Click add jetway on click position"); - print("Alt-click move selected jetway to click position"); - print("Ctrl-click select a jetway near click position"); - print("Shift-click deselect selected jetway"); - print("Backspace delete selected jetway"); - print("*******************************************************"); - }; - -_setlistener("/sim/signals/nasal-dir-initialized", func - { - kbd_shift = props.globals.getNode("/devices/status/keyboard/shift"); - kbd_ctrl = props.globals.getNode("/devices/status/keyboard/ctrl"); - kbd_alt = props.globals.getNode("/devices/status/keyboard/alt"); - enabled = props.globals.getNode("/sim/jetways/enable-editor"); - - setlistener("/sim/jetways/adjust/model", func(n) - { - var v = n.getValue(); - if (selected_jetway != nil and v != selected_jetway.model) - { - adjust("model", v); - } - }, 0, 0); - setlistener("/sim/jetways/adjust/door", func(n) - { - var v = n.getValue(); - if (selected_jetway != nil and v != selected_jetway.door) - { - adjust("door", v); - } - }, 0, 0); - setlistener("/sim/jetways/adjust/airline", func(n) - { - var v = n.getValue(); - if (selected_jetway != nil and v != selected_jetway.airline) - { - adjust("airline", v); - } - }, 0, 0); - setlistener("/sim/jetways/adjust/gate", func(n) - { - var v = n.getValue(); - if (selected_jetway != nil and v != selected_jetway.gate) - { - adjust("gate", v); - } - }, 0, 0); - setlistener("/devices/status/keyboard/event", func(event) - { - if (!event.getNode("pressed").getValue()) return; - if (enabled.getBoolValue() and event.getNode("key").getValue() == 8) delete(); - }); - setlistener("/devices/status/mice/mouse/button[1]", func(n) mouse_mmb = n.getBoolValue(), 1, 0); - setlistener("/sim/signals/click", func if (!mouse_mmb and enabled.getBoolValue()) click(geo.click_position())); - }); diff --git a/Nasal/tutorial.nas b/Nasal/tutorial/tutorial.nas similarity index 96% rename from Nasal/tutorial.nas rename to Nasal/tutorial/tutorial.nas index d72602671..67aceb08a 100644 --- a/Nasal/tutorial.nas +++ b/Nasal/tutorial/tutorial.nas @@ -15,7 +15,6 @@ var step_start_time = nil; var step_iter_count = 0; # number or step loop iterations var last_step_time = nil; # for set_targets() eta calculation var audio_dir = nil; -var do_welcome = 1; # property nodes (to be initialized with listener) var markerN = nil; @@ -26,7 +25,7 @@ var last_messageN = nil; var step_countN = nil; var step_timeN = nil; -_setlistener("/sim/signals/nasal-dir-initialized", func { +_setlistener("/nasal/tutorial/loaded", func { markerN = props.globals.getNode("/sim/model/marker", 1); headingN = props.globals.getNode("/orientation/heading-deg", 1); slipN = props.globals.getNode("/orientation/side-slip-deg", 1); @@ -37,14 +36,6 @@ _setlistener("/sim/signals/nasal-dir-initialized", func { setlistener("/sim/crashed", stopTutorial); }); -_setlistener("/sim/signals/fdm-initialized", func { - var haveTutorials = size(props.globals.getNode("/sim/tutorials", 1).getChildren("tutorial")); - gui.menuEnable("tutorial-start", haveTutorials); - if (do_welcome and haveTutorials) - settimer(func { setprop("/sim/messages/copilot", "Welcome aboard! Need help? Use 'Help -> Tutorials'.");}, 5.0); - do_welcome = 0; -}); - var startTutorial = func { var name = getprop("/sim/tutorials/current-tutorial"); if (name == nil) { diff --git a/gui/dialogs/tutorial.xml b/gui/dialogs/tutorial.xml index b95154682..358a01903 100644 --- a/gui/dialogs/tutorial.xml +++ b/gui/dialogs/tutorial.xml @@ -131,7 +131,10 @@ true nasal - + dialog-close diff --git a/preferences.xml b/preferences.xml index cc5f58aa9..610776ce8 100644 --- a/preferences.xml +++ b/preferences.xml @@ -1189,43 +1189,49 @@ Started September 2000 by David Megginson, david@megginson.com - false + false 1000 fg_log.csv , - false + false Longitude /position/longitude-deg - false + false Latitude /position/latitude-deg - false + false Altitude /position/altitude-ft - false + false Roll /orientation/roll-deg - false + false Pitch /orientation/pitch-deg - false + false Heading /orientation/heading-deg + + + false + + +