Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 119 additions & 1 deletion celstomp/celstomp-app.js
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,8 @@


function renderBounds() {
fxctx.setTransform(1, 0, 0, 1, 0, 0);
fxctx.clearRect(0, 0, fxCanvas.width, fxCanvas.height);
setTransform(bctx);
setTransform(fxctx);
bctx.fillStyle = "#2a2f38";
Expand Down Expand Up @@ -902,7 +904,13 @@
safeSetChecked(onion, onionEnabled);
safeSetChecked(psnap, playSnapped);
toggle?.addEventListener("click", () => {
if (isPlaying) pausePlayback(); else startPlayback();
if (isPlaying) {
pausePlayback();
toggle.classList.remove("playing");
} else {
startPlayback();
toggle.classList.add("playing");
}
});
prevF?.addEventListener("click", () => gotoFrame(stepBySnap(-1)));
nextF?.addEventListener("click", () => gotoFrame(stepBySnap(1)));
Expand All @@ -919,6 +927,95 @@
safeSetValue(snapValue, v);
updateHUD();
});
const gridToggle = $("tlGridBtn");
const gridSnapToggle = $("tlGridSnapBtn");
const rulersToggle = $("tlRulersBtn");
const guideSnapToggle = $("tlGuideSnapBtn");
const addHGuideBtn = $("addHGuideBtn");
const addVGuideBtn = $("addVGuideBtn");
const clearGuidesBtn = $("clearGuidesBtn");
const guideModeHint = $("guideModeHint");
const gridSizeInput = $("tlGridSize");

let guidePlacementMode = null;

if (gridToggle) {
gridToggle.addEventListener("click", e => {
gridEnabled = !gridEnabled;
gridToggle.classList.toggle("active", gridEnabled);
queueRenderAll();
});
}
if (gridSizeInput) {
gridSizeInput.addEventListener("change", e => {
const v = Math.max(8, Math.min(128, parseInt(e.target.value) || 32));
gridSize = v;
e.target.value = v;
queueRenderAll();
});
}
if (gridSnapToggle) {
gridSnapToggle.addEventListener("click", e => {
gridSnap = !gridSnap;
gridSnapToggle.classList.toggle("active", gridSnap);
});
}
if (rulersToggle) {
rulersToggle.addEventListener("click", e => {
rulersEnabled = !rulersEnabled;
rulersToggle.classList.toggle("active", rulersEnabled);
queueRenderAll();
});
}
if (guideSnapToggle) {
guideSnapToggle.addEventListener("click", e => {
guideSnap = !guideSnap;
guideSnapToggle.classList.toggle("active", guideSnap);
});
}
function setGuidePlacementMode(mode) {
guidePlacementMode = mode;
if (addHGuideBtn) addHGuideBtn.classList.toggle("active", mode === "horizontal");
if (addVGuideBtn) addVGuideBtn.classList.toggle("active", mode === "vertical");
if (guideModeHint) {
guideModeHint.hidden = !mode;
guideModeHint.textContent = mode === "horizontal" ? "Click Canvas To Place H Guide" : mode === "vertical" ? "Click Canvas To Place V Guide" : "";
}
if (!mode) {
document.body.classList.remove("guide-place-mode");
document.body.classList.remove("guide-place-h");
document.body.classList.remove("guide-place-v");
} else {
document.body.classList.add("guide-place-mode");
document.body.classList.toggle("guide-place-h", mode === "horizontal");
document.body.classList.toggle("guide-place-v", mode === "vertical");
}
}
if (addHGuideBtn) {
addHGuideBtn.addEventListener("click", e => {
if (guidePlacementMode === "horizontal") {
setGuidePlacementMode(null);
} else {
setGuidePlacementMode("horizontal");
}
});
}
if (addVGuideBtn) {
addVGuideBtn.addEventListener("click", e => {
if (guidePlacementMode === "vertical") {
setGuidePlacementMode(null);
} else {
setGuidePlacementMode("vertical");
}
});
}
if (clearGuidesBtn) {
clearGuidesBtn.addEventListener("click", () => {
guides = [];
queueRenderAll();
});
}
window.__celstompSetGuidePlacementMode = setGuidePlacementMode;
function rebuildTimelineKeepFrame() {
const cur = currentFrame;
buildTimeline();
Expand Down Expand Up @@ -953,6 +1050,7 @@
const showLeft = $("showLeftEdge");
const showRight = $("showRightEdge");
const showTl = $("showTimelineEdge");
const timelineEl = $("timeline");
const tLeft = $("toggleSidebarBtn");
const tRight = $("toggleRightbarBtn");
function applyLayoutChange() {
Expand All @@ -974,8 +1072,28 @@
}
function setTimelineOpen(open) {
app.classList.toggle("tl-collapsed", !open);
document.body?.classList.toggle("tl-collapsed", !open);
if (timelineEl) {
timelineEl.hidden = !open;
timelineEl.style.display = open ? "" : "none";
timelineEl.setAttribute("aria-hidden", open ? "false" : "true");
}
if (showTl) {
showTl.style.display = open ? "none" : "block";
}
applyLayoutChange();
}
if (!document._celstompPanelToggleDelegated) {
document._celstompPanelToggleDelegated = true;
document.addEventListener("click", e => {
if (e.target.closest("#hideLeftPanelBtn")) setLeftOpen(false);
if (e.target.closest("#hideRightPanelBtn")) setRightOpen(false);
if (e.target.closest("#hideTimelineBtn")) setTimelineOpen(false);
if (e.target.closest("#showLeftEdge")) setLeftOpen(true);
if (e.target.closest("#showRightEdge")) setRightOpen(true);
if (e.target.closest("#showTimelineEdge")) setTimelineOpen(true);
});
}
setLeftOpen(true);
setRightOpen(true);
setTimelineOpen(true);
Expand Down
68 changes: 68 additions & 0 deletions celstomp/css/components/island.css
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,50 @@
cursor: grabbing;
}

.islandDock.drag-lock-candidate {
outline: 2px solid rgba(92, 179, 255, 0.6);
outline-offset: -2px;
}

.islandDock.right-locked {
left: auto !important;
right: var(--dock-gap);
top: calc(var(--header-h) + var(--dock-gap));
bottom: calc(var(--timeline-h) + var(--dock-gap-bottom));
height: auto !important;
width: min(320px, 36vw);
}

.islandDock.right-locked .islandHeader {
background: rgba(92, 179, 255, 0.12);
border-bottom-color: rgba(92, 179, 255, 0.35);
}

.islandLockHint {
position: fixed;
top: calc(var(--header-h) + 14px);
right: 10px;
width: 180px;
height: calc(100vh - var(--header-h) - var(--timeline-h) - 24px);
border: 2px dashed rgba(92, 179, 255, 0.32);
border-radius: 10px;
background: rgba(92, 179, 255, 0.08);
color: rgba(180, 225, 255, 0.9);
display: none;
align-items: center;
justify-content: center;
text-align: center;
font-size: 11px;
letter-spacing: 0.08em;
text-transform: uppercase;
z-index: 39;
pointer-events: none;
}

.islandLockHint.active {
display: flex;
}

.islandTitle{
font-size: 12px;
letter-spacing: 0.08em;
Expand Down Expand Up @@ -222,6 +266,30 @@
overflow-x: hidden;
}

.islandSideBody {
scrollbar-width: thin;
scrollbar-color: rgba(255,255,255,0.24) rgba(0,0,0,0.22);
}

.islandSideBody::-webkit-scrollbar {
width: 10px;
}

.islandSideBody::-webkit-scrollbar-track {
background: rgba(0,0,0,0.24);
border-radius: 999px;
}

.islandSideBody::-webkit-scrollbar-thumb {
background: rgba(255,255,255,0.24);
border-radius: 999px;
border: 2px solid rgba(0,0,0,0.22);
}

.islandSideBody::-webkit-scrollbar-thumb:hover {
background: rgba(255,255,255,0.34);
}

.islandSideGrid{
display: flex;
flex-direction: column;
Expand Down
24 changes: 24 additions & 0 deletions celstomp/css/components/layers.css
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,30 @@ body.swatch-reordering{
border-radius: 0px;
}

#islandLayersSlot {
scrollbar-width: thin;
scrollbar-color: rgba(255,255,255,0.24) rgba(0,0,0,0.22);
}

#islandLayersSlot::-webkit-scrollbar {
width: 10px;
}

#islandLayersSlot::-webkit-scrollbar-track {
background: rgba(0,0,0,0.24);
border-radius: 999px;
}

#islandLayersSlot::-webkit-scrollbar-thumb {
background: rgba(255,255,255,0.24);
border-radius: 999px;
border: 2px solid rgba(0,0,0,0.22);
}

#islandLayersSlot::-webkit-scrollbar-thumb:hover {
background: rgba(255,255,255,0.34);
}

#islandLayersSlot #layerSeg{
display: flex !important;
flex-direction: column !important;
Expand Down
118 changes: 118 additions & 0 deletions celstomp/css/components/overlays.css
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,124 @@
opacity: .95;
}

.canvasTextEntry {
position: fixed;
inset: 0;
display: none;
align-items: center;
justify-content: center;
background: rgba(0, 0, 0, 0.32);
z-index: 9400;
}

.canvasTextEntry.open {
display: flex;
}

.canvasTextEntryCard {
width: min(420px, calc(100vw - 24px));
border: 1px solid rgba(255, 255, 255, 0.16);
background: rgba(16, 20, 28, 0.96);
border-radius: 10px;
box-shadow: 0 16px 42px rgba(0, 0, 0, 0.45);
padding: 12px;
display: grid;
gap: 10px;
}

.canvasTextEntryLabel {
font-size: 12px;
color: #c7d0db;
letter-spacing: 0.04em;
text-transform: uppercase;
}

.canvasTextEntryInput {
width: 100%;
min-height: 36px;
border: 1px solid rgba(255, 255, 255, 0.14);
background: rgba(0, 0, 0, 0.28);
color: #e2e8f0;
border-radius: 8px;
padding: 8px 10px;
}

.canvasTextEntryInput:focus {
outline: none;
border-color: rgba(92, 179, 255, 0.8);
box-shadow: 0 0 0 2px rgba(92, 179, 255, 0.2);
}

.canvasTextEntryOptions {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 8px;
}

.canvasTextEntryOpt {
display: grid;
gap: 4px;
}

.canvasTextEntryOpt > span {
font-size: 11px;
color: #b7c3d2;
letter-spacing: 0.03em;
}

.canvasTextEntrySelect,
.canvasTextEntryNum {
width: 100%;
min-height: 32px;
border: 1px solid rgba(255, 255, 255, 0.14);
background: rgba(0, 0, 0, 0.28);
color: #e2e8f0;
border-radius: 8px;
padding: 6px 8px;
}

.canvasTextEntrySelect:focus,
.canvasTextEntryNum:focus {
outline: none;
border-color: rgba(92, 179, 255, 0.8);
box-shadow: 0 0 0 2px rgba(92, 179, 255, 0.2);
}

.canvasTextEntryOptCheck {
align-items: center;
grid-template-columns: auto 1fr;
gap: 8px;
border: 1px solid rgba(255, 255, 255, 0.12);
border-radius: 8px;
background: rgba(255, 255, 255, 0.04);
padding: 6px 8px;
}

.canvasTextEntryOptCheck input {
margin: 0;
}

.canvasTextEntryActions {
display: flex;
justify-content: flex-end;
gap: 8px;
}

.canvasTextEntryBtn {
min-height: 34px;
padding: 0 12px;
border-radius: 8px;
border: 1px solid rgba(255, 255, 255, 0.14);
background: rgba(255, 255, 255, 0.06);
color: #d0d8e2;
}

.canvasTextEntryBtnPrimary {
border-color: rgba(92, 179, 255, 0.6);
background: rgba(92, 179, 255, 0.18);
color: #9fd5ff;
}

.infoList{
margin: 0;
padding-left: 18px;
Expand Down
Loading