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 { 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) => {
const {sheet_type, value: sprites} = getSheet(2);
if (!spritesheet) {
return;
}
const {sheet_type, value: sprites} = getSheet(spritesheet);
if (sheet_type !== "spritesheet") {
throw "Trying to run a non-code sheet as code."
}
@ -37,6 +46,7 @@ const faux = {
resetRepl();
clearScreen();
},
sprsht: useSpritesheet,
spr: drawSprite,
txt: drawText,
rect: fillRect,

View File

@ -5,7 +5,59 @@
},
{
"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",

View File

@ -2,15 +2,16 @@ import { clearScreen, fillRect } from "./window.ts";
import { fontWidth, fontHeight } from "./font.ts";
import { drawText } from "./builtins.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 { clipboard, tokenize } from "./deps.ts";
import { getContext } from "./runcode.ts";
import { page } from "./viewsheets.ts";
const historyDebounceFrames = 20;
const state = {
history: [{code: getCodeSheet(0), anchor: 0, focus: 0}],
history: [{code: getCodeSheet(page.activeSheet), anchor: 0, focus: 0}],
historyDebounce: 0,
historyIndex: 0,
undo() {
@ -201,10 +202,10 @@ const state = {
return match[0];
},
get code() {
return getCodeSheet(0);
return getCodeSheet(page.activeSheet);
},
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 { codetab } from "./codetab.ts";
import { spritetab } from "./spritetab.ts";
import { viewsheets, page } from "./viewsheets.ts";
import { COLOR } from "./colors.ts";
import { mouseClick, mousePos } from "./mouse.ts";
import { drawIcon } from "./builtins.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";
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,
];
type TabName = SheetType; // "code" | "sprite" | "map" | "sfx" | "music" | "sheet";
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({
update() {
if (mouseClick()) {
const {x: mouseX, y: mouseY} = mousePos();
if (inRect(mouseX, mouseY, x, y, 8, 8)) {
tab = tabname;
page.tab = tabname;
}
}
},
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("sprite", 88+8, 0, spriteIcon);
// makeTabButton("code", 88, 0, codeIcon);
// makeTabButton("sprite", 88+8, 0, spriteIcon);
makeTabButton("sheet", 120, 0, sheetsIcon);
const update = () => {
buttons.forEach(button => button.update());
if (tab === "code") {
if (page.tab === "code") {
codetab.update();
} else if (tab === "sprite") {
} else if (page.tab === "spritesheet") {
spritetab.update();
} else if (page.tab === "sheet") {
viewsheets.update();
} else if (page.tab === "none") {
nonetab.update();
}
}
const draw = () => {
clearScreen();
if (tab === "code") {
if (page.tab === "code") {
codetab.draw();
} else if (tab === "sprite") {
} else if (page.tab === "spritesheet") {
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, 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",
repl: "edit",
} as const)[mode];
console.log(`pressed escape (${mode} -> ${modeTo})`);
if (mode === "play") {
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",
value: Array<Array<number>>,
} | {
sheet_type: "none",
value: null,
}
export type SheetType = Sheet["sheet_type"];

View File

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