factor the MP aircraft monitoring code out of the dialog class and let
the dialog use it. Other services need the same functionality and it should only be done once.
This commit is contained in:
parent
c795f30862
commit
65e4b71406
1 changed files with 125 additions and 97 deletions
|
@ -160,49 +160,42 @@ var handle_key = func(key)
|
|||
#
|
||||
# multiplayer.dialog.show() -- displays the dialog and starts the update loop
|
||||
|
||||
var PILOTSDLG_RUNNING=0;
|
||||
var METER_TO_NM = 0.0005399568034557235;
|
||||
var PILOTSDLG_RUNNING = 0;
|
||||
|
||||
var dialog = {
|
||||
init : func(x = nil, y = nil) {
|
||||
init: func(x = nil, y = nil) {
|
||||
me.x = x;
|
||||
me.y = y;
|
||||
me.bg = [0, 0, 0, 0.3]; # background color
|
||||
me.fg = [[0.9, 0.9, 0.2, 1], [1.0, 1.0, 1.0, 1.0]]; # alternating foreground colors
|
||||
me.unit=1;
|
||||
me.unit = 1;
|
||||
me.toggle_unit(); # set to imperial
|
||||
#
|
||||
# "private"
|
||||
var font = { name: "FIXED_8x13" };
|
||||
me.header = [" callsign", "model", "brg", func { dialog.dist_hdr }, func { dialog.alt_hdr ~ " " }];
|
||||
me.columns = [
|
||||
{property:"callsign", format:" %s", label: "-----------", halign:"fill" },
|
||||
{property:"model-short", format:"%s", label: "--------------",halign:"fill" },
|
||||
{property:"bearing-to", format:" %3.0f",label: "----", halign: "right",font:{name:"FIXED_8x13"}},
|
||||
{property:func {dialog.dist_node}, format:" %8.2f",label: "---------",halign: "right",font:{name:"FIXED_8x13"}},
|
||||
{property:func {dialog.alt_node}, format:" %7.0f",label: "---------",halign: "right",font:{name:"FIXED_8x13"}}
|
||||
{property:"bearing-to", format:" %3.0f",label: "----", halign: "right", font: font },
|
||||
{property:func {dialog.dist_node}, format:" %8.2f",label: "---------",halign: "right", font: font },
|
||||
{property:func {dialog.alt_node}, format:" %7.0f",label: "---------",halign: "right", font: font }
|
||||
];
|
||||
me.name = "who-is-online";
|
||||
me.namenode = props.Node.new({"dialog-name" : me.name });
|
||||
me.dialog = nil;
|
||||
me.mp = props.globals.getNode("/ai/models");
|
||||
|
||||
me.listeners=[];
|
||||
append(me.listeners, setlistener("/sim/startup/xsize", func { me._redraw_() }));
|
||||
append(me.listeners, setlistener("/sim/startup/ysize", func { me._redraw_() }));
|
||||
append(me.listeners, setlistener("/ai/models/model-added", func(n) { me._multiplayer_update_(n) }));
|
||||
append(me.listeners, setlistener("/ai/models/model-removed", func(n) { me._multiplayer_update_(n) }));
|
||||
append(me.listeners, setlistener("/sim/startup/xsize", func me._redraw_()));
|
||||
append(me.listeners, setlistener("/sim/startup/ysize", func me._redraw_()));
|
||||
append(me.listeners, setlistener("/sim/signals/multiplayer-updated", func me.update()));
|
||||
},
|
||||
getloc : func (p) {
|
||||
var ploc = geo.Coord.new();
|
||||
ploc.set_xyz(p.getNode("global-x").getValue(), p.getNode("global-y").getValue(), p.getNode("global-z").getValue());
|
||||
return ploc;
|
||||
},
|
||||
create : func {
|
||||
create: func {
|
||||
if (me.dialog != nil)
|
||||
me.close();
|
||||
|
||||
me.dialog = gui.Widget.new();
|
||||
me.dialog.set("name", me.name);
|
||||
me.dialog.set("dialog-name", me.name);
|
||||
if (me.x != nil)
|
||||
me.dialog.set("x", me.x);
|
||||
if (me.y != nil)
|
||||
|
@ -213,7 +206,7 @@ var dialog = {
|
|||
|
||||
me.dialog.setColor(me.bg[0], me.bg[1], me.bg[2], me.bg[3]);
|
||||
|
||||
var titlebar=me.dialog.addChild("group");
|
||||
var titlebar = me.dialog.addChild("group");
|
||||
titlebar.set("layout", "hbox");
|
||||
|
||||
var w = titlebar.addChild("button");
|
||||
|
@ -223,8 +216,8 @@ var dialog = {
|
|||
titlebar.addChild("empty").set("stretch", 1);
|
||||
titlebar.addChild("text").set("label", "Pilots: ");
|
||||
|
||||
var p=titlebar.addChild("text");
|
||||
p.node.setValues({label: "---", live: 1, format: "%d", property: me.mp.getPath() ~ "/players"});
|
||||
var p = titlebar.addChild("text");
|
||||
p.node.setValues({label: "---", live: 1, format: "%d", property: "ai/models/num-players"});
|
||||
titlebar.addChild("empty").set("stretch", 1);
|
||||
|
||||
var w = titlebar.addChild("button");
|
||||
|
@ -233,95 +226,67 @@ var dialog = {
|
|||
|
||||
me.dialog.addChild("hrule");
|
||||
|
||||
var content=me.dialog.addChild("group");
|
||||
var content = me.dialog.addChild("group");
|
||||
content.set("layout", "table");
|
||||
content.set("default-padding", 0);
|
||||
|
||||
var row=0;
|
||||
var col=0;
|
||||
var row = 0;
|
||||
var col = 0;
|
||||
foreach (var h; me.header) {
|
||||
var w = content.addChild("text");
|
||||
var l = typeof(h) == "func" ? h() : h;
|
||||
w.node.setValues({"label":l, "row":row, "col":col, halign:me.columns[col].halign});
|
||||
w=content.addChild("hrule");
|
||||
w.node.setValues({"row":row+1,"col":col});
|
||||
col+=1;
|
||||
w.node.setValues({ "label": l, "row": row, "col": col, halign: me.columns[col].halign });
|
||||
w = content.addChild("hrule");
|
||||
w.node.setValues({ "row": row + 1,"col": col });
|
||||
col += 1;
|
||||
}
|
||||
row+=2;
|
||||
var children = me.mp.getChildren("multiplayer");
|
||||
var mp_vec=[];
|
||||
foreach(var c; children) {
|
||||
if(c.getNode("callsign") != nil and c.getNode("valid").getValue()) {
|
||||
append(mp_vec, { callsign:string.lc(c.getNode("callsign").getValue()), index:c.getIndex()});
|
||||
}
|
||||
}
|
||||
var sorted=sort(mp_vec, func(a,b) { return cmp(a.callsign,b.callsign) });
|
||||
foreach(var s; sorted) {
|
||||
var c = children[s.index];
|
||||
var col=0;
|
||||
row += 2;
|
||||
var odd = 0;
|
||||
foreach (var mp; model.list) {
|
||||
var col = 0;
|
||||
foreach (var column; me.columns) {
|
||||
var w = content.addChild("text");
|
||||
w.node.setValues(column);
|
||||
var p=typeof(column.property) == "func" ? column.property() : column.property;
|
||||
w.node.setValues({row: row, col: col, live: 1, property: c.getPath() ~ "/" ~ p});
|
||||
var odd = math.mod(row, 2);
|
||||
var p = typeof(column.property) == "func" ? column.property() : column.property;
|
||||
w.node.setValues({row: row, col: col, live: 1, property: mp.path ~ "/" ~ p});
|
||||
w.setColor(me.fg[odd][0], me.fg[odd][1], me.fg[odd][2], me.fg[odd][3]);
|
||||
col +=1;
|
||||
col += 1;
|
||||
}
|
||||
odd = !odd;
|
||||
row +=1;
|
||||
}
|
||||
|
||||
me.update();
|
||||
fgcommand("dialog-new", me.dialog.prop());
|
||||
fgcommand("dialog-show", me.namenode);
|
||||
fgcommand("dialog-show", me.dialog.prop());
|
||||
},
|
||||
update : func {
|
||||
var children = me.mp.getChildren("multiplayer");
|
||||
var loc = geo.aircraft_position();
|
||||
var players = 0;
|
||||
foreach(var c; children) {
|
||||
if ( c.getNode("valid") == nil or !c.getNode("valid").getValue())
|
||||
continue;
|
||||
players+=1;
|
||||
var ploc = me.getloc(c.getNode("position"));
|
||||
var ploc_course = loc.course_to(ploc);
|
||||
var ploc_dist = loc.distance_to(ploc);
|
||||
var altitude_m = c.getNode("position/altitude-ft").getValue()*FT2M;
|
||||
update: func {
|
||||
var self = geo.aircraft_position();
|
||||
foreach(var mp; model.list) {
|
||||
var n = mp.node;
|
||||
var ac = geo.Coord.new().set_xyz(
|
||||
n.getNode("position/global-x").getValue(),
|
||||
n.getNode("position/global-y").getValue(),
|
||||
n.getNode("position/global-z").getValue());
|
||||
var distance = self.distance_to(ac);
|
||||
|
||||
var pathN = c.getNode("sim/model/path");
|
||||
if (pathN != nil)
|
||||
var path = pathN.getValue();
|
||||
else
|
||||
var path="";
|
||||
|
||||
var name = split("/", path)[-1];
|
||||
var pos = find("-model", name);
|
||||
if (pos >= 0)
|
||||
name = substr(name, 0, pos);
|
||||
if (substr(name, -4) == ".xml")
|
||||
name = substr(name, 0, size(name) - 4);
|
||||
if (substr(name, -3) == ".ac")
|
||||
name = substr(name, 0, size(name) - 3);
|
||||
|
||||
c.setValues({"model-short":name, "bearing-to": ploc_course,
|
||||
"distance-to-km":ploc_dist/1000.0, "distance-to-nm":ploc_dist*METER_TO_NM,
|
||||
"position/altitude-m":altitude_m });
|
||||
n.setValues({
|
||||
"model-short": mp.model,
|
||||
"bearing-to": self.course_to(ac),
|
||||
"distance-to-km": distance / 1000.0,
|
||||
"distance-to-nm": distance * M2NM,
|
||||
"position/altitude-m": n.getNode("position/altitude-ft").getValue() * FT2M,
|
||||
});
|
||||
}
|
||||
me.mp.getNode("players", 1).setIntValue(players);
|
||||
if(PILOTSDLG_RUNNING)
|
||||
settimer( func { me.update() }, 0.4, 1);
|
||||
if (PILOTSDLG_RUNNING)
|
||||
settimer( func me.update(), 0.4, 1);
|
||||
},
|
||||
_redraw_ : func {
|
||||
_redraw_: func {
|
||||
if (me.dialog != nil) {
|
||||
me.close();
|
||||
me.create();
|
||||
}
|
||||
},
|
||||
_multiplayer_update_ : func(node) {
|
||||
var name = split("/", node.getValue())[-1];
|
||||
if(substr(name, 0, 11) == "multiplayer")
|
||||
me._redraw_()
|
||||
},
|
||||
toggle_unit : func {
|
||||
toggle_unit: func {
|
||||
me.unit = !me.unit;
|
||||
if(me.unit)
|
||||
{
|
||||
|
@ -340,30 +305,93 @@ var dialog = {
|
|||
me.unit_button = "SI";
|
||||
}
|
||||
},
|
||||
close : func {
|
||||
fgcommand("dialog-close", me.namenode);
|
||||
close: func {
|
||||
fgcommand("dialog-close", me.dialog.prop());
|
||||
},
|
||||
del : func {
|
||||
del: func {
|
||||
PILOTSDLG_RUNNING=0;
|
||||
me.close();
|
||||
foreach(var l; me.listeners)
|
||||
foreach (var l; me.listeners)
|
||||
removelistener(l);
|
||||
delete(gui.dialog, "\"" ~ me.name ~ "\"");
|
||||
},
|
||||
show : func {
|
||||
if(!PILOTSDLG_RUNNING)
|
||||
{
|
||||
show: func {
|
||||
if (!PILOTSDLG_RUNNING) {
|
||||
PILOTSDLG_RUNNING=1;
|
||||
me.init(-2, -2);
|
||||
me.create();
|
||||
me.update();
|
||||
}
|
||||
},
|
||||
toggle : func {
|
||||
if(!PILOTSDLG_RUNNING)
|
||||
toggle: func {
|
||||
if (!PILOTSDLG_RUNNING)
|
||||
me.show();
|
||||
else
|
||||
me.del();
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
||||
# Autonomous singleton class that monitors multiplayer aircraft,
|
||||
# maintains a data hash and a list (sorted by callsign), and raises
|
||||
# signal "/sim/signals/multiplayer-updated" whenever an aircraft
|
||||
# joined or left. Both multiplayer.model.data and multiplayer.model.list
|
||||
# contain hash entries of this form:
|
||||
#
|
||||
# {
|
||||
# callsign: "bimaus",
|
||||
# model: "bo105", # model name without suffixes (xml, ac, -anim, -model)
|
||||
# node: {...}, # node as props.Node hash
|
||||
# path: "/ai/models/multiplayer[4]",
|
||||
# }
|
||||
#
|
||||
#
|
||||
var model = {
|
||||
init: func {
|
||||
me.L = [];
|
||||
me.list = [];
|
||||
append(me.L, setlistener("ai/models/model-added", func(n) me.update(n.getValue())));
|
||||
append(me.L, setlistener("ai/models/model-removed", func(n) me.update(n.getValue())));
|
||||
me.update();
|
||||
},
|
||||
update: func(n = nil) {
|
||||
if (n != nil and props.globals.getNode(n, 1).getName() != "multiplayer")
|
||||
return;
|
||||
|
||||
me.data = {};
|
||||
foreach (var n; props.globals.getNode("ai/models", 1).getChildren("multiplayer")) {
|
||||
if (!n.getNode("valid", 1).getValue())
|
||||
continue;
|
||||
|
||||
if ((var callsign = n.getNode("callsign")) == nil or !(callsign = callsign.getValue()))
|
||||
continue;
|
||||
|
||||
var model = n.getNode("sim/model/path").getValue();
|
||||
model = split(".", split("/", model)[-1])[0];
|
||||
model = me.remove_suffix(model, "-model");
|
||||
model = me.remove_suffix(model, "-anim");
|
||||
|
||||
var path = n.getPath();
|
||||
me.data[path] = { node: n, callsign: callsign, model: model, path: path };
|
||||
}
|
||||
|
||||
me.list = sort(keys(me.data), func(a, b) string.icmp(me.data[a].callsign, me.data[b].callsign));
|
||||
forindex (var i; me.list)
|
||||
me.list[i] = me.data[me.list[i]];
|
||||
|
||||
setprop("ai/models/num-players", size(me.list));
|
||||
setprop("sim/signals/multiplayer-updated", 1);
|
||||
},
|
||||
remove_suffix: func(s, x) {
|
||||
var len = size(x);
|
||||
if (substr(s, -len) == x)
|
||||
return substr(s, 0, size(s) - len);
|
||||
return s;
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
setlistener("sim/signals/nasal-dir-initialized", func model.init());
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue