mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 18:34:02 +00:00
fix(ui): preserve Cyber and Cockpit visual state
This commit is contained in:
1 parent
e03bf008f3
commit
1dbc8a4452
16 files changed
+361
-97
No files matched your search
@@ -1359,6 +1359,8 @@ export class StyleManager extends ShellFacade {
|
||||
* @param {string} styleName - Target style ('normal'|'retro'|'surveillance'|'thermal'|'anime'|'noir'|'snow').
|
||||
* @param {object} [options]
|
||||
* @param {boolean} [options.applyPreset=true] - Whether to apply STYLE_PRESET_DEFAULTS for the new style.
|
||||
* @param {boolean} [options.userInitiated=false] - Whether a direct user preset choice owns the Cyber exit style.
|
||||
* @param {boolean} [options.preserveCyberRestore=false] - Whether an automatic style update keeps the Cyber entry snapshot.
|
||||
* @returns {void}
|
||||
*/
|
||||
setStyle(
|
||||
|
||||
@@ -52,11 +52,11 @@ export class CockpitViewController {
|
||||
{
|
||||
services,
|
||||
onVisionChange = null,
|
||||
getInitialVisionMode = null,
|
||||
onCameraTakeover = null,
|
||||
isEntryAllowed = null,
|
||||
onEntered = null,
|
||||
onExited = null,
|
||||
getInheritedVisionLabel = null,
|
||||
restoreTrackingFrame = null,
|
||||
} = {},
|
||||
) {
|
||||
@@ -121,13 +121,13 @@ export class CockpitViewController {
|
||||
this.visionNext = document.getElementById('cockpit-vision-next');
|
||||
this.visionMode = 'optical';
|
||||
this.onVisionChange = onVisionChange;
|
||||
this.getInitialVisionMode =
|
||||
typeof getInitialVisionMode === 'function'
|
||||
? getInitialVisionMode
|
||||
: () => 'optical';
|
||||
this.onCameraTakeover = onCameraTakeover;
|
||||
this.onEntered = onEntered;
|
||||
this.onExited = onExited;
|
||||
this.getInheritedVisionLabel =
|
||||
typeof getInheritedVisionLabel === 'function'
|
||||
? getInheritedVisionLabel
|
||||
: () => 'NORMAL';
|
||||
this.restoreTrackingFrame =
|
||||
typeof restoreTrackingFrame === 'function'
|
||||
? restoreTrackingFrame
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { CockpitViewController, CockpitDisplayPortal } from './cockpit.js';
|
||||
import { STYLE_STATUS_LABELS } from './visualPresets.js';
|
||||
import { cockpitEntryAllowed } from '../contextModePolicy.js';
|
||||
import { formatAwarenessLabel } from '../data/militaryAwarenessEngine.js';
|
||||
import { enterCockpitWithTracking } from '../cockpitTracking.js';
|
||||
import { cockpitVisionModeForStyle } from '../cockpitVisionPolicy.js';
|
||||
|
||||
/** Own Cockpit entry/rollback, readouts and the single Display portal. */
|
||||
export class CockpitCoordinator {
|
||||
@@ -72,11 +72,9 @@ export class CockpitCoordinator {
|
||||
},
|
||||
onVisionChange: (mode, active, options) =>
|
||||
this._setCockpitVision(mode, active, options),
|
||||
getInitialVisionMode: () => cockpitVisionModeForStyle(this.activeStyle),
|
||||
onCameraTakeover: () =>
|
||||
this._stampNavigation({ cancelPendingSelection: false }),
|
||||
getInheritedVisionLabel: () =>
|
||||
STYLE_STATUS_LABELS[this.activeStyle] ||
|
||||
String(this.activeStyle || 'normal').toUpperCase(),
|
||||
isEntryAllowed: () =>
|
||||
cockpitEntryAllowed({
|
||||
contextMode: this._contextMode,
|
||||
|
||||
@@ -217,22 +217,23 @@ export function syncWeatherToggle(enabled) {
|
||||
export function setVisionMode(mode, { revealParameters = false } = {}) {
|
||||
const next = normalizeCockpitVisionMode(mode);
|
||||
this.visionMode = next;
|
||||
const inherited = String(
|
||||
this.getInheritedVisionLabel?.() || 'NORMAL',
|
||||
).toUpperCase();
|
||||
const labels = {
|
||||
optical: inherited,
|
||||
optical: 'NORMAL',
|
||||
crt: 'CRT',
|
||||
nvg: 'NVG',
|
||||
thermal: 'FLIR',
|
||||
anime: 'ANIME',
|
||||
noir: 'NOIR',
|
||||
snow: 'SNOW',
|
||||
};
|
||||
const names = {
|
||||
optical: inherited,
|
||||
optical: 'Normal',
|
||||
crt: 'CRT',
|
||||
nvg: 'Night vision',
|
||||
thermal: 'Thermal',
|
||||
anime: 'Anime',
|
||||
noir: 'Noir',
|
||||
snow: 'Snow',
|
||||
};
|
||||
if (this.visionCurrent) {
|
||||
this.visionCurrent.dataset.cockpitVision = next;
|
||||
|
||||
@@ -194,7 +194,7 @@ export function enter() {
|
||||
`${trackLabel} · COURSE ${trackHeading}°`,
|
||||
);
|
||||
this.updateHud(info, performance.now(), true);
|
||||
this.setVisionMode(this.visionMode);
|
||||
this.setVisionMode(this.getInitialVisionMode());
|
||||
this.scheduleContextLayout();
|
||||
this.mapViewButton?.focus({ preventScroll: true });
|
||||
this.onEntered?.();
|
||||
|
||||
+95
-12
@@ -140,23 +140,74 @@ test('non-Cyber style presets and explicit HUD choices remain authoritative', (t
|
||||
}
|
||||
});
|
||||
|
||||
test('leaving an explicitly selected Cyber layout restores the prior visual preset', (t) => {
|
||||
test('leaving Cyber without a preset choice restores the prior visual preset', (t) => {
|
||||
const { owner, hud } = styleOwner(t, 'tactical');
|
||||
owner.setStyle('noir');
|
||||
|
||||
owner._setHudVariant('cyber', { applyVisualDefaults: true });
|
||||
assert.equal(owner.activeStyle, 'thermal');
|
||||
assert.equal(owner._preCyberStyle, 'noir');
|
||||
assert.equal(owner._cyberStyleUserSelected, false);
|
||||
|
||||
// A temporary choice made while Cyber is active does not replace the preset
|
||||
// that was active before the user entered Cyber.
|
||||
owner.setStyle('snow');
|
||||
owner._setHudVariant('cyber', { applyVisualDefaults: true });
|
||||
assert.equal(owner._preCyberStyle, 'noir');
|
||||
owner._setHudVariant('operator', { applyVisualDefaults: true });
|
||||
assert.equal(hud.getVariant(), 'operator');
|
||||
assert.equal(owner.activeStyle, 'noir');
|
||||
assert.equal(owner._preCyberStyle, null);
|
||||
assert.equal(owner._cyberStyleUserSelected, false);
|
||||
});
|
||||
|
||||
test('a preset explicitly selected in Cyber survives exit and resets for re-entry', (t) => {
|
||||
const { owner, hud } = styleOwner(t, 'tactical');
|
||||
owner.setStyle('noir');
|
||||
|
||||
owner._setHudVariant('cyber', { applyVisualDefaults: true });
|
||||
owner.setStyle('snow', { userInitiated: true });
|
||||
assert.equal(owner.activeStyle, 'snow');
|
||||
assert.equal(owner._preCyberStyle, 'noir');
|
||||
assert.equal(owner._cyberStyleUserSelected, true);
|
||||
|
||||
// Reselecting the active mode must not erase the user's preset intent.
|
||||
owner._setHudVariant('cyber', { applyVisualDefaults: true });
|
||||
assert.equal(owner._preCyberStyle, 'noir');
|
||||
owner._setHudVariant('operator', { applyVisualDefaults: true });
|
||||
assert.equal(hud.getVariant(), 'operator');
|
||||
assert.equal(owner.activeStyle, 'snow');
|
||||
assert.equal(owner._preCyberStyle, null);
|
||||
assert.equal(owner._cyberStyleUserSelected, false);
|
||||
|
||||
// A later untouched Cyber round trip restores the new pre-Cyber preset.
|
||||
owner._setHudVariant('cyber', { applyVisualDefaults: true });
|
||||
assert.equal(owner.activeStyle, 'thermal');
|
||||
assert.equal(owner._preCyberStyle, 'snow');
|
||||
owner._setHudVariant('minimal', { applyVisualDefaults: true });
|
||||
assert.equal(owner.activeStyle, 'snow');
|
||||
});
|
||||
|
||||
test('an explicit same-value FLIR choice is preserved on Cyber exit', (t) => {
|
||||
const { owner } = styleOwner(t, 'tactical');
|
||||
owner.setStyle('noir');
|
||||
owner._setHudVariant('cyber', { applyVisualDefaults: true });
|
||||
|
||||
owner.setStyle('thermal', { userInitiated: true });
|
||||
assert.equal(owner.activeStyle, 'thermal');
|
||||
assert.equal(owner._cyberStyleUserSelected, true);
|
||||
owner._setHudVariant('operator', { applyVisualDefaults: true });
|
||||
assert.equal(owner.activeStyle, 'thermal');
|
||||
});
|
||||
|
||||
test('an authoritative same-Cyber reset clears local preset ownership', (t) => {
|
||||
const { owner } = styleOwner(t, 'tactical');
|
||||
owner.setStyle('noir');
|
||||
owner._setHudVariant('cyber', { applyVisualDefaults: true });
|
||||
owner.setStyle('snow', { userInitiated: true });
|
||||
assert.equal(owner._cyberStyleUserSelected, true);
|
||||
|
||||
owner._setHudVariant('cyber');
|
||||
assert.equal(owner.activeStyle, 'snow');
|
||||
assert.equal(owner._preCyberStyle, null);
|
||||
assert.equal(owner._cyberStyleUserSelected, false);
|
||||
owner._setHudVariant('operator', { applyVisualDefaults: true });
|
||||
assert.equal(owner.activeStyle, 'snow');
|
||||
});
|
||||
|
||||
test('Display and voice HUD routes preserve explicit Cyber entry and exit authority', async (t) => {
|
||||
@@ -174,17 +225,25 @@ test('Display and voice HUD routes preserve explicit Cyber entry and exit author
|
||||
const display = makeOwner();
|
||||
const hudLayout = new EventTarget();
|
||||
hudLayout.value = 'cyber';
|
||||
const snowButton = new EventTarget();
|
||||
snowButton.dataset = { style: 'snow' };
|
||||
const controls = bindDisplayControls({
|
||||
elements: { hudLayout },
|
||||
actions: { setHudLayout: (value) => display.owner.setHudLayout(value) },
|
||||
elements: { hudLayout, styleButtons: [snowButton] },
|
||||
actions: {
|
||||
setHudLayout: (value) => display.owner.setHudLayout(value),
|
||||
setStyle: (value) =>
|
||||
display.owner.setStyle(value, { userInitiated: true }),
|
||||
},
|
||||
});
|
||||
hudLayout.dispatchEvent(new Event('change'));
|
||||
assert.equal(display.hud.getVariant(), 'cyber');
|
||||
assert.equal(display.owner.activeStyle, 'thermal');
|
||||
snowButton.dispatchEvent(new Event('click'));
|
||||
assert.equal(display.owner.activeStyle, 'snow');
|
||||
hudLayout.value = 'operator';
|
||||
hudLayout.dispatchEvent(new Event('change'));
|
||||
assert.equal(display.hud.getVariant(), 'operator');
|
||||
assert.equal(display.owner.activeStyle, 'noir');
|
||||
assert.equal(display.owner.activeStyle, 'snow');
|
||||
controls.destroy();
|
||||
|
||||
const voice = makeOwner();
|
||||
@@ -203,27 +262,34 @@ test('Display and voice HUD routes preserve explicit Cyber entry and exit author
|
||||
assert.equal(entered.ok, true);
|
||||
assert.equal(voice.hud.getVariant(), 'cyber');
|
||||
assert.equal(voice.owner.activeStyle, 'thermal');
|
||||
const selected = await runVoiceAction('set_visual_style', { style: 'snow' });
|
||||
assert.equal(selected.ok, true);
|
||||
assert.equal(voice.owner.activeStyle, 'snow');
|
||||
const exited = await runVoiceAction('set_hud', { layout: 'operator' });
|
||||
assert.equal(exited.ok, true);
|
||||
assert.equal(voice.hud.getVariant(), 'operator');
|
||||
assert.equal(voice.owner.activeStyle, 'noir');
|
||||
assert.equal(voice.owner.activeStyle, 'snow');
|
||||
});
|
||||
|
||||
test('scene and share HUD transitions do not restore a local pre-Cyber preset', async (t) => {
|
||||
const { owner, hud } = styleOwner(t, 'tactical');
|
||||
owner.setStyle('noir');
|
||||
owner._setHudVariant('cyber', { applyVisualDefaults: true });
|
||||
owner.setStyle('snow', { userInitiated: true });
|
||||
assert.equal(owner._cyberStyleUserSelected, true);
|
||||
|
||||
await owner.applyVisualState({ style: 'retro', hud: { variant: 'cyber' } });
|
||||
assert.equal(hud.getVariant(), 'cyber');
|
||||
assert.equal(owner.activeStyle, 'retro');
|
||||
assert.equal(owner._preCyberStyle, null);
|
||||
assert.equal(owner._cyberStyleUserSelected, false);
|
||||
owner._setHudVariant('operator', { applyVisualDefaults: true });
|
||||
assert.equal(owner.activeStyle, 'retro');
|
||||
|
||||
owner.setStyle('surveillance');
|
||||
owner._setHudVariant('cyber', { applyVisualDefaults: true });
|
||||
assert.equal(owner._preCyberStyle, 'surveillance');
|
||||
owner.setStyle('snow', { userInitiated: true });
|
||||
await owner.restoreShareState({
|
||||
style: 'thermal',
|
||||
hudVariant: 'cyber',
|
||||
@@ -231,6 +297,7 @@ test('scene and share HUD transitions do not restore a local pre-Cyber preset',
|
||||
assert.equal(hud.getVariant(), 'cyber');
|
||||
assert.equal(owner.activeStyle, 'thermal');
|
||||
assert.equal(owner._preCyberStyle, null);
|
||||
assert.equal(owner._cyberStyleUserSelected, false);
|
||||
owner._setHudVariant('tactical', { applyVisualDefaults: true });
|
||||
assert.equal(owner.activeStyle, 'thermal');
|
||||
assert.equal(owner._preCyberStyle, null);
|
||||
@@ -451,6 +518,14 @@ test('Cyber side panels share one width and one framed surface material', () =>
|
||||
cyberStyles,
|
||||
/#pp-toggles\s*> \.pp-header-row\s+\.pp-collapse-btn \{[\s\S]*?width: var\(--cyber-panel-control-size\);[\s\S]*?height: var\(--cyber-panel-control-size\);/,
|
||||
);
|
||||
assert.match(
|
||||
cyberStyles,
|
||||
/#right-context-rail\s+:is\(\s*\.cctv-panel-inner,\s*\.weather-panel-inner,\s*\.recent-imagery-panel-inner,\s*\.global-context-panel-inner\s*\) \{\s*padding-right: 8px;/,
|
||||
);
|
||||
assert.match(
|
||||
cyberStyles,
|
||||
/#right-context-rail[\s\S]*?:is\(\s*#cctv-panel,\s*#weather-panel,\s*#recent-imagery-panel,\s*#global-context-panel\s*\)\.collapsed[\s\S]*?> \.panel-header \{[\s\S]*?height: 48px;[\s\S]*?padding: 0 10px 0 14px;/,
|
||||
);
|
||||
assert.doesNotMatch(
|
||||
cyberStyles,
|
||||
/\.cockpit-utility-control\.is-expanded\s*\{[^}]*order:/,
|
||||
@@ -518,7 +593,15 @@ test('Cyber visual defaults update the style, thermal palette and render state',
|
||||
|
||||
assert.equal(owner.stages.thermal.uniforms.palette, 0.42);
|
||||
assert.deepEqual(calls, [
|
||||
['style', 'thermal', { applyPreset: false, revealParameters: false }],
|
||||
[
|
||||
'style',
|
||||
'thermal',
|
||||
{
|
||||
applyPreset: false,
|
||||
revealParameters: false,
|
||||
preserveCyberRestore: true,
|
||||
},
|
||||
],
|
||||
['sliders', 'thermal', { reveal: false }],
|
||||
['render', 'cyber-visual-defaults'],
|
||||
]);
|
||||
@@ -726,7 +809,7 @@ test('Cyber desktop cockpit collapsed utility frames match the 50px Data Layers
|
||||
);
|
||||
assert.match(
|
||||
desktop,
|
||||
/:root\[data-ui-theme='cyber'\]\s+body\.cockpit-mode\s+\.cockpit-utility-control:not\(\.is-expanded\)\s+\.cockpit-utility-launcher\s*\{\s*height: 50px;\s*min-height: 50px;\s*padding: 8px 18px 10px 24px;/,
|
||||
/:root\[data-ui-theme='cyber'\]\s+body\.cockpit-mode\s+\.cockpit-utility-control:not\(\.is-expanded\)\s+\.cockpit-utility-launcher\s*\{\s*height: 50px;\s*min-height: 50px;\s*padding: 9px 18px 9px 24px;/,
|
||||
);
|
||||
assert.match(
|
||||
desktop,
|
||||
|
||||
@@ -64,7 +64,7 @@ export class DisplayBindings {
|
||||
documentRef: document,
|
||||
searchInput: this._locationSearch,
|
||||
actions: {
|
||||
setStyle: (style) => this.setStyle(style),
|
||||
setStyle: (style) => this.setStyle(style, { userInitiated: true }),
|
||||
dismissSearch: () => {
|
||||
if (this._locationSearch.classList.contains('expanded')) {
|
||||
this._locationSearch.classList.remove('expanded');
|
||||
@@ -121,7 +121,7 @@ export class DisplayBindings {
|
||||
modelModeButtons: this._models3dBtn ? this._models3dModeBtns : [],
|
||||
},
|
||||
actions: {
|
||||
setStyle: (style) => this.setStyle(style),
|
||||
setStyle: (style) => this.setStyle(style, { userInitiated: true }),
|
||||
toggleBloom: () => {
|
||||
this.shareLinkManager?.claimRestoreLane?.('visual');
|
||||
this._setBloomEnabled(!this.bloomEnabled);
|
||||
|
||||
@@ -655,7 +655,7 @@ export class ShellFacade {
|
||||
return this._visualSettings._syncIrBoost(...arguments);
|
||||
}
|
||||
|
||||
/** Keep Cockpit's inherited label and restore target aligned with the active map preset. */
|
||||
/** Keep Cockpit's exit restore target aligned with the active map preset. */
|
||||
_syncCockpitInheritedStyle() {
|
||||
return this._visualSettings._syncCockpitInheritedStyle(...arguments);
|
||||
}
|
||||
|
||||
+60
-1
@@ -229,6 +229,65 @@
|
||||
border-bottom: 1px solid rgba(206, 222, 226, 0.08);
|
||||
}
|
||||
|
||||
/* The right-rail surfaces use different content gutters, but their disclosure
|
||||
controls should still read as one vertical column. Eight pixels here plus
|
||||
the shared two-pixel header inset matches Display's eleven-pixel framed
|
||||
edge inset once the surface border is included. */
|
||||
:root[data-ui-theme='cyber']
|
||||
#right-context-rail
|
||||
:is(
|
||||
.cctv-panel-inner,
|
||||
.weather-panel-inner,
|
||||
.recent-imagery-panel-inner,
|
||||
.global-context-panel-inner
|
||||
) {
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
/* Collapsed right-rail panels otherwise inherit different legacy gutters:
|
||||
CCTV lands five pixels low while Context lands four pixels high. Give every
|
||||
compact launcher the same centered 48px content row inside its 1px frame. */
|
||||
:root[data-ui-theme='cyber']
|
||||
#right-context-rail
|
||||
:is(
|
||||
#cctv-panel,
|
||||
#weather-panel,
|
||||
#recent-imagery-panel,
|
||||
#global-context-panel
|
||||
).collapsed
|
||||
> :is(
|
||||
.cctv-panel-inner,
|
||||
.weather-panel-inner,
|
||||
.recent-imagery-panel-inner,
|
||||
.global-context-panel-inner
|
||||
) {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
:root[data-ui-theme='cyber']
|
||||
#right-context-rail
|
||||
:is(
|
||||
#cctv-panel,
|
||||
#weather-panel,
|
||||
#recent-imagery-panel,
|
||||
#global-context-panel
|
||||
).collapsed
|
||||
> :is(
|
||||
.cctv-panel-inner,
|
||||
.weather-panel-inner,
|
||||
.recent-imagery-panel-inner,
|
||||
.global-context-panel-inner
|
||||
)
|
||||
> .panel-header {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
height: 48px;
|
||||
min-height: 48px;
|
||||
margin: 0;
|
||||
padding: 0 10px 0 14px;
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
:root[data-ui-theme='cyber']
|
||||
:is(
|
||||
.data-panel-inner,
|
||||
@@ -1623,7 +1682,7 @@
|
||||
.cockpit-utility-launcher {
|
||||
height: 50px;
|
||||
min-height: 50px;
|
||||
padding: 8px 18px 10px 24px;
|
||||
padding: 9px 18px 9px 24px;
|
||||
}
|
||||
|
||||
:root[data-ui-theme='cyber']
|
||||
|
||||
+33
-15
@@ -197,6 +197,7 @@ export class VisualSettings {
|
||||
});
|
||||
this.activeStyle = 'normal';
|
||||
this._preCyberStyle = null;
|
||||
this._cyberStyleUserSelected = false;
|
||||
document.documentElement.dataset.gevStyle = this.activeStyle;
|
||||
this._detectionUserOverridden = false;
|
||||
this._cockpitVisionMode = 'optical';
|
||||
@@ -342,23 +343,15 @@ export class VisualSettings {
|
||||
);
|
||||
}
|
||||
if (next === 'optical') {
|
||||
applyCockpitVisionStageIntensities(
|
||||
this.stages,
|
||||
next,
|
||||
this._cockpitVisionRestore,
|
||||
);
|
||||
applyCockpitVisionStageIntensities(this.stages, next);
|
||||
this._syncStagesEnabledFromIntensity();
|
||||
this._cockpitVisionMode = next;
|
||||
this._syncIrBoost();
|
||||
this._updateSliderPanel(this.activeStyle, { reveal: false });
|
||||
this._updateSliderPanel(null, { reveal: false });
|
||||
this._revealCockpitStyleParameters({ openDisplay: revealParameters });
|
||||
return;
|
||||
}
|
||||
const target = applyCockpitVisionStageIntensities(
|
||||
this.stages,
|
||||
next,
|
||||
this._cockpitVisionRestore,
|
||||
);
|
||||
const target = applyCockpitVisionStageIntensities(this.stages, next);
|
||||
this._syncStagesEnabledFromIntensity();
|
||||
this._cockpitVisionMode = next;
|
||||
this._syncIrBoost(); // Cockpit vision override ('nvg'/'thermal' boost; CRT/NOIR clear)
|
||||
@@ -370,8 +363,11 @@ export class VisualSettings {
|
||||
const cockpitMode = this.cockpitView?.active
|
||||
? this._cockpitVisionMode
|
||||
: null;
|
||||
const effective =
|
||||
cockpitMode && cockpitMode !== 'optical' ? cockpitMode : this.activeStyle;
|
||||
const effective = cockpitMode
|
||||
? cockpitMode === 'optical'
|
||||
? 'normal'
|
||||
: cockpitMode
|
||||
: this.activeStyle;
|
||||
const irBoost =
|
||||
effective === 'surveillance' ||
|
||||
effective === 'thermal' ||
|
||||
@@ -385,7 +381,7 @@ export class VisualSettings {
|
||||
new CustomEvent('gev:vision-change', {
|
||||
detail: {
|
||||
style: effective,
|
||||
cockpit: Boolean(cockpitMode && cockpitMode !== 'optical'),
|
||||
cockpit: Boolean(cockpitMode),
|
||||
},
|
||||
}),
|
||||
);
|
||||
@@ -622,8 +618,10 @@ export class VisualSettings {
|
||||
// the current Cyber variant. Do not let an older explicit entry restore
|
||||
// stale local preset memory on the next user-selected exit.
|
||||
this._preCyberStyle = null;
|
||||
this._cyberStyleUserSelected = false;
|
||||
} else if (enteredCyber) {
|
||||
this._preCyberStyle = this.activeStyle;
|
||||
this._cyberStyleUserSelected = false;
|
||||
}
|
||||
if (this._hudLayoutSelect && this._hudLayoutSelect.value !== nextVariant) {
|
||||
this._hudLayoutSelect.value = nextVariant;
|
||||
@@ -635,12 +633,17 @@ export class VisualSettings {
|
||||
);
|
||||
if (visualDefaults) this._applyCyberVisualDefaults(visualDefaults);
|
||||
if (leftCyber) {
|
||||
const restoreStyle = applyVisualDefaults ? this._preCyberStyle : null;
|
||||
const restoreStyle =
|
||||
applyVisualDefaults && !this._cyberStyleUserSelected
|
||||
? this._preCyberStyle
|
||||
: null;
|
||||
this._preCyberStyle = null;
|
||||
this._cyberStyleUserSelected = false;
|
||||
if (restoreStyle && restoreStyle !== this.activeStyle) {
|
||||
this.setStyle(restoreStyle, {
|
||||
applyPreset: false,
|
||||
revealParameters: false,
|
||||
preserveCyberRestore: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -653,6 +656,7 @@ export class VisualSettings {
|
||||
this.setStyle(style, {
|
||||
applyPreset: false,
|
||||
revealParameters: false,
|
||||
preserveCyberRestore: true,
|
||||
});
|
||||
const thermalUniforms = this.stages?.thermal?.uniforms;
|
||||
if (!thermalUniforms || thermalUniforms.palette === undefined) return;
|
||||
@@ -1530,10 +1534,24 @@ export class VisualSettings {
|
||||
applyPreset = true,
|
||||
revealParameters = applyPreset,
|
||||
restore = false,
|
||||
userInitiated = false,
|
||||
preserveCyberRestore = false,
|
||||
} = {},
|
||||
) {
|
||||
const { setDetectionStyle } = this.services;
|
||||
if (!restore) this.shareLinkManager?.claimRestoreLane?.('visual');
|
||||
if (this.hud.getVariant() === 'cyber') {
|
||||
if (userInitiated) {
|
||||
// A direct preset choice owns the active style even when it selects the
|
||||
// same value as Cyber's automatic FLIR default.
|
||||
this._cyberStyleUserSelected = true;
|
||||
} else if (!preserveCyberRestore) {
|
||||
// Scene/share/reset state is authoritative and must not be overwritten
|
||||
// by a remembered local Cyber entry when the user later exits.
|
||||
this._preCyberStyle = null;
|
||||
this._cyberStyleUserSelected = false;
|
||||
}
|
||||
}
|
||||
if (styleName === this.activeStyle) {
|
||||
if (revealParameters && styleName !== 'normal')
|
||||
this._revealStyleParameters();
|
||||
|
||||
Reference in new issue
Block a user