From 5afc8ef1edae2694c8e6f6dc08cf81e0d497efdf Mon Sep 17 00:00:00 2001 From: Misode Date: Thu, 27 Aug 2020 00:24:52 +0200 Subject: [PATCH] Add zooming the biome noise visualization --- src/app/app.ts | 6 +-- src/app/visualization/BiomeNoiseVisualizer.ts | 27 +++++++++--- .../visualization/NoiseSettingsVisualizer.ts | 4 +- src/app/visualization/Visualizer.ts | 5 ++- src/app/visualization/VisualizerView.ts | 42 ++++++++++++------- src/index.html | 5 ++- src/styles/global.css | 20 ++++++--- 7 files changed, 77 insertions(+), 32 deletions(-) diff --git a/src/app/app.ts b/src/app/app.ts index 158b3162..21ea62d3 100644 --- a/src/app/app.ts +++ b/src/app/app.ts @@ -120,13 +120,13 @@ const treeControlsMenu = document.getElementById('tree-controls-menu')! const treeControlsReset = document.getElementById('tree-controls-reset')! const treeControlsUndo = document.getElementById('tree-controls-undo')! const treeControlsRedo = document.getElementById('tree-controls-redo')! -const visualizerOutput = document.getElementById('visualizer-output')! +const visualizerContent = document.getElementById('visualizer-content')! Split([treeViewEl, sourceViewEl], { sizes: [66, 34] }) -Split([sourceViewOutput, visualizerOutput], { +Split([sourceViewOutput, visualizerContent], { sizes: [60, 40], direction: 'vertical' }) @@ -143,7 +143,7 @@ const views = { indentation: 2 }), 'errors': new ErrorsView(dummyModel, errorsViewEl), - 'visualizer': new VisualizerView(dummyModel, visualizerOutput as HTMLCanvasElement) + 'visualizer': new VisualizerView(dummyModel, visualizerContent) } const COLLECTIONS = getCollections() diff --git a/src/app/visualization/BiomeNoiseVisualizer.ts b/src/app/visualization/BiomeNoiseVisualizer.ts index ae76d0aa..df3679b8 100644 --- a/src/app/visualization/BiomeNoiseVisualizer.ts +++ b/src/app/visualization/BiomeNoiseVisualizer.ts @@ -1,6 +1,7 @@ import SimplexNoise from 'simplex-noise' import { DataModel, Path, ModelPath } from "@mcschema/core" import { Visualizer } from './Visualizer' +import { VisualizerView } from './VisualizerView' export class BiomeNoiseVisualizer extends Visualizer { @@ -8,6 +9,7 @@ export class BiomeNoiseVisualizer extends Visualizer { private noise: SimplexNoise[] private offsetX: number = 0 private offsetY: number = 0 + private viewScale: number = 0 private biomeColors: {[id: string]: number[]} = {} constructor() { @@ -26,10 +28,13 @@ export class BiomeNoiseVisualizer extends Visualizer { draw(model: DataModel, img: ImageData) { const data = img.data + const s = (2 ** this.viewScale) for (let x = 0; x < 200; x += 1) { for (let y = 0; y < 100; y += 1) { const i = (y * (img.width * 4)) + (x * 4) - const b = this.closestBiome(x, y) + const xx = (x - this.offsetX) * s - 100 * s + const yy = (y- this.offsetY) * s - 50 * s + const b = this.closestBiome(xx, yy) const color = this.getBiomeColor(b) data[i] = color[0] data[i + 1] = color[1] @@ -39,9 +44,21 @@ export class BiomeNoiseVisualizer extends Visualizer { } } - onDrag(from: number[], to: number[]) { - this.offsetX += to[0] - from[0] - this.offsetY += to[1] - from[1] + onDrag(fromX: number, fromY: number, toX: number, toY: number) { + this.offsetX += toX - fromX + this.offsetY += toY - fromY + } + + addControls(el: HTMLElement, view: VisualizerView) { + el.insertAdjacentHTML('beforeend', ``) + el.childNodes[0].addEventListener('click', () => { + this.viewScale -= 0.5 + view.redraw() + }) + el.childNodes[1].addEventListener('click', () => { + this.viewScale += 0.5 + view.redraw() + }) } private closestBiome(x: number, y: number): string { @@ -71,7 +88,7 @@ export class BiomeNoiseVisualizer extends Visualizer { let n = 0 let scale = 2**config.firstOctave for (let i = 0; i < config.amplitudes.length; i++) { - n += this.noise[index].noise2D((x - this.offsetX)*scale, (y- this.offsetY)*scale + i) + n += this.noise[index].noise2D(x * scale, y * scale + i) * config.amplitudes[i] / (2**scale) scale *= 2 } diff --git a/src/app/visualization/NoiseSettingsVisualizer.ts b/src/app/visualization/NoiseSettingsVisualizer.ts index a59c3fff..f1f2d263 100644 --- a/src/app/visualization/NoiseSettingsVisualizer.ts +++ b/src/app/visualization/NoiseSettingsVisualizer.ts @@ -37,8 +37,8 @@ export class NoiseSettingsVisualizer extends Visualizer { } } - onDrag(from: number[], to: number[]) { - this.offsetX += (to[0] - from[0]) + onDrag(fromX: number, fromY: number, toX: number, toY: number) { + this.offsetX += toX - fromX } private getColor(densities: number[], y: number): number { diff --git a/src/app/visualization/Visualizer.ts b/src/app/visualization/Visualizer.ts index 90822b5d..957565fa 100644 --- a/src/app/visualization/Visualizer.ts +++ b/src/app/visualization/Visualizer.ts @@ -1,4 +1,5 @@ import { DataModel, ModelPath } from "@mcschema/core" +import { VisualizerView } from "./VisualizerView" export abstract class Visualizer { state: any @@ -11,5 +12,7 @@ export abstract class Visualizer { abstract active(path: ModelPath): boolean abstract draw(model: DataModel, img: ImageData): void - onDrag(from: number[], to: number[]): void {} + onDrag(fromX: number, fromY: number, toX: number, toY: number): void {} + + addControls(el: HTMLElement, view: VisualizerView): void {} } diff --git a/src/app/visualization/VisualizerView.ts b/src/app/visualization/VisualizerView.ts index b3103420..8445e0e5 100644 --- a/src/app/visualization/VisualizerView.ts +++ b/src/app/visualization/VisualizerView.ts @@ -8,37 +8,47 @@ export class VisualizerView extends AbstractView { visualizer?: Visualizer active: boolean path?: ModelPath - canvas: HTMLElement + el: HTMLElement + canvas: HTMLCanvasElement sourceView: HTMLElement gutter: HTMLElement + controls: HTMLElement lastHeight?: string dragStart?: number[] - constructor(model: DataModel, canvas: HTMLCanvasElement) { + constructor(model: DataModel, el: HTMLElement) { super(model) - this.ctx = canvas.getContext('2d')! + this.el = el + this.canvas = el.querySelector('canvas') as HTMLCanvasElement + this.ctx = this.canvas.getContext('2d')! this.active = false - this.canvas = canvas - this.gutter = canvas.parentElement!.querySelector('.gutter') as HTMLElement - this.sourceView = canvas.parentElement!.getElementsByTagName('textarea')[0] as HTMLElement + this.gutter = el.parentElement!.querySelector('.gutter') as HTMLElement + this.sourceView = el.parentElement!.getElementsByTagName('textarea')[0] as HTMLElement + this.controls = el.querySelector('.visualizer-controls') as HTMLElement - canvas.addEventListener('mousedown', evt => { + this.canvas.addEventListener('mousedown', evt => { this.dragStart = [evt.offsetX, evt.offsetY] }) - canvas.addEventListener('mousemove', evt => { + this.canvas.addEventListener('mousemove', evt => { if (this.dragStart === undefined) return if (this.visualizer?.onDrag) { - this.visualizer.onDrag(this.dragStart, [evt.offsetX, evt.offsetY]) - this.visualizer.state = {} - this.invalidated() + this.visualizer.onDrag(this.dragStart[0], this.dragStart[1], evt.offsetX, evt.offsetY) + this.redraw() } this.dragStart = [evt.offsetX, evt.offsetY] }) - canvas.addEventListener('mouseup', evt => { + this.canvas.addEventListener('mouseup', evt => { this.dragStart = undefined }) } + redraw() { + if (this.active && this.visualizer) { + this.visualizer.state = {} + this.invalidated() + } + } + invalidated() { this.path = this.path?.withModel(this.model) let newState: any @@ -51,14 +61,14 @@ export class VisualizerView extends AbstractView { this.visualizer.draw(this.model, img) this.ctx.putImageData(img, 0, 0) } - this.canvas.style.display = 'block' + this.el.style.display = 'block' this.gutter.style.display = 'block' if (this.lastHeight) { this.sourceView.style.height = this.lastHeight this.lastHeight = undefined } } else { - this.canvas.style.display = 'none' + this.el.style.display = 'none' this.gutter.style.display = 'none' this.lastHeight = this.sourceView.style.height this.sourceView.style.height = '100%' @@ -70,7 +80,9 @@ export class VisualizerView extends AbstractView { this.visualizer = visualizer this.path = path this.visualizer.state = undefined - this.invalidated() + this.controls.innerHTML = '' + this.visualizer.addControls(this.controls, this) + this.redraw() } static visualizers: Visualizer[] = [ diff --git a/src/index.html b/src/index.html index a5bf768f..ae4d1e55 100644 --- a/src/index.html +++ b/src/index.html @@ -94,7 +94,10 @@
- +
+
+ +
diff --git a/src/styles/global.css b/src/styles/global.css index 1e314e60..eb76b021 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -193,7 +193,8 @@ body { } .tree-controls, -.source-controls { +.source-controls, +.visualizer-controls { display: flex; flex-direction: row-reverse; position: absolute; @@ -203,7 +204,8 @@ body { } .tree-controls .btn:not(:first-child), -.source-controls .btn:not(:first-child) { +.source-controls .btn:not(:first-child), +.visualizer-controls .btn:not(:first-child) { margin-right: 5px; } @@ -235,11 +237,19 @@ body { cursor: ew-resize; } -.source canvas { +.visualizer-content { width: 100%; max-width: 100%; - /* position: absolute; */ - /* bottom: 0; */ + position: relative; +} + +.visualizer-controls { + right: 0; +} + +.visualizer-content canvas { + width: 100%; + height: 100%; background-color: var(--nav-faded); display: block; cursor: grab;