1
0
Fork 0

Added maintainance dialog

Signed-off-by: fly <merspieler@airmail.cc>
This commit is contained in:
fly 2020-04-14 19:05:54 +00:00
parent d3fb74ef6f
commit 6c55b98035
3 changed files with 1022 additions and 0 deletions

View file

@ -340,6 +340,13 @@
</script>
</binding>
</item>
<item>
<label>Maintainance</label>
<binding>
<command>nasal</command>
<script>Dialogs.maintainance.toggle()</script>
</binding>
</item>
<item>
<label>Announcements</label>
<binding>
@ -3990,6 +3997,7 @@
<Dialogs>
<file>Aircraft/A320-family/gui/dialogs/refuel.nas</file>
<file>Aircraft/A320-family/gui/dialogs/rmp.nas</file>
<file>Aircraft/A320-family/gui/dialogs/maintainance.nas</file>
</Dialogs>
<save>
<file>Aircraft/A320-family/Nasal/Systems/save.nas</file>

View file

@ -0,0 +1,648 @@
#Font Mapper
var font_mapper = func(family, weight) {
return "Orbitron/Orbitron-Bold.ttf";
};
var clamp = func(value,min=0.0,max=0.0){
if(value < min) {value = min;}
if(value > max) {value = max;}
return value;
}
var MyWindow = {
# Constructor
#
# @param size ([width, height])
new: func(size, type = nil, id = nil)
{
var ghost = canvas._newWindowGhost(id);
var m = {
parents: [MyWindow, canvas.PropertyElement, ghost],
_node: props.wrapNode(ghost._node_ghost)
};
m.setInt("size[0]", size[0]);
m.setInt("size[1]", size[1]);
# TODO better default position
m.move(0,0);
# arg = [child, listener_node, mode, is_child_event]
setlistener(m._node, func m._propCallback(arg[0], arg[2]), 0, 2);
if( type )
m.set("type", type);
m._isOpen = 1;
return m;
},
# Destructor
del: func
{
me._node.remove();
me._node = nil;
if( me["_canvas"] != nil )
{
me._canvas.del();
me._canvas = nil;
}
me._isOpen = 0;
},
# Create the canvas to be used for this Window
#
# @return The new canvas
createCanvas: func()
{
var size = [
me.get("size[0]"),
me.get("size[1]")
];
me._canvas = canvas.new({
size: [2 * size[0], 2 * size[1]],
view: size,
placement: {
type: "window",
id: me.get("id")
}
});
me._canvas.addEventListener("mousedown", func me.raise());
return me._canvas;
},
# Set an existing canvas to be used for this Window
setCanvas: func(canvas_)
{
if( !isa(canvas_, canvas.Canvas) )
return debug.warn("Not a canvas.Canvas");
canvas_.addPlacement({type: "window", index: me._node.getIndex()});
me['_canvas'] = canvas_;
},
# Get the displayed canvas
getCanvas: func()
{
return me['_canvas'];
},
getCanvasDecoration: func()
{
return canvas.wrapCanvas(me._getCanvasDecoration());
},
setPosition: func(x, y)
{
me.setInt("tf/t[0]", x);
me.setInt("tf/t[1]", y);
},
move: func(x, y)
{
me.setInt("tf/t[0]", me.get("tf/t[0]", 10) + x);
me.setInt("tf/t[1]", me.get("tf/t[1]", 30) + y);
},
# Raise to top of window stack
raise: func()
{
# on writing the z-index the window always is moved to the top of all other
# windows with the same z-index.
me.setInt("z-index", me.get("z-index", 0));
},
# private:
_propCallback: func(child, mode)
{
if( !me._node.equals(child.getParent()) )
return;
var name = child.getName();
# support for CSS like position: absolute; with right and/or bottom margin
if( name == "right" )
me._handlePositionAbsolute(child, mode, name, 0);
else if( name == "bottom" )
me._handlePositionAbsolute(child, mode, name, 1);
# update decoration on type change
else if( name == "type" )
{
if( mode == 0 )
settimer(func me._updateDecoration(), 0);
}
},
_handlePositionAbsolute: func(child, mode, name, index)
{
# mode
# -1 child removed
# 0 value changed
# 1 child added
if( mode == 0 )
me._updatePos(index, name);
else if( mode == 1 )
me["_listener_" ~ name] = [
setlistener
(
"/sim/gui/canvas/size[" ~ index ~ "]",
func me._updatePos(index, name)
),
setlistener
(
me._node.getNode("size[" ~ index ~ "]"),
func me._updatePos(index, name)
)
];
else if( mode == -1 )
for(var i = 0; i < 2; i += 1)
removelistener(me["_listener_" ~ name][i]);
},
_updatePos: func(index, name)
{
me.setInt
(
"tf/t[" ~ index ~ "]",
getprop("/sim/gui/canvas/size[" ~ index ~ "]")
- me.get(name)
- me.get("size[" ~ index ~ "]")
);
},
_onClose : func(){
me.del();
},
_updateDecoration: func()
{
var border_radius = 9;
me.set("decoration-border", "25 1 1");
me.set("shadow-inset", int((1 - math.cos(45 * D2R)) * border_radius + 0.5));
me.set("shadow-radius", 5);
me.setBool("update", 1);
var canvas_deco = me.getCanvasDecoration();
canvas_deco.addEventListener("mousedown", func me.raise());
canvas_deco.set("blend-source-rgb", "src-alpha");
canvas_deco.set("blend-destination-rgb", "one-minus-src-alpha");
canvas_deco.set("blend-source-alpha", "one");
canvas_deco.set("blend-destination-alpha", "one");
var group_deco = canvas_deco.getGroup("decoration");
var title_bar = group_deco.createChild("group", "title_bar");
title_bar
.rect( 0, 0,
me.get("size[0]"),
me.get("size[1]"), #25,
{"border-top-radius": border_radius} )
.setColorFill(0.25,0.24,0.22)
.setStrokeLineWidth(0);
var style_dir = "gui/styles/AmbianceClassic/decoration/";
# close icon
var x = 10;
var y = 3;
var w = 19;
var h = 19;
var ico = title_bar.createChild("image", "icon-close")
.set("file", style_dir ~ "close_focused_normal.png")
.setTranslation(x,y);
ico.addEventListener("click", func me._onClose());
ico.addEventListener("mouseover", func ico.set("file", style_dir ~ "close_focused_prelight.png"));
ico.addEventListener("mousedown", func ico.set("file", style_dir ~ "close_focused_pressed.png"));
ico.addEventListener("mouseout", func ico.set("file", style_dir ~ "close_focused_normal.png"));
# title
me._title = title_bar.createChild("text", "title")
.set("alignment", "left-center")
.set("character-size", 14)
.set("font", "Orbitron/Orbitron-Bold.ttf")
.setTranslation( int(x + 1.5 * w + 0.5),
int(y + 0.5 * h + 0.5) );
var title = me.get("title", "Canvas Dialog");
me._node.getNode("title", 1).alias(me._title._node.getPath() ~ "/text");
me.set("title", title);
title_bar.addEventListener("drag", func(e) {
if( !ico.equals(e.target) )
me.move(e.deltaX, e.deltaY);
});
}
};
var COLOR = {};
COLOR["Red"] = "rgb(244,28,33)";
COLOR["Black"] = "#000000";
var SvgWidget = {
new: func(dialog,canvasGroup,name){
var m = {parents:[SvgWidget]};
m._class = "SvgWidget";
m._dialog = dialog;
m._listeners = [];
m._name = name;
m._group = canvasGroup;
return m;
},
removeListeners :func(){
foreach(l;me._listeners){
removelistener(l);
}
me._listeners = [];
},
setListeners : func(instance) {
},
init : func(instance=me){
},
deinit : func(){
me.removeListeners();
},
};
var BatteryWidget = {
new: func(dialog,canvasGroup,name){
var m = {parents:[BatteryWidget,SvgWidget.new(dialog,canvasGroup,name)]};
m._class = "BatteryWidget";
m._name = name;
if(m._name=="Front"){
m._nLevelPct = props.globals.initNode("/systems/electrical/battery-charge-percent-front",0.0,"DOUBLE");
}else{
m._nLevelPct = props.globals.initNode("/systems/electrical/battery-charge-percent-back",0.0,"DOUBLE");
}
m._fraction = m._nLevelPct.getValue();
m._capacity = 10.5; #10.5 kWh (per pack)
m._cFrame = m._group.getElementById(m._name~"_Frame");
m._cFrameV = m._group.getElementById(m._name~"_Frame_Vis");
m._cLevel = m._group.getElementById(m._name~"_Charge_Level");
m._cDataLevel = m._group.getElementById(m._name~"_Data_Level");
m._cDataAbs = m._group.getElementById(m._name~"_Data_Abs");
m._cDataLevel.setText(sprintf("%3d",m._fraction*100)~" %");
m._cDataAbs.setText(sprintf("%3.1f",m._fraction*m._capacity)~" kWh");
m._left = m._cFrame.get("coord[0]");
m._right = m._cFrame.get("coord[2]");
m._width = m._right - m._left;
return m;
},
setListeners : func(instance) {
append(me._listeners, setlistener(me._nLevelPct,func(n){me._onChargeLevelChange(n);},1,0) );
me._cFrameV.addEventListener("drag",func(e){me._onChargeInputChange(e);});
me._cLevel.addEventListener("drag",func(e){me._onChargeInputChange(e);});
me._cFrameV.addEventListener("wheel",func(e){me._onChargeInputChange(e);});
me._cLevel.addEventListener("wheel",func(e){me._onChargeInputChange(e);});
},
init : func(instance=me){
me.setListeners(instance);
},
deinit : func(){
me.removeListeners();
},
_onChargeLevelChange : func(n){
me._fraction = n.getValue();
me._cDataLevel.setText(sprintf("%3d",me._fraction*100)~" %");
me._cDataAbs.setText(sprintf("%3.1f",me._fraction*me._capacity)~" kWh");
me._cLevel.set("coord[2]", me._left + (me._width * me._fraction));
},
_onChargeInputChange : func(e){
var newFraction = 0;
if(e.type == "wheel"){
newFraction = me._fraction + (e.deltaY/me._width);
}else{
newFraction = me._fraction + (e.deltaX/me._width);
}
newFraction = clamp(newFraction,0.0,1.0);
me._nLevelPct.setValue(newFraction);
},
};
var WeightWidget = {
new: func(dialog,canvasGroup,name,widgets){
var m = {parents:[WeightWidget,SvgWidget.new(dialog,canvasGroup,name)]};
m._class = "WeightWidget";
m._widget = {};
foreach(w;keys(widgets)){
if(widgets[w] != nil){
if(widgets[w]._class == "PayloadWidget"){
m._widget[w] = widgets[w];
}
}
}
m._cWeightGrossKg = m._group.getElementById("Weight_Gross_Kg");
m._cWeightGrossLbs = m._group.getElementById("Weight_Gross_Lbs");
m._cWeightWarning = m._group.getElementById("Weight_Warning");
m._cWeightPilotKg = m._group.getElementById("Weight_Pilot_Kg");
m._cWeightPilotLbs = m._group.getElementById("Weight_Pilot_Lbs");
m._cWeightCopilotKg = m._group.getElementById("Weight_Copilot_Kg");
m._cWeightCopilotLbs = m._group.getElementById("Weight_Copilot_Lbs");
m._cWeightBaggageKg = m._group.getElementById("Weight_Baggage_Kg");
m._cWeightBaggageLbs = m._group.getElementById("Weight_Baggage_Lbs");
m._cCenterGravityX = m._group.getElementById("Center_Gravity_X");
m._cCenterGravityXWarning = m._group.getElementById("Center_Gravity_Warn");
m._nCGx = props.globals.initNode("/fdm/jsbsim/inertia/cg-x-mm-rp",0.0,"DOUBLE"); #calculated CG distance to reference point, set via system in Systems/dialogs.xml
m._nGross = props.globals.initNode("/fdm/jsbsim/inertia/weight-lbs");
m._nPilot = props.globals.initNode("/payload/weight[0]/weight-lb");
m._nCopilot = props.globals.initNode("/payload/weight[1]/weight-lb");
m._nBaggage = props.globals.initNode("/payload/weight[2]/weight-lb");
m._nTakeoff = props.globals.initNode("/limits/mtow-lbs");
m._cgX = 0;
m._pilot = 0;
m._copilot = 0;
m._baggage = 0;
m._gross = 0;
m._takeoff = 0;
m._takeoff = m._nTakeoff.getValue();
return m;
},
setListeners : func(instance) {
append(me._listeners, setlistener(maintainance._nGrossWeight,func(n){me._onGrossWeightChange(n);},1,0) );
append(me._listeners, setlistener(me._nCGx,func(n){me._onCGChange(n);},1,0) );
},
init : func(instance=me){
me.setListeners(instance);
},
deinit : func(){
me.removeListeners();
},
_onGrossWeightChange : func(n){
me._gross = me._nGross.getValue();
me._cWeightGrossKg.setText(sprintf("%5d",me._gross/KG2LB));
me._cWeightGrossLbs.setText(sprintf("%4d",me._gross));
me._pilot = me._nPilot.getValue();
me._cWeightPilotKg.setText(sprintf("%5d",me._pilot/KG2LB));
me._cWeightPilotLbs.setText(sprintf("%4d",me._pilot));
me._copilot = me._nCopilot.getValue();
me._cWeightCopilotKg.setText(sprintf("%5d",me._copilot/KG2LB));
me._cWeightCopilotLbs.setText(sprintf("%4d",me._copilot));
me._baggage = me._nBaggage.getValue();
me._cWeightBaggageKg.setText(sprintf("%5d",me._baggage/KG2LB));
me._cWeightBaggageLbs.setText(sprintf("%4d",me._baggage));
if (me._gross > me._takeoff){
me._cWeightWarning.show();
me._cWeightGrossKg.setColor(COLOR["Red"]);
me._cWeightGrossLbs.setColor(COLOR["Red"]);
}else{
me._cWeightWarning.hide();
me._cWeightGrossKg.setColor(COLOR["Black"]);
me._cWeightGrossLbs.setColor(COLOR["Black"]);
}
},
_onCGChange : func(n){
me._cgX = me._nCGx.getValue();
me._cCenterGravityX.setTranslation((me._cgX-200),0);
if(me._cgX>195 and me._cgX<368){
me._cCenterGravityXWarning.hide();
}else{
me._cCenterGravityXWarning.show();
}
},
};
var PayloadWidget = {
new: func(dialog,canvasGroup,name,index){
var m = {parents:[PayloadWidget,SvgWidget.new(dialog,canvasGroup,name)]};
m._class = "PayloadWidget";
m._index = index;
#debug.dump(m._listCategoryKeys);
m._nRoot = props.globals.getNode("/payload/weight["~m._index~"]");
m._nLable = m._nRoot.initNode("name","","STRING");
### HACK : listener on /payload/weight[0]/weight-lb not working
### two props one for fdm(weight-lb) one for dialog(nt-weight-lb) listener
m._nWeightFdm = m._nRoot.initNode("weight-lb",0.0,"DOUBLE");
m._weight = m._nWeightFdm.getValue(); # lbs
m._nWeight = m._nRoot.initNode("nt-weight-lb",m._weight,"DOUBLE");
m._nCapacity = m._nRoot.initNode("max-lb",0.0,"DOUBLE");
m._capacity = m._nCapacity.getValue();
m._fraction = m._weight / m._capacity;
m._cFrame = m._group.getElementById(m._name~"_Frame");
m._cFrame_Pick = m._group.getElementById(m._name~"_Frame_Pick");
m._cLevel = m._group.getElementById(m._name~"_Level");
m._cLBS = m._group.getElementById(m._name~"_Lbs");
m._cKG = m._group.getElementById(m._name~"_Kg");
m._cLBS.setText(sprintf("%3.0f",m._weight));
m._cKG.setText(sprintf("%3.0f",m._weight));
m._left = m._cFrame.get("coord[0]");
m._right = m._cFrame.get("coord[2]");
m._width = m._right - m._left;
return m;
},
setListeners : func(instance) {
### FIXME : use one property remove the HACK
append(me._listeners, setlistener(me._nWeight,func(n){me._onWeightChange(n);},1,0) );
me._cFrame_Pick.addEventListener("drag",func(e){me._onInputChange(e);});
me._cLevel.addEventListener("drag",func(e){me._onInputChange(e);});
me._cFrame_Pick.addEventListener("wheel",func(e){me._onInputChange(e);});
me._cLevel.addEventListener("wheel",func(e){me._onInputChange(e);});
},
init : func(instance=me){
me.setListeners(instance);
},
deinit : func(){
me.removeListeners();
},
setWeight : func(weight){
me._weight = weight;
### HACK : set two props
me._nWeight.setValue(me._weight);
me._nWeightFdm.setValue(me._weight);
},
_onWeightChange : func(n){
me._weight = me._nWeight.getValue();
#print("PayloadWidget._onWeightChange() ... "~me._weight);
me._fraction = me._weight / me._capacity;
me._cLBS.setText(sprintf("%3.0f",me._weight));
me._cKG.setText(sprintf("%3.0f",me._weight/KG2LB));
me._cLevel.set("coord[2]", me._left + (me._width * me._fraction));
},
_onInputChange : func(e){
var newFraction =0;
if(e.type == "wheel"){
newFraction = me._fraction + (e.deltaY/me._width);
}else{
newFraction = me._fraction + (e.deltaX/me._width);
}
newFraction = clamp(newFraction,0.0,1.0);
me._weight = me._capacity * newFraction;
me.setWeight(me._weight);
},
};
var maintainanceClass = {
new : func(){
var m = {parents:[maintainanceClass]};
m._nRoot = props.globals.initNode("/alphaelectro/dialog/config");
m._nGrossWeight = props.globals.initNode("/fdm/jsbsim/inertia/nt-weight-lbs",0.0,"DOUBLE"); #listener on weight-lbs not possible, set via system in Systems/fuelpayload.xml
m._name = "Maintainance";
m._title = "Maintainance";
m._fdmdata = {
grosswgt : "/fdm/jsbsim/inertia/weight-lbs",
payload : "/payload",
cg : "/fdm/jsbsim/inertia/cg-x-in",
};
m._listeners = [];
m._dlg = nil;
m._canvas = nil;
m._isOpen = 0;
m._isNotInitialized = 1;
m._widget = {
Front : nil,
Rear : nil,
Pilot : nil,
Copilot : nil,
Baggage : nil,
weight : nil,
};
return m;
},
toggle : func(){
if(me._dlg != nil){
if (me._dlg._isOpen){
me.close();
}else{
me.open();
}
}else{
me.open();
}
},
close : func(){
me._dlg.del();
me._dlg = nil;
},
removeListeners :func(){
foreach(l;me._listeners){
removelistener(l);
}
me._listeners = [];
},
setListeners : func(instance) {
},
_onClose : func(){
me.removeListeners();
me._dlg.del();
foreach(widget;keys(me._widget)){
if(me._widget[widget] != nil){
me._widget[widget].deinit();
me._widget[widget] = nil;
}
}
},
open : func(){
if(getprop("/gear/gear[1]/wow") == 1){
me.openBAP();
}else{
screen.log.write("Maintainance dialog not available in air!");
}
},
openBAP : func(){
me._dlg = MyWindow.new([1024, 512], "dialog");
me._dlg._onClose = func(){
maintainance._onClose();
}
me._dlg.set("title", "Maintainance");
me._dlg.move(100,100);
me._canvas = me._dlg.createCanvas();
me._canvas.set("background", "#c5c5c5ff");
me._group = me._canvas.createGroup();
canvas.parsesvg(me._group, "Aircraft/A320-family/gui/dialogs/maintainance.svg",{"font-mapper": font_mapper});
me._widget.Front = BatteryWidget.new(me,me._group,"Front");
me._widget.Rear = BatteryWidget.new(me,me._group,"Rear");
me._widget.Pilot = PayloadWidget.new(me,me._group,"Pilot",0);
me._widget.Copilot = PayloadWidget.new(me,me._group,"Copilot",1);
me._widget.Baggage = PayloadWidget.new(me,me._group,"Baggage",2);
me._widget.weight = WeightWidget.new(me,me._group,"Weight",me._widget);
foreach(widget;keys(me._widget)){
if(me._widget[widget] != nil){
me._widget[widget].init();
}
}
},
_onNotifyChange : func(n){
},
};
var maintainance = maintainanceClass.new();

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 328 KiB