mirror of
https://github.com/misode/misode.github.io.git
synced 2026-04-24 23:56:51 +00:00
Rewrite noise settings preview
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
export const Octicon = {
|
||||
arrow_both: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M3.72 3.72a.75.75 0 011.06 1.06L2.56 7h10.88l-2.22-2.22a.75.75 0 011.06-1.06l3.5 3.5a.75.75 0 010 1.06l-3.5 3.5a.75.75 0 11-1.06-1.06l2.22-2.22H2.56l2.22 2.22a.75.75 0 11-1.06 1.06l-3.5-3.5a.75.75 0 010-1.06l3.5-3.5z"></path></svg>',
|
||||
arrow_left: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.78 12.53a.75.75 0 01-1.06 0L2.47 8.28a.75.75 0 010-1.06l4.25-4.25a.75.75 0 011.06 1.06L4.81 7h7.44a.75.75 0 010 1.5H4.81l2.97 2.97a.75.75 0 010 1.06z"></path></svg>',
|
||||
arrow_right: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M8.22 2.97a.75.75 0 011.06 0l4.25 4.25a.75.75 0 010 1.06l-4.25 4.25a.75.75 0 01-1.06-1.06l2.97-2.97H3.75a.75.75 0 010-1.5h7.44L8.22 4.03a.75.75 0 010-1.06z"></path></svg>',
|
||||
chevron_down: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M12.78 6.22a.75.75 0 010 1.06l-4.25 4.25a.75.75 0 01-1.06 0L3.22 7.28a.75.75 0 011.06-1.06L8 9.94l3.72-3.72a.75.75 0 011.06 0z"></path></svg>',
|
||||
@@ -7,6 +8,7 @@ export const Octicon = {
|
||||
code: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M4.72 3.22a.75.75 0 011.06 1.06L2.06 8l3.72 3.72a.75.75 0 11-1.06 1.06L.47 8.53a.75.75 0 010-1.06l4.25-4.25zm6.56 0a.75.75 0 10-1.06 1.06L13.94 8l-3.72 3.72a.75.75 0 101.06 1.06l4.25-4.25a.75.75 0 000-1.06l-4.25-4.25z"></path></svg>',
|
||||
dash: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M2 8a.75.75 0 01.75-.75h10.5a.75.75 0 010 1.5H2.75A.75.75 0 012 8z"></path></svg>',
|
||||
download: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.47 10.78a.75.75 0 001.06 0l3.75-3.75a.75.75 0 00-1.06-1.06L8.75 8.44V1.75a.75.75 0 00-1.5 0v6.69L4.78 5.97a.75.75 0 00-1.06 1.06l3.75 3.75zM3.75 13a.75.75 0 000 1.5h8.5a.75.75 0 000-1.5h-8.5z"></path></svg>',
|
||||
gear: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.429 1.525a6.593 6.593 0 011.142 0c.036.003.108.036.137.146l.289 1.105c.147.56.55.967.997 1.189.174.086.341.183.501.29.417.278.97.423 1.53.27l1.102-.303c.11-.03.175.016.195.046.219.31.41.641.573.989.014.031.022.11-.059.19l-.815.806c-.411.406-.562.957-.53 1.456a4.588 4.588 0 010 .582c-.032.499.119 1.05.53 1.456l.815.806c.08.08.073.159.059.19a6.494 6.494 0 01-.573.99c-.02.029-.086.074-.195.045l-1.103-.303c-.559-.153-1.112-.008-1.529.27-.16.107-.327.204-.5.29-.449.222-.851.628-.998 1.189l-.289 1.105c-.029.11-.101.143-.137.146a6.613 6.613 0 01-1.142 0c-.036-.003-.108-.037-.137-.146l-.289-1.105c-.147-.56-.55-.967-.997-1.189a4.502 4.502 0 01-.501-.29c-.417-.278-.97-.423-1.53-.27l-1.102.303c-.11.03-.175-.016-.195-.046a6.492 6.492 0 01-.573-.989c-.014-.031-.022-.11.059-.19l.815-.806c.411-.406.562-.957.53-1.456a4.587 4.587 0 010-.582c.032-.499-.119-1.05-.53-1.456l-.815-.806c-.08-.08-.073-.159-.059-.19a6.44 6.44 0 01.573-.99c.02-.029.086-.075.195-.045l1.103.303c.559.153 1.112.008 1.529-.27.16-.107.327-.204.5-.29.449-.222.851-.628.998-1.189l.289-1.105c.029-.11.101-.143.137-.146zM8 0c-.236 0-.47.01-.701.03-.743.065-1.29.615-1.458 1.261l-.29 1.106c-.017.066-.078.158-.211.224a5.994 5.994 0 00-.668.386c-.123.082-.233.09-.3.071L3.27 2.776c-.644-.177-1.392.02-1.82.63a7.977 7.977 0 00-.704 1.217c-.315.675-.111 1.422.363 1.891l.815.806c.05.048.098.147.088.294a6.084 6.084 0 000 .772c.01.147-.038.246-.088.294l-.815.806c-.474.469-.678 1.216-.363 1.891.2.428.436.835.704 1.218.428.609 1.176.806 1.82.63l1.103-.303c.066-.019.176-.011.299.071.213.143.436.272.668.386.133.066.194.158.212.224l.289 1.106c.169.646.715 1.196 1.458 1.26a8.094 8.094 0 001.402 0c.743-.064 1.29-.614 1.458-1.26l.29-1.106c.017-.066.078-.158.211-.224a5.98 5.98 0 00.668-.386c.123-.082.233-.09.3-.071l1.102.302c.644.177 1.392-.02 1.82-.63.268-.382.505-.789.704-1.217.315-.675.111-1.422-.364-1.891l-.814-.806c-.05-.048-.098-.147-.088-.294a6.1 6.1 0 000-.772c-.01-.147.039-.246.088-.294l.814-.806c.475-.469.679-1.216.364-1.891a7.992 7.992 0 00-.704-1.218c-.428-.609-1.176-.806-1.82-.63l-1.103.303c-.066.019-.176.011-.299-.071a5.991 5.991 0 00-.668-.386c-.133-.066-.194-.158-.212-.224L10.16 1.29C9.99.645 9.444.095 8.701.031A8.094 8.094 0 008 0zm1.5 8a1.5 1.5 0 11-3 0 1.5 1.5 0 013 0zM11 8a3 3 0 11-6 0 3 3 0 016 0z"></path></svg>',
|
||||
globe: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M1.543 7.25h2.733c.144-2.074.866-3.756 1.58-4.948.12-.197.237-.381.353-.552a6.506 6.506 0 00-4.666 5.5zm2.733 1.5H1.543a6.506 6.506 0 004.666 5.5 11.13 11.13 0 01-.352-.552c-.715-1.192-1.437-2.874-1.581-4.948zm1.504 0h4.44a9.637 9.637 0 01-1.363 4.177c-.306.51-.612.919-.857 1.215a9.978 9.978 0 01-.857-1.215A9.637 9.637 0 015.78 8.75zm4.44-1.5H5.78a9.637 9.637 0 011.363-4.177c.306-.51.612-.919.857-1.215.245.296.55.705.857 1.215A9.638 9.638 0 0110.22 7.25zm1.504 1.5c-.144 2.074-.866 3.756-1.58 4.948-.12.197-.237.381-.353.552a6.506 6.506 0 004.666-5.5h-2.733zm2.733-1.5h-2.733c-.144-2.074-.866-3.756-1.58-4.948a11.738 11.738 0 00-.353-.552 6.506 6.506 0 014.666 5.5zM8 0a8 8 0 100 16A8 8 0 008 0z"></path></svg>',
|
||||
history: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M1.643 3.143L.427 1.927A.25.25 0 000 2.104V5.75c0 .138.112.25.25.25h3.646a.25.25 0 00.177-.427L2.715 4.215a6.5 6.5 0 11-1.18 4.458.75.75 0 10-1.493.154 8.001 8.001 0 101.6-5.684zM7.75 4a.75.75 0 01.75.75v2.992l2.028.812a.75.75 0 01-.557 1.392l-2.5-1A.75.75 0 017 8.25v-3.5A.75.75 0 017.75 4z"></path></svg>',
|
||||
info: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M8 1.5a6.5 6.5 0 100 13 6.5 6.5 0 000-13zM0 8a8 8 0 1116 0A8 8 0 010 8zm6.5-.25A.75.75 0 017.25 7h1a.75.75 0 01.75.75v2.75h.25a.75.75 0 010 1.5h-2a.75.75 0 010-1.5h.25v-2h-.25a.75.75 0 01-.75-.75zM8 6a1 1 0 100-2 1 1 0 000 2z"></path></svg>',
|
||||
@@ -19,6 +21,8 @@ export const Octicon = {
|
||||
play: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M1.5 8a6.5 6.5 0 1113 0 6.5 6.5 0 01-13 0zM8 0a8 8 0 100 16A8 8 0 008 0zM6.379 5.227A.25.25 0 006 5.442v5.117a.25.25 0 00.379.214l4.264-2.559a.25.25 0 000-.428L6.379 5.227z"></path></svg>',
|
||||
plus: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M8 2a.75.75 0 01.75.75v4.5h4.5a.75.75 0 010 1.5h-4.5v4.5a.75.75 0 01-1.5 0v-4.5h-4.5a.75.75 0 010-1.5h4.5v-4.5A.75.75 0 018 2z"></path></svg>',
|
||||
plus_circle: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M1.5 8a6.5 6.5 0 1113 0 6.5 6.5 0 01-13 0zM8 0a8 8 0 100 16A8 8 0 008 0zm.75 4.75a.75.75 0 00-1.5 0v2.5h-2.5a.75.75 0 000 1.5h2.5v2.5a.75.75 0 001.5 0v-2.5h2.5a.75.75 0 000-1.5h-2.5v-2.5z"></path></svg>',
|
||||
square: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M4 5.75C4 4.784 4.784 4 5.75 4h4.5c.966 0 1.75.784 1.75 1.75v4.5A1.75 1.75 0 0110.25 12h-4.5A1.75 1.75 0 014 10.25v-4.5zm1.75-.25a.25.25 0 00-.25.25v4.5c0 .138.112.25.25.25h4.5a.25.25 0 00.25-.25v-4.5a.25.25 0 00-.25-.25h-4.5z"></path></svg>',
|
||||
square_fill: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M5.75 4A1.75 1.75 0 004 5.75v4.5c0 .966.784 1.75 1.75 1.75h4.5A1.75 1.75 0 0012 10.25v-4.5A1.75 1.75 0 0010.25 4h-4.5z"></path></svg>',
|
||||
sun: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M8 10.5a2.5 2.5 0 100-5 2.5 2.5 0 000 5zM8 12a4 4 0 100-8 4 4 0 000 8zM8 0a.75.75 0 01.75.75v1.5a.75.75 0 01-1.5 0V.75A.75.75 0 018 0zm0 13a.75.75 0 01.75.75v1.5a.75.75 0 01-1.5 0v-1.5A.75.75 0 018 13zM2.343 2.343a.75.75 0 011.061 0l1.06 1.061a.75.75 0 01-1.06 1.06l-1.06-1.06a.75.75 0 010-1.06zm9.193 9.193a.75.75 0 011.06 0l1.061 1.06a.75.75 0 01-1.06 1.061l-1.061-1.06a.75.75 0 010-1.061zM16 8a.75.75 0 01-.75.75h-1.5a.75.75 0 010-1.5h1.5A.75.75 0 0116 8zM3 8a.75.75 0 01-.75.75H.75a.75.75 0 010-1.5h1.5A.75.75 0 013 8zm10.657-5.657a.75.75 0 010 1.061l-1.061 1.06a.75.75 0 11-1.06-1.06l1.06-1.06a.75.75 0 011.06 0zm-9.193 9.193a.75.75 0 010 1.06l-1.06 1.061a.75.75 0 11-1.061-1.06l1.06-1.061a.75.75 0 011.061 0z"></path></svg>',
|
||||
tag: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M2.5 7.775V2.75a.25.25 0 01.25-.25h5.025a.25.25 0 01.177.073l6.25 6.25a.25.25 0 010 .354l-5.025 5.025a.25.25 0 01-.354 0l-6.25-6.25a.25.25 0 01-.073-.177zm-1.5 0V2.75C1 1.784 1.784 1 2.75 1h5.025c.464 0 .91.184 1.238.513l6.25 6.25a1.75 1.75 0 010 2.474l-5.026 5.026a1.75 1.75 0 01-2.474 0l-6.25-6.25A1.75 1.75 0 011 7.775zM6 5a1 1 0 100 2 1 1 0 000-2z"></path></svg>',
|
||||
trashcan: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M6.5 1.75a.25.25 0 01.25-.25h2.5a.25.25 0 01.25.25V3h-3V1.75zm4.5 0V3h2.25a.75.75 0 010 1.5H2.75a.75.75 0 010-1.5H5V1.75C5 .784 5.784 0 6.75 0h2.5C10.216 0 11 .784 11 1.75zM4.496 6.675a.75.75 0 10-1.492.15l.66 6.6A1.75 1.75 0 005.405 15h5.19c.9 0 1.652-.681 1.741-1.576l.66-6.6a.75.75 0 00-1.492-.149l-.66 6.6a.25.25 0 01-.249.225h-5.19a.25.25 0 01-.249-.225l-.66-6.6z"></path></svg>',
|
||||
|
||||
@@ -7,20 +7,30 @@ import { Octicon } from '../Octicon';
|
||||
|
||||
export const PreviewPanel = (view: View, model: DataModel) => {
|
||||
const panel = view.register(el => {
|
||||
const canvasEl = el.querySelector('canvas')!
|
||||
const controlsEl = el.querySelector('.panel-controls')!
|
||||
const canvas = el.querySelector('canvas')!
|
||||
const redraw = () => {
|
||||
const preview = App.preview.get()
|
||||
if (preview && preview.path && preview.path.withModel(model).get()) {
|
||||
const ctx = canvasEl.getContext('2d')!
|
||||
const img = ctx.createImageData(200, 100)
|
||||
const ctx = canvas.getContext('2d')!
|
||||
const newState = preview.path.withModel(model).get()
|
||||
preview.state = JSON.parse(JSON.stringify(newState))
|
||||
const [width, height] = preview.getSize()
|
||||
canvas.width = width
|
||||
canvas.height = height
|
||||
const img = ctx.createImageData(width, height)
|
||||
preview.draw(model, img)
|
||||
ctx.putImageData(img, 0, 0)
|
||||
} else {
|
||||
App.preview.set(null)
|
||||
}
|
||||
|
||||
view.mount(el.querySelector('.panel-controls')!, `
|
||||
${App.preview.get()?.menu(view, redraw) ?? ''}
|
||||
<div class="btn" data-id="${view.onClick(() => {
|
||||
Tracker.hidePreview(); App.preview.set(null)
|
||||
})}">
|
||||
${Octicon.x}
|
||||
</div>`, false)
|
||||
}
|
||||
model.addListener({
|
||||
invalidated: redraw
|
||||
@@ -44,23 +54,22 @@ export const PreviewPanel = (view: View, model: DataModel) => {
|
||||
;(el as HTMLCanvasElement).addEventListener('mousemove', evt => {
|
||||
if (dragStart === undefined) return
|
||||
if (App.preview.get()?.onDrag) {
|
||||
App.preview.get()?.onDrag(dragStart[0], dragStart[1], evt.offsetX, evt.offsetY)
|
||||
redraw()
|
||||
const [width, height] = App.preview.get()!.getSize()
|
||||
const dx = (evt.offsetX - dragStart[0]) * width / canvas.clientWidth
|
||||
const dy = (evt.offsetY - dragStart[1]) * height / canvas.clientHeight
|
||||
if (!(dx === 0 && dy === 0)) {
|
||||
App.preview.get()?.onDrag(dx, dy)
|
||||
redraw()
|
||||
}
|
||||
}
|
||||
dragStart = [evt.offsetX, evt.offsetY]
|
||||
})
|
||||
;(el as HTMLCanvasElement).addEventListener('mouseup', evt => {
|
||||
dragStart = undefined
|
||||
})
|
||||
|
||||
view.mount(controlsEl, `
|
||||
${App.preview.get()?.menu(view, redraw) ?? ''}
|
||||
<div class="btn" data-id="${view.onClick(() => {
|
||||
Tracker.hidePreview(); App.preview.set(null)
|
||||
})}">${Octicon.x}</div>`, false)
|
||||
})
|
||||
return `<div class="panel preview-panel" data-id="${panel}">
|
||||
<div class="panel-controls"></div>
|
||||
<canvas width="200" height="100">
|
||||
<canvas width="512" height="256">
|
||||
</div>`
|
||||
}
|
||||
|
||||
@@ -50,6 +50,10 @@ export class BiomeNoisePreview extends Preview {
|
||||
</div>`
|
||||
}
|
||||
|
||||
getSize(): [number, number] {
|
||||
return [200, 100]
|
||||
}
|
||||
|
||||
draw(model: DataModel, img: ImageData) {
|
||||
this.noise = BiomeNoisePreview.noiseMaps.map((id, i) => {
|
||||
const config = this.state[`${id}_noise`]
|
||||
@@ -78,9 +82,9 @@ export class BiomeNoisePreview extends Preview {
|
||||
}
|
||||
}
|
||||
|
||||
onDrag(fromX: number, fromY: number, toX: number, toY: number) {
|
||||
this.offsetX += toX - fromX
|
||||
this.offsetY += toY - fromY
|
||||
onDrag(dx: number, dy: number) {
|
||||
this.offsetX += dx
|
||||
this.offsetY += dy
|
||||
}
|
||||
|
||||
private closestBiome(x: number, y: number): string {
|
||||
|
||||
@@ -1,17 +1,23 @@
|
||||
import SimplexNoise from 'simplex-noise'
|
||||
import { DataModel, Path, ModelPath } from "@mcschema/core"
|
||||
import { Preview } from './Preview'
|
||||
|
||||
const debug = false
|
||||
import { toggleMenu, View } from '../views/View'
|
||||
import { Octicon } from '../components/Octicon'
|
||||
|
||||
export class NoiseSettingsPreview extends Preview {
|
||||
private noise: SimplexNoise
|
||||
private offsetX: number
|
||||
private width: number = 512
|
||||
private chunkWidth: number = 4
|
||||
private chunkHeight: number = 4
|
||||
private chunkCountY: number = 32
|
||||
private offsetX: number = 0
|
||||
private debug: boolean = false
|
||||
private depth: number = 0.1
|
||||
private scale: number = 0.2
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
this.noise = new SimplexNoise()
|
||||
this.offsetX = 0
|
||||
}
|
||||
|
||||
getName() {
|
||||
@@ -22,14 +28,69 @@ export class NoiseSettingsPreview extends Preview {
|
||||
return path.endsWith(new Path(['noise']))
|
||||
}
|
||||
|
||||
menu(view: View, redraw: () => void) {
|
||||
return `<div class="panel-menu">
|
||||
<div class="btn" data-id="${view.onClick(toggleMenu)}">
|
||||
${Octicon.kebab_horizontal}
|
||||
</div>
|
||||
<div class="panel-menu-list btn-group">
|
||||
<div class="btn input">
|
||||
${Octicon.gear}
|
||||
<label data-i18n="preview.depth"></label>
|
||||
<input type="number" step="0.1" data-id="${view.register(el => {
|
||||
(el as HTMLInputElement).value = this.depth.toString()
|
||||
el.addEventListener('change', () => {
|
||||
this.depth = parseFloat((el as HTMLInputElement).value)
|
||||
redraw()
|
||||
})
|
||||
})}">
|
||||
</div>
|
||||
<div class="btn input">
|
||||
${Octicon.gear}
|
||||
<label data-i18n="preview.scale"></label>
|
||||
<input type="number" step="0.1" data-id="${view.register(el => {
|
||||
(el as HTMLInputElement).value = this.scale.toString()
|
||||
el.addEventListener('change', () => {
|
||||
this.scale = parseFloat((el as HTMLInputElement).value)
|
||||
redraw()
|
||||
})
|
||||
})}">
|
||||
</div>
|
||||
<div class="btn input">
|
||||
${Octicon.arrow_both}
|
||||
<label data-i18n="preview.width"></label>
|
||||
<input type="number" step="16" data-id="${view.register(el => {
|
||||
(el as HTMLInputElement).value = this.width.toString()
|
||||
el.addEventListener('change', () => {
|
||||
this.width = parseFloat((el as HTMLInputElement).value)
|
||||
redraw()
|
||||
})
|
||||
})}">
|
||||
</div>
|
||||
<div class="btn" data-id="${view.onClick(() => {this.debug = !this.debug; redraw()})}">
|
||||
${this.debug ? Octicon.square_fill : Octicon.square}
|
||||
<span data-i18n="preview.show_density"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>`
|
||||
}
|
||||
|
||||
getSize(): [number, number] {
|
||||
return [this.width, this.state.height]
|
||||
}
|
||||
|
||||
draw(model: DataModel, img: ImageData) {
|
||||
this.chunkWidth = this.state.size_horizontal * 4
|
||||
this.chunkHeight = this.state.size_vertical * 4
|
||||
this.chunkCountY = Math.floor(this.state.height / this.chunkHeight)
|
||||
|
||||
const data = img.data
|
||||
for (let x = 0; x < 200; x += 1) {
|
||||
const densities = this.fillNoiseColumn(x - this.offsetX).reverse()
|
||||
for (let y = 0; y < 100; y += 1) {
|
||||
for (let x = 0; x < this.width; x += 1) {
|
||||
const noise = this.iterateNoiseColumn(x - this.offsetX).reverse()
|
||||
for (let y = 0; y < this.state.height; y += 1) {
|
||||
const i = (y * (img.width * 4)) + (x * 4)
|
||||
const color = this.getColor(densities, y)
|
||||
data[i] = (debug && densities[y] > 0) ? 255 : color
|
||||
const color = this.getColor(noise, y)
|
||||
data[i] = (this.debug && noise[y] > 0) ? 255 : color
|
||||
data[i + 1] = color
|
||||
data[i + 2] = color
|
||||
data[i + 3] = 255
|
||||
@@ -37,57 +98,78 @@ export class NoiseSettingsPreview extends Preview {
|
||||
}
|
||||
}
|
||||
|
||||
onDrag(fromX: number, fromY: number, toX: number, toY: number) {
|
||||
this.offsetX += toX - fromX
|
||||
onDrag(dx: number, dy: number) {
|
||||
this.offsetX += dx
|
||||
}
|
||||
|
||||
private getColor(densities: number[], y: number): number {
|
||||
if (debug) {
|
||||
return -densities[y] * 128 + 128
|
||||
private getColor(noise: number[], y: number): number {
|
||||
if (this.debug) {
|
||||
return -noise[y] / 2 + 128
|
||||
}
|
||||
if (densities[y] > 0) {
|
||||
if (noise[y] > 0) {
|
||||
return 0
|
||||
}
|
||||
if (densities[y+1] > 0) {
|
||||
if (noise[y+1] > 0) {
|
||||
return 150
|
||||
}
|
||||
return 255
|
||||
}
|
||||
|
||||
private fillNoiseColumn(x: number) {
|
||||
const data = Array(100)
|
||||
for (let y = 0; y < 100; y += 1) {
|
||||
let density = this.getNoise(x, y)
|
||||
density = density < -1 ? -1 : density > 1 ? 1 : density
|
||||
private iterateNoiseColumn(x: number): number[] {
|
||||
const data = Array(this.chunkCountY * this.chunkHeight)
|
||||
const cx = Math.floor(x / this.chunkWidth)
|
||||
const ox = Math.floor(x % this.chunkWidth) / this.chunkWidth
|
||||
const noise1 = this.fillNoiseColumn(cx)
|
||||
const noise2 = this.fillNoiseColumn(cx + 1)
|
||||
|
||||
const heightFactor = (1 - y / 50) * this.state.density_factor + this.state.density_offset
|
||||
density += heightFactor * (heightFactor > 0 ? 16 : 4)
|
||||
|
||||
if (this.state.top_slide.size > 0) {
|
||||
density = this.clampedLerp(
|
||||
this.state.top_slide.target / 100,
|
||||
density,
|
||||
(100 - y - (this.state.top_slide.offset * 4)) / (this.state.top_slide.size * 4)
|
||||
)
|
||||
for (let y = this.chunkCountY - 1; y >= 0; y -= 1) {
|
||||
for (let yy = this.chunkHeight; yy >= 0; yy -= 1) {
|
||||
const oy = yy / this.chunkHeight
|
||||
const i = y * this.chunkHeight + yy
|
||||
data[i] = this.lerp2(oy, ox, noise1[y], noise1[y+1], noise2[y], noise2[y+1]);
|
||||
}
|
||||
|
||||
if (this.state.bottom_slide.size > 0) {
|
||||
density = this.clampedLerp(
|
||||
this.state.bottom_slide.target / 100,
|
||||
density,
|
||||
(y - (this.state.bottom_slide.offset * 4)) / (this.state.bottom_slide.size * 4)
|
||||
)
|
||||
}
|
||||
data[y] = density
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
private getNoise(x: number, y: number) {
|
||||
private fillNoiseColumn(x: number): number[] {
|
||||
const data = Array(this.chunkCountY + 1)
|
||||
|
||||
const scaledDepth = 0.265625 * this.depth
|
||||
const scaledScale = 96 / this.scale
|
||||
|
||||
for (let y = 0; y <= this.chunkCountY; y += 1) {
|
||||
let noise = this.getNoise(x, y)
|
||||
const yOffset = 1 - y * 2 / this.chunkCountY
|
||||
const density = yOffset * this.state.density_factor + this.state.density_offset
|
||||
const falloff = (density + scaledDepth) * scaledScale
|
||||
noise += falloff * (falloff > 0 ? 4 : 1)
|
||||
|
||||
if (this.state.top_slide.size > 0) {
|
||||
noise = this.clampedLerp(
|
||||
this.state.top_slide.target,
|
||||
noise,
|
||||
(this.chunkCountY - y - (this.state.top_slide.offset)) / (this.state.top_slide.size)
|
||||
)
|
||||
}
|
||||
|
||||
if (this.state.bottom_slide.size > 0) {
|
||||
noise = this.clampedLerp(
|
||||
this.state.bottom_slide.target,
|
||||
noise,
|
||||
(y - (this.state.bottom_slide.offset)) / (this.state.bottom_slide.size)
|
||||
)
|
||||
}
|
||||
data[y] = noise
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
private getNoise(x: number, y: number): number {
|
||||
const octaves = [ [64, 1], [32, 2], [16, 4], [8, 8], [4, 16] ]
|
||||
return octaves
|
||||
.map(o => this.noise.noise2D(x / o[0], y / o[0]) / o[1])
|
||||
.reduce((prev, acc) => prev + acc)
|
||||
.reduce((prev, acc) => prev + acc) * 256
|
||||
}
|
||||
|
||||
private clampedLerp(a: number, b: number, c: number): number {
|
||||
@@ -96,7 +178,15 @@ export class NoiseSettingsPreview extends Preview {
|
||||
} else if (c > 1) {
|
||||
return b
|
||||
} else {
|
||||
return a + c * (b - a);
|
||||
return this.lerp(c, a, b)
|
||||
}
|
||||
}
|
||||
|
||||
public lerp(a: number, b: number, c: number): number {
|
||||
return b + a * (c - b);
|
||||
}
|
||||
|
||||
public lerp2(a: number, b: number, c: number, d: number, e: number, f: number): number {
|
||||
return this.lerp(b, this.lerp(a, c, d), this.lerp(a, e, f));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,9 +13,10 @@ export abstract class Preview {
|
||||
return ''
|
||||
}
|
||||
|
||||
abstract getSize(): [number, number]
|
||||
abstract getName(): string
|
||||
abstract active(path: ModelPath): boolean
|
||||
abstract draw(model: DataModel, img: ImageData): void
|
||||
|
||||
onDrag(fromX: number, fromY: number, toX: number, toY: number): void {}
|
||||
onDrag(dx: number, dy: number): void {}
|
||||
}
|
||||
|
||||
@@ -54,8 +54,10 @@ export class View {
|
||||
}
|
||||
|
||||
export const toggleMenu = (el: Element) => {
|
||||
el.classList.toggle('active')
|
||||
el.classList.add('active')
|
||||
document.body.addEventListener('click', evt => {
|
||||
if ((evt.target as Element).matches('.btn.input')) return
|
||||
if ((evt.target as Element).closest('.btn')?.classList.contains('input')) return
|
||||
el.classList.remove('active')
|
||||
}, { capture: true, once: true })
|
||||
}
|
||||
|
||||
@@ -15,6 +15,10 @@
|
||||
"title.home": "Data Pack Generators",
|
||||
"title.suffix": "%0% Minecraft 1.16, 1.17",
|
||||
"preview": "Visualize",
|
||||
"preview.show_density": "Show Density",
|
||||
"preview.scale": "Scale",
|
||||
"preview.depth": "Depth",
|
||||
"preview.width": "Width",
|
||||
"undo": "Undo",
|
||||
"world": "World Settings",
|
||||
"worldgen/biome": "Biome",
|
||||
|
||||
@@ -311,7 +311,7 @@ nav > .toggle span {
|
||||
transition: background-color var(--style-transition);
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
.btn:not(.input):hover {
|
||||
background-color: var(--btn-hover);
|
||||
}
|
||||
|
||||
@@ -335,6 +335,15 @@ nav > .toggle span {
|
||||
color: var(--btn-active);
|
||||
}
|
||||
|
||||
.btn.input {
|
||||
cursor: initial;
|
||||
}
|
||||
|
||||
.btn input {
|
||||
margin-left: 5px;
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.errors {
|
||||
position: fixed;
|
||||
display: flex;
|
||||
|
||||
Reference in New Issue
Block a user