Add sheet viewer page

This commit is contained in:
dylan 2023-05-06 14:49:46 -07:00
parent 0adfdabffa
commit 471fa9e0b6
11 changed files with 269 additions and 56 deletions

View File

@ -10,8 +10,17 @@ import { resetRepl } from "./repl.ts";
import { COLOR } from "./colors.ts"; import { COLOR } from "./colors.ts";
import { getSheet, getCodeSheet } from "./sheet.ts"; import { getSheet, getCodeSheet } from "./sheet.ts";
let spritesheet: number | null = null;
export const useSpritesheet = (sheet: number) => {
spritesheet = sheet;
}
export const drawSprite = (x: number, y: number, spr: number) => { export const drawSprite = (x: number, y: number, spr: number) => {
const {sheet_type, value: sprites} = getSheet(2); if (!spritesheet) {
return;
}
const {sheet_type, value: sprites} = getSheet(spritesheet);
if (sheet_type !== "spritesheet") { if (sheet_type !== "spritesheet") {
throw "Trying to run a non-code sheet as code." throw "Trying to run a non-code sheet as code."
} }
@ -37,6 +46,7 @@ const faux = {
resetRepl(); resetRepl();
clearScreen(); clearScreen();
}, },
sprsht: useSpritesheet,
spr: drawSprite, spr: drawSprite,
txt: drawText, txt: drawText,
rect: fillRect, rect: fillRect,

View File

@ -5,7 +5,59 @@
}, },
{ {
"sheet_type": "code", "sheet_type": "code",
"value": "speed = 2;\nreturn 8;" "value": "sprsht(15);\nspeed = 2;\nreturn 8;"
},
{
"sheet_type": "none",
"value": null
},
{
"sheet_type": "none",
"value": null
},
{
"sheet_type": "none",
"value": null
},
{
"sheet_type": "none",
"value": null
},
{
"sheet_type": "none",
"value": null
},
{
"sheet_type": "none",
"value": null
},
{
"sheet_type": "none",
"value": null
},
{
"sheet_type": "none",
"value": null
},
{
"sheet_type": "none",
"value": null
},
{
"sheet_type": "none",
"value": null
},
{
"sheet_type": "none",
"value": null
},
{
"sheet_type": "none",
"value": null
},
{
"sheet_type": "none",
"value": null
}, },
{ {
"sheet_type": "spritesheet", "sheet_type": "spritesheet",

View File

@ -2,15 +2,16 @@ import { clearScreen, fillRect } from "./window.ts";
import { fontWidth, fontHeight } from "./font.ts"; import { fontWidth, fontHeight } from "./font.ts";
import { drawText } from "./builtins.ts"; import { drawText } from "./builtins.ts";
import { COLOR } from "./colors.ts"; import { COLOR } from "./colors.ts";
import {getCodeSheet, setSheet} from "./sheet.ts"; import { getCodeSheet, setSheet } from "./sheet.ts";
import { K, ctrlKeyDown, getKeyboardString, keyPressed, shiftKeyDown } from "./keyboard.ts"; import { K, ctrlKeyDown, getKeyboardString, keyPressed, shiftKeyDown } from "./keyboard.ts";
import { clipboard, tokenize } from "./deps.ts"; import { clipboard, tokenize } from "./deps.ts";
import { getContext } from "./runcode.ts"; import { getContext } from "./runcode.ts";
import { page } from "./viewsheets.ts";
const historyDebounceFrames = 20; const historyDebounceFrames = 20;
const state = { const state = {
history: [{code: getCodeSheet(0), anchor: 0, focus: 0}], history: [{code: getCodeSheet(page.activeSheet), anchor: 0, focus: 0}],
historyDebounce: 0, historyDebounce: 0,
historyIndex: 0, historyIndex: 0,
undo() { undo() {
@ -201,10 +202,10 @@ const state = {
return match[0]; return match[0];
}, },
get code() { get code() {
return getCodeSheet(0); return getCodeSheet(page.activeSheet);
}, },
set code(val) { set code(val) {
setSheet(0, "code", val); setSheet(page.activeSheet, "code", val);
} }
} }

View File

@ -1,72 +1,61 @@
import { clearScreen, fillRect } from "./window.ts"; import { clearScreen, fillRect } from "./window.ts";
import { codetab } from "./codetab.ts"; import { codetab } from "./codetab.ts";
import { spritetab } from "./spritetab.ts"; import { spritetab } from "./spritetab.ts";
import { viewsheets, page } from "./viewsheets.ts";
import { COLOR } from "./colors.ts"; import { COLOR } from "./colors.ts";
import { mouseClick, mousePos } from "./mouse.ts"; import { mouseClick, mousePos } from "./mouse.ts";
import { drawIcon } from "./builtins.ts"; import { drawIcon } from "./builtins.ts";
import { inRect } from "./util.ts"; import { inRect } from "./util.ts";
import { sheetsIcon } from "./icons.ts";
import { SheetType } from "./sheet.ts";
import { nonetab } from "./nonetab.ts";
type TabName = "code" | "sprite" | "map" | "sfx" | "music"; type TabName = SheetType; // "code" | "sprite" | "map" | "sfx" | "music" | "sheet";
let tab: TabName = "code";
const codeIcon = [
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 1, 0, 0,
0, 1, 1, 0, 0, 1, 1, 0,
0, 1, 0, 0, 0, 0, 1, 0,
0, 1, 0, 0, 0, 0, 1, 0,
0, 1, 1, 0, 0, 1, 1, 0,
0, 0, 1, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
];
const spriteIcon = [
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 1, 1, 1, 0, 0,
0, 1, 1, 0, 1, 1, 1, 0,
0, 1, 1, 1, 1, 0, 0, 0,
0, 1, 1, 1, 0, 0, 0, 0,
0, 1, 1, 1, 1, 1, 1, 0,
0, 0, 1, 1, 1, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
];
const buttons: Array<{update: () => void, draw: () => void}> = []; const buttons: Array<{update: () => void, draw: () => void}> = [];
const makeTabButton = (tabname: TabName, x: number, y: number, icon: Array<number>) => { const makeTabButton = (tabname: TabName | "sheet", x: number, y: number, icon: Array<number>) => {
buttons.push({ buttons.push({
update() { update() {
if (mouseClick()) { if (mouseClick()) {
const {x: mouseX, y: mouseY} = mousePos(); const {x: mouseX, y: mouseY} = mousePos();
if (inRect(mouseX, mouseY, x, y, 8, 8)) { if (inRect(mouseX, mouseY, x, y, 8, 8)) {
tab = tabname; page.tab = tabname;
} }
} }
}, },
draw() { draw() {
drawIcon(x, y, icon, tab === tabname ? COLOR.YELLOW : COLOR.WHITE); drawIcon(x, y, icon, page.tab === tabname ? COLOR.YELLOW : COLOR.WHITE);
} }
}) })
} }
makeTabButton("code", 88, 0, codeIcon); // makeTabButton("code", 88, 0, codeIcon);
makeTabButton("sprite", 88+8, 0, spriteIcon); // makeTabButton("sprite", 88+8, 0, spriteIcon);
makeTabButton("sheet", 120, 0, sheetsIcon);
const update = () => { const update = () => {
buttons.forEach(button => button.update()); buttons.forEach(button => button.update());
if (tab === "code") { if (page.tab === "code") {
codetab.update(); codetab.update();
} else if (tab === "sprite") { } else if (page.tab === "spritesheet") {
spritetab.update(); spritetab.update();
} else if (page.tab === "sheet") {
viewsheets.update();
} else if (page.tab === "none") {
nonetab.update();
} }
} }
const draw = () => { const draw = () => {
clearScreen(); clearScreen();
if (tab === "code") { if (page.tab === "code") {
codetab.draw(); codetab.draw();
} else if (tab === "sprite") { } else if (page.tab === "spritesheet") {
spritetab.draw(); spritetab.draw();
} else if (page.tab === "sheet") {
viewsheets.draw();
} else if (page.tab === "none") {
nonetab.draw();
} }
fillRect(0, 0, 128, 8, COLOR.RED); fillRect(0, 0, 128, 8, COLOR.RED);
fillRect(0, 120, 128, 8, COLOR.RED); fillRect(0, 120, 128, 8, COLOR.RED);

32
icons.ts Normal file
View File

@ -0,0 +1,32 @@
export const codeIcon = [
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 1, 0, 0,
0, 1, 1, 0, 0, 1, 1, 0,
0, 1, 0, 0, 0, 0, 1, 0,
0, 1, 0, 0, 0, 0, 1, 0,
0, 1, 1, 0, 0, 1, 1, 0,
0, 0, 1, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
];
export const spriteIcon = [
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 1, 1, 1, 0, 0,
0, 1, 1, 0, 1, 1, 1, 0,
0, 1, 1, 1, 1, 0, 0, 0,
0, 1, 1, 1, 0, 0, 0, 0,
0, 1, 1, 1, 1, 1, 1, 0,
0, 0, 1, 1, 1, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
];
export const sheetsIcon = [
0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 1, 0, 0, 1, 1, 0,
0, 1, 1, 0, 0, 1, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 1, 0, 0, 1, 1, 0,
0, 1, 1, 0, 0, 1, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0,
];

View File

@ -32,7 +32,6 @@ await mainloop(async (_t) => {
edit: "repl", edit: "repl",
repl: "edit", repl: "edit",
} as const)[mode]; } as const)[mode];
console.log(`pressed escape (${mode} -> ${modeTo})`);
if (mode === "play") { if (mode === "play") {
resetRepl(); resetRepl();
} }

58
nonetab.ts Normal file
View File

@ -0,0 +1,58 @@
import { clearScreen, fillRect } from "./window.ts";
import { drawIcon } from "./builtins.ts";
import { COLOR } from "./colors.ts";
import { getSheet, setSheet } from "./sheet.ts";
import { mouseClick, mousePos } from "./mouse.ts";
import { reGridWithGap } from "./util.ts";
import { page } from "./viewsheets.ts";
import { useSpritesheet } from "./builtins.ts";
import { codeIcon, spriteIcon } from "./icons.ts";
const gridX = 8;
const gridY = 16;
const cellW = 8;
const cellH = 8;
const gapX = 8;
const gapY = 8;
const sheetTypes = ["code", "spritesheet"] as const;
const defaultSheetVal = {
code: () => "",
spritesheet: () => Array(64).fill(0).map(() => Array(64).fill(0)),
none: () =>null,
}
const update = () => {
if (mouseClick()) {
const {x: mouseX, y: mouseY} = mousePos();
const g = reGridWithGap(mouseX, mouseY, gridX, gridY, cellW, cellH, gapX, gapY);
if (g) {
const {x, y: _y} = g;
const sheetType = sheetTypes[x];
setSheet(page.activeSheet, sheetType, defaultSheetVal[sheetType]());
page.tab = getSheet(page.activeSheet).sheet_type;
}
}
}
const draw = () => {
clearScreen();
useSpritesheet(page.activeSheet);
fillRect(0, 8, 128, 112, COLOR.BLACK);
// Draw the spritesheet
sheetTypes.forEach((sheetType, i) => {
const sx = gridX+(cellW+gapX)*(i%6);
const sy = gridY+(cellH+gapY)*Math.floor(i/6);
const icon = {
code: codeIcon,
spritesheet: spriteIcon,
none: null,
}[sheetType];
drawIcon(sx, sy, icon, COLOR.BLUE);
});
}
export const nonetab = {
update,
draw,
}

View File

@ -8,6 +8,9 @@ export type Sheet = {
} | { } | {
sheet_type: "spritesheet", sheet_type: "spritesheet",
value: Array<Array<number>>, value: Array<Array<number>>,
} | {
sheet_type: "none",
value: null,
} }
export type SheetType = Sheet["sheet_type"]; export type SheetType = Sheet["sheet_type"];

View File

@ -1,22 +1,20 @@
import { clearScreen, fillRect, setPixelColor } from "./window.ts"; import { clearScreen, fillRect, setPixelColor } from "./window.ts";
import { drawSprite } from "./builtins.ts"; import { drawSprite } from "./builtins.ts";
import { COLOR } from "./colors.ts"; import { COLOR } from "./colors.ts";
import {getSheet, setSheet} from "./sheet.ts"; import { getSpriteSheet, setSheet } from "./sheet.ts";
import { mouseHeld, mousePos } from "./mouse.ts"; import { mouseHeld, mousePos } from "./mouse.ts";
import { inRect } from "./util.ts"; import { inRect, reGrid } from "./util.ts";
import { page } from "./viewsheets.ts";
import { useSpritesheet } from "./builtins.ts";
const state = { const state = {
selectedSprite: 0, selectedSprite: 0,
selectedColor: 0, selectedColor: 0,
get sprites() { get sprites() {
const {sheet_type, value} = getSheet(2); return getSpriteSheet(page.activeSheet);
if (sheet_type !== "spritesheet") {
throw "Trying to use a non-sprite sheet as a spritesheet."
}
return value;
}, },
set sprites(val) { set sprites(val) {
setSheet(0, "spritesheet", val); setSheet(page.activeSheet, "spritesheet", val);
} }
} }
@ -40,13 +38,6 @@ const sheetY = 88;
const sheetW = 16; const sheetW = 16;
const sheetH = 4; const sheetH = 4;
const reGrid = (x: number, y: number, gridX: number, gridY: number, cellW: number, cellH: number) => {
return {
x: Math.floor((x-gridX)/cellW),
y: Math.floor((y-gridY)/cellH),
}
}
const update = () => { const update = () => {
if (mouseHeld()) { if (mouseHeld()) {
const {x: mouseX, y: mouseY} = mousePos(); const {x: mouseX, y: mouseY} = mousePos();
@ -87,6 +78,7 @@ const drawTransparentRect = (x: number, y: number, w: number, h: number) => {
const draw = () => { const draw = () => {
const {sprites, selectedSprite, selectedColor} = state; const {sprites, selectedSprite, selectedColor} = state;
clearScreen(); clearScreen();
useSpritesheet(page.activeSheet);
fillRect(0, 8, 128, 112, COLOR.BROWN); fillRect(0, 8, 128, 112, COLOR.BROWN);
// Draw the palette // Draw the palette

21
util.ts
View File

@ -5,4 +5,25 @@ export const inRect = (x: number, y: number, rectX: number, rectY: number, rectW
y >= rectY && y >= rectY &&
y < rectY+rectH y < rectY+rectH
) )
}
export function reGridWithGap (x: number, y: number, gridX: number, gridY: number, cellW: number, cellH: number, gapX: number, gapY: number): {x: number, y: number} | null {
const gx = Math.floor((x-gridX)/(cellW+gapX));
const gy = Math.floor((y-gridY)/(cellH+gapY));
if (x >= gridX+(cellW+gapX)*gx+cellW || y >= gridY+(cellH+gapY)*gy+cellH) {
return null;
}
return {
x: Math.floor((x-gridX)/(cellW+gapX)),
y: Math.floor((y-gridY)/(cellH+gapY)),
}
}
export function reGrid (x: number, y: number, gridX: number, gridY: number, cellW: number, cellH: number): {x: number, y: number} {
const gx = Math.floor((x-gridX)/(cellW));
const gy = Math.floor((y-gridY)/(cellH));
return {
x: gx,
y: gy,
}
} }

56
viewsheets.ts Normal file
View File

@ -0,0 +1,56 @@
import { clearScreen, fillRect } from "./window.ts";
import { drawIcon, drawText } from "./builtins.ts";
import { COLOR } from "./colors.ts";
import { getSheet } from "./sheet.ts";
import { mouseClick, mousePos } from "./mouse.ts";
import { getCart } from "./cart.ts";
import { fontHeight } from "./font.ts";
import { codeIcon, spriteIcon } from "./icons.ts";
import { reGridWithGap } from "./util.ts";
export const page = {activeSheet: 0, tab: "sheet"};
const gridX = 8;
const gridY = 20;
const cellW = 22;
const cellH = 16;
const gapX = 8;
const gapY = 8;
const update = () => {
if (mouseClick()) {
const {x: mouseX, y: mouseY} = mousePos();
const g = reGridWithGap(mouseX, mouseY, gridX, gridY, cellW, cellH, gapX, gapY);
if (g) {
const {x, y} = g;
page.activeSheet = 4*y+x;
page.tab = getSheet(page.activeSheet).sheet_type;
}
}
}
const draw = () => {
clearScreen();
fillRect(0, 8, 128, 112, COLOR.BROWN);
// Draw the sheet grid
getCart().forEach((sheet, i) => {
const x = gridX+(cellW+gapX)*(i%4);
const y = gridY+(cellH+gapY)*Math.floor(i/4);
fillRect(x, y, cellW, cellH, i===page.activeSheet ? COLOR.PURPLE : COLOR.BLACK);
drawText(x+(cellW)/2, y+(cellH-fontHeight)/2, i.toString().padStart(2,"0"));
const icon = {
code: codeIcon,
spritesheet: spriteIcon,
none: null,
}[sheet.sheet_type];
if (icon) {
drawIcon(x+2, y+4, icon, COLOR.WHITE);
}
});
}
export const viewsheets = {
update,
draw,
}