Nasal スクリプト集

概要

ffe.nas は、燃費、予測航続距離及び予測後続時間をダイアログで表示します。ダイアログ部分はおまけなので適当ですが、ご勘弁を。

インストール方法

添付ファイルのソース (ffe.nas) を ~/.fgfs/Nasal/ffe.nas として保存してください (Windows の場合は C:/Documents and Settings/<ユーザ名>/Applciation Data/flightgear.org/Nasal/ffe.nas)。 あとは FlightGear を起動するだけで準備完了です。特に機体側の変更は必要ありません。

使用方法

起動後、Nasal コンソールから以下のコマンドを入力し Execute ボタンを押せばダイアログが表示されます。

ffe.Dialog.show();

毎回入力するのは面倒ですので、一度 ESC を押してフライトギアを終了させると、次回からは Nasal コンソールを開くだけで上記コマンドが表示されますので、Execute ボタンを押すだけで起動するようになります。

処理概要

処理は大きく分けて2つです。1つは燃費等の計算処理で、もう1つはダイアログ表示処理です。 計算処理では、settimer で 5秒毎に表示する3つの値を計算しています。燃費は瞬間燃費のことで「対地速度 / 燃料消費量」とから計算していまして、単位は nm / us-gal (ガロン) です。予測航続距離は「燃費×燃料の残量」でして、単位は us-gal (ガロン) です。要望があればガロン単位に変更します。予想後続時間は「燃料の残量÷燃料消費量」で、書式は HH:MM:SSです。

ソース

このソースは参考に表示しているものです。ダウンロードは下の添付ファイルをクリックして保存してください。

###############################################################################
# ffe.nas by Tatsuhiro Nishioka
# - Shows Fuel Efficiency, Estimate Cruise Range, and Estimate Cruise Time.
# 
# Copyright (C) 2008 Tatsuhiro Nishioka (tat dot fgmacosx at gmail dot com)
# This file is licensed under the GPL license version 2 or later.
# 
###############################################################################


var Dialog = {};
Dialog.init = func (x = nil, y = nil) {
  me.x = x;
  me.y = y;
  me.bg = [0, 0, 0, 0.3];
  me.fg = [[0.9, 0.9, 0.2, 1],[1.0, 1.0, 1.0, 1.0]];
  me.name = "Fuel Efficiency";
  me.namenode = props.Node.new({"dialog-name" : me.name });
  me.dialog = nil;
  me.node = props.globals.getNode("/sim/gui/dialogs/fuel-efficiency");
  me.properties = [
    { property : "efficiency", name : "Efficiency",            format : "%1.4f", unit : "nm/gal", halign : "right" },
    { property : "range",      name : "Estinate Cruise Rqnge", format : "%05d",  unit : "nm",     halign : "right" },
    { property : "time",       name : "Estimate Cruise Time",  format : "%8s",   unit : "time",    halign : "right" }
  ];
  
  me.listeners=[];
  append(me.listeners, setlistener("/sim/startup/xsize", func { me._redraw() }));
  append(me.listeners, setlistener("/sim/startup/ysize", func { me._redraw() }));
}

Dialog.create = func {
  if (me.dialog != nil)
    me.close();
  
  me.dialog = gui.Widget.new();
  me.dialog.set("name", me.name);
  if (me.x != nil)
    me.dialog.set("x", me.x);
  if (me.y != nil)
    me.dialog.set("y", me.y);
  
  me.dialog.set("layout", "vbox");
  me.dialog.set("default-padding", 0);
  
  me.dialog.setColor(me.bg[0], me.bg[1], me.bg[2], me.bg[3]);
  
  var titlebar=me.dialog.addChild("group");
  titlebar.set("layout", "hbox");
  
  titlebar.addChild("empty").set("stretch", 1);
  titlebar.addChild("text").set("label", "Fuel Efficiency");
  
  var w = titlebar.addChild("button");
  w.node.setValues({"pref-width": 16, "pref-height": 16, legend: "", default: 0}); # key: "esc" is no good
  w.setBinding("nasal", "ffe.Dialog.destroy()");
  
  me.dialog.addChild("hrule");
  
  var content = me.dialog.addChild("group");
  content.set("layout", "table");
  content.set("defalt-padding", 0);
  var row = 0;
  
  foreach (var property; me.properties) {
    var col = 0;
    foreach (var column; ["name", "property", "unit"]) {
      var w = content.addChild("text");
      if (column == "property") {
        w.node.setValues({row: row, col: col, label: "--------", live : 1, 
                          format : property.format, halign : property.halign,
                          property: me.node.getPath() ~ "/" ~ property.property});
      } else {
        var label = property[column]; 
        w.node.setValues({row: row, col: col, label : label, format : "%s", halign : "left"});
      }
      col += 1;
    }
    row += 1;
  }
  
  fgcommand("dialog-new", me.dialog.prop());
  fgcommand("dialog-show", me.namenode);
}

Dialog._redraw = func {
  if (me.dialog != nil) {
    me.close();
    me.create();
  }
}

Dialog.close = func {
  fgcommand("dialog-close", me.namenode);
}

Dialog.destroy = func {
  me.close();
  foreach(var l; me.listeners)
    removelistener(l);
  delete(gui.dialog, "\"" ~ me.name ~ "\"");
}

Dialog.show = func {
  me.init(-2, -2);
  me.create();
}

var FuelEfficiency = {};
FuelEfficiency.new = func(interval) {
  obj = { parents : [FuelEfficiency] };
  obj.speedNode = props.globals.getNode("velocities/groundspeed-kt");
  obj.engineRunningNode = props.globals.getNode("engines/engine/running");
  obj.interval = interval;
  obj.fuelFlow = 0;
  obj.fuelEfficiency = 0;
  obj.range = 0;
  settimer(func { obj.update(); }, 5);
  return obj;
}

FuelEfficiency.update = func {
  me.updateFuelEfficiency();
  me.calcTotalFuel();
  me.estimateCruiseRange();
  me.estimateCruiseTime();
  settimer(func { me.update(); }, me.interval);
}

#
# calculate fuel efficiency (nm/us-gal)
#
FuelEfficiency.updateFuelEfficiency = func {
  var fuelFlow = 0;
  var groundSpeed = getprop("/velocities/groundspeed-kt");
  var engineRunning = getprop("/engines/engine/running");
  if (engineRunning == nil) {
    engineRunning = 0;
  } else {
    foreach(var engine; props.globals.getNode("/engines").getChildren("engine")) {
      fuelFlow += me.getFuelFlow(engine);
    }
  }
  me.fuelFlow = fuelFlow;
  me.fuelEfficiency = (engineRunning * fuelFlow == 0) ? 0 : (groundSpeed / fuelFlow);
  setprop("/sim/gui/dialogs/fuel-efficiency/efficiency", me.fuelEfficiency);
}

FuelEfficiency.getFuelFlow = func(engine) {
  var flowNode = engine.getNode("fuel-flow-gph");
  var flow = 0;
  if (flowNode != nil)
    flow = flowNode.getValue();
  if (flow == 0 or flowNode == nil) {
    flowNode = engine.getNode("fuel-flow_pph");
    if (flowNode != nil)
      flow = flowNode.getValue() / 5.92;
    else
      flow = 0;
  }
  return flow;
}

#
# calculate total fuel (us-gal)
#
FuelEfficiency.calcTotalFuel = func {
  var totalFuel = 0;
  foreach (var tank; props.globals.getNode("/consumables/fuel").getChildren("tank")) {
    var fuelLevelNode = tank.getNode("level-lb");
    if (fuelLevelNode != nil) {
      totalFuel += fuelLevelNode.getValue() / 5.92;
    }
  }
  setprop("/sim/gui/dialogs/fuel-efficiency/fuel-gal", totalFuel);
  me.totalFuel = totalFuel;
}

FuelEfficiency.estimateCruiseRange = func {
  var range = me.fuelEfficiency * me.totalFuel;
  setprop("/sim/gui/dialogs/fuel-efficiency/range", range);
  return range;
}

FuelEfficiency.estimateCruiseTime = func {
  var time = 0;
  if (me.totalFuel > 0) {
    time = me.totalFuel / me.fuelFlow * 60;
  }
  var hour = int(time / 60);
  var min = int(math.mod(time, 60));
  var sec = int(math.mod(time * 60, 60));
  setprop("/sim/gui/dialogs/fuel-efficiency/time", sprintf("%02d:%02d:%02d", hour, min, sec));
  return 
}

var efficiency = nil;

_setlistener("/sim/signals/fdm-initialized", func {
  efficiency = FuelEfficiency.new(1);
});

添付ファイル: fileffe.nas 519件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2008-05-05 (月) 16:02:12 (4002d)