1
0
Fork 0

Add framework for new Emesary based display framework. This is based off work by Richard Harrison on the F-15, making use of the FrameNotification concept

This commit is contained in:
legoboyvdlp R 2020-10-27 21:35:17 +00:00
parent cbaa9f2aa8
commit 6bb53d70d1
8 changed files with 524 additions and 112 deletions

View file

@ -1182,6 +1182,7 @@
</comm>
<electrical n="0">
<bus>
<ac-ess type="double">0</ac-ess>
<dc-1 type="double">0</dc-1>
<dc-2 type="double">0</dc-2>
</bus>
@ -4335,6 +4336,9 @@
</aircraft>
<nasal>
<notifications>
<file>Aircraft/A320-family/Nasal/emesary/M_frame_notification.nas</file>
</notifications>
<pts>
<file>Aircraft/A320-family/Nasal/Libraries/property-tree-setup.nas</file>
</pts>
@ -4442,7 +4446,9 @@
<file>Aircraft/A320-family/Models/Instruments/ND/canvas/ND.nas</file>
</canvas_nd>
<canvas_ecam>
<file>Aircraft/A320-family/Models/Instruments/Upper-ECAM/Upper-ECAM.nas</file>
<file>Aircraft/A320-family/Nasal/emesary/exec.nas</file>
<!--<file>Aircraft/A320-family/Models/Instruments/Upper-ECAM/Upper-ECAM.nas</file>-->
<file>Aircraft/A320-family/Models/Instruments/Upper-ECAM/Upper-ECAM.new.nas</file>
<file>Aircraft/A320-family/Models/Instruments/Lower-ECAM/Lower-ECAM.nas</file>
</canvas_ecam>
<canvas_iesi>

View file

@ -118,31 +118,8 @@ var thrLimit = 0;
var canvas_upperECAM_base = {
init: func(canvas_group, file) {
var font_mapper = func(family, weight) {
return "LiberationFonts/LiberationSans-Regular.ttf";
};
canvas.parsesvg(canvas_group, file, {"font-mapper": font_mapper});
var svg_keys = me.getKeys();
foreach(var key; svg_keys) {
me[key] = canvas_group.getElementById(key);
var clip_el = canvas_group.getElementById(key ~ "_clip");
if (clip_el != nil) {
clip_el.setVisible(0);
var tran_rect = clip_el.getTransformedBounds();
var clip_rect = sprintf("rect(%d,%d, %d,%d)",
tran_rect[1], # 0 ys
tran_rect[2], # 1 xe
tran_rect[3], # 2 ye
tran_rect[0]); #3 xs
# coordinates are top,right,bottom,left (ys, xe, ye, xs) ref: l621 of simgear/canvas/CanvasElement.cxx
me[key].set("clip", clip_rect);
me[key].set("clip-frame", canvas.Element.PARENT);
}
}
# set font
me["ECAML1"].setFont("LiberationMonoCustom.ttf");
@ -199,29 +176,30 @@ var canvas_upperECAM_base = {
update: func() {
elapsedtime = pts.Sim.Time.elapsedSec.getValue();
cur_eng_option = eng_option.getValue();
if (systems.ELEC.Bus.acEss.getValue() >= 110 and du3_lgt.getValue() > 0.01) {
if (du3_test_time.getValue() + du3_test_amount.getValue() >= elapsedtime) {
upperECAM_cfm_eis2.page.hide();
upperECAM_iae_eis2.page.hide();
upperECAM_test.page.show();
upperECAM_test.update();
if (1 == 0) {
if (systems.ELEC.Bus.acEss.getValue() >= 110 and du3_lgt.getValue() > 0.01) {
if (du3_test_time.getValue() + du3_test_amount.getValue() >= elapsedtime) {
upperECAM_cfm_eis2.page.hide();
upperECAM_iae_eis2.page.hide();
upperECAM_test.page.show();
upperECAM_test.update();
} else {
upperECAM_test.page.hide();
if (cur_eng_option == "CFM") {
upperECAM_cfm_eis2.page.show();
upperECAM_iae_eis2.page.hide();
upperECAM_cfm_eis2.update();
} else if (cur_eng_option == "IAE") {
upperECAM_cfm_eis2.page.hide();
upperECAM_iae_eis2.page.show();
upperECAM_iae_eis2.update();
}
}
} else {
upperECAM_test.page.hide();
if (cur_eng_option == "CFM") {
upperECAM_cfm_eis2.page.show();
upperECAM_iae_eis2.page.hide();
upperECAM_cfm_eis2.update();
} else if (cur_eng_option == "IAE") {
upperECAM_cfm_eis2.page.hide();
upperECAM_iae_eis2.page.show();
upperECAM_iae_eis2.update();
}
upperECAM_cfm_eis2.page.hide();
upperECAM_iae_eis2.page.hide();
}
} else {
upperECAM_test.page.hide();
upperECAM_cfm_eis2.page.hide();
upperECAM_iae_eis2.page.hide();
}
},
getColorString: func(color) {
@ -241,7 +219,7 @@ var canvas_upperECAM_base = {
return [1,1,1];
}
},
updateBase: func() {
updateBase: func(notification) {
# Reversers
rev_1_cur = pts.Engines.Engine.reverser[0].getValue();
rev_2_cur = pts.Engines.Engine.reverser[1].getValue();
@ -280,27 +258,6 @@ var canvas_upperECAM_base = {
me["REV2"].setColor(0.7333,0.3803,0);
}
# Flap Indicator
flapsPos = pts.Controls.Flight.flapsPos.getValue();
if (flapsPos == 1) {
me["FlapTxt"].setText("1");
} else if (flapsPos == 2) {
me["FlapTxt"].setText("1+F");
} else if (flapsPos == 3) {
me["FlapTxt"].setText("2");
} else if (flapsPos == 4) {
me["FlapTxt"].setText("3");
} else if (flapsPos == 5) {
me["FlapTxt"].setText("FULL");
} else {
me["FlapTxt"].setText(" "); # More efficient then hide/show
}
if (flapsPos > 0) {
me["FlapDots"].show();
} else {
me["FlapDots"].hide();
}
if (pts.Fdm.JSBsim.Fcs.slatLocked.getValue()) {
if (slatLockGoing == 0) {
@ -325,16 +282,6 @@ var canvas_upperECAM_base = {
me["FlapLine"].setTranslation(flapXTranslate.getValue(),flapYTranslate.getValue());
me["SlatLine"].setTranslation(slatXTranslate.getValue(),slatYTranslate.getValue());
# FOB
if (acconfig_weight_kgs.getValue())
{
me["FOB-LBS"].setText(sprintf("%s", math.round(pts.Consumables.Fuel.totalFuelLbs.getValue() * LBS2KGS, 10)));
me["FOB-weight-unit"].setText("KG");
} else {
me["FOB-LBS"].setText(sprintf("%s", math.round(pts.Consumables.Fuel.totalFuelLbs.getValue(), 10)));
me["FOB-weight-unit"].setText("LBS");
}
# ECAM Messages
me["ECAML1"].setText(sprintf("%s", ECAM_line1.getValue()));
@ -358,24 +305,70 @@ var canvas_upperECAM_base = {
me["ECAMR8"].setText(sprintf("%s", ECAM_line8r.getValue()));
me["ECAM_Right"].show();
foreach(var update_item; me.update_items)
{
update_item.update(notification);
}
},
updateAFloor: func() {
if (fadec.Thrust.alphaFloor.getBoolValue()) {
me["aFloor"].show();
} else {
me["aFloor"].hide();
}
},
updateFlaps: func() {
# Flap Indicator
flapsPos = pts.Controls.Flight.flapsPos.getValue();
if (flapsPos == 1) {
me["FlapTxt"].setText("1");
} else if (flapsPos == 2) {
me["FlapTxt"].setText("1+F");
} else if (flapsPos == 3) {
me["FlapTxt"].setText("2");
} else if (flapsPos == 4) {
me["FlapTxt"].setText("3");
} else if (flapsPos == 5) {
me["FlapTxt"].setText("FULL");
} else {
me["FlapTxt"].setText(" "); # More efficient then hide/show
}
if (flapsPos > 0) {
me["FlapDots"].show();
} else {
me["FlapDots"].hide();
}
},
updateFlx: func() {
if (fadec.Thrust.thrustLimit.getValue() == "FLX") {
me["FlxLimDegreesC"].show();
me["FlxLimTemp"].show();
me["FlxLimTemp"].setText(sprintf("%2.0d",fmgc.FMGCNodes.flexTemp.getValue()));
} else {
me["FlxLimDegreesC"].hide();
me["FlxLimTemp"].hide();
}
},
update_items: [
props.UpdateManager.FromHashValue("fuelTotalLbs", 1, func(val) {
# FOB
}),
],
};
var canvas_upperECAM_cfm_eis2 = {
new: func(canvas_group, file) {
var m = {parents: [canvas_upperECAM_cfm_eis2, canvas_upperECAM_base]};
m.init(canvas_group, file);
m.updateAFloor();
m.updateFlx();
return m;
},
getKeys: func() {
return ["N11-needle","N11-thr","N11-ylim","N11","N11-decpnt","N11-decimal","N11-box","N11-scale","N11-scale2","N11-scaletick","N11-scalenum","N11-XX","N11-XX2","N11-XX-box","EGT1-needle","EGT1","EGT1-scale","EGT1-box","EGT1-scale2","EGT1-scaletick",
"EGT1-XX","N21","N21-decpnt","N21-decimal","N21-XX","FF1","FF1-XX","N12-needle","N12-thr","N12-ylim","N12","N12-decpnt","N12-decimal","N12-box","N12-scale","N12-scale2","N12-scaletick","N12-scalenum","N12-XX","N12-XX2","N12-XX-box","EGT2-needle","EGT2",
"EGT2-scale","EGT2-box","EGT2-scale2","EGT2-scaletick","EGT2-XX","N22","N22-decpnt","N22-decimal","N22-XX","FF2","FF2-XX","FOB-LBS","FlapTxt","FlapDots","N1Lim-mode","N1Lim","N1Lim-decpnt","N1Lim-decimal","N1Lim-percent","N1Lim-XX","N1Lim-XX2","REV1",
"REV1-box","REV2","REV2-box","ECAM_Left","ECAML1","ECAML2","ECAML3","ECAML4","ECAML5","ECAML6","ECAML7","ECAML8","ECAMR1", "ECAMR2", "ECAMR3", "ECAMR4", "ECAMR5", "ECAMR6", "ECAMR7", "ECAMR8", "ECAM_Right",
"FOB-weight-unit","FFlow-weight-unit","SlatAlphaLock","SlatIndicator","FlapIndicator","SlatLine","FlapLine"];
},
update: func() {
update: func(notification) {
# N1
N1_1_cur = N1_1.getValue();
N1_2_cur = N1_2.getValue();
@ -615,7 +608,7 @@ var canvas_upperECAM_cfm_eis2 = {
me["N1Lim-percent"].hide();
}
me.updateBase();
me.updateBase(notification);
},
};
@ -623,7 +616,8 @@ var canvas_upperECAM_iae_eis2 = {
new: func(canvas_group, file) {
var m = {parents: [canvas_upperECAM_iae_eis2, canvas_upperECAM_base]};
m.init(canvas_group, file);
m.updateAFloor();
m.updateFlx();
return m;
},
getKeys: func() {
@ -632,9 +626,9 @@ var canvas_upperECAM_iae_eis2 = {
"EPR2-decimal","EPR2-box","EPR2-scale","EPR2-scaletick","EPR2-scalenum","EPR2-XX","EPR2-XX2","EGT2-needle","EGT2","EGT2-scale","EGT2-scale2","EGT2-box","EGT2-scaletick","EGT2-XX","N12-needle","N12-thr","N12-ylim","N12","N12-decpnt","N12-decimal",
"N12-scale","N12-scale2","N12-scaletick","N12-scalenum","N12-XX","N22","N22-decpnt","N22-decimal","N22-XX","FF2","FF2-XX","FOB-LBS","FlapTxt","FlapDots","EPRLim-mode","EPRLim","EPRLim-decpnt","EPRLim-decimal","EPRLim-XX","EPRLim-XX2","REV1","REV1-box",
"REV2","REV2-box","ECAM_Left","ECAML1","ECAML2","ECAML3","ECAML4","ECAML5","ECAML6","ECAML7","ECAML8", "ECAMR1", "ECAMR2", "ECAMR3", "ECAMR4", "ECAMR5", "ECAMR6", "ECAMR7", "ECAMR8", "ECAM_Right",
"FFlow1-weight-unit", "FFlow2-weight-unit", "FOB-weight-unit","SlatAlphaLock","SlatIndicator","FlapIndicator","SlatLine","FlapLine"];
"FFlow1-weight-unit", "FFlow2-weight-unit", "FOB-weight-unit","SlatAlphaLock","SlatIndicator","FlapIndicator","SlatLine","FlapLine","aFloor","FlxLimDegreesC","FlxLimTemp"];
},
update: func() {
update: func(notification) {
N1_1_cur = N1_1.getValue();
N1_2_cur = N1_2.getValue();
N1_1_act = pts.Engines.Engine.n1Actual[0].getValue();
@ -942,7 +936,7 @@ var canvas_upperECAM_iae_eis2 = {
me["EPRLim-decimal"].hide();
}
me.updateBase();
me.updateBase(notification);
},
};
@ -1009,22 +1003,58 @@ var createListenerForLine = func(prop, node, key) {
}, 0, 0);
};
var _init = 0;
var UpperECAMRecipientCFM =
{
new: func(_ident, group)
{
var new_class = emesary.Recipient.new(_ident);
new_class.MainScreen = nil;
new_class.Receive = func(notification)
{
if (notification.NotificationType == "FrameNotification")
{
if (new_class.MainScreen == nil)
new_class.MainScreen = canvas_upperECAM_cfm_eis2.new(group, "Aircraft/A320-family/Models/Instruments/Upper-ECAM/res/cfm-eis2.svg");
upperECAM_cfm_eis2 = new_class.MainScreen;
if (!math.mod(notifications.frameNotification.FrameCount,2)){
new_class.MainScreen.update(notification);
}
return emesary.Transmitter.ReceiptStatus_OK;
}
return emesary.Transmitter.ReceiptStatus_NotProcessed;
};
return new_class;
},
};
var UpperECAMRecipientIAE =
{
new: func(_ident, group)
{
var new_class = emesary.Recipient.new(_ident);
new_class.MainScreen = nil;
new_class.Receive = func(notification)
{
if (notification.NotificationType == "FrameNotification")
{
if (new_class.MainScreen == nil)
new_class.MainScreen = canvas_upperECAM_iae_eis2.new(group, "Aircraft/A320-family/Models/Instruments/Upper-ECAM/res/iae-eis2.svg");
upperECAM_iae_eis2 = new_class.MainScreen;
if (!math.mod(notifications.frameNotification.FrameCount,2)){
new_class.MainScreen.update(notification);
}
return emesary.Transmitter.ReceiptStatus_OK;
}
return emesary.Transmitter.ReceiptStatus_NotProcessed;
};
return new_class;
},
};
setlistener("sim/signals/fdm-initialized", func {
upperECAM_display = canvas.new({
"name": "upperECAM",
"size": [1024, 1024],
"view": [1024, 1024],
"mipmapping": 1
});
upperECAM_display.addPlacement({"node": "uecam.screen"});
var group_cfm_eis2 = upperECAM_display.createGroup();
var group_iae_eis2 = upperECAM_display.createGroup();
var group_test = upperECAM_display.createGroup();
upperECAM_cfm_eis2 = canvas_upperECAM_cfm_eis2.new(group_cfm_eis2, "Aircraft/A320-family/Models/Instruments/Upper-ECAM/res/cfm-eis2.svg");
upperECAM_iae_eis2 = canvas_upperECAM_iae_eis2.new(group_iae_eis2, "Aircraft/A320-family/Models/Instruments/Upper-ECAM/res/iae-eis2.svg");
upperECAM_test = canvas_upperECAM_test.new(group_test, "Aircraft/A320-family/Models/Instruments/Common/res/du-test.svg");
createListenerForLine("/ECAM/msg/linec1", ECAM_line1c, "ECAML1");
createListenerForLine("/ECAM/msg/linec2", ECAM_line2c, "ECAML2");
@ -1044,6 +1074,10 @@ setlistener("sim/signals/fdm-initialized", func {
createListenerForLine("/ECAM/rightmsg/linec7", ECAM_line7rc, "ECAMR7");
createListenerForLine("/ECAM/rightmsg/linec8", ECAM_line8rc, "ECAMR8");
if (!_init) {
}
upperECAM_update.start();
if (rate.getValue() > 1) {
u_rateApply();
@ -1067,7 +1101,6 @@ setlistener("/systems/electrical/bus/ac-ess", func() {
canvas_upperECAM_base.updateDu3();
}, 0, 0);
var slatLockGoing = 0;
var slatLockTimer = maketimer(0.50, func {
if (!slatLockFlash.getBoolValue()) {

View file

@ -0,0 +1,113 @@
var canvas_upperECAM = {
new: func(svg) {
var obj = {parents: [canvas_upperECAM] };
obj.canvas = canvas.new({
"name": "upperECAM",
"size": [1024, 1024],
"view": [1024, 1024],
"mipmapping": 1,
});
obj.canvas.addPlacement({"node": "uecam.screen"});
obj.group = obj.canvas.createGroup();
obj.font_mapper = func(family, weight) {
return "LiberationFonts/LiberationSans-Regular.ttf";
};
canvas.parsesvg(obj.group, svg, {"font-mapper": obj.font_mapper} );
foreach(var key; obj.getKeys()) {
obj[key] = obj.group.getElementById(key);
var clip_el = obj.group.getElementById(key ~ "_clip");
if (clip_el != nil) {
clip_el.setVisible(0);
var tran_rect = clip_el.getTransformedBounds();
var clip_rect = sprintf("rect(%d,%d, %d,%d)",
tran_rect[1],
tran_rect[2],
tran_rect[3],
tran_rect[0]);
obj[key].set("clip", clip_rect);
obj[key].set("clip-frame", canvas.Element.PARENT);
}
};
obj.update_items = [
props.UpdateManager.FromHashValue("fuelTotalLbs", 1, func(val) {
if (acconfig_weight_kgs.getValue())
{
obj["FOB-LBS"].setText(sprintf("%s", math.round(val * LBS2KGS, 10)));
obj["FOB-weight-unit"].setText("KG");
} else {
obj["FOB-LBS"].setText(sprintf("%s", math.round(val, 10)));
obj["FOB-weight-unit"].setText("LBS");
}
}),
props.UpdateManager.FromHashList(["AcEssBus", "DisplayBrightness"], 0.01, func(val) {
if (val.DisplayBrightness > 0.01 and val.AcEssBus >= 110) {
obj.group.setVisible(1);
} else {
obj.group.setVisible(0);
}
}),
];
obj.page = obj.group;
return obj;
},
getKeys: func() {
return ["N11-needle","N11-thr","N11-ylim","N11","N11-decpnt","N11-decimal","N11-box","N11-scale","N11-scale2","N11-scaletick","N11-scalenum","N11-XX","N11-XX2","N11-XX-box","EGT1-needle","EGT1","EGT1-scale","EGT1-box","EGT1-scale2","EGT1-scaletick",
"EGT1-XX","N21","N21-decpnt","N21-decimal","N21-XX","FF1","FF1-XX","N12-needle","N12-thr","N12-ylim","N12","N12-decpnt","N12-decimal","N12-box","N12-scale","N12-scale2","N12-scaletick","N12-scalenum","N12-XX","N12-XX2","N12-XX-box","EGT2-needle","EGT2",
"EGT2-scale","EGT2-box","EGT2-scale2","EGT2-scaletick","EGT2-XX","N22","N22-decpnt","N22-decimal","N22-XX","FF2","FF2-XX","FOB-LBS","FlapTxt","FlapDots","N1Lim-mode","N1Lim","N1Lim-decpnt","N1Lim-decimal","N1Lim-percent","N1Lim-XX","N1Lim-XX2","REV1",
"REV1-box","REV2","REV2-box","ECAM_Left","ECAML1","ECAML2","ECAML3","ECAML4","ECAML5","ECAML6","ECAML7","ECAML8","ECAMR1", "ECAMR2", "ECAMR3", "ECAMR4", "ECAMR5", "ECAMR6", "ECAMR7", "ECAMR8", "ECAM_Right",
"FOB-weight-unit","FFlow-weight-unit","SlatAlphaLock","SlatIndicator","FlapIndicator","SlatLine","FlapLine","aFloor","FlxLimDegreesC","FlxLimTemp"];
},
update: func(notification) {
foreach(var update_item; me.update_items)
{
update_item.update(notification);
}
},
};
var UpperECAMRecipient =
{
new: func(_ident)
{
var new_class = emesary.Recipient.new(_ident);
new_class.MainScreen = nil;
new_class.Receive = func(notification)
{
if (notification.NotificationType == "FrameNotification")
{
if (new_class.MainScreen == nil)
new_class.MainScreen = canvas_upperECAM.new("Aircraft/A320-family/Models/Instruments/Upper-ECAM/res/cfm-eis2.svg", "A320 Upper ECAM CFM");
if (!math.mod(notifications.frameNotification.FrameCount,2)){
new_class.MainScreen.update(notification);
}
return emesary.Transmitter.ReceiptStatus_OK;
}
return emesary.Transmitter.ReceiptStatus_NotProcessed;
};
return new_class;
},
};
emesary.GlobalTransmitter.Register(UpperECAMRecipient.new("A320 Upper ECAM"));
input = {
fuelTotalLbs: "/consumables/fuel/total-fuel-lbs",
AcEssBus: "/systems/electrical/bus/ac-ess",
DisplayBrightness: "/controls/lighting/DU/du3",
};
foreach (var name; keys(input)) {
emesary.GlobalTransmitter.NotifyAll(notifications.FrameNotificationAddProperty.new("A320 Upper ECAM", name, input[name]));
}
setlistener("/sim/signals/fdm-initialized", func() {
execLoop();
}, 0, 0);

View file

@ -41,9 +41,9 @@
inkscape:window-height="705"
id="namedview371"
showgrid="true"
inkscape:zoom="1"
inkscape:cx="718.57047"
inkscape:cy="505.8628"
inkscape:zoom="0.25"
inkscape:cx="971.41703"
inkscape:cy="1420.8195"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
@ -1428,4 +1428,43 @@
width="137.63597"
id="SlatLine_clip"
style="opacity:0.5;fill:none;fill-opacity:1;stroke:none;stroke-width:3.34691048;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:31.71383667px;line-height:1.25;font-family:'Bitstream Vera Sans';-inkscape-font-specification:'Bitstream Vera Sans';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.7928459"
x="38.122616"
y="47.904297"
id="aFloor"
transform="scale(0.94595932,1.0571279)"
inkscape:label="#text1027"><tspan
sodipodi:role="line"
id="tspan1025"
x="38.122616"
y="47.904297"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:39.99999902px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';fill:#c56100;fill-opacity:1;stroke-width:0.7928459">A FLOOR</tspan></text>
<text
transform="scale(0.97051272,1.0303832)"
inkscape:label="#text4314"
id="FlxLimTemp"
y="122.78025"
x="919.25299"
style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#179ab7;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:40.71494293px;line-height:1.25;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;text-anchor:middle;fill:#179ab7;fill-opacity:1;"
y="122.78025"
x="919.25299"
id="tspan1029"
sodipodi:role="line">00</tspan></text>
<text
inkscape:label="#text4443"
id="FlxLimDegreesC"
y="108.14707"
x="1061.88"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#179ab7;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"
transform="scale(0.87983286,1.1365795)"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:31.25978088px;line-height:1.25;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';fill:#179ab7;fill-opacity:1"
y="108.14707"
x="1061.88"
id="tspan1033"
sodipodi:role="line">°C</tspan></text>
</svg>

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 89 KiB

View file

@ -42,8 +42,8 @@
id="namedview371"
showgrid="false"
inkscape:zoom="0.43942712"
inkscape:cx="180.81625"
inkscape:cy="433.53356"
inkscape:cx="623.25944"
inkscape:cy="936.15332"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
@ -1755,7 +1755,7 @@
x="650.08069"
y="575.68427"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:31.25px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';fill:#0dc04b;fill-opacity:1;stroke-width:0.75">A-LOCK</tspan></text>
<path
<path
style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#0dc04b;stroke-width:5.44862556;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
d="M 555.26245,639.8335 691.24239,597.33411"
id="SlatLine"
@ -1796,4 +1796,43 @@
width="137.63597"
id="SlatLine_clip"
style="opacity:0.5;fill:none;fill-opacity:1;stroke:none;stroke-width:3.34691048;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:31.71383667px;line-height:1.25;font-family:'Bitstream Vera Sans';-inkscape-font-specification:'Bitstream Vera Sans';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.7928459"
x="38.122616"
y="47.904297"
id="aFloor"
transform="scale(0.94595932,1.0571279)"
inkscape:label="#text1027"><tspan
sodipodi:role="line"
id="tspan1025"
x="38.122616"
y="47.904297"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:39.99999902px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';fill:#c56100;fill-opacity:1;stroke-width:0.7928459">A FLOOR</tspan></text>
<text
transform="scale(0.97051272,1.0303832)"
inkscape:label="#text4314"
id="FlxLimTemp"
y="122.78025"
x="919.25299"
style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#179ab7;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:40.71494293px;line-height:1.25;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;text-anchor:middle;fill:#179ab7;fill-opacity:1;"
y="122.78025"
x="919.25299"
id="tspan1029"
sodipodi:role="line">00</tspan></text>
<text
inkscape:label="#text4443"
id="FlxLimDegreesC"
y="108.14707"
x="1061.88"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#179ab7;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"
transform="scale(0.87983286,1.1365795)"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:31.25978088px;line-height:1.25;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';fill:#179ab7;fill-opacity:1"
y="108.14707"
x="1061.88"
id="tspan1033"
sodipodi:role="line">°C</tspan></text>
</svg>

Before

Width:  |  Height:  |  Size: 109 KiB

After

Width:  |  Height:  |  Size: 112 KiB

View file

@ -247,6 +247,7 @@ var postInit = func() {
var FMGCNodes = {
costIndex: props.globals.initNode("/FMGC/internal/cost-index", 0, "DOUBLE"),
flexSet: props.globals.initNode("/FMGC/internal/flex-set", 0, "BOOL"),
flexTemp: props.globals.initNode("/FMGC/internal/flex", 0, "INT"),
mngSpdAlt: props.globals.getNode("/FMGC/internal/mng-alt-spd"),
mngMachAlt: props.globals.getNode("/FMGC/internal/mng-alt-mach"),
toFromSet: props.globals.initNode("/FMGC/internal/tofrom-set", 0, "BOOL"),

View file

@ -0,0 +1,99 @@
#---------------------------------------------------------------------------
#
# Title : Emesary based rt exec frame notifications
#
# File Type : Implementation File
#
# Description : Uses emesary notifications to permit nasal subsystems to be notified each frame.
# : A frame is defined by the timer rate; which is usually the maximum rate as determined by the FPS.
# : This is an alternative to the timer based or explicit function calling way of invoking
# : aircraft systems.
# : It has the advantage of using less timers and remaining modular, as each aircraft subsytem
# : can simply register itself with the global transmitter to receive the frame notification.
#
# Author : Richard Harrison (richard@zaretto.com)
#
# Creation Date : 4 June 2018
#
# Version : 1.0
#
# Copyright (C) 2018 Richard Harrison Released under GPL V2
#
#---------------------------------------------------------------------------*/
var FrameNotification =
{
debug: 0,
new: func(_rate)
{
var new_class = emesary.Notification.new("FrameNotification", _rate);
new_class.Rate = _rate;
new_class.FrameRate = 60;
new_class.FrameCount = 0;
new_class.ElapsedSeconds = 0;
new_class.monitored = {};
new_class.properties = {};
#
# embed a recipient within this notification to allow the monitored property
# mapping list to be modified.
new_class.Recipient = emesary.Recipient.new("FrameNotification");
new_class.Recipient.Receive = func(notification)
{
if (notification.NotificationType == "FrameNotificationAddProperty")
{
var root_node = props.globals;
if (notification.root_node != nil) {
root_node = notification.root_node;
}
if (new_class.properties[notification.property] != nil
and new_class.properties[notification.property] != notification.variable)
print("[WARNING]: (",notification.module,") FrameNotification: already have variable ",new_class.properties[notification.property]," for ",notification.variable, " referencing property ",notification.property);
if (new_class.monitored[notification.variable] != nil
and new_class.monitored[notification.variable].getPath() != notification.property
and new_class.monitored[notification.variable].getPath() != "/"~notification.property)
print("[WARNING]: (",notification.module,") FrameNotification: already have variable ",notification.variable,"=",new_class.monitored[notification.variable].getPath(), " using different property ",notification.property);
# else if (new_class.monitored[notification.variable] == nil)
# print("[INFO]: (",notification.module,") FrameNotification.",notification.variable, " = ",notification.property);
new_class.monitored[notification.variable] = root_node.getNode(notification.property,1);
new_class.properties[notification.property] = notification.variable;
print("[INFO]: (",notification.module,") FrameNotification.",notification.variable, " = ",notification.property, " -> ", new_class.monitored[notification.variable].getPath() );
return emesary.Transmitter.ReceiptStatus_OK;
}
return emesary.Transmitter.ReceiptStatus_NotProcessed;
};
new_class.fetchvars = func() {
foreach (var mp; keys(new_class.monitored)){
if(new_class.monitored[mp] != nil){
if (FrameNotification.debug > 1)
print(" ",mp, " = ",new_class.monitored[mp].getValue());
new_class[mp] = new_class.monitored[mp].getValue();
}
}
};
emesary.GlobalTransmitter.Register(new_class.Recipient);
return new_class;
},
};
var FrameNotificationAddProperty =
{
new: func(module, variable, property, root_node=nil)
{
var new_class = emesary.Notification.new("FrameNotificationAddProperty", variable);
if (root_node == nil)
root_node = props.globals;
new_class.module = module ;
new_class.variable = variable;
new_class.property = property;
new_class.root_node = root_node;
return new_class;
},
};
#
var frameNotification = FrameNotification.new(1);

82
Nasal/emesary/exec.nas Normal file
View file

@ -0,0 +1,82 @@
#---------------------------------------------------------------------------
#
# Title : Emesary based real time executive
#
# File Type : Implementation File
#
# Description : Uses emesary notifications to permit nasal subsystems to
# : be invoked in a controlled manner.
#
# Author : Richard Harrison (richard@zaretto.com)
#
# Creation Date : 4 June 2018
#
# Version : 1.0
#
# Copyright (C) 2018 Richard Harrison Released under GPL V2
#
#---------------------------------------------------------------------------*/
# to add properties to the FrameNotification simply send a FrameNotificationAddProperty
# to the global transmitter. This will be received by the frameNotifcation object and
# included in the update.
#emesary.GlobalTransmitter.NotifyAll(new FrameNotificationAddProperty("MODULE", "wow","gear/gear[0]/wow"));
#emesary.GlobalTransmitter.NotifyAll(new FrameNotificationAddProperty("MODULE", "engine_n2", "engines/engine[0]/n2"));
#
#
# real time exec loop.
var frame_inc = 0;
var cur_frame_inc = 0.05;
var execLoop = func
{
#
notifications.frameNotification.fetchvars();
if (notifications.frameNotification.FrameCount >= 4) {
notifications.frameNotification.FrameCount = 0;
}
emesary.GlobalTransmitter.NotifyAll(notifications.frameNotification);
#
notifications.frameNotification.FrameCount = notifications.frameNotification.FrameCount + 1;
#
# framecount
# 0: HUD targets, Radar, RWR
# 1: HUD targets, RDR, VSD
# 2: HUD targets, HUD trig, HUD text
# 3: HUD targets, VSD, RDR
#
if (notifications.frameNotification.frame_rate_worst < 5) {
frame_inc = 0.25;#3.3
} elsif (notifications.frameNotification.frame_rate_worst < 10) {
frame_inc = 0.125;#6.6
} elsif (notifications.frameNotification.frame_rate_worst < 15) {
frame_inc = 0.10;#8.3
} elsif (notifications.frameNotification.frame_rate_worst < 20) {
frame_inc = 0.075;#12.5
} elsif (notifications.frameNotification.frame_rate_worst < 25) {
frame_inc = 0.05;#14.3
} else {
frame_inc = 0.05;#20.0
}
if (frame_inc != cur_frame_inc) {
cur_frame_inc = frame_inc;
}
settimer(execLoop, cur_frame_inc);
}
# setup the properties to monitor for this system
input = {
FrameRate : "/sim/frame-rate",
frame_rate : "/sim/frame-rate",
frame_rate_worst : "/sim/frame-rate-worst",
elapsed_seconds : "/sim/time/elapsed-sec",
};
foreach (var name; keys(input)) {
emesary.GlobalTransmitter.NotifyAll(notifications.FrameNotificationAddProperty.new("EXEC", name, input[name]));
}