From f71c76c3061046ed440b6e65cfb7bc13f0c4c595 Mon Sep 17 00:00:00 2001 From: German Khokhlov Date: Mon, 2 Nov 2026 13:19:21 +0400 Subject: [PATCH] Restore engine-specific Cinematic sharpness across live switches --- scripts/qa-engine-switch.mjs | 27 +++++++++++++++++++++++++++ src/sharelink.js | 13 +++++++++++-- src/ui/shareLinks.test.mjs | 19 +++++++++++++++++++ src/ui/visualSettings.js | 30 ++++++++++++------------------ 4 files changed, 69 insertions(+), 20 deletions(-) diff --git a/scripts/qa-engine-switch.mjs b/scripts/qa-engine-switch.mjs index 681e57b0b..74e46bea7 100644 --- a/scripts/qa-engine-switch.mjs +++ b/scripts/qa-engine-switch.mjs @@ -104,14 +104,41 @@ try { } await page.goto(base.href, { waitUntil: 'domcontentloaded' }); await ready('cesium'); + const sharpen = () => + page.evaluate( + () => window.__godsEyeView.styleManager.getControlState().sharpen, + ); + await page.evaluate(() => { + const style = window.__godsEyeView.styleManager; + style.setStyle('retro'); + style.setStyle('normal'); + }); + assert.deepEqual(await sharpen(), { enabled: true, intensityPct: 49 }); await switchTo('navara'); + assert.deepEqual(await sharpen(), { enabled: true, intensityPct: 80 }); + assert.ok( + await page.evaluate( + () => + Math.abs(window.__godsEyeView.engine.render.sharpen().amount - 1.7) < + 1e-6, + ), + ); assert.equal(await stored(), 'navara'); await page.goBack({ waitUntil: 'domcontentloaded' }); await ready('cesium'); + assert.equal((await sharpen()).intensityPct, 49); await page.goForward(); await ready('navara'); + assert.equal((await sharpen()).intensityPct, 80); + await page.evaluate(() => + window.__godsEyeView.styleManager.setSharpen({ + enabled: false, + intensityPct: 49, + }), + ); await switchTo('cesium'); await switchTo('navara'); + assert.deepEqual(await sharpen(), { enabled: false, intensityPct: 49 }); await page.goto(base.href, { waitUntil: 'domcontentloaded' }); await ready('navara'); await switchTo('cesium'); diff --git a/src/sharelink.js b/src/sharelink.js index 82594de6e..0aeddca5d 100644 --- a/src/sharelink.js +++ b/src/sharelink.js @@ -12,6 +12,7 @@ import { decodeLayerStateParams, encodeLayerStateParams, } from './data/layerState.js'; +import { ENGINE_SHARPEN_DEFAULT } from './ui/visualPresets.js'; import { STYLE_URL_NAMES } from './view/index.js'; import { SHARE_VIEW_PANELS, @@ -223,7 +224,10 @@ export class ShareLinkManager { sharpen: params.get('sharpen') === '1', bloomIntensity: parseOr(params.get('bi'), LEGACY_BLOOM_FALLBACK), bloomVersion: parseOr(params.get('bv'), 1), - sharpenIntensity: parseOr(params.get('si'), 49), + sharpenIntensity: + params.get('siAuto') === '1' + ? ENGINE_SHARPEN_DEFAULT + : parseOr(params.get('si'), 49), hudVariant: params.get('hud') || 'tactical', hudVisible: params.get('hv') === '1', detectionMode: restoredDetection.enabled @@ -540,8 +544,10 @@ export class ShareLinkManager { this._bloomIntensity = extras.bloomIntensity; if (typeof extras.bloomVersion === 'number') this._bloomVersion = extras.bloomVersion; - if (typeof extras.sharpenIntensity === 'number') + if (typeof extras.sharpenIntensity === 'number') { this._sharpenIntensity = extras.sharpenIntensity; + this._sharpenFollowsEngine = extras.sharpenFollowsEngine === true; + } if (typeof extras.hudVariant === 'string') this._hudVariant = extras.hudVariant; if (typeof extras.hudVisible === 'boolean') @@ -646,6 +652,9 @@ export class ShareLinkManager { const url = parseSharePath(new URL(window.location.href).pathname) ? appRootUrl(window.location.href) : new URL(window.location.href); + // The live URL follows the active engine's preset. Copied shares keep + // the rendered numeric value from _buildHashParams. + if (this._sharpenFollowsEngine) params.set('siAuto', '1'); url.hash = params.toString(); this._knownHash = url.hash.slice(1); history.replaceState(null, '', url.href); diff --git a/src/ui/shareLinks.test.mjs b/src/ui/shareLinks.test.mjs index b15c35411..b992e7a9c 100644 --- a/src/ui/shareLinks.test.mjs +++ b/src/ui/shareLinks.test.mjs @@ -402,6 +402,25 @@ test('a shared vessel is selected once the vessel feed has it', async (t) => { assert.match(page.notices.at(-1), /^366999712 isn't reporting now/); }); +test('the live preset follows the engine while a copied link keeps its rendered sharpness', (t) => { + const { location } = installPage(t, 'https://gev.example/?engine=navara'); + const manager = new ShareLinkManager(viewerEngine(fakeViewer())); + t.after(() => manager.destroy()); + manager.onToggleChange(false, true, { + sharpenIntensity: 80, + sharpenFollowsEngine: true, + }); + manager.flush(); + assert.equal(new URLSearchParams(location.hash.slice(1)).get('siAuto'), '1'); + const code = parseSharePath(new URL(manager.buildLink()).pathname).code; + assert.equal(decodeShareView(code).state.sharpenIntensity, 80); + manager.onToggleChange(false, true, { sharpenIntensity: 80 }); + manager.flush(); + const params = new URLSearchParams(location.hash.slice(1)); + assert.equal(params.has('siAuto'), false); + assert.equal(params.get('si'), '80'); +}); + test('the share button links to /share/, following the followed entity', (t) => { installPage(t, 'https://gev.example/?lang=ru#v=2&lat=1&lon=2'); const manager = new ShareLinkManager(viewerEngine(fakeViewer())); diff --git a/src/ui/visualSettings.js b/src/ui/visualSettings.js index 74ef07e13..01774a00a 100644 --- a/src/ui/visualSettings.js +++ b/src/ui/visualSettings.js @@ -1,5 +1,6 @@ import { clampScopeFeatherPct } from '../scopeMaskPolicy.js'; import { + ENGINE_SHARPEN_DEFAULT, STYLE_STATUS_LABELS, presetSharpenIntensity, } from './visualPresets.js'; @@ -104,8 +105,7 @@ export class VisualSettings { const intensity = decodeBloomIntensity(bloomIntensity, bloomVersion); this._setBloomIntensity(intensity, { syncShare: false }); } - if (typeof sharpenIntensity === 'number') - this._setSharpenIntensity(sharpenIntensity, { syncShare: false }); + this._setSharpenIntensity(sharpenIntensity, { syncShare: false }); if (typeof bloom === 'boolean') this._setBloomEnabled(bloom); if (typeof sharpen === 'boolean') this._setSharpenEnabled(sharpen); if (hudVariant) this._setHudVariant(hudVariant); @@ -210,6 +210,7 @@ export class VisualSettings { }); // The sharpen amount as a whole percentage. VisualEffects keeps the // fraction it applies, and drops writes once it is stopped. + this._sharpenFollowsEngine = true; this._sharpenPct = presetSharpenIntensity( GLOBAL_POST_DEFAULTS.sharpen.intensity, this._engineKind, @@ -588,8 +589,10 @@ export class VisualSettings { /** Set the sharpen amount, a percentage clamped to 0-100, and apply it. */ _setSharpenIntensity(pct, { syncShare = true } = {}) { - if (!Number.isFinite(pct)) return; - this._sharpenPct = Math.max(0, Math.min(100, Math.round(pct))); + const value = presetSharpenIntensity(pct, this._engineKind); + if (!Number.isFinite(value)) return; + this._sharpenFollowsEngine = pct === ENGINE_SHARPEN_DEFAULT; + this._sharpenPct = Math.max(0, Math.min(100, Math.round(value))); this._applySharpenIntensity(this._sharpenPct / 100); this._publishDisplay(); if (syncShare) this._syncShareState(); @@ -798,12 +801,7 @@ export class VisualSettings { } const sharpenInput = preset.sharpen || {}; - const presetSharpen = presetSharpenIntensity( - sharpenInput.intensity, - this._engineKind, - ); - if (typeof presetSharpen === 'number') - this._setSharpenIntensity(presetSharpen, { syncShare: false }); + this._setSharpenIntensity(sharpenInput.intensity, { syncShare: false }); if (typeof sharpenInput.enabled === 'boolean') { this._setSharpenEnabled(sharpenInput.enabled); } @@ -845,14 +843,9 @@ export class VisualSettings { this._setBloomEnabled(defaults.bloom.enabled); } - const defaultSharpen = presetSharpenIntensity( - defaults.sharpen?.intensity, - this._engineKind, - ); - if (typeof defaultSharpen === 'number') - this._setSharpenIntensity(defaultSharpen, { - syncShare: false, - }); + this._setSharpenIntensity(defaults.sharpen?.intensity, { + syncShare: false, + }); if (typeof defaults.sharpen?.enabled === 'boolean') { this._setSharpenEnabled(defaults.sharpen.enabled); } @@ -912,6 +905,7 @@ export class VisualSettings { bloomIntensity: this._getBloomIntensity(), bloomVersion: BLOOM_SCALE_VERSION, sharpenIntensity: this._sharpenPct, + sharpenFollowsEngine: this._sharpenFollowsEngine, hudVariant: this.hud.getVariant(), hudVisible: this.hud.visible, detectionMode: detection.mode,