work on converting timeline to widgets
This commit is contained in:
parent
33896c693d
commit
b76dcc7a7e
327
src/main.js
327
src/main.js
|
|
@ -60,7 +60,7 @@ import {
|
||||||
shadow,
|
shadow,
|
||||||
} from "./styles.js";
|
} from "./styles.js";
|
||||||
import { Icon } from "./icon.js";
|
import { Icon } from "./icon.js";
|
||||||
import { AlphaSelectionBar, ColorSelectorWidget, ColorWidget, HueSelectionBar, SaturationValueSelectionGradient, Widget } from "./widgets.js";
|
import { AlphaSelectionBar, ColorSelectorWidget, ColorWidget, HueSelectionBar, SaturationValueSelectionGradient, TimelineWindow, Widget } from "./widgets.js";
|
||||||
const {
|
const {
|
||||||
writeTextFile: writeTextFile,
|
writeTextFile: writeTextFile,
|
||||||
readTextFile: readTextFile,
|
readTextFile: readTextFile,
|
||||||
|
|
@ -6302,6 +6302,9 @@ function timeline() {
|
||||||
let timeline_cvs = document.createElement("canvas");
|
let timeline_cvs = document.createElement("canvas");
|
||||||
timeline_cvs.className = "timeline";
|
timeline_cvs.className = "timeline";
|
||||||
|
|
||||||
|
// Start building widget hierarchy
|
||||||
|
timeline_cvs.timelinewindow = new TimelineWindow(0, 0, context)
|
||||||
|
|
||||||
// Load icons for show/hide layer
|
// Load icons for show/hide layer
|
||||||
timeline_cvs.icons = {};
|
timeline_cvs.icons = {};
|
||||||
timeline_cvs.icons.volume_up_fill = new Icon("assets/volume-up-fill.svg");
|
timeline_cvs.icons.volume_up_fill = new Icon("assets/volume-up-fill.svg");
|
||||||
|
|
@ -6359,6 +6362,8 @@ function timeline() {
|
||||||
0,
|
0,
|
||||||
Math.min(maxScroll, timeline_cvs.offsetY + deltaY),
|
Math.min(maxScroll, timeline_cvs.offsetY + deltaY),
|
||||||
);
|
);
|
||||||
|
timeline_cvs.timelinewindow.offsetX = -timeline_cvs.offsetX
|
||||||
|
timeline_cvs.timelinewindow.offsetY = -timeline_cvs.offsetY
|
||||||
|
|
||||||
const currentTime = Date.now();
|
const currentTime = Date.now();
|
||||||
if (currentTime - lastResizeTime > throttleIntervalMs) {
|
if (currentTime - lastResizeTime > throttleIntervalMs) {
|
||||||
|
|
@ -7139,6 +7144,14 @@ function renderLayers() {
|
||||||
ctx.fillRect(0, 0, width, height);
|
ctx.fillRect(0, 0, width, height);
|
||||||
ctx.lineWidth = 1;
|
ctx.lineWidth = 1;
|
||||||
|
|
||||||
|
|
||||||
|
ctx.save()
|
||||||
|
ctx.translate(layerWidth, gutterHeight)
|
||||||
|
canvas.timelinewindow.width = width - layerWidth
|
||||||
|
canvas.timelinewindow.height = height - gutterHeight
|
||||||
|
canvas.timelinewindow.draw(ctx)
|
||||||
|
ctx.restore()
|
||||||
|
|
||||||
// Draw timeline top
|
// Draw timeline top
|
||||||
ctx.save();
|
ctx.save();
|
||||||
ctx.save();
|
ctx.save();
|
||||||
|
|
@ -7222,164 +7235,166 @@ function renderLayers() {
|
||||||
labelColor,
|
labelColor,
|
||||||
);
|
);
|
||||||
ctx.restore();
|
ctx.restore();
|
||||||
ctx.save();
|
|
||||||
ctx.beginPath();
|
// ctx.save();
|
||||||
ctx.rect(layerWidth, i * layerHeight, width, layerHeight);
|
// ctx.beginPath();
|
||||||
ctx.clip();
|
// ctx.rect(layerWidth, i * layerHeight, width, layerHeight);
|
||||||
ctx.translate(layerWidth - offsetX, i * layerHeight);
|
// ctx.clip();
|
||||||
// Draw empty frames
|
// ctx.translate(layerWidth - offsetX, i * layerHeight);
|
||||||
for (let j = Math.floor(offsetX / frameWidth); j < frameCount; j++) {
|
// // Draw empty frames
|
||||||
ctx.fillStyle = (j + 1) % 5 == 0 ? shade : backgroundColor;
|
// for (let j = Math.floor(offsetX / frameWidth); j < frameCount; j++) {
|
||||||
drawBorderedRect(
|
// ctx.fillStyle = (j + 1) % 5 == 0 ? shade : backgroundColor;
|
||||||
ctx,
|
// drawBorderedRect(
|
||||||
j * frameWidth,
|
// ctx,
|
||||||
0,
|
// j * frameWidth,
|
||||||
frameWidth,
|
// 0,
|
||||||
layerHeight,
|
// frameWidth,
|
||||||
shadow,
|
// layerHeight,
|
||||||
highlight,
|
// shadow,
|
||||||
shadow,
|
// highlight,
|
||||||
shadow,
|
// shadow,
|
||||||
);
|
// shadow,
|
||||||
}
|
// );
|
||||||
// Draw existing frames
|
// }
|
||||||
if (layer instanceof Layer) {
|
// // Draw existing frames
|
||||||
for (let j=0; j<layer.frames.length; j++) {
|
// if (layer instanceof Layer) {
|
||||||
const frameInfo = layer.getFrameValue(j)
|
// for (let j=0; j<layer.frames.length; j++) {
|
||||||
if (frameInfo.valueAtN) {
|
// const frameInfo = layer.getFrameValue(j)
|
||||||
ctx.fillStyle = foregroundColor;
|
// if (frameInfo.valueAtN) {
|
||||||
drawBorderedRect(
|
// ctx.fillStyle = foregroundColor;
|
||||||
ctx,
|
// drawBorderedRect(
|
||||||
j * frameWidth,
|
// ctx,
|
||||||
0,
|
// j * frameWidth,
|
||||||
frameWidth,
|
// 0,
|
||||||
layerHeight,
|
// frameWidth,
|
||||||
highlight,
|
// layerHeight,
|
||||||
shadow,
|
// highlight,
|
||||||
shadow,
|
// shadow,
|
||||||
shadow,
|
// shadow,
|
||||||
);
|
// shadow,
|
||||||
ctx.fillStyle = "#111";
|
// );
|
||||||
ctx.beginPath();
|
// ctx.fillStyle = "#111";
|
||||||
ctx.arc(
|
// ctx.beginPath();
|
||||||
(j + 0.5) * frameWidth,
|
// ctx.arc(
|
||||||
layerHeight * 0.75,
|
// (j + 0.5) * frameWidth,
|
||||||
frameWidth * 0.25,
|
// layerHeight * 0.75,
|
||||||
0,
|
// frameWidth * 0.25,
|
||||||
2 * Math.PI,
|
// 0,
|
||||||
);
|
// 2 * Math.PI,
|
||||||
ctx.fill();
|
// );
|
||||||
if (frameInfo.valueAtN.keyTypes.has("motion")) {
|
// ctx.fill();
|
||||||
ctx.strokeStyle = "#7a00b3";
|
// if (frameInfo.valueAtN.keyTypes.has("motion")) {
|
||||||
ctx.lineWidth = 2;
|
// ctx.strokeStyle = "#7a00b3";
|
||||||
ctx.beginPath()
|
// ctx.lineWidth = 2;
|
||||||
ctx.moveTo(j*frameWidth, layerHeight*0.25)
|
// ctx.beginPath()
|
||||||
ctx.lineTo((j+1)*frameWidth, layerHeight*0.25)
|
// ctx.moveTo(j*frameWidth, layerHeight*0.25)
|
||||||
ctx.stroke()
|
// ctx.lineTo((j+1)*frameWidth, layerHeight*0.25)
|
||||||
}
|
// ctx.stroke()
|
||||||
if (frameInfo.valueAtN.keyTypes.has("shape")) {
|
// }
|
||||||
ctx.strokeStyle = "#9bff9b";
|
// if (frameInfo.valueAtN.keyTypes.has("shape")) {
|
||||||
ctx.lineWidth = 2;
|
// ctx.strokeStyle = "#9bff9b";
|
||||||
ctx.beginPath()
|
// ctx.lineWidth = 2;
|
||||||
ctx.moveTo(j*frameWidth, layerHeight*0.35)
|
// ctx.beginPath()
|
||||||
ctx.lineTo((j+1)*frameWidth, layerHeight*0.35)
|
// ctx.moveTo(j*frameWidth, layerHeight*0.35)
|
||||||
ctx.stroke()
|
// ctx.lineTo((j+1)*frameWidth, layerHeight*0.35)
|
||||||
}
|
// ctx.stroke()
|
||||||
} else if (frameInfo.prev && frameInfo.next) {
|
// }
|
||||||
ctx.fillStyle = foregroundColor;
|
// } else if (frameInfo.prev && frameInfo.next) {
|
||||||
drawBorderedRect(
|
// ctx.fillStyle = foregroundColor;
|
||||||
ctx,
|
// drawBorderedRect(
|
||||||
j * frameWidth,
|
// ctx,
|
||||||
0,
|
// j * frameWidth,
|
||||||
frameWidth,
|
// 0,
|
||||||
layerHeight,
|
// frameWidth,
|
||||||
highlight,
|
// layerHeight,
|
||||||
shadow,
|
// highlight,
|
||||||
backgroundColor,
|
// shadow,
|
||||||
backgroundColor,
|
// backgroundColor,
|
||||||
);
|
// backgroundColor,
|
||||||
if (frameInfo.prev.keyTypes.has("motion")) {
|
// );
|
||||||
ctx.strokeStyle = "#7a00b3";
|
// if (frameInfo.prev.keyTypes.has("motion")) {
|
||||||
ctx.lineWidth = 2;
|
// ctx.strokeStyle = "#7a00b3";
|
||||||
ctx.beginPath()
|
// ctx.lineWidth = 2;
|
||||||
ctx.moveTo(j*frameWidth, layerHeight*0.25)
|
// ctx.beginPath()
|
||||||
ctx.lineTo((j+1)*frameWidth, layerHeight*0.25)
|
// ctx.moveTo(j*frameWidth, layerHeight*0.25)
|
||||||
ctx.stroke()
|
// ctx.lineTo((j+1)*frameWidth, layerHeight*0.25)
|
||||||
}
|
// ctx.stroke()
|
||||||
if (frameInfo.prev.keyTypes.has("shape")) {
|
// }
|
||||||
ctx.strokeStyle = "#9bff9b";
|
// if (frameInfo.prev.keyTypes.has("shape")) {
|
||||||
ctx.lineWidth = 2;
|
// ctx.strokeStyle = "#9bff9b";
|
||||||
ctx.beginPath()
|
// ctx.lineWidth = 2;
|
||||||
ctx.moveTo(j*frameWidth, layerHeight*0.35)
|
// ctx.beginPath()
|
||||||
ctx.lineTo((j+1)*frameWidth, layerHeight*0.35)
|
// ctx.moveTo(j*frameWidth, layerHeight*0.35)
|
||||||
ctx.stroke()
|
// ctx.lineTo((j+1)*frameWidth, layerHeight*0.35)
|
||||||
}
|
// ctx.stroke()
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
// layer.frames.forEach((frame, j) => {
|
// }
|
||||||
// if (!frame) return;
|
// // layer.frames.forEach((frame, j) => {
|
||||||
// switch (frame.frameType) {
|
// // if (!frame) return;
|
||||||
// case "keyframe":
|
// // switch (frame.frameType) {
|
||||||
// ctx.fillStyle = foregroundColor;
|
// // case "keyframe":
|
||||||
// drawBorderedRect(
|
// // ctx.fillStyle = foregroundColor;
|
||||||
// ctx,
|
// // drawBorderedRect(
|
||||||
// j * frameWidth,
|
// // ctx,
|
||||||
// 0,
|
// // j * frameWidth,
|
||||||
// frameWidth,
|
// // 0,
|
||||||
// layerHeight,
|
// // frameWidth,
|
||||||
// highlight,
|
// // layerHeight,
|
||||||
// shadow,
|
// // highlight,
|
||||||
// shadow,
|
// // shadow,
|
||||||
// shadow,
|
// // shadow,
|
||||||
// );
|
// // shadow,
|
||||||
// ctx.fillStyle = "#111";
|
// // );
|
||||||
// ctx.beginPath();
|
// // ctx.fillStyle = "#111";
|
||||||
// ctx.arc(
|
// // ctx.beginPath();
|
||||||
// (j + 0.5) * frameWidth,
|
// // ctx.arc(
|
||||||
// layerHeight * 0.75,
|
// // (j + 0.5) * frameWidth,
|
||||||
// frameWidth * 0.25,
|
// // layerHeight * 0.75,
|
||||||
// 0,
|
// // frameWidth * 0.25,
|
||||||
// 2 * Math.PI,
|
// // 0,
|
||||||
// );
|
// // 2 * Math.PI,
|
||||||
// ctx.fill();
|
// // );
|
||||||
// break;
|
// // ctx.fill();
|
||||||
// case "normal":
|
// // break;
|
||||||
// ctx.fillStyle = foregroundColor;
|
// // case "normal":
|
||||||
// drawBorderedRect(
|
// // ctx.fillStyle = foregroundColor;
|
||||||
// ctx,
|
// // drawBorderedRect(
|
||||||
// j * frameWidth,
|
// // ctx,
|
||||||
// 0,
|
// // j * frameWidth,
|
||||||
// frameWidth,
|
// // 0,
|
||||||
// layerHeight,
|
// // frameWidth,
|
||||||
// highlight,
|
// // layerHeight,
|
||||||
// shadow,
|
// // highlight,
|
||||||
// backgroundColor,
|
// // shadow,
|
||||||
// backgroundColor,
|
// // backgroundColor,
|
||||||
// );
|
// // backgroundColor,
|
||||||
// break;
|
// // );
|
||||||
// case "motion":
|
// // break;
|
||||||
// ctx.fillStyle = "#7a00b3";
|
// // case "motion":
|
||||||
// ctx.fillRect(j * frameWidth, 0, frameWidth, layerHeight);
|
// // ctx.fillStyle = "#7a00b3";
|
||||||
// break;
|
// // ctx.fillRect(j * frameWidth, 0, frameWidth, layerHeight);
|
||||||
// case "shape":
|
// // break;
|
||||||
// ctx.fillStyle = "#9bff9b";
|
// // case "shape":
|
||||||
// ctx.fillRect(j * frameWidth, 0, frameWidth, layerHeight);
|
// // ctx.fillStyle = "#9bff9b";
|
||||||
// break;
|
// // ctx.fillRect(j * frameWidth, 0, frameWidth, layerHeight);
|
||||||
// }
|
// // break;
|
||||||
// });
|
// // }
|
||||||
} else if (layer instanceof AudioLayer) {
|
// // });
|
||||||
// TODO: split waveform into chunks
|
// } else if (layer instanceof AudioLayer) {
|
||||||
for (let i in layer.sounds) {
|
// // TODO: split waveform into chunks
|
||||||
let sound = layer.sounds[i];
|
// for (let i in layer.sounds) {
|
||||||
// layerTrack.appendChild(sound.img)
|
// let sound = layer.sounds[i];
|
||||||
ctx.drawImage(sound.img, 0, 0);
|
// // layerTrack.appendChild(sound.img)
|
||||||
}
|
// ctx.drawImage(sound.img, 0, 0);
|
||||||
}
|
// }
|
||||||
// if (context.activeObject.currentFrameNum)
|
// }
|
||||||
ctx.restore();
|
// // if (context.activeObject.currentFrameNum)
|
||||||
|
// ctx.restore();
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
ctx.restore();
|
ctx.restore();
|
||||||
|
|
||||||
// Draw highlighted frame
|
// Draw highlighted frame
|
||||||
ctx.save();
|
ctx.save();
|
||||||
ctx.translate(layerWidth - offsetX, -offsetY);
|
ctx.translate(layerWidth - offsetX, -offsetY);
|
||||||
|
|
|
||||||
789
src/widgets.js
789
src/widgets.js
|
|
@ -1,340 +1,531 @@
|
||||||
import { clamp, drawCheckerboardBackground, hslToRgb, hsvToRgb, rgbToHex } from "./utils.js"
|
import { backgroundColor, foregroundColor, frameWidth, highlight, layerHeight, shade, shadow } from "./styles.js";
|
||||||
|
import { clamp, drawBorderedRect, drawCheckerboardBackground, hslToRgb, hsvToRgb, rgbToHex } from "./utils.js"
|
||||||
|
|
||||||
function growBoundingBox(bboxa, bboxb) {
|
function growBoundingBox(bboxa, bboxb) {
|
||||||
bboxa.x.min = Math.min(bboxa.x.min, bboxb.x.min);
|
bboxa.x.min = Math.min(bboxa.x.min, bboxb.x.min);
|
||||||
bboxa.y.min = Math.min(bboxa.y.min, bboxb.y.min);
|
bboxa.y.min = Math.min(bboxa.y.min, bboxb.y.min);
|
||||||
bboxa.x.max = Math.max(bboxa.x.max, bboxb.x.max);
|
bboxa.x.max = Math.max(bboxa.x.max, bboxb.x.max);
|
||||||
bboxa.y.max = Math.max(bboxa.y.max, bboxb.y.max);
|
bboxa.y.max = Math.max(bboxa.y.max, bboxb.y.max);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SCROLL = {
|
||||||
|
HORIZONTAL: 1,
|
||||||
|
VERTICAL: 2,
|
||||||
|
}
|
||||||
|
|
||||||
class Widget {
|
class Widget {
|
||||||
constructor(x, y) {
|
constructor(x, y) {
|
||||||
this._globalEvents = new Set()
|
this._globalEvents = new Set()
|
||||||
this.x = x
|
this.x = x
|
||||||
this.y = y
|
this.y = y
|
||||||
this.scale_x = 1
|
this.scale_x = 1
|
||||||
this.scale_y = 1
|
this.scale_y = 1
|
||||||
this.rotation = 0
|
this.rotation = 0
|
||||||
this.children = []
|
this.children = []
|
||||||
}
|
}
|
||||||
handleMouseEvent(eventType, x, y) {
|
handleMouseEvent(eventType, x, y) {
|
||||||
for (let child of this.children) {
|
for (let child of this.children) {
|
||||||
// Adjust for translation
|
// Adjust for translation
|
||||||
const dx = x - child.x;
|
const dx = x - child.x;
|
||||||
const dy = y - child.y;
|
const dy = y - child.y;
|
||||||
|
|
||||||
// Apply inverse rotation
|
// Apply inverse rotation
|
||||||
const cosTheta = Math.cos(child.rotation);
|
const cosTheta = Math.cos(child.rotation);
|
||||||
const sinTheta = Math.sin(child.rotation);
|
const sinTheta = Math.sin(child.rotation);
|
||||||
|
|
||||||
// Rotate coordinates to child's local space
|
// Rotate coordinates to child's local space
|
||||||
const rotatedX = dx * cosTheta + dy * sinTheta;
|
const rotatedX = dx * cosTheta + dy * sinTheta;
|
||||||
const rotatedY = -dx * sinTheta + dy * cosTheta;
|
const rotatedY = -dx * sinTheta + dy * cosTheta;
|
||||||
|
|
||||||
// First, perform hit test using original (global) coordinates
|
// First, perform hit test using original (global) coordinates
|
||||||
if (child.hitTest(rotatedX, rotatedY) || child._globalEvents.has(eventType)) {
|
if (child.hitTest(rotatedX, rotatedY) || child._globalEvents.has(eventType)) {
|
||||||
child.handleMouseEvent(eventType, rotatedX, rotatedY);
|
child.handleMouseEvent(eventType, rotatedX, rotatedY);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
const eventTypes = [
|
|
||||||
"mousedown",
|
|
||||||
"mousemove",
|
|
||||||
"mouseup",
|
|
||||||
"dblclick"
|
|
||||||
]
|
|
||||||
if (eventTypes.indexOf(eventType)!=-1) {
|
|
||||||
if (typeof(this[eventType]) == "function") {
|
|
||||||
this[eventType](x, y)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
hitTest(x, y) {
|
const eventTypes = [
|
||||||
// if ((x >= this.x) && (x <= this.x+this.width) &&
|
"mousedown",
|
||||||
// (y >= this.y) && (y <= this.y+this.height)) {
|
"mousemove",
|
||||||
if ((x>=0) && (x <= this.width) && (y >= 0) && (y <= this.height)) {
|
"mouseup",
|
||||||
return true
|
"dblclick"
|
||||||
}
|
]
|
||||||
return false
|
if (eventTypes.indexOf(eventType)!=-1) {
|
||||||
|
if (typeof(this[eventType]) == "function") {
|
||||||
|
this[eventType](x, y)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
bbox() {
|
}
|
||||||
let bbox;
|
hitTest(x, y) {
|
||||||
if (this.children.length > 0) {
|
// if ((x >= this.x) && (x <= this.x+this.width) &&
|
||||||
if (!bbox) {
|
// (y >= this.y) && (y <= this.y+this.height)) {
|
||||||
bbox = structuredClone(this.children[0].bbox());
|
if ((x>=0) && (x <= this.width) && (y >= 0) && (y <= this.height)) {
|
||||||
}
|
return true
|
||||||
for (let child of this.children) {
|
|
||||||
growBoundingBox(bbox, child.bbox());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (bbox == undefined) {
|
|
||||||
bbox = { x: { min: 0, max: 0 }, y: { min: 0, max: 0 } };
|
|
||||||
}
|
|
||||||
bbox.x.max *= this.scale_x;
|
|
||||||
bbox.y.max *= this.scale_y;
|
|
||||||
bbox.x.min += this.x;
|
|
||||||
bbox.x.max += this.x;
|
|
||||||
bbox.y.min += this.y;
|
|
||||||
bbox.y.max += this.y;
|
|
||||||
return bbox;
|
|
||||||
}
|
}
|
||||||
draw(ctx) {
|
return false
|
||||||
for (let child of this.children) {
|
}
|
||||||
const transform = ctx.getTransform()
|
bbox() {
|
||||||
ctx.translate(child.x, child.y)
|
let bbox;
|
||||||
ctx.scale(child.scale_x, child.scale_y)
|
if (this.children.length > 0) {
|
||||||
ctx.rotate(child.rotation)
|
if (!bbox) {
|
||||||
child.draw(ctx)
|
bbox = structuredClone(this.children[0].bbox());
|
||||||
ctx.setTransform(transform)
|
}
|
||||||
}
|
for (let child of this.children) {
|
||||||
|
growBoundingBox(bbox, child.bbox());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (bbox == undefined) {
|
||||||
|
bbox = { x: { min: 0, max: 0 }, y: { min: 0, max: 0 } };
|
||||||
|
}
|
||||||
|
bbox.x.max *= this.scale_x;
|
||||||
|
bbox.y.max *= this.scale_y;
|
||||||
|
bbox.x.min += this.x;
|
||||||
|
bbox.x.max += this.x;
|
||||||
|
bbox.y.min += this.y;
|
||||||
|
bbox.y.max += this.y;
|
||||||
|
return bbox;
|
||||||
|
}
|
||||||
|
draw(ctx) {
|
||||||
|
for (let child of this.children) {
|
||||||
|
const transform = ctx.getTransform()
|
||||||
|
ctx.translate(child.x, child.y)
|
||||||
|
ctx.scale(child.scale_x, child.scale_y)
|
||||||
|
ctx.rotate(child.rotation)
|
||||||
|
child.draw(ctx)
|
||||||
|
ctx.setTransform(transform)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
class HueSelectionBar extends Widget {
|
class HueSelectionBar extends Widget {
|
||||||
constructor(width, height, x, y, colorCvs) {
|
constructor(width, height, x, y, colorCvs) {
|
||||||
super(x, y)
|
super(x, y)
|
||||||
this.width = width
|
this.width = width
|
||||||
this.height = height
|
this.height = height
|
||||||
this.colorCvs = colorCvs
|
this.colorCvs = colorCvs
|
||||||
}
|
}
|
||||||
|
|
||||||
draw(ctx) {
|
draw(ctx) {
|
||||||
const [h, s, v] = this.colorCvs.currentHSV
|
const [h, s, v] = this.colorCvs.currentHSV
|
||||||
const hueGradient = ctx.createImageData(this.width, this.height);
|
const hueGradient = ctx.createImageData(this.width, this.height);
|
||||||
const data = hueGradient.data;
|
const data = hueGradient.data;
|
||||||
for (let i = 0; i < data.length; i += 4) {
|
for (let i = 0; i < data.length; i += 4) {
|
||||||
const x = ((i / 4) % this.width) / this.width;
|
const x = ((i / 4) % this.width) / this.width;
|
||||||
const y = Math.floor(i / 4 / this.height);
|
const y = Math.floor(i / 4 / this.height);
|
||||||
const rgb = hslToRgb(x, 1, 0.5);
|
const rgb = hslToRgb(x, 1, 0.5);
|
||||||
data[i + 0] = rgb.r;
|
data[i + 0] = rgb.r;
|
||||||
data[i + 1] = rgb.g;
|
data[i + 1] = rgb.g;
|
||||||
data[i + 2] = rgb.b;
|
data[i + 2] = rgb.b;
|
||||||
data[i + 3] = 255;
|
data[i + 3] = 255;
|
||||||
}
|
|
||||||
const transform = ctx.getTransform();
|
|
||||||
ctx.putImageData(hueGradient, transform.e, transform.f);
|
|
||||||
// draw pointer
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.rect(
|
|
||||||
h * this.width - 2,
|
|
||||||
0,
|
|
||||||
4,
|
|
||||||
this.height,
|
|
||||||
);
|
|
||||||
ctx.strokeStyle = "white";
|
|
||||||
ctx.stroke();
|
|
||||||
}
|
}
|
||||||
updateColorFromMouse(x, y) {
|
const transform = ctx.getTransform();
|
||||||
let [h, s, v] = this.colorCvs.currentHSV
|
ctx.putImageData(hueGradient, transform.e, transform.f);
|
||||||
x = clamp(x / this.width);
|
// draw pointer
|
||||||
let rgb = hsvToRgb(x, s, v);
|
ctx.beginPath();
|
||||||
let alpha = this.colorCvs.currentColor.slice(7, 9) || "ff";
|
ctx.rect(
|
||||||
this.colorCvs.currentColor = rgbToHex(rgb.r, rgb.g, rgb.b) + alpha;
|
h * this.width - 2,
|
||||||
this.colorCvs.currentHSV = [x, s, v]
|
0,
|
||||||
this.colorCvs.currentAlpha = alpha
|
4,
|
||||||
}
|
this.height,
|
||||||
mousedown(x, y) {
|
);
|
||||||
this._globalEvents.add("mousemove")
|
ctx.strokeStyle = "white";
|
||||||
this._globalEvents.add("mouseup")
|
ctx.stroke();
|
||||||
|
}
|
||||||
|
updateColorFromMouse(x, y) {
|
||||||
|
let [h, s, v] = this.colorCvs.currentHSV
|
||||||
|
x = clamp(x / this.width);
|
||||||
|
let rgb = hsvToRgb(x, s, v);
|
||||||
|
let alpha = this.colorCvs.currentColor.slice(7, 9) || "ff";
|
||||||
|
this.colorCvs.currentColor = rgbToHex(rgb.r, rgb.g, rgb.b) + alpha;
|
||||||
|
this.colorCvs.currentHSV = [x, s, v]
|
||||||
|
this.colorCvs.currentAlpha = alpha
|
||||||
|
}
|
||||||
|
mousedown(x, y) {
|
||||||
|
this._globalEvents.add("mousemove")
|
||||||
|
this._globalEvents.add("mouseup")
|
||||||
|
|
||||||
this.updateColorFromMouse(x, y)
|
this.updateColorFromMouse(x, y)
|
||||||
this.clicked = true;
|
this.clicked = true;
|
||||||
}
|
}
|
||||||
mousemove(x, y) {
|
mousemove(x, y) {
|
||||||
if (this.clicked) {
|
if (this.clicked) {
|
||||||
this.updateColorFromMouse(x, y)
|
this.updateColorFromMouse(x, y)
|
||||||
}
|
|
||||||
}
|
|
||||||
mouseup(x, y) {
|
|
||||||
this._globalEvents.delete("mousemove")
|
|
||||||
this._globalEvents.delete("mouseup")
|
|
||||||
this.clicked = false
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
mouseup(x, y) {
|
||||||
|
this._globalEvents.delete("mousemove")
|
||||||
|
this._globalEvents.delete("mouseup")
|
||||||
|
this.clicked = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SaturationValueSelectionGradient extends Widget {
|
class SaturationValueSelectionGradient extends Widget {
|
||||||
constructor(width, height, x, y, colorCvs) {
|
constructor(width, height, x, y, colorCvs) {
|
||||||
super(x, y)
|
super(x, y)
|
||||||
this.width = width
|
this.width = width
|
||||||
this.height = height
|
this.height = height
|
||||||
this.colorCvs = colorCvs
|
this.colorCvs = colorCvs
|
||||||
}
|
}
|
||||||
draw(ctx) {
|
draw(ctx) {
|
||||||
let mainGradient = ctx.createImageData(this.width, this.height);
|
let mainGradient = ctx.createImageData(this.width, this.height);
|
||||||
let data = mainGradient.data;
|
let data = mainGradient.data;
|
||||||
// let { h, s, v } = hexToHsv(colorCvs.currentColor);
|
// let { h, s, v } = hexToHsv(colorCvs.currentColor);
|
||||||
let [h, s, v] = this.colorCvs.currentHSV
|
let [h, s, v] = this.colorCvs.currentHSV
|
||||||
for (let i = 0; i < data.length; i += 4) {
|
for (let i = 0; i < data.length; i += 4) {
|
||||||
let x = ((i / 4) % this.width) / this.width;
|
let x = ((i / 4) % this.width) / this.width;
|
||||||
let y = Math.floor(i / 4 / this.height) / this.height;
|
let y = Math.floor(i / 4 / this.height) / this.height;
|
||||||
let hue = h;
|
let hue = h;
|
||||||
let rgb = hsvToRgb(hue, x, 1 - y);
|
let rgb = hsvToRgb(hue, x, 1 - y);
|
||||||
data[i + 0] = rgb.r;
|
data[i + 0] = rgb.r;
|
||||||
data[i + 1] = rgb.g;
|
data[i + 1] = rgb.g;
|
||||||
data[i + 2] = rgb.b;
|
data[i + 2] = rgb.b;
|
||||||
data[i + 3] = 255;
|
data[i + 3] = 255;
|
||||||
}
|
|
||||||
const transform = ctx.getTransform();
|
|
||||||
ctx.putImageData(mainGradient, transform.e, transform.f);
|
|
||||||
// draw pointer
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.arc(
|
|
||||||
s * this.width,
|
|
||||||
(1 - v) * this.height,
|
|
||||||
3,
|
|
||||||
0,
|
|
||||||
2 * Math.PI,
|
|
||||||
);
|
|
||||||
ctx.strokeStyle = "white";
|
|
||||||
ctx.stroke();
|
|
||||||
}
|
|
||||||
updateColorFromMouse(x, y) {
|
|
||||||
const [h, s, v] = this.colorCvs.currentHSV
|
|
||||||
const _x = clamp(x / this.width);
|
|
||||||
const _y = clamp(y / this.height);
|
|
||||||
const rgb = hsvToRgb(h, _x, 1 - _y);
|
|
||||||
const alpha = this.colorCvs.currentColor.slice(7, 9) || "ff";
|
|
||||||
this.colorCvs.currentColor = rgbToHex(rgb.r, rgb.g, rgb.b) + alpha;
|
|
||||||
this.colorCvs.currentHSV = [h, _x, 1 - _y]
|
|
||||||
this.colorCvs.currentAlpha = alpha
|
|
||||||
}
|
}
|
||||||
|
const transform = ctx.getTransform();
|
||||||
|
ctx.putImageData(mainGradient, transform.e, transform.f);
|
||||||
|
// draw pointer
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(
|
||||||
|
s * this.width,
|
||||||
|
(1 - v) * this.height,
|
||||||
|
3,
|
||||||
|
0,
|
||||||
|
2 * Math.PI,
|
||||||
|
);
|
||||||
|
ctx.strokeStyle = "white";
|
||||||
|
ctx.stroke();
|
||||||
|
}
|
||||||
|
updateColorFromMouse(x, y) {
|
||||||
|
const [h, s, v] = this.colorCvs.currentHSV
|
||||||
|
const _x = clamp(x / this.width);
|
||||||
|
const _y = clamp(y / this.height);
|
||||||
|
const rgb = hsvToRgb(h, _x, 1 - _y);
|
||||||
|
const alpha = this.colorCvs.currentColor.slice(7, 9) || "ff";
|
||||||
|
this.colorCvs.currentColor = rgbToHex(rgb.r, rgb.g, rgb.b) + alpha;
|
||||||
|
this.colorCvs.currentHSV = [h, _x, 1 - _y]
|
||||||
|
this.colorCvs.currentAlpha = alpha
|
||||||
|
}
|
||||||
|
|
||||||
mousedown(x, y) {
|
mousedown(x, y) {
|
||||||
this._globalEvents.add("mousemove")
|
this._globalEvents.add("mousemove")
|
||||||
this._globalEvents.add("mouseup")
|
this._globalEvents.add("mouseup")
|
||||||
this.updateColorFromMouse(x, y)
|
this.updateColorFromMouse(x, y)
|
||||||
this.clicked = true;
|
this.clicked = true;
|
||||||
}
|
}
|
||||||
mousemove(x, y) {
|
mousemove(x, y) {
|
||||||
if (this.clicked) {
|
if (this.clicked) {
|
||||||
this.updateColorFromMouse(x, y)
|
this.updateColorFromMouse(x, y)
|
||||||
}
|
|
||||||
}
|
|
||||||
mouseup(x, y) {
|
|
||||||
this._globalEvents.delete("mousemove")
|
|
||||||
this._globalEvents.delete("mouseup")
|
|
||||||
this.clicked = false
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
mouseup(x, y) {
|
||||||
|
this._globalEvents.delete("mousemove")
|
||||||
|
this._globalEvents.delete("mouseup")
|
||||||
|
this.clicked = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AlphaSelectionBar extends Widget {
|
class AlphaSelectionBar extends Widget {
|
||||||
constructor(width, height, x, y, colorCvs) {
|
constructor(width, height, x, y, colorCvs) {
|
||||||
super(x, y)
|
super(x, y)
|
||||||
this.width = width
|
this.width = width
|
||||||
this.height = height
|
this.height = height
|
||||||
this.colorCvs = colorCvs
|
this.colorCvs = colorCvs
|
||||||
}
|
}
|
||||||
|
|
||||||
draw(ctx) {
|
draw(ctx) {
|
||||||
drawCheckerboardBackground(ctx, 0, 0, this.width, this.height, 10);
|
drawCheckerboardBackground(ctx, 0, 0, this.width, this.height, 10);
|
||||||
// Vertical gradient
|
// Vertical gradient
|
||||||
const gradient = ctx.createLinearGradient( 0, 0, 0, this.height);
|
const gradient = ctx.createLinearGradient( 0, 0, 0, this.height);
|
||||||
gradient.addColorStop(0, `${this.colorCvs.currentColor.slice(0, 7)}ff`); // Full color at the top
|
gradient.addColorStop(0, `${this.colorCvs.currentColor.slice(0, 7)}ff`); // Full color at the top
|
||||||
gradient.addColorStop(1, `${this.colorCvs.currentColor.slice(0, 7)}00`);
|
gradient.addColorStop(1, `${this.colorCvs.currentColor.slice(0, 7)}00`);
|
||||||
ctx.fillStyle = gradient;
|
ctx.fillStyle = gradient;
|
||||||
ctx.fillRect(0, 0, this.width, this.height);
|
ctx.fillRect(0, 0, this.width, this.height);
|
||||||
let alpha =
|
let alpha =
|
||||||
parseInt(this.colorCvs.currentColor.slice(7, 9) || "ff", 16) / 255;
|
parseInt(this.colorCvs.currentColor.slice(7, 9) || "ff", 16) / 255;
|
||||||
// draw pointer
|
// draw pointer
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.rect(0, (1 - alpha) * this.height - 2, this.width, 4);
|
ctx.rect(0, (1 - alpha) * this.height - 2, this.width, 4);
|
||||||
ctx.strokeStyle = "white";
|
ctx.strokeStyle = "white";
|
||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
}
|
}
|
||||||
updateColorFromMouse(x, y) {
|
updateColorFromMouse(x, y) {
|
||||||
y = 1 - y / this.height;
|
y = 1 - y / this.height;
|
||||||
const alpha = Math.round(clamp(y) * 255).toString(16);
|
const alpha = Math.round(clamp(y) * 255).toString(16);
|
||||||
this.colorCvs.currentColor = `${this.colorCvs.currentColor.slice(0, 7)}${alpha}`;
|
this.colorCvs.currentColor = `${this.colorCvs.currentColor.slice(0, 7)}${alpha}`;
|
||||||
this.colorCvs.currentAlpha = alpha
|
this.colorCvs.currentAlpha = alpha
|
||||||
}
|
}
|
||||||
mousedown(x, y) {
|
mousedown(x, y) {
|
||||||
this._globalEvents.add("mousemove")
|
this._globalEvents.add("mousemove")
|
||||||
this._globalEvents.add("mouseup")
|
this._globalEvents.add("mouseup")
|
||||||
this.updateColorFromMouse(x, y)
|
this.updateColorFromMouse(x, y)
|
||||||
this.clicked = true;
|
this.clicked = true;
|
||||||
}
|
}
|
||||||
mousemove(x, y) {
|
mousemove(x, y) {
|
||||||
if (this.clicked) {
|
if (this.clicked) {
|
||||||
this.updateColorFromMouse(x, y)
|
this.updateColorFromMouse(x, y)
|
||||||
}
|
|
||||||
}
|
|
||||||
mouseup(x, y) {
|
|
||||||
this._globalEvents.delete("mousemove")
|
|
||||||
this._globalEvents.delete("mouseup")
|
|
||||||
this.clicked = false
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
mouseup(x, y) {
|
||||||
|
this._globalEvents.delete("mousemove")
|
||||||
|
this._globalEvents.delete("mouseup")
|
||||||
|
this.clicked = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ColorWidget extends Widget {
|
class ColorWidget extends Widget {
|
||||||
constructor(width, height, x, y, colorCvs) {
|
constructor(width, height, x, y, colorCvs) {
|
||||||
super(x, y)
|
super(x, y)
|
||||||
this.width = width
|
this.width = width
|
||||||
this.height = height
|
this.height = height
|
||||||
this.colorCvs = colorCvs
|
this.colorCvs = colorCvs
|
||||||
}
|
}
|
||||||
draw(ctx) {
|
draw(ctx) {
|
||||||
drawCheckerboardBackground(ctx, 0, 0, this.width, this.height, 10);
|
drawCheckerboardBackground(ctx, 0, 0, this.width, this.height, 10);
|
||||||
ctx.fillStyle = this.colorCvs.currentColor;
|
ctx.fillStyle = this.colorCvs.currentColor;
|
||||||
ctx.fillRect(0, 0, this.width, this.height);
|
ctx.fillRect(0, 0, this.width, this.height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class ColorSelectorWidget extends Widget {
|
||||||
|
constructor(x, y, colorCvs) {
|
||||||
|
super(x, y)
|
||||||
|
this.colorCvs = colorCvs
|
||||||
|
const padding = 10;
|
||||||
|
const gradwidth = 25;
|
||||||
|
const ccwidth = 300;
|
||||||
|
const mainSize = ccwidth - (3 * padding + gradwidth);
|
||||||
|
this.children = [
|
||||||
|
new ColorWidget(
|
||||||
|
colorCvs.width - 2 * padding,
|
||||||
|
50,
|
||||||
|
padding,
|
||||||
|
padding,
|
||||||
|
colorCvs
|
||||||
|
),
|
||||||
|
new HueSelectionBar(
|
||||||
|
mainSize,
|
||||||
|
gradwidth,
|
||||||
|
padding,
|
||||||
|
3 * padding + 50 + mainSize, colorCvs
|
||||||
|
),
|
||||||
|
new SaturationValueSelectionGradient(
|
||||||
|
mainSize,
|
||||||
|
mainSize,
|
||||||
|
padding,
|
||||||
|
2 * padding + 50,
|
||||||
|
colorCvs
|
||||||
|
),
|
||||||
|
new AlphaSelectionBar(
|
||||||
|
gradwidth,
|
||||||
|
mainSize,
|
||||||
|
colorCvs.width - (padding + gradwidth),
|
||||||
|
2 * padding + 50,
|
||||||
|
colorCvs
|
||||||
|
)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
draw(ctx) {
|
||||||
|
const darkMode =
|
||||||
|
window.matchMedia &&
|
||||||
|
window.matchMedia("(prefers-color-scheme: dark)").matches;
|
||||||
|
ctx.lineWidth = 2;
|
||||||
|
if (darkMode) {
|
||||||
|
ctx.fillStyle = "#333";
|
||||||
|
} else {
|
||||||
|
ctx.fillStyle = "#ccc"; //TODO
|
||||||
}
|
}
|
||||||
|
ctx.fillRect(0, 0, this.colorCvs.width, this.colorCvs.height);
|
||||||
|
super.draw(ctx)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ColorSelectorWidget extends Widget {
|
class HBox extends Widget {
|
||||||
constructor(x, y, colorCvs) {
|
constructor(x, y) {
|
||||||
super(x, y)
|
super(x, y)
|
||||||
this.colorCvs = colorCvs
|
this.width = 0;
|
||||||
const padding = 10;
|
this.height = 0;
|
||||||
const gradwidth = 25;
|
}
|
||||||
const ccwidth = 300;
|
add(child) {
|
||||||
const mainSize = ccwidth - (3 * padding + gradwidth);
|
child.x = this.width
|
||||||
this.children = [
|
child.y = 0
|
||||||
new ColorWidget(
|
this.children.push(child)
|
||||||
colorCvs.width - 2 * padding,
|
this.width += child.width
|
||||||
50,
|
}
|
||||||
padding,
|
}
|
||||||
padding,
|
class VBox extends Widget {
|
||||||
colorCvs
|
constructor(x, y) {
|
||||||
),
|
super(x, y)
|
||||||
new HueSelectionBar(
|
this.width = 0;
|
||||||
mainSize,
|
this.height = 0;
|
||||||
gradwidth,
|
}
|
||||||
padding,
|
add(child) {
|
||||||
3 * padding + 50 + mainSize, colorCvs
|
child.x = 0
|
||||||
),
|
child.y = this.height
|
||||||
new SaturationValueSelectionGradient(
|
this.children.push(child)
|
||||||
mainSize,
|
this.height += child.height
|
||||||
mainSize,
|
}
|
||||||
padding,
|
}
|
||||||
2 * padding + 50,
|
|
||||||
colorCvs
|
class ScrollableWindowHeaders extends Widget {
|
||||||
),
|
constructor(x, y, scrollableWindow, scrollDirection, headers) {
|
||||||
new AlphaSelectionBar(
|
this.scrollableWindow = scrollableWindow
|
||||||
gradwidth,
|
this.children = [this.scrollableWindow]
|
||||||
mainSize,
|
if (scrollDirection & SCROLL.HORIZONTAL) {
|
||||||
colorCvs.width - (padding + gradwidth),
|
this.vbox = new VBox(0, headers.y)
|
||||||
2 * padding + 50,
|
this.children.push(this.vbox)
|
||||||
colorCvs
|
|
||||||
)
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
draw(ctx) {
|
if (scrollDirection & SCROLL.VERTICAL) {
|
||||||
const darkMode =
|
this.hbox = new HBox(0, headers.y)
|
||||||
window.matchMedia &&
|
this.children.push(this.hbox)
|
||||||
window.matchMedia("(prefers-color-scheme: dark)").matches;
|
}
|
||||||
ctx.lineWidth = 2;
|
}
|
||||||
if (darkMode) {
|
wheel(dx, dy) {
|
||||||
ctx.fillStyle = "#333";
|
|
||||||
} else {
|
}
|
||||||
ctx.fillStyle = "#ccc"; //TODO
|
}
|
||||||
|
|
||||||
|
class ScrollableWindow extends Widget {
|
||||||
|
constructor(x, y) {
|
||||||
|
super(x, y)
|
||||||
|
this.offsetX = 0
|
||||||
|
this.offsetY = 0
|
||||||
|
}
|
||||||
|
draw(ctx) {
|
||||||
|
ctx.save()
|
||||||
|
ctx.beginPath()
|
||||||
|
ctx.rect(0, 0, this.width, this.height)
|
||||||
|
ctx.clip()
|
||||||
|
ctx.translate(this.offsetX, this.offsetY)
|
||||||
|
this.drawContents(ctx)
|
||||||
|
ctx.restore()
|
||||||
|
}
|
||||||
|
drawContents(ctx) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TimelineWindow extends ScrollableWindow {
|
||||||
|
constructor(x, y, context) {
|
||||||
|
super(x, y)
|
||||||
|
this.context = context
|
||||||
|
this.width = 100
|
||||||
|
this.height = 100
|
||||||
|
}
|
||||||
|
drawContents(ctx) {
|
||||||
|
const startFrame = Math.floor(-this.offsetX / frameWidth)
|
||||||
|
const frameCount = (this.width / frameWidth) + 1
|
||||||
|
for (let k = this.context.activeObject.allLayers.length - 1; k >= 0; k--) {
|
||||||
|
let layer = this.context.activeObject.allLayers[k];
|
||||||
|
// if (layer instanceof Layer) {
|
||||||
|
if (layer.frames) {
|
||||||
|
// Draw background
|
||||||
|
for (let j = startFrame; j < startFrame + frameCount; j++) {
|
||||||
|
ctx.fillStyle = (j + 1) % 5 == 0 ? shade : backgroundColor;
|
||||||
|
drawBorderedRect(
|
||||||
|
ctx,
|
||||||
|
j * frameWidth,
|
||||||
|
0,
|
||||||
|
frameWidth,
|
||||||
|
layerHeight,
|
||||||
|
shadow,
|
||||||
|
highlight,
|
||||||
|
shadow,
|
||||||
|
shadow,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
ctx.fillRect(0, 0, this.colorCvs.width, this.colorCvs.height);
|
// Draw frames
|
||||||
super.draw(ctx)
|
for (let j=0; j<layer.frames.length; j++) {
|
||||||
|
const frameInfo = layer.getFrameValue(j)
|
||||||
|
if (frameInfo.valueAtN) {
|
||||||
|
ctx.fillStyle = foregroundColor;
|
||||||
|
drawBorderedRect(
|
||||||
|
ctx,
|
||||||
|
j * frameWidth,
|
||||||
|
0,
|
||||||
|
frameWidth,
|
||||||
|
layerHeight,
|
||||||
|
highlight,
|
||||||
|
shadow,
|
||||||
|
shadow,
|
||||||
|
shadow,
|
||||||
|
);
|
||||||
|
ctx.fillStyle = "#111";
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(
|
||||||
|
(j + 0.5) * frameWidth,
|
||||||
|
layerHeight * 0.75,
|
||||||
|
frameWidth * 0.25,
|
||||||
|
0,
|
||||||
|
2 * Math.PI,
|
||||||
|
);
|
||||||
|
ctx.fill();
|
||||||
|
if (frameInfo.valueAtN.keyTypes.has("motion")) {
|
||||||
|
ctx.strokeStyle = "#7a00b3";
|
||||||
|
ctx.lineWidth = 2;
|
||||||
|
ctx.beginPath()
|
||||||
|
ctx.moveTo(j*frameWidth, layerHeight*0.25)
|
||||||
|
ctx.lineTo((j+1)*frameWidth, layerHeight*0.25)
|
||||||
|
ctx.stroke()
|
||||||
|
}
|
||||||
|
if (frameInfo.valueAtN.keyTypes.has("shape")) {
|
||||||
|
ctx.strokeStyle = "#9bff9b";
|
||||||
|
ctx.lineWidth = 2;
|
||||||
|
ctx.beginPath()
|
||||||
|
ctx.moveTo(j*frameWidth, layerHeight*0.35)
|
||||||
|
ctx.lineTo((j+1)*frameWidth, layerHeight*0.35)
|
||||||
|
ctx.stroke()
|
||||||
|
}
|
||||||
|
} else if (frameInfo.prev && frameInfo.next) {
|
||||||
|
ctx.fillStyle = foregroundColor;
|
||||||
|
drawBorderedRect(
|
||||||
|
ctx,
|
||||||
|
j * frameWidth,
|
||||||
|
0,
|
||||||
|
frameWidth,
|
||||||
|
layerHeight,
|
||||||
|
highlight,
|
||||||
|
shadow,
|
||||||
|
backgroundColor,
|
||||||
|
backgroundColor,
|
||||||
|
);
|
||||||
|
if (frameInfo.prev.keyTypes.has("motion")) {
|
||||||
|
ctx.strokeStyle = "#7a00b3";
|
||||||
|
ctx.lineWidth = 2;
|
||||||
|
ctx.beginPath()
|
||||||
|
ctx.moveTo(j*frameWidth, layerHeight*0.25)
|
||||||
|
ctx.lineTo((j+1)*frameWidth, layerHeight*0.25)
|
||||||
|
ctx.stroke()
|
||||||
|
}
|
||||||
|
if (frameInfo.prev.keyTypes.has("shape")) {
|
||||||
|
ctx.strokeStyle = "#9bff9b";
|
||||||
|
ctx.lineWidth = 2;
|
||||||
|
ctx.beginPath()
|
||||||
|
ctx.moveTo(j*frameWidth, layerHeight*0.35)
|
||||||
|
ctx.lineTo((j+1)*frameWidth, layerHeight*0.35)
|
||||||
|
ctx.stroke()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// } else if (layer instanceof AudioLayer) {
|
||||||
|
} else if (layer.sounds) {
|
||||||
|
// TODO: split waveform into chunks
|
||||||
|
for (let i in layer.sounds) {
|
||||||
|
let sound = layer.sounds[i];
|
||||||
|
ctx.drawImage(sound.img, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ctx.translate(0,layerHeight)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
mousedown(x, y) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
Widget,
|
SCROLL,
|
||||||
HueSelectionBar,
|
Widget,
|
||||||
SaturationValueSelectionGradient,
|
HueSelectionBar,
|
||||||
AlphaSelectionBar,
|
SaturationValueSelectionGradient,
|
||||||
ColorWidget,
|
AlphaSelectionBar,
|
||||||
ColorSelectorWidget
|
ColorWidget,
|
||||||
|
ColorSelectorWidget,
|
||||||
|
HBox, VBox,
|
||||||
|
ScrollableWindow,
|
||||||
|
ScrollableWindowHeaders,
|
||||||
|
TimelineWindow
|
||||||
};
|
};
|
||||||
Loading…
Reference in New Issue