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
be38465
initial commit of scishop
32bitkid May 20, 2024
73b1763
consolidate the render pressure when navigating the cmd stack
32bitkid May 20, 2024
7b7eb4f
more matrix math/render consolidation
32bitkid May 20, 2024
75672b8
remove debugging logger
32bitkid May 21, 2024
6166864
WIP still more work on UI
32bitkid May 24, 2024
2c06e4b
WIP more work to scishop
32bitkid May 24, 2024
9090a5c
WIP more work on line/user-input.
32bitkid May 26, 2024
a396363
WIP some more tweaks before a refactor into EditorCommands
32bitkid May 26, 2024
a73bf26
WIP refactored low-level DrawCommand stacks into EditorCommand stacks
32bitkid May 26, 2024
d6d3cf2
WIP prototyping on scishop
32bitkid May 28, 2024
dddedc5
WIP: add path editing.
32bitkid May 28, 2024
4b230f2
WIP: extract vec2 helpers into @4bitlabs/vec2
32bitkid May 28, 2024
6c9d21f
WIP: refactoring closestPoint finders
32bitkid May 29, 2024
413abbe
WIP: more core updates/features
32bitkid May 29, 2024
2e94339
WIP: fix pixel outlines on exact integer positions with floor(n) + 1
32bitkid May 29, 2024
5f6c756
WIP: allow multi-select move, though the UI doesn't support selecting it
32bitkid May 29, 2024
64b9b62
WIP: more plumbing for multiselect vertex
32bitkid May 30, 2024
b252462
WIP: updating sci0@3 and changes for the underlying DrawCommand changes
32bitkid May 30, 2024
8a11419
WIP: simplify drag-state shape
32bitkid May 30, 2024
0db24a2
WIP: implementing mutli-select vertex move
32bitkid May 30, 2024
dcc9f13
WIP: simplify stores
32bitkid May 31, 2024
2bccf5b
WIP: de-singleton-ify the store refs, use vue provide/inject instead
32bitkid May 31, 2024
849fc06
WIP: start splitting apart input-machine
32bitkid Jun 1, 2024
82f4c23
WIP: refix softener
32bitkid Jun 1, 2024
5f358b0
WIP: refactor performance impact of palette calculations
32bitkid Jun 1, 2024
6435446
WIP: implement "find" tool. *bump sci0 version*
32bitkid Jun 1, 2024
05688fe
WIP: experiments in generative art
32bitkid Jun 3, 2024
28a03fe
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