Skip to content

Commit

Permalink
feat: add horizontal FOV converter
Browse files Browse the repository at this point in the history
  • Loading branch information
wertiop121 committed Jul 28, 2024
1 parent ed70c78 commit e819518
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 11 deletions.
18 changes: 17 additions & 1 deletion layout/pages/settings/video.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

<scripts>
<include src="file://{scripts}/pages/settings/page.js" />
<include src="file://{scripts}/util/math.js" />
<include src="file://{scripts}/pages/settings/fov.js" />
</scripts>

<Panel class="settings-page">
Expand All @@ -31,7 +33,21 @@
<Label class="settings-group__title" text="#Settings_Video" />
</Panel>

<SettingsSlider text="#Settings_Video_FOV" min="50" max="130" convar="fov_desired" hasdocspage="false" />
<SettingsSlider id="FOV" text="#Settings_Video_FOV" min="50" max="130" convar="fov_desired" hasdocspage="false" onvaluechanged="Fov.updateFOV()" />

<Panel class="settings-group__combo" onload="Fov.loadSettings()" infotitle="#Settings_Video_Horizontal_FOV" infomessage="#Settings_Video_Horizontal_FOV_Info">
<Panel class="settings-enum">
<Label text="#Settings_Video_Horizontal_FOV" class="settings-enum__title" />
<Panel class="settings-enum__values">
<TextEntry id="FOV_Horizontal" class="textentry settings-slider__textentry HasInput ml-4" multiline="false" textmode="numeric" oninputsubmit="Fov.updateHorizontalFov()" />
<DropDown id="FOV_Horizontal_AspectRatioEnum" class="dropdown ml-4" menuclass="dropdown-menu" onuserinputsubmit="Fov.updateFOV()">
<Label text="#Settings_Video_AspectRatio_Normal" value="0" id="aspectratio0" />
<Label text="#Settings_Video_AspectRatio_16x9" value="1" id="aspectratio1" />
<Label text="#Settings_Video_AspectRatio_16x10" value="2" id="aspectratio2" />
</DropDown>
</Panel>
</Panel>
</Panel>

<SettingsSlider text="#Settings_Video_MaxFPS" min="0" max="400" convar="fps_max" infomessage="#Settings_Video_MaxFPS_Info" hasdocspage="false" />

Expand Down
62 changes: 62 additions & 0 deletions scripts/pages/settings/fov.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
class Fov {
static panels = {
/** @type {SettingsSlider} @static */
fov: $('#FOV'),
/** @type {TextEntry} @static */
horizontalFov: $('#FOV_Horizontal'),
aspectRatio: $('#FOV_Horizontal_AspectRatioEnum')
};

static loadSettings() {
this.panels.aspectRatio.SetSelected('aspectratio1');
this.updateFOV();
}

static aspectRatio() {
const id = this.panels.aspectRatio.GetSelected().id;
switch (id) {
case 'aspectratio0':
return 4 / 3;
case 'aspectratio1':
return 16 / 9;
case 'aspectratio2':
return 16 / 10;
}
return Number.NaN;
}

// based on https://casualhacks.net/Source-FOV-calculator.html
static fovToHorizontal(fov) {
const ratioRatio = this.aspectRatio() / (4 / 3);
return 2 * rad2deg(Math.atan(Math.tan(deg2rad(fov) / 2) * ratioRatio));
}

static horizontalToFov(horizontalFov) {
const ratioRatio = this.aspectRatio() / (4 / 3);
return 2 * rad2deg(Math.atan(Math.tan(deg2rad(horizontalFov) / 2) / ratioRatio));
}

static updateFOV() {
if (!this.panels.fov || !this.panels.horizontalFov) return;

let fov = GameInterfaceAPI.GetSettingFloat('fov_desired');
fov = Math.round(this.fovToHorizontal(fov));

if (!Number.isNaN(fov)) {
this.panels.horizontalFov.text = fov;
}
}

static updateHorizontalFov() {
if (!this.panels.fov || !this.panels.horizontalFov) return;

let fov = Number.parseFloat(this.panels.horizontalFov.text);
fov = Math.round(this.horizontalToFov(fov));

if (!Number.isNaN(fov)) {
const fovText = this.panels.fov.FindChildTraverse('Value');
fovText.text = fov;
fovText.Submit();
}
}
}
18 changes: 8 additions & 10 deletions scripts/pages/settings/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -244,9 +244,7 @@ class MainMenuSettings {

static initPanelsRecursive(panel) {
// Initialise info panel event handlers
if (this.isSettingsPanel(panel) || this.isSpeedometerPanel(panel)) {
this.setPanelInfoEvents(panel);
}
this.setPanelInfoEvents(panel);

// Initialise all the settings using persistent storage
// Only Enum and EnumDropDown are currently supported, others can be added when/if needed
Expand Down Expand Up @@ -312,15 +310,19 @@ class MainMenuSettings {

static setPanelInfoEvents(panel) {
const message = panel.GetAttributeString('infomessage', '');
const title = panel.GetAttributeString('infotitle', '');

// Don't set events if there's no info to show
if (!this.isSettingsPanel(panel) && message === '' && title === '' && !panel.convar && !panel.bind) return;

// Default to true if not set
const hasDocs = !(panel.GetAttributeString('hasdocspage', '') === 'false');

panel.SetPanelEvent('onmouseover', () => {
// Set onmouseover events for all settings panels
this.showInfo(
// If a panel has a specific title use that, if not use the panel's name. Child ID names vary between panel types, blame Valve
panel.GetAttributeString('infotitle', '') ||
panel.FindChildTraverse('Title')?.text ||
panel.FindChildTraverse('title')?.text,
title || panel.FindChildTraverse('Title')?.text || panel.FindChildTraverse('title')?.text,
message,
panel.convar ?? panel.bind,
hasDocs,
Expand Down Expand Up @@ -434,8 +436,4 @@ class MainMenuSettings {
'ConVarColorDisplay'
].includes(panel.paneltype);
}

static isSpeedometerPanel(panel) {
return ['SpeedometersContainer', 'RangeColorProfilesContainer'].includes(panel.id);
}
}
8 changes: 8 additions & 0 deletions scripts/util/math.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,11 @@ function mapAngleToScreenDist(angle: number, fov: number, length: number, scale:
return Math.round((1 + Math.tan(angle * 0.5) / Math.tan(fov * 0.5)) * screenDist * 0.5);
}
}

function deg2rad(x: number): number {
return (x / 180) * Math.PI;
}

function rad2deg(x: number): number {
return (x * 180) / Math.PI;
}

0 comments on commit e819518

Please sign in to comment.