UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

199 lines (145 loc) 4.98 kB
import { obtainTerrain } from "../../../src/engine/ecs/terrain/util/obtainTerrain.js"; import { sampler2d_to_data_url } from "../../../src/engine/graphics/texture/sampler/sampler2d_to_data_url.js"; import { ActionUpdateTexture } from "../../actions/concrete/ActionUpdateTexture.js"; import { ArrayCopyAction } from "../../actions/concrete/ArrayCopyAction.js"; import { ModifyPatchTextureArray2DAction } from "../../actions/concrete/ModifyPatchTextureArray2DAction.js"; import { TerrainPaintTool } from "./TerrainPaintTool.js"; export class TerrainTexturePaintTool extends TerrainPaintTool { constructor() { super(); this.name = "texture-paint-terrain"; /** * * @type {number} */ this.settings.splatIndex = 0; /** * * @type {Float32Array} * @private */ this.__splatMapScratch = new Float32Array(0); this.__iconLayer = null; } updateIcon(editor) { /** * * @type {Terrain} */ const terrain = obtainTerrain(editor.engine.entityManager.dataset); if (terrain === null) { // no terrain return; } /** * * @type {TerrainLayer} */ const layer = terrain.layers.get(this.settings.splatIndex); if (layer === this.__iconLayer) { return; } this.__iconLayer = layer; this.buildIcon(terrain); } /** * * @param {Terrain} terrain */ buildIcon(terrain) { /** * * @type {TerrainLayer} */ const layer = terrain.layers.get(this.settings.splatIndex); if (layer === undefined) { return; } let url = layer.textureDiffuseURL; if (url === null) { // no URL, try to sample texture directly url = sampler2d_to_data_url(layer.diffuse); } this.icon.set(url); } initialize() { super.initialize(); } finalize() { super.finalize(); } async paint(timeDelta) { const power = this.settings.brushStrength * timeDelta; /** * * @type {Terrain} */ const terrain = this.terrain; const brushPosition = this.__brushPosition; const brushSize = this.settings.brushSize; const terrainSize = terrain.size; const terrainHeight = terrainSize.y; const terrainWidth = terrainSize.x; const uv_x = brushPosition.x / terrainWidth; const uv_y = brushPosition.y / terrainHeight; const uv_w = brushSize / terrainWidth; const uv_h = brushSize / terrainHeight; const uv_x0 = uv_x - uv_w / 2; const uv_x1 = uv_x + uv_w / 2; const uv_y0 = uv_y - uv_h / 2; const uv_y1 = uv_y + uv_h / 2; const marker = this.settings.marker; const direction = this.modifiers.shift ? -1 : 1; const speed = power * direction; /** * * @type {Float32Array} */ const weightData = this.__splatMapScratch; /** * * @type {SplatMapping} */ const splat = terrain.splat; const splatWidth = splat.size.x; const splatHeight = splat.size.y; const h_x0 = uv_x0 * splatWidth; const h_x1 = uv_x1 * splatWidth; const h_y0 = uv_y0 * splatHeight; const h_y1 = uv_y1 * splatHeight; const x0 = Math.ceil(h_x0); const x1 = Math.floor(h_x1); const y0 = Math.ceil(h_y0); const y1 = Math.floor(h_y1); const splatIndex = this.settings.splatIndex; //create action // const m_action = new ModifyPatchSampler2DAction(splat_layer_sampler, [x0, y0, x1, y1]); const m_action = new ModifyPatchTextureArray2DAction(weightData, [splat.size.x, splat.size.y, splat.depth], [x0, y0, x1, y1]); m_action.applyWeightStampToLayer( uv_x * splat.size.x, uv_y * splat.size.y, marker, splatIndex, speed, 0, 255 ); await this.editor.actions.doMany([ m_action, new ArrayCopyAction(weightData, splat.weightData), new ActionUpdateTexture(splat.weightTexture) ]); } start() { super.start(); /** * * @type {Terrain} */ const terrain = this.terrain; const splat = terrain.splat; const weightData = splat.weightData; /** * * @type {Float32Array} */ this.__splatMapScratch = new Float32Array(weightData); this.editor.actions.mark('paint terrain texture'); } }