Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
b7a954c
initial commit of scishop
32bitkid May 20, 2024
e0e05b4
consolidate the render pressure when navigating the cmd stack
32bitkid May 20, 2024
051af62
more matrix math/render consolidation
32bitkid May 20, 2024
9844e04
remove debugging logger
32bitkid May 21, 2024
045782a
WIP still more work on UI
32bitkid May 24, 2024
7396f5c
WIP more work to scishop
32bitkid May 24, 2024
8869d5c
WIP more work on line/user-input.
32bitkid May 26, 2024
b7b734f
WIP some more tweaks before a refactor into EditorCommands
32bitkid May 26, 2024
3f8289c
WIP refactored low-level DrawCommand stacks into EditorCommand stacks
32bitkid May 26, 2024
e9aa33f
WIP prototyping on scishop
32bitkid May 28, 2024
d41b3a8
WIP: add path editing.
32bitkid May 28, 2024
987d16e
WIP: extract vec2 helpers into @4bitlabs/vec2
32bitkid May 28, 2024
0e5bc0d
WIP: refactoring closestPoint finders
32bitkid May 29, 2024
5ad6a1f
WIP: more core updates/features
32bitkid May 29, 2024
a4f03cb
WIP: fix pixel outlines on exact integer positions with floor(n) + 1
32bitkid May 29, 2024
ca57ece
WIP: allow multi-select move, though the UI doesn't support selecting it
32bitkid May 29, 2024
f228b37
WIP: more plumbing for multiselect vertex
32bitkid May 30, 2024
6ce9731
WIP: updating sci0@3 and changes for the underlying DrawCommand changes
32bitkid May 30, 2024
8b8132a
WIP: simplify drag-state shape
32bitkid May 30, 2024
1133fd1
WIP: implementing mutli-select vertex move
32bitkid May 30, 2024
d296871
WIP: simplify stores
32bitkid May 31, 2024
835460a
WIP: de-singleton-ify the store refs, use vue provide/inject instead
32bitkid May 31, 2024
cef45f8
WIP: start splitting apart input-machine
32bitkid Jun 1, 2024
46e74d4
WIP: refix softener
32bitkid Jun 1, 2024
72d92b5
WIP: refactor performance impact of palette calculations
32bitkid Jun 1, 2024
5725915
WIP: implement "find" tool. *bump sci0 version*
32bitkid Jun 1, 2024
29f34f5
WIP: experiments in generative art
32bitkid Jun 3, 2024
6e4f255
WIP: updating and cleaning up dependencies
32bitkid Jul 4, 2024
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
26 changes: 26 additions & 0 deletions apps/scishop/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

src/data/tmp*.json
3 changes: 3 additions & 0 deletions apps/scishop/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# scishop

Create, edit and export `Sci0` & `Sci01` PIC resources.
12 changes: 12 additions & 0 deletions apps/scishop/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>scishop</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="./src/main.ts"></script>
</body>
</html>
27 changes: 27 additions & 0 deletions apps/scishop/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"name": "scishop",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vue-tsc && vite build",
"preview": "vite preview"
},
"dependencies": {
"@4bitlabs/sci0": "^4.0.1",
"@4bitlabs/color": "^2.1.5",
"@4bitlabs/color-space": "^1.2.3",
"@4bitlabs/image": "^3.3.11",
"@4bitlabs/vec2": "^1.2.0",
"fast-deep-equal": "^3.1.3",
"vue": "^3.4.21",
"transformation-matrix": "^2.16.1"
},
"devDependencies": {
"@vitejs/plugin-vue": "^5.0.4",
"typescript": "^5.2.2",
"vite": "^5.2.0",
"vue-tsc": "^2.0.6"
}
}
18 changes: 18 additions & 0 deletions apps/scishop/src/App.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<script setup lang="ts">
import Header from './components/Header.vue';
import Toolbar from './components/Toolbar.vue';
import SideBar from './components/Sidebar.vue';
import Stage from './components/Stage.vue';
import StatusBar from './components/StatusBar.vue';
import { useAppStoreProvider } from './data/useAppStoreProvider.ts';

useAppStoreProvider();
</script>

<template>
<Stage />
<Toolbar />
<SideBar />
<StatusBar />
<Header />
</template>
8 changes: 8 additions & 0 deletions apps/scishop/src/assets/cursor-pen-minus.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions apps/scishop/src/assets/cursor-pen-plus.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions apps/scishop/src/assets/cursor-pen-star.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions apps/scishop/src/assets/cursor-pen.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
59 changes: 59 additions & 0 deletions apps/scishop/src/components/Header.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<script setup lang="ts"></script>

<template>
<div :class="$style.header">
<hr :class="$style.spacer" />
<div :class="$style.pal">
Pal
<button type="button">1</button>
<button type="button">2</button>
<button type="button">3</button>
<button type="button">4</button>
</div>
</div>

<Teleport to="body"> </Teleport>
</template>

<style module>
.header {
background-color: var(--clr-surface--default);
color: var(--clr-ink);
grid-area: header;
display: flex;
align-items: center;
gap: 1ch;
padding-inline: 1ch;
}

.spacer {
flex-grow: 1;
width: auto;
border: 0;
}

.pal {
align-self: center;
height: 75%;
}

.pal button {
aspect-ratio: 9 / 11;
height: 90%;
text-align: center;

border-top: 1px solid var(--clr-surface-200);
border-bottom: 1px solid var(--clr-surface-200);
border-right: 1px solid var(--clr-surface-200);
&:first-of-type {
border-left: 1px solid var(--clr-surface-200);
border-top-left-radius: 0.25lh;
border-bottom-left-radius: 0.25lh;
}

&:last-of-type {
border-top-right-radius: 0.25lh;
border-bottom-right-radius: 0.25lh;
}
}
</style>
173 changes: 173 additions & 0 deletions apps/scishop/src/components/LayerNavigator.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
<script setup lang="ts">
import { computed, unref } from 'vue';
import type { Component } from 'vue';
import GenericCommandItem from './command-items/GenericCommandItem.vue';
import PolyLineCommandItem from './command-items/PolyLineCommandItem.vue';
import FillCommandItem from './command-items/FillCommandItem.vue';
import BrushCommandItem from './command-items/BrushCommandItem.vue';
import SetPaletteCommand from './command-items/SetPaletteCommand.vue';
import {
DrawCommand,
FillCommand,
PolylineCommand,
BrushCommand,
} from '@4bitlabs/sci0';
import { mustInject } from '../data/mustInject.ts';
import {
drawStateKey,
layersKey,
paletteKey,
pointersKey,
} from '../data/keys.ts';

const { raw: rawDrawState } = mustInject(drawStateKey);
const layersRef = mustInject(layersKey);
const { topIdx: topIdxRef, selectedIdx: selectedIdxRef } =
mustInject(pointersKey);
const { resolvePaletteAtIdx } = mustInject(paletteKey);

const stack = computed(() => Array.from(unref(layersRef).entries()).reverse());

const component = new Map<string, Component>([
['SET_PALETTE', SetPaletteCommand],
['UPDATE_PALETTE', GenericCommandItem],
['BRUSH', BrushCommandItem],
['FILL', FillCommandItem],
['PLINE', PolyLineCommandItem],
['CEL', GenericCommandItem],
['group', GenericCommandItem],
]);

function isHasDrawModes(
it: DrawCommand,
): it is FillCommand | PolylineCommand | BrushCommand {
return it[0] === 'FILL' || it[0] === 'PLINE' || it[0] === 'BRUSH';
}

const handleClick = (e: MouseEvent, idx: number) => {
if (e.shiftKey) {
topIdxRef.value = idx + 1;
}

selectedIdxRef.value = unref(selectedIdxRef) !== idx ? idx : null;
const ecmd = unref(layersRef)[idx];
const lastCmd = ecmd.commands.findLast(isHasDrawModes);
if (lastCmd) {
const [, options] = lastCmd;
const [drawMode, drawCodes] = options;
rawDrawState.value = [drawMode, ...drawCodes];
}
};
</script>

<template>
<menu :class="$style.list">
<li :class="$style.head">
<div>Layer</div>
<div>Tool</div>
<div>V</div>
<div>P</div>
<div>C</div>
</li>
<component
v-for="[idx, { id, type, commands }] in stack"
:key="id"
:is="component.get(type) ?? GenericCommandItem"
:command="commands[0]"
:pals="resolvePaletteAtIdx(idx)"
:class="[
$style.item,
idx === selectedIdxRef && $style.current,
idx >= topIdxRef && $style.hidden,
idx === topIdxRef - 1 && $style.top,
]"
@click="handleClick($event, idx)"
/>
</menu>
</template>

<style module>
.list {
--lnc-item-height: 32px;
box-sizing: border-box;
display: grid;
grid-template-columns: 1fr 1.4rem 1rem 1rem 1px;
grid-template-rows: auto;
grid-auto-rows: var(--lnc-item-height);
column-gap: 0.5ch;
overflow-x: clip;
overflow-y: auto;
scrollbar-width: thin;
align-items: center;
align-content: start;
padding-bottom: 0.5lh;
background-image: var(--transparent-img);
background-color: var(--clr-surface--default);
min-height: 15rem;
}

.head {
display: grid;
grid-template-columns: subgrid;
position: sticky;
top: 0;
background-color: var(--clr-surface--default);
grid-column: 1 / -1;
box-shadow: 0 0.125em 0.5em rgba(0 0 0 / 10%);
z-index: 1;
}

.head :nth-child(1) {
font-size: 0.85rem;
font-weight: bold;
padding-inline-start: 0.5ch;
padding-block: 0.5lh 0.5ch;
grid-column: 1 / -1;
border-bottom: 1px solid var(--clr-surface-200);
}

.head :nth-child(n + 2) {
padding-block: 0.5lh;
padding-inline-start: 0.5ch;
font: normal normal 0.75em monospace;
font-weight: bold;
}

.head :nth-child(n + 3) {
text-align: center;
}

.item {
font: normal normal 0.75em monospace;
display: grid;
grid-column: 1 / -1;
grid-template-columns: subgrid;
padding-block: calc(0.5lh + 1px) 0.5lh;
padding-inline-start: 0.5ch;
border-top: 1px solid #ddd;
cursor: pointer;
user-select: none;
align-content: center;
background-color: var(--clr-surface--default);
background-clip: padding-box;
height: var(--lnc-item-height);
box-sizing: border-box;
}

.item:last-of-type {
box-shadow: 0 0.125em 0.5em rgba(0 0 0 / 10%);
}

.top {
padding-block: 0.5lh;
border-top: 2px dashed var(--clr-primary-700);
}

.current {
background-color: var(--clr-primary-800);
}

.hidden > * {
opacity: 0.25;
}
</style>
Loading