From 44522c03ac3aa80c16f03e1bc6f07debcabccc42 Mon Sep 17 00:00:00 2001 From: Einar Andersson <72999+drdator@users.noreply.github.com> Date: Wed, 29 Jul 2026 16:58:07 +0200 Subject: [PATCH] Refine light theme contrast --- src/gl-utils.ts | 3 ++- src/style.css | 18 +++++++++++++++--- src/theme-colors.ts | 18 ++++++------------ src/viewport3d-render.ts | 9 ++++++++- src/viewport3d.ts | 3 +++ tests/theme-colors.test.ts | 7 ++++--- 6 files changed, 38 insertions(+), 20 deletions(-) diff --git a/src/gl-utils.ts b/src/gl-utils.ts index 00bb8fe..4d747af 100644 --- a/src/gl-utils.ts +++ b/src/gl-utils.ts @@ -80,9 +80,10 @@ void main() { export const LINE_FRAG_SRC = `#version 300 es precision mediump float; uniform vec3 uColor; +uniform float uAlpha; out vec4 fragColor; void main() { - fragColor = vec4(uColor, 1.0); + fragColor = vec4(uColor, uAlpha); } `; diff --git a/src/style.css b/src/style.css index 4391fa8..1153b13 100644 --- a/src/style.css +++ b/src/style.css @@ -70,9 +70,9 @@ html:not(.landing-active) * { --control-bg: #fff; --control-bg-hover: #f7f7f7; --viewport-bg: #f0f0f0; - --grid-major: rgba(70, 70, 70, 0.65); - --grid-minor: rgba(110, 110, 110, 0.35); - --grid-origin: rgba(0, 90, 180, 0.75); + --grid-major: rgba(90, 100, 110, 0.42); + --grid-minor: rgba(115, 125, 135, 0.22); + --grid-origin: rgba(0, 90, 180, 0.58); --select-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23252525' stroke-width='1.75' stroke-linecap='square' stroke-linejoin='miter'%3E%3Cpath d='m5 9 7 7 7-7'/%3E%3C/svg%3E"); } @@ -1028,6 +1028,13 @@ textarea:focus-visible { color: var(--accent); } +:root[data-editor-theme="light"] .tool-btn.active { + background: #fff1d2; + border-color: #925800; + color: #7a4900; + box-shadow: inset 0 0 0 1px rgba(146, 88, 0, 0.12); +} + .tool-btn.disabled { opacity: 0.35; } @@ -1042,6 +1049,11 @@ textarea:focus-visible { box-shadow: 0 0 0 1px rgba(255, 102, 0, 0.2); } +:root[data-editor-theme="light"] .tool-btn.active-panel { + border-color: #925800; + box-shadow: 0 0 0 1px rgba(146, 88, 0, 0.25); +} + .tool-btn.active.snap-abs { border-color: #c44; color: #e55; diff --git a/src/theme-colors.ts b/src/theme-colors.ts index 4ffaee6..cdaa71b 100644 --- a/src/theme-colors.ts +++ b/src/theme-colors.ts @@ -6,6 +6,7 @@ export interface EditorThemeRenderColors { selection: string; viewportRgb: [number, number, number]; gridMajorRgb: [number, number, number]; + gridMajorAlpha: number; selectionRgb: [number, number, number]; } @@ -16,7 +17,8 @@ const FALLBACK_COLORS: EditorThemeRenderColors = { gridOrigin: 'rgba(0, 100, 180, 0.5)', selection: '#ff6600', viewportRgb: [30 / 255, 30 / 255, 30 / 255], - gridMajorRgb: [62 / 255, 62 / 255, 62 / 255], + gridMajorRgb: [70 / 255, 70 / 255, 70 / 255], + gridMajorAlpha: 0.8, selectionRgb: [1, 102 / 255, 0], }; @@ -49,16 +51,6 @@ function cssRgb(value: string, fallback: [number, number, number]): [number, num return cssRgba(value, fallback).rgb; } -function cssRgbOver( - value: string, - background: [number, number, number], - fallback: [number, number, number], -): [number, number, number] { - const parsed = cssRgba(value, fallback); - return parsed.rgb.map((component, index) => - component * parsed.alpha + background[index] * (1 - parsed.alpha)) as [number, number, number]; -} - export function refreshEditorThemeColors(root: Element = document.documentElement): void { const styles = getComputedStyle(root); const value = (name: string, fallback: string): string => @@ -69,6 +61,7 @@ export function refreshEditorThemeColors(root: Element = document.documentElemen const gridOrigin = value('--grid-origin', FALLBACK_COLORS.gridOrigin); const selection = value('--selection', FALLBACK_COLORS.selection); const viewportRgb = cssRgb(viewport, FALLBACK_COLORS.viewportRgb); + const parsedGridMajor = cssRgba(gridMajor, FALLBACK_COLORS.gridMajorRgb); current = { viewport, gridMajor, @@ -76,7 +69,8 @@ export function refreshEditorThemeColors(root: Element = document.documentElemen gridOrigin, selection, viewportRgb, - gridMajorRgb: cssRgbOver(gridMajor, viewportRgb, FALLBACK_COLORS.gridMajorRgb), + gridMajorRgb: parsedGridMajor.rgb, + gridMajorAlpha: parsedGridMajor.alpha, selectionRgb: cssRgb(selection, FALLBACK_COLORS.selectionRgb), }; } diff --git a/src/viewport3d-render.ts b/src/viewport3d-render.ts index 73e9e88..7ade5e9 100644 --- a/src/viewport3d-render.ts +++ b/src/viewport3d-render.ts @@ -78,6 +78,7 @@ export interface Viewport3DRenderContext { lineProg: WebGLProgram; linePVLoc: WebGLUniformLocation; lineColorLoc: WebGLUniformLocation; + lineAlphaLoc: WebGLUniformLocation; solidVAO: WebGLVertexArrayObject; drawGroups: DrawGroup[]; clipBoxVAO: WebGLVertexArrayObject; @@ -149,12 +150,18 @@ export function renderViewport3D(ctx: Viewport3DRenderContext): Mat4 { const pv = mat4Multiply(proj, view); const isGameView = ctx.fullscreen && ctx.fullscreenMode !== 'edit'; + ctx.gl.useProgram(ctx.lineProg); + ctx.gl.uniform1f(ctx.lineAlphaLoc, 1.0); if (!isGameView && ctx.editor.display.showGrid3D) { - ctx.gl.useProgram(ctx.lineProg); ctx.gl.uniformMatrix4fv(ctx.linePVLoc, false, pv); ctx.gl.uniform3f(ctx.lineColorLoc, theme.gridMajorRgb[0], theme.gridMajorRgb[1], theme.gridMajorRgb[2]); + ctx.gl.uniform1f(ctx.lineAlphaLoc, theme.gridMajorAlpha); + ctx.gl.enable(ctx.gl.BLEND); + ctx.gl.blendFunc(ctx.gl.SRC_ALPHA, ctx.gl.ONE_MINUS_SRC_ALPHA); ctx.gl.bindVertexArray(ctx.gridVAO); ctx.gl.drawArrays(ctx.gl.LINES, 0, ctx.gridCount); + ctx.gl.disable(ctx.gl.BLEND); + ctx.gl.uniform1f(ctx.lineAlphaLoc, 1.0); } if (ctx.drawGroups.length > 0 && ctx.editor.display.rendererMode !== 'wireframe') { diff --git a/src/viewport3d.ts b/src/viewport3d.ts index d9260d9..dd19e93 100644 --- a/src/viewport3d.ts +++ b/src/viewport3d.ts @@ -92,6 +92,7 @@ export class Viewport3D { private lineProg!: WebGLProgram; private linePVLoc!: WebGLUniformLocation; private lineColorLoc!: WebGLUniformLocation; + private lineAlphaLoc!: WebGLUniformLocation; private solidVAO!: WebGLVertexArrayObject; private solidVBO!: WebGLBuffer; @@ -493,6 +494,7 @@ export class Viewport3D { this.lineProg = createProgram(gl, LINE_VERT_SRC, LINE_FRAG_SRC); this.linePVLoc = gl.getUniformLocation(this.lineProg, 'uPV')!; this.lineColorLoc = gl.getUniformLocation(this.lineProg, 'uColor')!; + this.lineAlphaLoc = gl.getUniformLocation(this.lineProg, 'uAlpha')!; const solid = createSolidBuffer(gl); this.solidVAO = solid.vao; this.solidVBO = solid.vbo; @@ -654,6 +656,7 @@ export class Viewport3D { lineProg: this.lineProg, linePVLoc: this.linePVLoc, lineColorLoc: this.lineColorLoc, + lineAlphaLoc: this.lineAlphaLoc, solidVAO: this.solidVAO, drawGroups: this.drawGroups, clipBoxVAO: this.clipBoxVAO, diff --git a/tests/theme-colors.test.ts b/tests/theme-colors.test.ts index 403121d..c2cae59 100644 --- a/tests/theme-colors.test.ts +++ b/tests/theme-colors.test.ts @@ -32,10 +32,11 @@ describe('editor theme render colors', () => { selection: '#ff00aa', viewportRgb: [170 / 255, 187 / 255, 204 / 255], gridMajorRgb: [ - 10 / 255 * 0.5 + 170 / 255 * 0.5, - 20 / 255 * 0.5 + 187 / 255 * 0.5, - 30 / 255 * 0.5 + 204 / 255 * 0.5, + 10 / 255, + 20 / 255, + 30 / 255, ], + gridMajorAlpha: 0.5, selectionRgb: [1, 0, 170 / 255], }); });