diff --git a/src-tauri/capabilities/default.json b/src-tauri/capabilities/default.json index 1efef12..0b6d6a4 100644 --- a/src-tauri/capabilities/default.json +++ b/src-tauri/capabilities/default.json @@ -7,6 +7,7 @@ ], "permissions": [ "core:default", + "core:window:allow-close", "shell:allow-open", "fs:default", { diff --git a/src/main.js b/src/main.js index a5fc5a4..cf77569 100644 --- a/src/main.js +++ b/src/main.js @@ -591,9 +591,10 @@ function redo() { class Frame { - constructor(uuid) { + constructor(frameType="normal", uuid=undefined) { this.keys = {} this.shapes = [] + this.frameType = frameType if (!uuid) { this.idx = uuidv4() } else { @@ -608,7 +609,7 @@ class Frame { class Layer { constructor(uuid) { - this.frames = [new Frame()] + this.frames = [new Frame("keyframe")] this.children = [] if (!uuid) { this.idx = uuidv4() @@ -955,7 +956,21 @@ class GraphicsObject { return this.layers[this.currentLayer].children } get currentFrame() { - return this.layers[this.currentLayer].frames[this.currentFrameNum] + if (this.layers[this.currentLayer].frames[this.currentFrameNum]) { + if (this.layers[this.currentLayer].frames[this.currentFrameNum].frameType == "keyframe") { + return this.layers[this.currentLayer].frames[this.currentFrameNum] + } else if (this.layers[this.currentLayer].frames[this.currentFrameNum].frameType == "motion") { + + } else if (this.layers[this.currentLayer].frames[this.currentFrameNum].frameType == "shape") { + + } else { + for (let i=this.currentFrameNum; i>=0; i--) { + if (this.layers[this.currentLayer].frames[i].frameType == "keyframe") { + return this.layers[this.currentLayer].frames[i] + } + } + } + } } get maxFrame() { let maxFrames = [] @@ -1134,7 +1149,7 @@ window.addEventListener("resize", () => { updateAll() }) -window.addEventListener("keypress", (e) => { +window.addEventListener("keydown", (e) => { // let shortcuts = {} // for (let shortcut of config.shortcuts) { // shortcut = shortcut.split("+") @@ -1158,8 +1173,28 @@ window.addEventListener("keypress", (e) => { } else if (e.key == config.shortcuts.quit && e.ctrlKey == true) { quit() } + else if (e.key == "ArrowRight") { + advanceFrame() + } + else if (e.key == "ArrowLeft") { + decrementFrame() + } }) +function advanceFrame() { + context.activeObject.currentFrameNum += 1 + updateLayers() + updateMenu() +} + +function decrementFrame() { + if (context.activeObject.currentFrameNum > 0) { + context.activeObject.currentFrameNum -= 1 + updateLayers() + updateMenu() + } +} + function _newFile(width, height) { root = new GraphicsObject("root"); context.activeObject = root @@ -1727,106 +1762,6 @@ function infopanel() { return panel } -async function setupMenu() { - const fileSubmenu = await Submenu.new({ - text: 'File', - items: [ - { - text: 'New file...', - enabled: true, - action: newFile, - }, - { - text: 'Save', - enabled: true, - action: save, - }, - { - text: 'Save As...', - enabled: true, - action: saveAs, - }, - { - text: 'Open File...', - enabled: true, - action: open, - }, - { - text: 'Quit', - enabled: true, - action: quit, - }, - ] - }) - - const editSubmenu = await Submenu.new({ - text: "Edit", - items: [ - { - text: "Undo", - enabled: true, - action: undo - }, - { - text: "Redo", - enabled: true, - action: redo - }, - { - text: "Cut", - enabled: true, - action: () => {} - }, - { - text: "Copy", - enabled: true, - action: () => {} - }, - { - text: "Paste", - enabled: true, - action: () => {} - }, - ] - }); - const viewSubmenu = await Submenu.new({ - text: "View", - items: [ - { - text: "Zoom In", - enabled: true, - action: () => {} - }, - { - text: "Zoom Out", - enabled: true, - action: () => {} - }, - ] - }); - const helpSubmenu = await Submenu.new({ - text: "Help", - items: [ - { - text: "About...", - enabled: true, - action: () => { - messageDialog(`Lightningbeam version ${appVersion}\nDeveloped by Skyler Lehmkuhl`, - {title: 'About', kind: "info"} - ) - } - } - ] -}); - - const menu = await Menu.new({ - items: [fileSubmenu, editSubmenu, viewSubmenu, helpSubmenu], - }) - await (macOS ? menu.setAsAppMenu() : menu.setAsWindowMenu()) -} - -// Initialize the menu when the app starts -setupMenu(); createNewFileDialog(_newFile); showNewFileDialog() @@ -1947,12 +1882,173 @@ function updateLayers() { let layerTrack = document.createElement("div") layerTrack.className = "layer-track" framescontainer.appendChild(layerTrack) - for (let frame of layer.frames) { + let highlightedFrame = false + layer.frames.forEach((frame, i) => { // for (let j=0; j<5-i; j++) { let frameEl = document.createElement("div") frameEl.className = "frame" + if (i == context.activeObject.currentFrameNum) { + frameEl.classList.add("active") + highlightedFrame = true + } + console.log(frame.frameType) + if (frame.frameType == "keyframe") { + frameEl.classList.add("keyframe") + } layerTrack.appendChild(frameEl) + }) + if (!highlightedFrame) { + let highlightObj = document.createElement("div") + let frameCount = layer.frames.length + highlightObj.className = "frame-highlight" + highlightObj.style.left = `${(context.activeObject.currentFrameNum - frameCount) * 25}px`; + layerTrack.appendChild(highlightObj) } } } -} \ No newline at end of file +} + +async function updateMenu() { + let activeFrame; + let newFrameMenuItem; + let newKeyframeMenuItem; + let deleteFrameMenuItem; + + + if (context.activeObject.activeLayer.frames[context.activeObject.currentFrameNum]) { + activeFrame = true + } else { + activeFrame = false + } + const fileSubmenu = await Submenu.new({ + text: 'File', + items: [ + { + text: 'New file...', + enabled: true, + action: newFile, + }, + { + text: 'Save', + enabled: true, + action: save, + }, + { + text: 'Save As...', + enabled: true, + action: saveAs, + }, + { + text: 'Open File...', + enabled: true, + action: open, + }, + { + text: 'Quit', + enabled: true, + action: quit, + }, + ] + }) + + const editSubmenu = await Submenu.new({ + text: "Edit", + items: [ + { + text: "Undo", + enabled: true, + action: undo + }, + { + text: "Redo", + enabled: true, + action: redo + }, + { + text: "Cut", + enabled: true, + action: () => {} + }, + { + text: "Copy", + enabled: true, + action: () => {} + }, + { + text: "Paste", + enabled: true, + action: () => {} + }, + ] + }); + + newFrameMenuItem = { + text: "New Frame", + enabled: !activeFrame, + action: () => {} + } + newKeyframeMenuItem = { + text: "New Keyframe", + enabled: !activeFrame, + action: () => {} + } + deleteFrameMenuItem = { + text: "Delete Frame", + enabled: activeFrame, + action: () => {} + } + + const timelineSubmenu = await Submenu.new({ + text: "Timeline", + items: [ + newFrameMenuItem, + newKeyframeMenuItem, + deleteFrameMenuItem, + { + text: "Return to start", + enabled: false, + action: () => {} + }, + { + text: "Play", + enabled: false, + action: () => {} + }, + ] + }); + const viewSubmenu = await Submenu.new({ + text: "View", + items: [ + { + text: "Zoom In", + enabled: false, + action: () => {} + }, + { + text: "Zoom Out", + enabled: false, + action: () => {} + }, + ] + }); + const helpSubmenu = await Submenu.new({ + text: "Help", + items: [ + { + text: "About...", + enabled: true, + action: () => { + messageDialog(`Lightningbeam version ${appVersion}\nDeveloped by Skyler Lehmkuhl`, + {title: 'About', kind: "info"} + ) + } + } + ] +}); + + const menu = await Menu.new({ + items: [fileSubmenu, editSubmenu, timelineSubmenu, viewSubmenu, helpSubmenu], + }) + await (macOS ? menu.setAsAppMenu() : menu.setAsWindowMenu()) +} +updateMenu() \ No newline at end of file diff --git a/src/styles.css b/src/styles.css index 9489948..728f835 100644 --- a/src/styles.css +++ b/src/styles.css @@ -286,7 +286,31 @@ button { .frame:hover { background-color: #555555; } - +.frame.active { + background-color: #666666; +} +.frame.keyframe { + position: relative; +} +.frame.keyframe::before { + content: ''; /* Creates a pseudo-element */ + position: absolute; + bottom: 0; /* Position the circle at the bottom of the div */ + left: 50%; /* Center the circle horizontally */ + transform: translateX(-50%); /* Adjust for perfect centering */ + width: 50%; /* Set the width of the circle to half of the div's width */ + height: 0; /* Initially set to 0 */ + padding-bottom: 50%; /* Set padding-bottom to 50% of the div's width to create a circle */ + border-radius: 50%; /* Make the shape a circle */ + background-color: #222; /* Set the color of the circle (black in this case) */ + margin-bottom: 5px; +} +.frame-highlight { + background-color: red; + width: 25px; + height: calc( 2 * var(--lineheight) - 2px); + position: relative; +} .hidden { display: none;