mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 09:50:43 +00:00
Add map hover/railroad graphics overrides and fix territory highlight
Extend GraphicsOverrides with a mapOverlay group (territory highlight, border highlight amount, border highlight thickness) and a railroad group (train track draw distance), wired through the schema, applyGraphicsOverrides, and new sliders in the graphics settings modal. Fix the territory hover highlight: the shader received uHighlightBrighten but ignored it, applying a hardcoded saturation boost so the setting had no effect. It now drives a contrast boost (push channels away from mid-gray), with 0 disabling the effect. The train track slider is presented as a "draw distance" (inverted railMinZoom) so higher = tracks stay visible when more zoomed out. Also move the Graphics settings button to the top of the settings modal.
This commit is contained in:
@@ -937,6 +937,15 @@
|
||||
"section_structure_icons": "Structure Icons",
|
||||
"classic_icons_label": "Classic icons",
|
||||
"classic_icons_desc": "Lighter outline with near-black interior",
|
||||
"section_map": "Map",
|
||||
"highlight_fill_label": "Territory highlight",
|
||||
"highlight_fill_desc": "How strongly territory brightens on hover (0 to disable)",
|
||||
"highlight_brighten_label": "Border highlight amount",
|
||||
"highlight_brighten_desc": "How strongly the border brightens on hover (0 to disable)",
|
||||
"highlight_thicken_label": "Border highlight thickness",
|
||||
"highlight_thicken_desc": "How much the border thickens on hover",
|
||||
"rail_distance_label": "Train track draw distance",
|
||||
"rail_distance_desc": "How far zoomed out train tracks remain visible",
|
||||
"reset_label": "Reset to defaults",
|
||||
"reset_desc": "Clear all graphics overrides"
|
||||
},
|
||||
|
||||
@@ -20,6 +20,24 @@ const NAME_CULL_MIN = 0;
|
||||
const NAME_CULL_MAX = 0.05;
|
||||
const NAME_CULL_STEP = 0.001;
|
||||
|
||||
const HIGHLIGHT_FILL_MIN = 0;
|
||||
const HIGHLIGHT_FILL_MAX = 1;
|
||||
const HIGHLIGHT_FILL_STEP = 0.01;
|
||||
|
||||
const HIGHLIGHT_BRIGHTEN_MIN = 0;
|
||||
const HIGHLIGHT_BRIGHTEN_MAX = 1;
|
||||
const HIGHLIGHT_BRIGHTEN_STEP = 0.01;
|
||||
|
||||
const HIGHLIGHT_THICKEN_MIN = 0;
|
||||
const HIGHLIGHT_THICKEN_MAX = 5;
|
||||
const HIGHLIGHT_THICKEN_STEP = 1;
|
||||
|
||||
// Train track "draw distance" is presented inverted: a higher slider value means
|
||||
// tracks stay visible when more zoomed out, i.e. a lower railMinZoom.
|
||||
const RAIL_ZOOM_MIN = 0;
|
||||
const RAIL_ZOOM_MAX = 10;
|
||||
const RAIL_ZOOM_STEP = 0.1;
|
||||
|
||||
export class ShowGraphicsSettingsModalEvent {
|
||||
constructor(
|
||||
public readonly isVisible: boolean = true,
|
||||
@@ -136,6 +154,73 @@ export class GraphicsSettingsModal extends LitElement implements Controller {
|
||||
this.requestUpdate();
|
||||
}
|
||||
|
||||
private patchMapOverlay(patch: Partial<GraphicsOverrides["mapOverlay"]>) {
|
||||
const current = this.userSettings.graphicsOverrides();
|
||||
this.userSettings.setGraphicsOverrides({
|
||||
...current,
|
||||
mapOverlay: { ...current.mapOverlay, ...patch },
|
||||
});
|
||||
this.requestUpdate();
|
||||
}
|
||||
|
||||
private patchRailroad(patch: Partial<GraphicsOverrides["railroad"]>) {
|
||||
const current = this.userSettings.graphicsOverrides();
|
||||
this.userSettings.setGraphicsOverrides({
|
||||
...current,
|
||||
railroad: { ...current.railroad, ...patch },
|
||||
});
|
||||
this.requestUpdate();
|
||||
}
|
||||
|
||||
private currentHighlightFill(): number {
|
||||
return (
|
||||
this.userSettings.graphicsOverrides().mapOverlay?.highlightFillBrighten ??
|
||||
renderDefaults.mapOverlay.highlightFillBrighten
|
||||
);
|
||||
}
|
||||
|
||||
private currentHighlightBrighten(): number {
|
||||
return (
|
||||
this.userSettings.graphicsOverrides().mapOverlay?.highlightBrighten ??
|
||||
renderDefaults.mapOverlay.highlightBrighten
|
||||
);
|
||||
}
|
||||
|
||||
private currentHighlightThicken(): number {
|
||||
return (
|
||||
this.userSettings.graphicsOverrides().mapOverlay?.highlightThicken ??
|
||||
renderDefaults.mapOverlay.highlightThicken
|
||||
);
|
||||
}
|
||||
|
||||
private currentRailMinZoom(): number {
|
||||
return (
|
||||
this.userSettings.graphicsOverrides().railroad?.railMinZoom ??
|
||||
renderDefaults.railroad.railMinZoom
|
||||
);
|
||||
}
|
||||
|
||||
private onHighlightFillChange(event: Event) {
|
||||
const value = parseFloat((event.target as HTMLInputElement).value);
|
||||
this.patchMapOverlay({ highlightFillBrighten: value });
|
||||
}
|
||||
|
||||
private onHighlightBrightenChange(event: Event) {
|
||||
const value = parseFloat((event.target as HTMLInputElement).value);
|
||||
this.patchMapOverlay({ highlightBrighten: value });
|
||||
}
|
||||
|
||||
private onHighlightThickenChange(event: Event) {
|
||||
const value = parseFloat((event.target as HTMLInputElement).value);
|
||||
this.patchMapOverlay({ highlightThicken: value });
|
||||
}
|
||||
|
||||
private onRailDrawDistanceChange(event: Event) {
|
||||
const drawDistance = parseFloat((event.target as HTMLInputElement).value);
|
||||
// Invert: higher draw distance => tracks visible when more zoomed out.
|
||||
this.patchRailroad({ railMinZoom: RAIL_ZOOM_MAX - drawDistance });
|
||||
}
|
||||
|
||||
private currentClassicIcons(): boolean {
|
||||
return (
|
||||
this.userSettings.graphicsOverrides().structure?.classicIcons ?? false
|
||||
@@ -179,6 +264,10 @@ export class GraphicsSettingsModal extends LitElement implements Controller {
|
||||
const nameCull = this.currentNameCull();
|
||||
const namesColored = !this.currentDarkNames();
|
||||
const classicIcons = this.currentClassicIcons();
|
||||
const highlightFill = this.currentHighlightFill();
|
||||
const highlightBrighten = this.currentHighlightBrighten();
|
||||
const highlightThicken = this.currentHighlightThicken();
|
||||
const railDrawDistance = RAIL_ZOOM_MAX - this.currentRailMinZoom();
|
||||
|
||||
return html`
|
||||
<div
|
||||
@@ -309,6 +398,112 @@ export class GraphicsSettingsModal extends LitElement implements Controller {
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<div
|
||||
class="px-3 py-1 text-xs font-semibold text-slate-400 uppercase tracking-wider mt-2"
|
||||
>
|
||||
${translateText("graphics_setting.section_map")}
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="flex gap-3 items-center w-full text-left p-3 hover:bg-slate-700 rounded-sm text-white transition-colors"
|
||||
>
|
||||
<div class="flex-1">
|
||||
<div class="font-medium">
|
||||
${translateText("graphics_setting.highlight_fill_label")}
|
||||
</div>
|
||||
<div class="text-sm text-slate-400">
|
||||
${translateText("graphics_setting.highlight_fill_desc")}
|
||||
</div>
|
||||
<input
|
||||
type="range"
|
||||
min=${HIGHLIGHT_FILL_MIN}
|
||||
max=${HIGHLIGHT_FILL_MAX}
|
||||
step=${HIGHLIGHT_FILL_STEP}
|
||||
.value=${String(highlightFill)}
|
||||
@input=${this.onHighlightFillChange}
|
||||
class="w-full border border-slate-500 rounded-lg"
|
||||
/>
|
||||
</div>
|
||||
<div class="text-sm text-slate-400 w-12 text-right">
|
||||
${highlightFill.toFixed(2)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="flex gap-3 items-center w-full text-left p-3 hover:bg-slate-700 rounded-sm text-white transition-colors"
|
||||
>
|
||||
<div class="flex-1">
|
||||
<div class="font-medium">
|
||||
${translateText("graphics_setting.highlight_brighten_label")}
|
||||
</div>
|
||||
<div class="text-sm text-slate-400">
|
||||
${translateText("graphics_setting.highlight_brighten_desc")}
|
||||
</div>
|
||||
<input
|
||||
type="range"
|
||||
min=${HIGHLIGHT_BRIGHTEN_MIN}
|
||||
max=${HIGHLIGHT_BRIGHTEN_MAX}
|
||||
step=${HIGHLIGHT_BRIGHTEN_STEP}
|
||||
.value=${String(highlightBrighten)}
|
||||
@input=${this.onHighlightBrightenChange}
|
||||
class="w-full border border-slate-500 rounded-lg"
|
||||
/>
|
||||
</div>
|
||||
<div class="text-sm text-slate-400 w-12 text-right">
|
||||
${highlightBrighten.toFixed(2)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="flex gap-3 items-center w-full text-left p-3 hover:bg-slate-700 rounded-sm text-white transition-colors"
|
||||
>
|
||||
<div class="flex-1">
|
||||
<div class="font-medium">
|
||||
${translateText("graphics_setting.highlight_thicken_label")}
|
||||
</div>
|
||||
<div class="text-sm text-slate-400">
|
||||
${translateText("graphics_setting.highlight_thicken_desc")}
|
||||
</div>
|
||||
<input
|
||||
type="range"
|
||||
min=${HIGHLIGHT_THICKEN_MIN}
|
||||
max=${HIGHLIGHT_THICKEN_MAX}
|
||||
step=${HIGHLIGHT_THICKEN_STEP}
|
||||
.value=${String(highlightThicken)}
|
||||
@input=${this.onHighlightThickenChange}
|
||||
class="w-full border border-slate-500 rounded-lg"
|
||||
/>
|
||||
</div>
|
||||
<div class="text-sm text-slate-400 w-12 text-right">
|
||||
${highlightThicken.toFixed(0)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="flex gap-3 items-center w-full text-left p-3 hover:bg-slate-700 rounded-sm text-white transition-colors"
|
||||
>
|
||||
<div class="flex-1">
|
||||
<div class="font-medium">
|
||||
${translateText("graphics_setting.rail_distance_label")}
|
||||
</div>
|
||||
<div class="text-sm text-slate-400">
|
||||
${translateText("graphics_setting.rail_distance_desc")}
|
||||
</div>
|
||||
<input
|
||||
type="range"
|
||||
min=${RAIL_ZOOM_MIN}
|
||||
max=${RAIL_ZOOM_MAX}
|
||||
step=${RAIL_ZOOM_STEP}
|
||||
.value=${String(railDrawDistance)}
|
||||
@input=${this.onRailDrawDistanceChange}
|
||||
class="w-full border border-slate-500 rounded-lg"
|
||||
/>
|
||||
</div>
|
||||
<div class="text-sm text-slate-400 w-12 text-right">
|
||||
${railDrawDistance.toFixed(1)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="border-t border-slate-600 pt-3 mt-4">
|
||||
<button
|
||||
class="flex gap-3 items-center w-full text-left p-3 hover:bg-slate-700 rounded-sm text-white transition-colors"
|
||||
|
||||
@@ -245,6 +245,26 @@ export class SettingsModal extends LitElement implements Controller {
|
||||
</div>
|
||||
|
||||
<div class="p-4 flex flex-col gap-3">
|
||||
<button
|
||||
class="flex gap-3 items-center w-full text-left p-3 hover:bg-slate-700 rounded-sm text-white transition-colors"
|
||||
@click="${this.onGraphicsSettingsButtonClick}"
|
||||
>
|
||||
<img
|
||||
src=${settingsIcon}
|
||||
alt="graphicsSettings"
|
||||
width="20"
|
||||
height="20"
|
||||
/>
|
||||
<div class="flex-1">
|
||||
<div class="font-medium">
|
||||
${translateText("user_setting.graphics_settings_label")}
|
||||
</div>
|
||||
<div class="text-sm text-slate-400">
|
||||
${translateText("user_setting.graphics_settings_desc")}
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<div
|
||||
class="flex gap-3 items-center w-full text-left p-3 hover:bg-slate-700 rounded-sm text-white transition-colors"
|
||||
>
|
||||
@@ -491,26 +511,6 @@ export class SettingsModal extends LitElement implements Controller {
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="flex gap-3 items-center w-full text-left p-3 hover:bg-slate-700 rounded-sm text-white transition-colors"
|
||||
@click="${this.onGraphicsSettingsButtonClick}"
|
||||
>
|
||||
<img
|
||||
src=${settingsIcon}
|
||||
alt="graphicsSettings"
|
||||
width="20"
|
||||
height="20"
|
||||
/>
|
||||
<div class="flex-1">
|
||||
<div class="font-medium">
|
||||
${translateText("user_setting.graphics_settings_label")}
|
||||
</div>
|
||||
<div class="text-sm text-slate-400">
|
||||
${translateText("user_setting.graphics_settings_desc")}
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<div class="border-t border-slate-600 pt-3 mt-4">
|
||||
<div
|
||||
class="px-3 py-1 text-xs font-semibold text-slate-400 uppercase tracking-wider"
|
||||
|
||||
@@ -14,6 +14,18 @@ export const GraphicsOverridesSchema = z
|
||||
classicIcons: z.boolean(),
|
||||
})
|
||||
.partial(),
|
||||
mapOverlay: z
|
||||
.object({
|
||||
highlightFillBrighten: z.number(),
|
||||
highlightBrighten: z.number(),
|
||||
highlightThicken: z.number(),
|
||||
})
|
||||
.partial(),
|
||||
railroad: z
|
||||
.object({
|
||||
railMinZoom: z.number(),
|
||||
})
|
||||
.partial(),
|
||||
})
|
||||
.partial();
|
||||
|
||||
|
||||
@@ -23,6 +23,21 @@ export function applyGraphicsOverrides(
|
||||
settings.structure.iconB = 0;
|
||||
settings.structure.iconAlpha = 0.75;
|
||||
}
|
||||
if (overrides.mapOverlay?.highlightFillBrighten !== undefined) {
|
||||
settings.mapOverlay.highlightFillBrighten =
|
||||
overrides.mapOverlay.highlightFillBrighten;
|
||||
}
|
||||
if (overrides.mapOverlay?.highlightBrighten !== undefined) {
|
||||
settings.mapOverlay.highlightBrighten =
|
||||
overrides.mapOverlay.highlightBrighten;
|
||||
}
|
||||
if (overrides.mapOverlay?.highlightThicken !== undefined) {
|
||||
settings.mapOverlay.highlightThicken =
|
||||
overrides.mapOverlay.highlightThicken;
|
||||
}
|
||||
if (overrides.railroad?.railMinZoom !== undefined) {
|
||||
settings.railroad.railMinZoom = overrides.railroad.railMinZoom;
|
||||
}
|
||||
if (overrides.name?.darkNames !== undefined) {
|
||||
const dark = overrides.name.darkNames;
|
||||
// Dark: black fill + player-colored outline. Force outline RGB to black
|
||||
|
||||
@@ -21,7 +21,7 @@ uniform float uStaleNukeVariation;
|
||||
uniform float uStaleNukeAlpha;
|
||||
uniform vec3 uStaleNukeColor;
|
||||
uniform uint uHighlightOwner; // 0 = no highlight; otherwise smallID of hovered owner
|
||||
uniform float uHighlightBrighten; // mix amount toward white for highlighted tiles
|
||||
uniform float uHighlightBrighten; // hover contrast boost strength; 0 = disabled
|
||||
uniform sampler2D uDefenseCoverageTex; // R8 — 1.0 = tile defended by same-owner post
|
||||
uniform float uDefenseDarken; // multiplier applied to fill on defended tiles
|
||||
uniform sampler2D uBorderTex; // RGBA8 — border flags; R > 0.25 = border tile
|
||||
@@ -104,11 +104,11 @@ void main() {
|
||||
}
|
||||
}
|
||||
|
||||
// Hover highlight: boost saturation on the hovered player's tiles.
|
||||
// luma = grayscale equivalent; mixing past 1.0 pushes color away from gray.
|
||||
if (uHighlightOwner != 0u && owner == uHighlightOwner) {
|
||||
float luma = dot(color.rgb, vec3(0.299, 0.587, 0.114));
|
||||
color.rgb = clamp(mix(vec3(luma), color.rgb, 1.6), 0.0, 1.0);
|
||||
// Hover highlight: boost contrast on the hovered player's tiles, pushing
|
||||
// channels away from mid-gray. uHighlightBrighten is the strength; 0 disables.
|
||||
if (uHighlightOwner != 0u && owner == uHighlightOwner && uHighlightBrighten > 0.0) {
|
||||
float contrast = 1.0 + uHighlightBrighten;
|
||||
color.rgb = clamp((color.rgb - 0.5) * contrast + 0.5, 0.0, 1.0);
|
||||
}
|
||||
|
||||
// Defense bonus: darken the fill on interior tiles defended by a same-owner
|
||||
|
||||
Reference in New Issue
Block a user