UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

220 lines (163 loc) • 7.02 kB
import { typedArrayConstructorByInstance } from "../../../../src/core/collection/array/typed/typedArrayConstructorByInstance.js"; import { FrameRunner } from "../../../../src/engine/graphics/FrameRunner.js"; import html_canvas_to_sampler2d from "../../../../src/engine/graphics/texture/html_canvas_to_sampler2d.js"; import { downloadSampler2DAsPNG } from "../../../../src/engine/graphics/texture/sampler/downloadSamplerAsPNG.js"; import { sampler2d_scale } from "../../../../src/engine/graphics/texture/sampler/resize/sampler2d_scale.js"; import { Sampler2D } from "../../../../src/engine/graphics/texture/sampler/Sampler2D.js"; import { sampler2d_compute_texel_value_conversion_scale_to_uint8 } from "../../../../src/engine/graphics/texture/sampler/sampler2d_compute_texel_value_conversion_scale_to_uint8.js"; import sampler2D2Canvas from "../../../../src/engine/graphics/texture/sampler/sampler2d_to_html_canvas.js"; import { sampler2d_transfer_data } from "../../../../src/engine/graphics/texture/sampler/sampler2d_transfer_data.js"; import { MouseEvents } from "../../../../src/engine/input/devices/events/MouseEvents.js"; import { CanvasView } from "../../../../src/view/elements/CanvasView.js"; import EmptyView from "../../../../src/view/elements/EmptyView.js"; import { TypeEditor } from "../TypeEditor.js"; const UPDATE_DELAY = 200; /** * * @param {Sampler2D} sampler * @param {HTMLCanvasElement} domElement */ function draw_sampler(sampler, domElement) { let TypedArrayConstructor = typedArrayConstructorByInstance(sampler.data); if (TypedArrayConstructor === Uint8Array) { // use clamped array to avoid filtering artifacts TypedArrayConstructor = Uint8ClampedArray; } const res = 32; const result_sampler = new Sampler2D(new TypedArrayConstructor(sampler.itemSize * res * res), sampler.itemSize, res, res); sampler2d_scale(sampler, result_sampler); const { scale, offset } = sampler2d_compute_texel_value_conversion_scale_to_uint8(result_sampler); sampler2D2Canvas(result_sampler, scale, offset, domElement); } /** * * @param {*} parent * @param {HTMLCanvasElement} element * @param {FieldDescriptor} field */ function enable_drop(parent, element, field) { /** * * @param {DragEvent} ev */ function handleDrop(ev) { ev.preventDefault(); let processed = false; /** * * @param {File} file */ function processFile(file) { if (processed) { return; } var img = new Image(); // URL @ Mozilla, webkitURL @ Chrome img.src = (window.webkitURL ? webkitURL : URL).createObjectURL(file); // call ctx.drawImage when the image got loaded img.onload = function () { var canvas = document.createElement("canvas"); var ctx = canvas.getContext("2d"); const width = img.width; const height = img.height; canvas.style.width = `${width}px`; canvas.style.height = `${height}px`; canvas.width = width; canvas.height = height; // ctx.drawImage(img, 0, 0); ctx.drawImage(img, 0, 0, width, height, 0, 0, width, height); // stretch img to canvas size const file_data_sampler = html_canvas_to_sampler2d(canvas); /** * @type {Sampler2D} */ const sampler = field.adapter.read(parent, field.name); sampler.resize(width, height, false); sampler2d_transfer_data(file_data_sampler, sampler); }; processed = true; } if (ev.dataTransfer.items) { // Use DataTransferItemList interface to access the file(s) for (var i = 0; i < ev.dataTransfer.items.length; i++) { // If dropped items aren't files, reject them if (ev.dataTransfer.items[i].kind === 'file') { var file = ev.dataTransfer.items[i].getAsFile(); processFile(file); } } } else { // Use DataTransfer interface to access the file(s) for (var i = 0; i < ev.dataTransfer.files.length; i++) { const file = ev.dataTransfer.files[i]; processFile(file); } } } function handleDragOver(ev) { // Prevent default behavior (Prevent file from being opened) ev.preventDefault(); } element.addEventListener('dragover', handleDragOver); element.addEventListener('drop', handleDrop); } export class Sampler2DEditor extends TypeEditor { build(parent, field, context) { /** * @type {Sampler2D} */ const sampler = field.adapter.read(parent, field.name); let last_version = -1; let last_update_time = 0; let last_update_duration = 0; const view_container = new EmptyView({ css:{ width: "min-content", height:"min-content" } }); const canvas_view = new CanvasView(); canvas_view.css({ background: 'black', position: 'relative', }); function draw() { const draw_start_time = performance.now(); draw_sampler(sampler, canvas_view.el); last_version = sampler.version; const draw_end_time = performance.now(); last_update_duration = draw_end_time - draw_start_time; last_update_time = draw_end_time; } canvas_view.on.linked.add(try_update); function try_update() { if (sampler.version !== last_version) { const time_now = performance.now(); if ((time_now - last_update_time) >= UPDATE_DELAY) { draw(); } } } const frameRunner = new FrameRunner(try_update); canvas_view.on.linked.add(frameRunner.startup, frameRunner); canvas_view.on.unlinked.add(frameRunner.shutdown, frameRunner); //drop target const allow_drop = true; if (allow_drop) { enable_drop(parent, canvas_view.el, field); } const allow_download = true; if (allow_download) { canvas_view.el.addEventListener(MouseEvents.Click, () => { downloadSampler2DAsPNG(sampler, field.name); }); // add download marker view_container.addClass('downloadable'); } view_container.addChild(canvas_view); return view_container; } }