diff --git a/src/assets/volume-mute.svg b/src/assets/volume-mute.svg
new file mode 100644
index 0000000..d06d3dc
--- /dev/null
+++ b/src/assets/volume-mute.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/src/assets/volume-up-fill.svg b/src/assets/volume-up-fill.svg
new file mode 100644
index 0000000..0f94073
--- /dev/null
+++ b/src/assets/volume-up-fill.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/src/main.js b/src/main.js
index 7ed7019..85f011e 100644
--- a/src/main.js
+++ b/src/main.js
@@ -1601,6 +1601,7 @@ class Layer {
this.name = "Layer"
this.frames = [new Frame("keyframe", this.idx+"-F1")]
this.visible = true
+ this.audible = true
pointerList[this.idx] = this
}
getFrame(num) {
@@ -1827,6 +1828,7 @@ class AudioLayer {
} else {
this.name = name
}
+ this.audible = true
}
copy(idx) {
let newAudioLayer = new AudioLayer(idx.slice(0,8)+this.idx.slice(8), this.name)
@@ -2280,6 +2282,9 @@ class GraphicsObject {
get children() {
return this.activeLayer.children
}
+ get allLayers() {
+ return [...this.audioLayers, ...this.layers]
+ }
get currentFrame() {
return this.getFrame(this.currentFrameNum)
}
@@ -4083,6 +4088,8 @@ function timeline() {
// Load icons for show/hide layer
timeline_cvs.icons = {}
+ timeline_cvs.icons.volume_up_fill = new Icon('assets/volume-up-fill.svg');
+ timeline_cvs.icons.volume_mute = new Icon('assets/volume-mute.svg');
timeline_cvs.icons.eye_fill = new Icon('assets/eye-fill.svg');
timeline_cvs.icons.eye_slash = new Icon('assets/eye-slash.svg');
@@ -4215,8 +4222,8 @@ function timeline() {
} else {
mouse.y -= gutterHeight
let l = Math.floor(mouse.y / layerHeight)
- if (l < context.activeObject.layers.length) {
- let i = context.activeObject.layers.length - (l+1)
+ if (l < context.activeObject.allLayers.length) {
+ let i = context.activeObject.allLayers.length - (l+1)
mouse.y -= l*layerHeight
if (
mouse.x > layerWidth - iconSize - 5 &&
@@ -4224,7 +4231,16 @@ function timeline() {
mouse.y > 0.5 * (layerHeight - iconSize) &&
mouse.y < 0.5 * (layerHeight + iconSize)
) {
- context.activeObject.layers[i].visible = !context.activeObject.layers[i].visible
+ context.activeObject.allLayers[i].visible = !context.activeObject.allLayers[i].visible
+ updateUI()
+ updateMenu()
+ } else if (
+ mouse.x > layerWidth - iconSize*2 - 10 &&
+ mouse.x < layerWidth - iconSize - 5 &&
+ mouse.y > 0.5 * (layerHeight - iconSize) &&
+ mouse.y < 0.5 * (layerHeight + iconSize)
+ ) {
+ context.activeObject.allLayers[i].audible = !context.activeObject.allLayers[i].audible
updateUI()
updateMenu()
} else {
@@ -4722,8 +4738,8 @@ function updateLayers() {
ctx.translate(0, -offsetY)
// Draw layer headers
let i=0;
- for (let k = context.activeObject.layers.length - 1; k >= 0; k--) {
- let layer = context.activeObject.layers[k];
+ for (let k = context.activeObject.allLayers.length - 1; k >= 0; k--) {
+ let layer = context.activeObject.allLayers[k];
if (context.activeObject.activeLayer == layer) {
ctx.fillStyle = darkMode ? "#444" : "#ccc"
} else {
@@ -4733,8 +4749,10 @@ function updateLayers() {
ctx.fillStyle = darkMode ? "white": "black"
drawHorizontallyCenteredText(ctx, layer.name, 5, (i+0.5)*layerHeight, layerHeight*0.4)
ctx.save()
- const visibilityIcon = layer.visible ? canvas.icons.eye_fill : canvas.icons.eye_slash
- visibilityIcon.render(ctx, layerWidth - iconSize - 5, (i+0.5)*layerHeight - iconSize*0.5, iconSize, iconSize, labelColor)
+ const visibilityIcon = layer.visible ? canvas.icons.eye_fill : canvas.icons.eye_slash
+ visibilityIcon.render(ctx, layerWidth - iconSize - 5, (i+0.5)*layerHeight - iconSize*0.5, iconSize, iconSize, labelColor)
+ const audibilityIcon = layer.audible ? canvas.icons.volume_up_fill : canvas.icons.volume_mute
+ audibilityIcon.render(ctx, layerWidth - iconSize*2 - 10, (i+0.5)*layerHeight - iconSize*0.5, iconSize, iconSize, labelColor)
ctx.restore()
ctx.save()
ctx.beginPath()
@@ -4747,31 +4765,40 @@ function updateLayers() {
drawBorderedRect(ctx, j*frameWidth, 0, frameWidth, layerHeight, shadow, highlight, shadow, shadow)
}
// Draw existing frames
- layer.frames.forEach((frame, j) => {
- if (!frame) return;
- switch (frame.frameType) {
- case "keyframe":
- 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()
- break;
- case "normal":
- ctx.fillStyle = foregroundColor
- drawBorderedRect(ctx, j*frameWidth, 0, frameWidth, layerHeight, highlight, shadow, backgroundColor, backgroundColor)
- break;
- case "motion":
- ctx.fillStyle = "#7a00b3"
- ctx.fillRect(j*frameWidth, 0, frameWidth, layerHeight)
- break;
- case "shape":
- ctx.fillStyle = "#9bff9b"
- ctx.fillRect(j*frameWidth, 0, frameWidth, layerHeight)
- break;
+ if (layer instanceof Layer) {
+ layer.frames.forEach((frame, j) => {
+ if (!frame) return;
+ switch (frame.frameType) {
+ case "keyframe":
+ 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()
+ break;
+ case "normal":
+ ctx.fillStyle = foregroundColor
+ drawBorderedRect(ctx, j*frameWidth, 0, frameWidth, layerHeight, highlight, shadow, backgroundColor, backgroundColor)
+ break;
+ case "motion":
+ ctx.fillStyle = "#7a00b3"
+ ctx.fillRect(j*frameWidth, 0, frameWidth, layerHeight)
+ break;
+ case "shape":
+ ctx.fillStyle = "#9bff9b"
+ ctx.fillRect(j*frameWidth, 0, frameWidth, layerHeight)
+ break;
+ }
+ })
+ } else if (layer instanceof AudioLayer) {
+ // TODO: split waveform into chunks
+ for (let i in layer.sounds) {
+ let sound = layer.sounds[i]
+ // layerTrack.appendChild(sound.img)
+ ctx.drawImage(sound.img, 0,0)
}
- })
+ }
// if (context.activeObject.currentFrameNum)
ctx.restore()
i++;