@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
220 lines (163 loc) • 7.02 kB
JavaScript
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;
}
}