Update view.screenWidthCompens
* make into singleton class * make sure FOV changes take place *immediately* when required * current FOV is scaled with changes, though being preserved: resizing window and going back ends up with the same FOV
This commit is contained in:
parent
197e74b6ce
commit
9a3bf2d0a7
2 changed files with 70 additions and 47 deletions
115
Nasal/view.nas
115
Nasal/view.nas
|
@ -233,7 +233,7 @@ var manager = {
|
||||||
me.current.handler.start();
|
me.current.handler.start();
|
||||||
if (hasmember(me.current.handler, "update"))
|
if (hasmember(me.current.handler, "update"))
|
||||||
me._loop_(me.loopid += 1);
|
me._loop_(me.loopid += 1);
|
||||||
# resetFOV();
|
screenWidthCompens.update();
|
||||||
},
|
},
|
||||||
reset : func {
|
reset : func {
|
||||||
if (hasmember(me.current.handler, "reset"))
|
if (hasmember(me.current.handler, "reset"))
|
||||||
|
@ -652,57 +652,71 @@ var point = {
|
||||||
# view.ScreenWidthCompens: optional FOV compensation for wider screens.
|
# view.ScreenWidthCompens: optional FOV compensation for wider screens.
|
||||||
# It keeps an equivalent of 55° FOV on a 4:3 zone centered on the screen
|
# 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.
|
# 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 screenWidthCompens = {
|
||||||
var oldW = 0;
|
defaultFov: nil,
|
||||||
var oldH = 0;
|
oldW: nil, oldH: nil, oldOpt: nil,
|
||||||
var fovStore = {};
|
assumedW: 4, assumedH: 3,
|
||||||
|
fovStore: [],
|
||||||
|
lastViewStatus: {},
|
||||||
|
statusNode: nil, # = /sim/current-view/field-of-view-compensation
|
||||||
|
getStatus: func me.statusNode.getValue(),
|
||||||
|
setStatus: func(state) me.statusNode.setValue(state),
|
||||||
|
calcNewFov: func(fov=55, oldW=nil, oldH=nil, w=nil, h=nil) {
|
||||||
|
if (w == nil) w = getprop("/sim/rendering/camera-group/camera/viewport/width");
|
||||||
|
if (h == nil) h = getprop("/sim/rendering/camera-group/camera/viewport/height");
|
||||||
|
if (oldW == nil) oldW = me.assumedW;
|
||||||
|
if (oldH == nil) oldH = me.assumedH;
|
||||||
|
if (w/h == oldW/oldH or h > w) return fov;
|
||||||
|
else return math.atan2(w/h, oldW/oldH / math.tan(fov * D2R)) * R2D;
|
||||||
|
},
|
||||||
|
init: func() {
|
||||||
|
me.defaultFov = getprop("/sim/current-view/config/default-field-of-view-deg");
|
||||||
|
me.statusNode = props.globals.getNode("/sim/current-view/field-of-view-compensation", 1);
|
||||||
|
me.oldW = getprop("/sim/rendering/camera-group/camera/viewport/width");
|
||||||
|
me.oldH = getprop("/sim/rendering/camera-group/camera/viewport/height");
|
||||||
|
|
||||||
var screenWidthCompens = func(status) {
|
setsize(me.fovStore, size(views));
|
||||||
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) {
|
forindex (var i; views) {
|
||||||
var defaultFovNode = views[i].getNode("config/default-field-of-view-deg", 1);
|
me.fovStore[i] = views[i].getNode("config/default-field-of-view-deg", 1).getValue() or 55;
|
||||||
fovStore[i] = defaultFovNode.getValue();
|
me.lastViewStatus[i] = { w:me.assumedW, h:me.assumedH };
|
||||||
}
|
}
|
||||||
} elsif (status == 1) {
|
me.update(opt:nil, force:1);
|
||||||
opt = ! opt;
|
},
|
||||||
setprop("/sim/current-view/field-of-view-compensation", opt);
|
toggle: func() me.update(!me.getStatus(), 1),
|
||||||
if (! opt) {
|
update: func(opt=nil, force=0) {
|
||||||
forindex (var i; views) {
|
if (opt == nil)
|
||||||
var defaultFovNode = views[i].getNode("config/default-field-of-view-deg", 1);
|
opt = me.getStatus();
|
||||||
defaultFovNode.setValue(fovStore[i]);
|
else me.setStatus(opt);
|
||||||
|
var w = getprop("/sim/rendering/camera-group/camera/viewport/width");
|
||||||
|
var h = getprop("/sim/rendering/camera-group/camera/viewport/height");
|
||||||
|
# Update config/default-field-of-view-deg nodes if state changed:
|
||||||
|
if (force or me.oldOpt != opt or me.oldW/me.oldH != w/h) {
|
||||||
|
me.oldW = w;
|
||||||
|
me.oldH = h;
|
||||||
|
me.oldOpt = opt;
|
||||||
|
if (!opt) {
|
||||||
|
setprop("/sim/current-view/config/default-field-of-view-deg", me.defaultFov);
|
||||||
|
forindex (var i; views)
|
||||||
|
views[i].setValue("config/default-field-of-view-deg", me.fovStore[i]);
|
||||||
|
} else {
|
||||||
|
setprop("/sim/current-view/config/default-field-of-view-deg",
|
||||||
|
me.calcNewFov(fov:me.defaultFov, w:w, h:h));
|
||||||
|
forindex (var i; views)
|
||||||
|
views[i].setValue("config/default-field-of-view-deg",
|
||||||
|
me.calcNewFov(fov:me.fovStore[i], w:w, h:h));
|
||||||
}
|
}
|
||||||
var vn = getprop("/sim/current-view/view-number");
|
|
||||||
setprop("/sim/current-view/field-of-view", fovStore[vn]);
|
|
||||||
}
|
}
|
||||||
} elsif (status == 2 and ! opt) {
|
# Update this view if necessary:
|
||||||
return;
|
if (!opt) (w,h) = (me.assumedW,me.assumedH); # back to default FOV
|
||||||
}
|
var thisview = me.lastViewStatus[index];
|
||||||
var w = getprop("/sim/rendering/camera-group/camera/viewport/width");
|
if (thisview.w/thisview.h != w/h) {
|
||||||
var h = getprop("/sim/rendering/camera-group/camera/viewport/height");
|
fovProp.setValue(me.calcNewFov(fovProp.getValue(), thisview.w, thisview.h, w, h))
|
||||||
if (! opt) {
|
and
|
||||||
setprop("/sim/current-view/config/default-field-of-view-deg", defaultFov);
|
((thisview.opt,thisview.w,thisview.h) = (opt,w,h));
|
||||||
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 {
|
_setlistener("/sim/signals/nasal-dir-initialized", func {
|
||||||
|
@ -715,10 +729,19 @@ _setlistener("/sim/signals/nasal-dir-initialized", func {
|
||||||
}, 1);
|
}, 1);
|
||||||
|
|
||||||
props.globals.initNode("/position/altitude-agl-ft"); # needed by Fly-By View
|
props.globals.initNode("/position/altitude-agl-ft"); # needed by Fly-By View
|
||||||
|
screenWidthCompens.init();
|
||||||
manager.init();
|
manager.init();
|
||||||
manager.register("Fly-By View", fly_by_view_handler);
|
manager.register("Fly-By View", fly_by_view_handler);
|
||||||
manager.register("Model View", model_view_handler);
|
manager.register("Model View", model_view_handler);
|
||||||
screenWidthCompens(0);
|
});
|
||||||
|
_setlistener("/sim/signals/reinit", func {
|
||||||
|
screenWidthCompens.update(opt:nil,force:1);
|
||||||
|
});
|
||||||
|
_setlistener("/sim/startup/xsize", func {
|
||||||
|
screenWidthCompens.update();
|
||||||
|
});
|
||||||
|
_setlistener("/sim/startup/ysize", func {
|
||||||
|
screenWidthCompens.update();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -214,7 +214,7 @@
|
||||||
<property>sim/current-view/field-of-view-compensation</property>
|
<property>sim/current-view/field-of-view-compensation</property>
|
||||||
<binding>
|
<binding>
|
||||||
<command>nasal</command>
|
<command>nasal</command>
|
||||||
<script>view.screenWidthCompens(1)</script>
|
<script>view.screenWidthCompens.toggle()</script>
|
||||||
</binding>
|
</binding>
|
||||||
</checkbox>
|
</checkbox>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue