Spaces:
Build error
Build error
File size: 6,215 Bytes
30c32c8 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
const xmlEscape = require('../../util/xml-escape');
const uid = require('../../util/uid');
const StageLayering = require('../../engine/stage-layering');
class CanvasVar {
static customId = 'canvasData'
/**
* initiats the variable
* @param {Runtime} runtime the runtime this canvas exists inside
* @param {string} id this canvas's id
* @param {string} name the name of this canvas
* @param {[number,number]|string|Image} [img=[1, 1]] optionally the image to be loaded into this canvas
*/
constructor (runtime, id, name, img = [1, 1]) {
this.id = id ?? uid();
this.name = name;
this.type = 'canvas';
this.customId = CanvasVar.customId;
this.runtime = runtime;
this.renderer = runtime.renderer;
this.canvas = document.createElement('canvas');
this._costumeDrawer = this.renderer.createDrawable(StageLayering.SPRITE_LAYER);
this._skinId = this.renderer.createBitmapSkin(this.canvas, 1);
this._monitorUpToDate = false;
this._cachedMonContent = [null, 0];
this._cameraStuff = {
x: 0,
y: 0,
rotation: 0,
scaleX: 1,
scaleY: 1
};
// img is just a size to be given to the canvas
if (Array.isArray(img)) {
this.size = img;
return;
}
if (img) this.loadImage(img);
}
serialize(canvas) {
const instance = canvas ?? this;
return [instance.id, instance.name, instance.canvas.toDataURL()];
}
getSnapshot() {
const snap = new Image();
snap.src = this.canvas.toDataURL();
return snap;
}
toReporterContent() {
return this.canvas;
}
toMonitorContent() {
if (!this._monitorUpToDate) {
this._cachedMonContent = this.getSnapshot();
this._monitorUpToDate = true;
}
return this._cachedMonContent;
}
toListEditor() {
return this.toString();
}
fromListEditor(edit) {
if (this.toString() !== edit) {
this.loadImage(edit);
}
return this;
}
toString() {
return this.canvas.toDataURL();
}
toXML(isLocal) {
return `<variable type="canvas" id="${this.id}" islocal="${isLocal
}" iscloud="false">${xmlEscape(this.name)}</variable>`;
}
toToolboxDefault(fieldName) {
return `<field name="${fieldName}" id="${this.id}" variabletype="canvas">${xmlEscape(this.name)}</field>`;
}
get size() {
return [this.canvas.width, this.canvas.height];
}
set size(size) {
this.canvas.width = size[0];
this.canvas.height = size[1];
}
/**
* load an image onto the 2d canvas
* @param {Image} img the image to load onto the 2d canvas
*/
async loadImage(img) {
// we where not given something we can use imediatly :(
if (img instanceof Image && !img.complete) {
await new Promise(resolve => {
img.onload = resolve;
img.onerror = resolve;
});
}
if (typeof img === 'string') {
await new Promise(resolve => {
const src = img;
img = new Image();
img.onload = resolve;
img.onerror = resolve;
img.src = src;
});
}
this.canvas.width = img.width;
this.canvas.height = img.height;
const ctx = this.canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
// do this cause we just added new content
this.updateCanvasContentRenders();
}
stampDrawable(id, x, y) {
// drawable doesnt exist, we will get an error if we try to access this drawable
if (!this.renderer._allDrawables[id]) return;
const drawable = this.renderer.extractDrawableScreenSpace(id);
// never got any data, ignore request
if (!drawable) return;
const ctx = this.canvas.getContext('2d');
ctx.putImageData(drawable.imageData, x, y);
}
stampCostume(target, costumeName, x, y) {
const skin = costumeName !== '__current__'
? (() => {
const costumeIdx = target.getCostumeIndexByName(costumeName);
const costumeList = target.getCostumes();
const costume = costumeList[costumeIdx];
return this.renderer._allSkins[costume.skinId];
})()
: this.renderer._allDrawables[target.drawableID].skin;
const ctx = this.canvas.getContext('2d');
// draw svg skins loaded image element
if (skin._svgImage) {
ctx.drawImage(skin._svgImage, x, y);
return;
}
// draw the generated content of TextCostumeSkin or TextBubbleSkin directly
if (skin._canvas) {
ctx.drawImage(skin._canvas, x, y);
return;
}
// shit, alright we cant just goofy ahh our way through this
// we need to somehow request some form of image that we can just draw to the canvas
// from either the webgl texture that the skin gives us or the sprite
/**
* TODO: please if someone could make this not shitty ass and make it just draw a
* fucking webgl texture directly that would be amazing
*/
this.renderer.updateDrawableSkinId(this._costumeDrawer, skin.id);
this.stampDrawable(this._costumeDrawer);
}
updateCanvasContentRenders() {
this._monitorUpToDate = false;
// if width or height are smaller then one, replace them with one
const width = Math.max(this.canvas.width, 1);
const height = Math.max(this.canvas.height, 1);
const ctx = this.canvas.getContext('2d');
const printSkin = this.renderer._allSkins[this._skinId];
const imageData = ctx.getImageData(0, 0, width, height);
printSkin._setTexture(imageData);
}
applyCanvasToTarget(target) {
this.renderer.updateDrawableSkinId(target.drawableID, this._skinId);
this.runtime.requestRedraw();
}
}
module.exports = CanvasVar;
|