1
0
Fork 0

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:
mfranz 2009-01-31 17:15:48 +00:00
parent c795f30862
commit 65e4b71406

View file

@ -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());