From 752e1ae42506db23761ad596e4d18df4969dd433 Mon Sep 17 00:00:00 2001 From: Andras Schmelczer Date: Sat, 27 May 2023 15:00:04 +0100 Subject: [PATCH] Add settings sliders --- .eslintrc.json | 4 +- src/index.html | 18 +++---- src/index.scss | 61 ++++++++++++++++++++++-- src/index.ts | 11 +++-- src/page/collapsible-panel-animator.ts | 18 +++---- src/page/set-up-settings-page.ts | 65 ++++++++++++++++++++++++++ src/settings.ts | 27 ++++++----- src/style/vars.scss | 6 +-- src/utils/settings-slider.ts | 8 +++- 9 files changed, 170 insertions(+), 48 deletions(-) create mode 100644 src/page/set-up-settings-page.ts diff --git a/.eslintrc.json b/.eslintrc.json index bcfcc71..24a82da 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -18,12 +18,12 @@ "plugins": ["unused-imports", "@typescript-eslint", "prettier"], "rules": { "prettier/prettier": "error", - "no-unused-vars": "off", "unused-imports/no-unused-imports-ts": "error", "@typescript-eslint/no-unused-vars": ["warn", { "argsIgnorePattern": "^_" }], "@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/explicit-module-boundary-types": "off", "@typescript-eslint/no-non-null-assertion": "off", - "@typescript-eslint/ban-ts-comment": "off" + "@typescript-eslint/ban-ts-comment": "off", + "@typescript-eslint/no-empty-function": "off" } } diff --git a/src/index.html b/src/index.html index 843d0c6..943cdf0 100644 --- a/src/index.html +++ b/src/index.html @@ -49,16 +49,18 @@ -
-

Title

-

- Lorem ipsum dolor sit amet consectetur adipisicing elit. Eaque itaque - perspiciatis nesciunt, molestiae officiis dignissimos porro! Provident totam sit - enim, dolores dicta possimus ex assumenda earum, ea tempore, aut quidem? -

+
+
+

Title

+

+ Lorem ipsum dolor sit amet consectetur adipisicing elit. Eaque itaque + perspiciatis nesciunt, molestiae officiis dignissimos porro! Provident totam + sit enim, dolores dicta possimus ex assumenda earum, ea tempore, aut quidem? +

+
-
+
diff --git a/src/index.scss b/src/index.scss index ea7a648..58f3dd6 100644 --- a/src/index.scss +++ b/src/index.scss @@ -31,7 +31,6 @@ p { html { height: 100%; -webkit-font-smooth: antialiased; - > body { width: 100%; height: 100%; @@ -89,6 +88,7 @@ html { top: 50%; left: 0; transform: translateY(-50%); + height: 400px; } @include on-small-screen { @@ -133,10 +133,20 @@ html { } > main.pages { - overflow: hidden; + overflow-x: hidden; + overflow-y: auto; + &::-webkit-scrollbar-track, + &::-webkit-scrollbar { + background-color: transparent; + width: 6px; + } + &::-webkit-scrollbar-thumb { + background-color: var(--main-color); + border-radius: var(--border-radius); + } &, - * { + > * { transition: width var(--transition-time-long), height var(--transition-time-long); @@ -160,7 +170,50 @@ html { } > section { - margin: var(--normal-margin); + padding: var(--normal-margin); + + .slider { + $track-height: 12px; + margin-bottom: var(--small-margin); + + p { + display: flex; + justify-content: space-between; + } + + input[type='range'] { + width: 100%; + height: $track-height; + appearance: none; + background: transparent; + outline: none; + border-radius: 1000px; + + &::-webkit-slider-runnable-track { + appearance: none; + cursor: pointer; + border-radius: 1000px; + @include square(15px); + background: var(--accent-color); + } + + &::-webkit-slider-thumb { + appearance: none; + cursor: pointer; + border-radius: 1000px; + $size: 24px; + @include square($size); + background: white; + box-shadow: 0 0 5px 1px var(--accent-color); + + transform: translateY(-5px); + transition: transform var(--transition-time); + &:hover { + transform: translateY(-5px) scale(1.1); + } + } + } + } } } } diff --git a/src/index.ts b/src/index.ts index 6c9b18b..9a05826 100644 --- a/src/index.ts +++ b/src/index.ts @@ -67,14 +67,17 @@ const main = async () => { const infoPageHandler = new CollapsiblePanelAnimator( elements.infoButton, - elements.infoElement + elements.infoElement, + elements.aside ); const settingsPageHandler = new CollapsiblePanelAnimator( elements.settingsButton, - elements.settingsPage + elements.settingsPage, + elements.aside ); settingsPageHandler.onOpen = infoPageHandler.close.bind(infoPageHandler); infoPageHandler.onOpen = settingsPageHandler.close.bind(settingsPageHandler); + infoPageHandler.open(); new MenuHider(elements.aside, FullScreenHandler.isInFullScreenMode); new FullScreenHandler( @@ -103,9 +106,7 @@ next gen: ${formatNumber(game?.aliveAgentCounts.nextGenerationCount ?? 0)}`; game = new GameLoop(elements.canvas, gpu, deltaTimeCalculator, gameRules); if (!isSettingsPageSetUp) { isSettingsPageSetUp = true; - setUpSettingsPage(elements.settingsPage, game.maxAgentCount, () => - game?.destroy() - ); + setUpSettingsPage(elements.settingsPage, game.maxAgentCount); } await game.start(); diff --git a/src/page/collapsible-panel-animator.ts b/src/page/collapsible-panel-animator.ts index db81376..9589fff 100644 --- a/src/page/collapsible-panel-animator.ts +++ b/src/page/collapsible-panel-animator.ts @@ -6,20 +6,14 @@ export class CollapsiblePanelAnimator { public constructor( infoButton: HTMLButtonElement, - private readonly infoPage: HTMLElement + private readonly infoPage: HTMLElement, + ignoreForCloseOnClick: HTMLElement ) { infoButton.addEventListener('click', this.toggle.bind(this)); - window.addEventListener('click', (event) => { - if ([infoButton, this.infoPage].includes(event.target as HTMLElement)) { - return; - } - - if (this.infoPage.contains(event.target as Node)) { - return; - } - - this.close(); - }); + window.addEventListener( + 'click', + (event) => !ignoreForCloseOnClick.contains(event.target as Node) && this.close() + ); } public open() { diff --git a/src/page/set-up-settings-page.ts b/src/page/set-up-settings-page.ts new file mode 100644 index 0000000..9769dcf --- /dev/null +++ b/src/page/set-up-settings-page.ts @@ -0,0 +1,65 @@ +import { settings } from '../settings'; +import { SettingsSlider, ValueScaling } from '../utils/settings-slider'; + +export const setUpSettingsPage = ( + settingsPage: HTMLDivElement, + maxAgentCount: number +) => { + const sliders = [ + [ + new SettingsSlider(settings, 'agentCount', { + min: 1, + max: maxAgentCount, + scaling: ValueScaling.Logarithmic, + rounding: Math.round, + }), + + new SettingsSlider(settings, 'aggressionFactor', { + min: 0, + max: 10, + }), + + new SettingsSlider(settings, 'nextGenerationSpawnRadius', { + min: 1, + max: 1000, + }), + + new SettingsSlider(settings, 'nextGenerationSpawnInterval', { + min: 0.1, + max: 600, + }), + + new SettingsSlider(settings, 'moveSpeed', { + min: 10, + max: 500, + }), + ], + [ + new SettingsSlider(settings, 'brushWidth', { + min: 1, + max: 60, + }), + + new SettingsSlider(settings, 'brushWidthRandomness', { + min: 0, + max: 1, + }), + ], + [ + new SettingsSlider(settings, 'clarity', { + min: 0.1, + max: 8, + }), + ], + ]; + + sliders.forEach((sliderContainer) => { + const sliderContainerElement = document.createElement('div'); + + sliderContainer.forEach((slider) => { + sliderContainerElement.appendChild(slider.element); + }); + + settingsPage.querySelector('section').appendChild(sliderContainerElement); + }); +}; diff --git a/src/settings.ts b/src/settings.ts index 84759d1..16dfe93 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -3,23 +3,21 @@ import { AgentSettings } from './pipelines/agents/agent-settings'; import { BrushSettings } from './pipelines/brush/brush-settings'; import { DiffusionSettings } from './pipelines/diffusion/diffusion-settings'; import { RenderSettings } from './pipelines/render/render-settings'; +import { persist } from './utils/persist'; -export const settings: GameLoopSettings & +export const settings: { [key: string]: number } & GameLoopSettings & AgentSettings & BrushSettings & DiffusionSettings & - RenderSettings = { - agentCount: 4_000_000, // requires restart + RenderSettings = persist({ + agentCount: 1_000_000, + + brushWidth: 12, + brushWidthRandomness: 0.5, aggressionFactor: 3, nextGenerationSpawnRadius: 5, - nextGenerationSpawnInterval: 1, - - renderSpeed: 2, - simulatedDelayMs: 0, - - brushWidth: 12, - brushWidthRandomness: 5.5, + nextGenerationSpawnInterval: 600, brushTrailWeight: 5, moveSpeed: 80, @@ -37,5 +35,12 @@ export const settings: GameLoopSettings & decayRateBrush: 0.003, clarity: 2, + startColorHue: 200, -}; + + maxAgentCountUpperLimit: 64_000_000, // requires restart + + // debug options + renderSpeed: 1, + simulatedDelayMs: 0, +}); diff --git a/src/style/vars.scss b/src/style/vars.scss index 5e5d4e7..f50b47c 100644 --- a/src/style/vars.scss +++ b/src/style/vars.scss @@ -5,12 +5,10 @@ --transition-time-long: 350ms; --line-width: 4px; --line-height: 1.125rem; - --accent-color: #ff6b6b; - --sun-color: #f7f78c; + --accent-color: rgb(6.39851188659668, 70.28645324707031, 102.23043060302734); --very-light-text-color: #ffffff; - --background: #ffffff; + --main-color: #aaa; --normal-text-color: #31343f; - --card-color: #ffffff; --blurred-card-color: transparent; --blur-radius: 12px; --special-text-color: var(--accent-color); diff --git a/src/utils/settings-slider.ts b/src/utils/settings-slider.ts index f72a69b..4b10a9d 100644 --- a/src/utils/settings-slider.ts +++ b/src/utils/settings-slider.ts @@ -63,11 +63,15 @@ export class SettingsSlider> { valueDisplay: HTMLSpanElement ) { const wrapper = document.createElement('div'); + wrapper.classList.add('slider'); const label = document.createElement('label'); - label.innerText = SettingsSlider.formatLabel(name); + const title = document.createElement('p'); + title.innerText = SettingsSlider.formatLabel(name); + title.appendChild(valueDisplay); + + label.appendChild(title); label.appendChild(slider); - label.appendChild(valueDisplay); wrapper.appendChild(label); return wrapper;