diff --git a/Nasal/view.nas b/Nasal/view.nas
index 6af58faa2..09244dd11 100644
--- a/Nasal/view.nas
+++ b/Nasal/view.nas
@@ -6,7 +6,7 @@
var index = nil; # current view index
var views = nil; # list of all view branches (/sim/view[n]) as props.Node
var current = nil; # current view branch (e.g. /sim/view[1]) as props.Node
-
+var fovProp = nil;
var hasmember = func(class, member) {
if (contains(class, member))
@@ -235,6 +235,7 @@ var manager = {
me.current.handler.start();
if (hasmember(me.current.handler, "update"))
me._loop_(me.loopid += 1);
+ resetFOV();
},
reset : func {
if (hasmember(me.current.handler, "reset"))
@@ -638,7 +639,61 @@ var point = {
-var fovProp = nil;
+##
+# view.ScreenWidthCompens: optional FOV compensation for wider screens.
+# It keeps an equivalent of 55° FOV on a 4:3 zone centered on the screen
+# whichever is the screen width/height ratio. Works only if width >= height.
+#
+# status: 0=Init, 1=toggle option, 2=waiting for the window size to change.
+
+var defaultFov = nil;
+var oldW = 0;
+var oldH = 0;
+var fovStore = {};
+
+var screenWidthCompens = func(status) {
+ var opt = getprop("/sim/current-view/field-of-view-compensation");
+ if (status == 0) {
+ defaultFov = getprop("/sim/current-view/config/default-field-of-view-deg");
+ forindex (var i; views) {
+ var defaultFovNode = views[i].getNode("config/default-field-of-view-deg", 1);
+ fovStore[i] = defaultFovNode.getValue();
+ }
+ } elsif (status == 1) {
+ opt = ! opt;
+ setprop("/sim/current-view/field-of-view-compensation", opt);
+ if (! opt) {
+ forindex (var i; views) {
+ var defaultFovNode = views[i].getNode("config/default-field-of-view-deg", 1);
+ defaultFovNode.setValue(fovStore[i]);
+ }
+ var vn = getprop("/sim/current-view/view-number");
+ setprop("/sim/current-view/field-of-view", fovStore[vn]);
+ }
+ } elsif (status == 2 and ! opt) {
+ return;
+ }
+ var w = getprop("/sim/rendering/camera-group/camera/viewport/width");
+ var h = getprop("/sim/rendering/camera-group/camera/viewport/height");
+ if (! opt) {
+ setprop("/sim/current-view/config/default-field-of-view-deg", defaultFov);
+ return;
+ }
+ if ( w != oldW or h != oldH or status == 1) {
+ oldW = w;
+ oldH = h;
+ d = 1.28066 * h; # 1.28066 = 4/3 (width/height ratio) / 2 / tan(55°)
+ newFov = 2 * math.atan2( w / h * h / 2, d) * R2D;
+ setprop("/sim/current-view/config/default-field-of-view-deg", newFov);
+ forindex (var i; views) {
+ var defaultFovNode = views[i].getNode("config/default-field-of-view-deg", 1);
+ defaultFovNode.setValue(newFov);
+ }
+ fovProp.setValue(newFov);
+ }
+ settimer(func { screenWidthCompens(2); }, 1);
+}
+
_setlistener("/sim/signals/nasal-dir-initialized", func {
@@ -654,6 +709,7 @@ _setlistener("/sim/signals/nasal-dir-initialized", func {
manager.init();
manager.register("Fly-By View", fly_by_view_handler);
manager.register("Model View", model_view_handler);
+ screenWidthCompens(0);
});
diff --git a/gui/dialogs/view.xml b/gui/dialogs/view.xml
index 1bd235bd3..7ef301cfb 100644
--- a/gui/dialogs/view.xml
+++ b/gui/dialogs/view.xml
@@ -87,6 +87,25 @@
+
+
+ hbox
+
+ sim/current-view/field-of-view-compensation
+ false
+
+ nasal
+
+
+
+
+
+
+
+
+
+
+