Newer
Older
/**
* (Low-level API)
* Prepare a layer to be rendered.
*
* See {@link CompositeLayerSpec} definition for details on options.
*
* Arguments are processed depending on their type:
* String argument is `src` option (image source)
* Number argument is `z` option (z-index)
* Object argument is full or partial CompositeLayerSpec object
* @example
* <<run canvaslayer(10, 'img.png', {blendMode:'hard-light', blend:'#00ff00'});>>
* <<run canvaslayer({z:10, src:'img.png'}, {blendMode:'hard-light', blend:'#00ff00'});>>
*/
function canvaslayer() {
const layers = T.CanvasLayers;
if (!layers) throw new Error("'canvaslayer()' without 'canvasstart'");
let theOptions = {};
for (let i = arguments.length - 1; i >= 0; i--) {
const arg = arguments[i];
theOptions = Object.assign(theOptions, arg);
break;
throw new Error("Invalid canvaslayer() argument " + i + ": " + typeof arg);
}
layers.push(theOptions);
}
window.canvaslayer = canvaslayer;
// use 2x2 pixels in generated images
Renderer.pixelSize = 2;
Renderer.Stats = {
trace: false,
traceAnim: false,
lastLoadTime: 0,
lastRenderTime: 0,
logmsgLoad: new ObservableValue(""),
logmsgRender: new ObservableValue(""),
logmsgAnimate: new ObservableValue(""),
nlayers: 0,
const msg = (error.stack || error.message || "" + error).replace(/\(?[^( )]*:\d+:\d+\)?/gm, "").replace(/\(?eval at [\w.]+/gm, "");
Renderer.Stats.loadErrors = 0;
if (Renderer.Stats.trace) {
console.log(DOL.Perflog.millitime().toFixed(3), "Composing " + layers.length + " layers...");
processingStep(layer, processing, canvas, dt) {
DOL.Perflog.logWidgetTime("_render:" + processing, dt);
},
// logged to console by Renderer itself
Renderer.Stats.loadErrors++;
Errors.report("Failed to load image " + src + " for layer " + layer);
let msg = "Loaded " + layersLoaded + " images in " + time.toFixed(3) + " ms";
if (Renderer.Stats.loadErrors > 0) msg += " (" + Renderer.Stats.loadErrors + " failed)";
Renderer.Stats.logmsgLoad.value = msg;
if (Renderer.Stats.trace) {
console.log(DOL.Perflog.millitime().toFixed(3), msg);
}
},
Renderer.Stats.nlayers = layers.length;
Renderer.Stats.ncached = 0;
},
const msg = "Rendered " + Renderer.Stats.nlayers + " layers" + " (" + Renderer.Stats.ncached + " cached)" + " in " + time.toFixed(3) + " ms";
}
Renderer.Stats.logmsgRender.value = msg;
},
console.log(
DOL.Perflog.millitime().toFixed(3),
"animation",
animation,
"keyframe",
keyframeIndex,
"frame",
keyframe.frame,
"duration",
keyframe.duration
);
console.log(
DOL.Perflog.millitime().toFixed(3),
"KeyframeRender",
spec,
cacheHit ? "cache hit, render time " + cacheRenderTime.toFixed(3) + " ms" : "cache miss"
);
}
if (cacheHit && Renderer.Stats.logmsgAnimate) {
Renderer.Stats.logmsgAnimate.value = "Cached keyframe rendered in " + cacheRenderTime.toFixed(3) + " ms";
if (Renderer.Stats.traceAnim) {
console.log(DOL.Perflog.millitime().toFixed(3), "Animation stopped");
}
requestAnimationFrame(() => {
const canvasModel = Renderer.locateModel(model, "sidebar");
if (canvasModel.canvas) {
Renderer.invalidateLayerCaches(canvasModel.layerList);
canvasModel.redraw();
}
});
}
function refreshModels(e, overlay) {
if (overlay === "options") {
refreshCanvas("lighting");
$(document).on(":passagestart", () => {
if (State.current !== State.top) {
Skin.recache();
}
});
$(document).on(":onloadsave", () => {
Skin.recache();
refreshCanvas("lighting");
});
$(document).on(":enginerestart", () => {
Skin.recache();
});