From bc4d21e252494cc4d0a6dbe4ae21b7c12f7a580a Mon Sep 17 00:00:00 2001 From: "Lu[ke] Wilson" Date: Thu, 4 Jan 2024 23:13:01 +0000 Subject: [PATCH 01/18] preview cell's kids --- source/arroost/components/infinite.js | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/source/arroost/components/infinite.js b/source/arroost/components/infinite.js index b78a961..3526e3b 100644 --- a/source/arroost/components/infinite.js +++ b/source/arroost/components/infinite.js @@ -10,7 +10,7 @@ import { Style } from "./style.js" import { c, getCell, getTemplate, iterateCells, iterateWires, t } from "../../nogan/nogan.js" import { CHILD_SCALE, PARENT_SCALE, ZOOMING_IN_THRESHOLD, ZOOM_IN_THRESHOLD } from "../unit.js" import { ArrowOfCreation } from "../entities/arrows/creation.js" -import { CELL_CONSTRUCTORS, WIRE_CONSTRUCTOR } from "./tunnel.js" +import { CELL_CONSTRUCTORS, Tunnel, WIRE_CONSTRUCTOR } from "./tunnel.js" import { Entity } from "../entities/entity.js" import { EASE, lerp } from "../../../libraries/lerp.js" import { Ellipse } from "../entities/shapes/ellipse.js" @@ -89,7 +89,9 @@ export class Infinite extends Component { this.use(() => { switch (this.state.get()) { case "zooming-in": { - this.appendContentsForLevel(shared.level) + if (!this.dom?.input.entity?.tunnel) throw new Error("Missing tunnel") + const tunnel = this.dom.input.entity.tunnel + this.appendContentsForLevel(tunnel.id) break } case "none": { @@ -112,14 +114,21 @@ export class Infinite extends Component { } /** - * @param {number} level + * @param {number} newLevel */ - appendContentsForLevel(level) { + appendContentsForLevel(newLevel) { const cellEntities = [] const wireEntities = [] + const oldLevelCell = getCell(shared.nogan, shared.level) + const newLevelCell = getCell(shared.nogan, newLevel) + + if (!oldLevelCell || !newLevelCell) { + throw new Error("Missing level cell - this shouldn't happen") + } + for (const cell of iterateCells(shared.nogan)) { - if (cell.parent !== level) continue + if (cell.parent !== newLevel) continue const entity = CELL_CONSTRUCTORS[cell.type]({ id: cell.id, position: cell.position, @@ -139,7 +148,7 @@ export class Infinite extends Component { for (const wire of iterateWires(shared.nogan)) { const cells = wire.cells.map((id) => getCell(shared.nogan, id)) - if (!cells.every((cell) => cell?.parent === level)) continue + if (!cells.every((cell) => cell?.parent === newLevel)) continue const entity = WIRE_CONSTRUCTOR({ id: wire.id, From fded1bd151c39d6ed749e8efdbb486d8e672abd6 Mon Sep 17 00:00:00 2001 From: "Lu[ke] Wilson" Date: Thu, 4 Jan 2024 23:18:23 +0000 Subject: [PATCH 02/18] zoom in --- source/arroost/entities/scene.js | 48 ++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/source/arroost/entities/scene.js b/source/arroost/entities/scene.js index 0be2ef7..0196f3e 100644 --- a/source/arroost/entities/scene.js +++ b/source/arroost/entities/scene.js @@ -20,7 +20,7 @@ import { replenishUnlocks } from "./unlock.js" import { Title } from "./title.js" import { TextHtml } from "./shapes/text-html.js" import { Transform } from "../components/transform.js" -import { Tunnel } from "../components/tunnel.js" +import { CELL_CONSTRUCTORS, Tunnel, WIRE_CONSTRUCTOR } from "../components/tunnel.js" import { CHILD_SCALE, PARENT_SCALE, @@ -28,7 +28,7 @@ import { ZOOMING_OUT_THRESHOLD, ZOOM_IN_THRESHOLD, } from "../unit.js" -import { c, getCell, t } from "../../nogan/nogan.js" +import { c, getCell, getTemplate, iterateCells, iterateWires, t } from "../../nogan/nogan.js" import { Infinite } from "../components/infinite.js" import { checkUnderPointer, triggerSomethingHasMoved } from "../machines/hover.js" import { Marker } from "./debug/marker.js" @@ -373,7 +373,49 @@ export class Scene extends Entity { replaceLayer(tunnel) { for (const layerName of this.sceneLayerNames) { const layer = this.layer[layerName] - // layer.dispose() + layer.dispose() + } + + shared.level = tunnel.id + + this.recreateSceneLayers() + + const wireEntities = [] + const cellEntities = [] + + for (const cell of iterateCells(shared.nogan)) { + if (cell.parent !== shared.level) continue + const entity = CELL_CONSTRUCTORS[cell.type]({ + id: cell.id, + position: cell.position, + template: getTemplate(cell), + }) + + if (!entity) continue + cellEntities.push(entity) + } + + for (const wire of iterateWires(shared.nogan)) { + const cells = wire.cells.map((id) => getCell(shared.nogan, id)) + if (!cells.every((cell) => cell?.parent === shared.level)) continue + + const entity = WIRE_CONSTRUCTOR({ + id: wire.id, + colour: wire.colour, + timing: wire.timing, + source: wire.source, + target: wire.target, + preview: false, + }) + wireEntities.push(entity) + } + + for (const entity of wireEntities) { + this.dom?.append(entity.dom) + } + + for (const entity of cellEntities) { + this.dom?.append(entity.dom) } const { center } = this.bounds.get() From 481328a7f322ddce21cf3848d44b244d06fcfb40 Mon Sep 17 00:00:00 2001 From: "Lu[ke] Wilson" Date: Thu, 4 Jan 2024 23:24:30 +0000 Subject: [PATCH 03/18] auto create --- source/arroost/components/infinite.js | 10 ++++++++++ source/arroost/entities/arrows/creation.js | 3 ++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/source/arroost/components/infinite.js b/source/arroost/components/infinite.js index 3526e3b..9ea0543 100644 --- a/source/arroost/components/infinite.js +++ b/source/arroost/components/infinite.js @@ -165,6 +165,16 @@ export class Infinite extends Component { } } + if (cellEntities.length === 0) { + const entity = new ArrowOfCreation({ + position: [0, 0], + preview: true, + level: newLevel, + }) + cellEntities.push(entity) + this.previews.add(entity) + } + const background = new Ellipse() background.dom.style.fill.set(BLACK.toString()) diff --git a/source/arroost/entities/arrows/creation.js b/source/arroost/entities/arrows/creation.js index 089f158..f67cb87 100644 --- a/source/arroost/entities/arrows/creation.js +++ b/source/arroost/entities/arrows/creation.js @@ -25,7 +25,8 @@ export class ArrowOfCreation extends Entity { pulling = this.use(false) constructor({ - id = createCell(shared.nogan, { parent: shared.level, type: "creation" }).id, + level = shared.level, + id = createCell(shared.nogan, { parent: level, type: "creation" }).id, position = t([0, 0]), preview = false, }) { From e09d1a40f8c563f6f4ebf74f3d040caf1205f63f Mon Sep 17 00:00:00 2001 From: "Lu[ke] Wilson" Date: Thu, 4 Jan 2024 23:33:28 +0000 Subject: [PATCH 04/18] spawn defaults in triangle --- source/arroost/components/infinite.js | 51 +++++++++++++++++-- source/arroost/entities/arrows/connection.js | 3 +- source/arroost/entities/arrows/destruction.js | 3 +- 3 files changed, 50 insertions(+), 7 deletions(-) diff --git a/source/arroost/components/infinite.js b/source/arroost/components/infinite.js index 9ea0543..b2f954d 100644 --- a/source/arroost/components/infinite.js +++ b/source/arroost/components/infinite.js @@ -8,12 +8,20 @@ import { Transform } from "./transform.js" import { Movement } from "./movement.js" import { Style } from "./style.js" import { c, getCell, getTemplate, iterateCells, iterateWires, t } from "../../nogan/nogan.js" -import { CHILD_SCALE, PARENT_SCALE, ZOOMING_IN_THRESHOLD, ZOOM_IN_THRESHOLD } from "../unit.js" +import { + CHILD_SCALE, + FULL, + PARENT_SCALE, + ZOOMING_IN_THRESHOLD, + ZOOM_IN_THRESHOLD, +} from "../unit.js" import { ArrowOfCreation } from "../entities/arrows/creation.js" import { CELL_CONSTRUCTORS, Tunnel, WIRE_CONSTRUCTOR } from "./tunnel.js" import { Entity } from "../entities/entity.js" import { EASE, lerp } from "../../../libraries/lerp.js" import { Ellipse } from "../entities/shapes/ellipse.js" +import { ArrowOfConnection } from "../entities/arrows/connection.js" +import { ArrowOfDestruction } from "../entities/arrows/destruction.js" export function ilerp(x, a, b) { return (x - a) / (b - a) @@ -166,13 +174,46 @@ export class Infinite extends Component { } if (cellEntities.length === 0) { - const entity = new ArrowOfCreation({ - position: [0, 0], + const distance = FULL * 2 + const angle = Math.random() * Math.PI * 2 + + // Three points of an equilateral triangle + /** @type {[number, number][]} */ + const positions = [ + [distance * Math.cos(angle), distance * Math.sin(angle)], + [ + distance * Math.cos(angle + (2 * Math.PI) / 3), + distance * Math.sin(angle + (2 * Math.PI) / 3), + ], + [ + distance * Math.cos(angle + (4 * Math.PI) / 3), + distance * Math.sin(angle + (4 * Math.PI) / 3), + ], + ] + + const entity1 = new ArrowOfCreation({ + position: positions[0], preview: true, level: newLevel, }) - cellEntities.push(entity) - this.previews.add(entity) + cellEntities.push(entity1) + this.previews.add(entity1) + + const entity2 = new ArrowOfConnection({ + position: positions[1], + preview: true, + level: newLevel, + }) + cellEntities.push(entity2) + this.previews.add(entity2) + + const entity3 = new ArrowOfDestruction({ + position: positions[2], + preview: true, + level: newLevel, + }) + cellEntities.push(entity3) + this.previews.add(entity3) } const background = new Ellipse() diff --git a/source/arroost/entities/arrows/connection.js b/source/arroost/entities/arrows/connection.js index 1760cbe..40a6a60 100644 --- a/source/arroost/entities/arrows/connection.js +++ b/source/arroost/entities/arrows/connection.js @@ -23,7 +23,8 @@ export class ArrowOfConnection extends Entity { pulling = this.use(false) constructor({ - id = createCell(shared.nogan, { parent: shared.level, type: "connection" }).id, + level = shared.level, + id = createCell(shared.nogan, { parent: level, type: "connection" }).id, position = t([0, 0]), preview = false, }) { diff --git a/source/arroost/entities/arrows/destruction.js b/source/arroost/entities/arrows/destruction.js index 52e80db..3a7e248 100644 --- a/source/arroost/entities/arrows/destruction.js +++ b/source/arroost/entities/arrows/destruction.js @@ -34,7 +34,8 @@ export class ArrowOfDestruction extends Entity { pulling = this.use(false) constructor({ - id = createCell(shared.nogan, { parent: shared.level, type: "destruction" }).id, + level = shared.level, + id = createCell(shared.nogan, { parent: level, type: "destruction" }).id, position = t([0, 0]), preview = false, }) { From fa46289ebbd4107d0f7059392ac5ec5b900afc48 Mon Sep 17 00:00:00 2001 From: "Lu[ke] Wilson" Date: Thu, 4 Jan 2024 23:58:57 +0000 Subject: [PATCH 05/18] append replacement world to correct layers --- source/arroost/entities/scene.js | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/source/arroost/entities/scene.js b/source/arroost/entities/scene.js index 0196f3e..199cb28 100644 --- a/source/arroost/entities/scene.js +++ b/source/arroost/entities/scene.js @@ -32,6 +32,8 @@ import { c, getCell, getTemplate, iterateCells, iterateWires, t } from "../../no import { Infinite } from "../components/infinite.js" import { checkUnderPointer, triggerSomethingHasMoved } from "../machines/hover.js" import { Marker } from "./debug/marker.js" +import { ArrowOfTiming } from "./arrows/timing.js" +import { ArrowOfColour } from "./arrows/colour.js" const ZOOM_FRICTION = 0.75 @@ -306,6 +308,9 @@ export class Scene extends Entity { let distanceFromScreenCenter = Infinity let closestTunnel = null for (const tunnel of Tunnel.inViewInfiniteTunnels.values()) { + const cell = getCell(shared.nogan, tunnel.id) + if (!cell) throw new Error("No cell found for tunnel") + if (cell.parent !== shared.level) continue const { transform } = tunnel.entity.dom const position = transform.position.get() const distance = distanceBetween(position, this.bounds.get().center) @@ -411,11 +416,17 @@ export class Scene extends Entity { } for (const entity of wireEntities) { - this.dom?.append(entity.dom) + this.layer.wire.append(entity.dom) } for (const entity of cellEntities) { - this.dom?.append(entity.dom) + if (entity instanceof ArrowOfTiming) { + this.layer.timing.append(entity.dom) + } else if (entity instanceof ArrowOfColour) { + this.layer.timing.append(entity.dom) + } else { + this.layer.cell.append(entity.dom) + } } const { center } = this.bounds.get() From 694e1910b67486e8c8720c847a9f0072e0ecdd2d Mon Sep 17 00:00:00 2001 From: "Lu[ke] Wilson" Date: Fri, 5 Jan 2024 08:30:34 +0000 Subject: [PATCH 06/18] come out and in --- source/arroost/components/infinite.js | 1 + source/arroost/entities/scene.js | 93 ++++++++++++++++++--------- 2 files changed, 65 insertions(+), 29 deletions(-) diff --git a/source/arroost/components/infinite.js b/source/arroost/components/infinite.js index b2f954d..e37d2e1 100644 --- a/source/arroost/components/infinite.js +++ b/source/arroost/components/infinite.js @@ -217,6 +217,7 @@ export class Infinite extends Component { } const background = new Ellipse() + this.background = background background.dom.style.fill.set(BLACK.toString()) const parent = this.parent diff --git a/source/arroost/entities/scene.js b/source/arroost/entities/scene.js index 199cb28..15731a5 100644 --- a/source/arroost/entities/scene.js +++ b/source/arroost/entities/scene.js @@ -385,7 +385,66 @@ export class Scene extends Entity { this.recreateSceneLayers() + this.rebuildWorldFromNogan() + + const { center } = this.bounds.get() + const targetPosition = tunnel.entity.dom.transform.absolutePosition.get() + const position = scale(subtract(center, targetPosition), PARENT_SCALE) + + const zoomDiff = shared.scene.dom.transform.scale.get().x - ZOOM_IN_THRESHOLD + this.setZoom((ZOOM_IN_THRESHOLD + zoomDiff) * CHILD_SCALE) + this.setCameraCenter(position) + this.infiniteTarget.get()?.infinite.state.set("none") + this.infiniteTarget.set(null) + checkUnderPointer() + // this.recreateSceneLayers() + // shared.level = tunnel.id + } + + replaceLayerBackwards() { + for (const layerName of this.sceneLayerNames) { + const layer = this.layer[layerName] + layer.dispose() + } + + const oldLevelCell = getCell(shared.nogan, shared.level) + if (!oldLevelCell) throw new Error("Missing level cell - this shouldn't happen") + shared.level = oldLevelCell.parent + + let cellToComeOutOf = oldLevelCell.id + // If we're at the top level, just find any cell on the top level + if (shared.level === 0) { + for (const cell of iterateCells(shared.nogan)) { + if (cell.id === 0) continue + if (cell.parent === 0) { + cellToComeOutOf = cell.id + break + } + } + } + + this.recreateSceneLayers() + this.rebuildWorldFromNogan() + + const { center } = this.bounds.get() + const cell = getCell(shared.nogan, cellToComeOutOf) + if (!cell) { + return + // throw new Error("Couldn't find cell to come out of") + } + + const position = add(cell.position, scale(center, CHILD_SCALE)) + const zoomDiff = shared.scene.dom.transform.scale.get().x - ZOOMING_OUT_THRESHOLD + const zoom = (ZOOMING_OUT_THRESHOLD + zoomDiff) * PARENT_SCALE + this.dom.transform.scale.set([zoom, zoom]) + this.setCameraCenter(position) + this.dealWithInfinites() + } + + rebuildWorldFromNogan() { const wireEntities = [] + + /** @type { (Entity & {dom: Dom; infinite?: Infinite})[] } */ const cellEntities = [] for (const cell of iterateCells(shared.nogan)) { @@ -426,37 +485,13 @@ export class Scene extends Entity { this.layer.timing.append(entity.dom) } else { this.layer.cell.append(entity.dom) + if (entity.infinite) { + // entity.infinite.background?.dom.style.sendToBack() + // entity.infinite.dom?.style.bringToFront() + entity.dom.style.bringToFront() + } } } - - const { center } = this.bounds.get() - const targetPosition = tunnel.entity.dom.transform.absolutePosition.get() - const position = scale(subtract(center, targetPosition), PARENT_SCALE) - - const zoomDiff = shared.scene.dom.transform.scale.get().x - ZOOM_IN_THRESHOLD - this.setZoom((ZOOM_IN_THRESHOLD + zoomDiff) * CHILD_SCALE) - this.setCameraCenter(position) - this.infiniteTarget.get()?.infinite.state.set("none") - this.infiniteTarget.set(null) - checkUnderPointer() - // this.recreateSceneLayers() - // shared.level = tunnel.id - } - - replaceLayerBackwards() { - const { center } = this.bounds.get() - const cell = getCell(shared.nogan, 1) - if (!cell) { - return - // throw new Error("Couldn't find cell to come out of") - } - - const position = add(cell.position, scale(center, CHILD_SCALE)) - const zoomDiff = shared.scene.dom.transform.scale.get().x - ZOOMING_OUT_THRESHOLD - const zoom = (ZOOMING_OUT_THRESHOLD + zoomDiff) * PARENT_SCALE - this.dom.transform.scale.set([zoom, zoom]) - this.setCameraCenter(position) - this.dealWithInfinites() } } From 55a1ab01220a16f0cdcc899f204041ae8984f16c Mon Sep 17 00:00:00 2001 From: "Lu[ke] Wilson" Date: Fri, 5 Jan 2024 08:36:07 +0000 Subject: [PATCH 07/18] fix wire constructo --- source/arroost/components/tunnel.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/arroost/components/tunnel.js b/source/arroost/components/tunnel.js index 9808823..2979052 100644 --- a/source/arroost/components/tunnel.js +++ b/source/arroost/components/tunnel.js @@ -457,8 +457,9 @@ export const CELL_CONSTRUCTORS = { // Must be called only after all relevant cells have been created export const WIRE_CONSTRUCTOR = ({ id, colour, timing, source, target, preview }) => { - const targetTunnel = Tunnel.get(target, Tunnel.tunnelPreviews) - const sourceTunnel = Tunnel.get(source, Tunnel.tunnelPreviews) + const store = preview ? Tunnel.tunnelPreviews : Tunnel.tunnels + const targetTunnel = Tunnel.get(target, store) + const sourceTunnel = Tunnel.get(source, store) const targetEntity = targetTunnel?.entity const sourceEntity = sourceTunnel?.entity From afe6261cd38d19188ad9b25c2e391dd2d00d3d96 Mon Sep 17 00:00:00 2001 From: "Lu[ke] Wilson" Date: Fri, 5 Jan 2024 08:41:02 +0000 Subject: [PATCH 08/18] fix tool --- source/arroost/entities/tool.js | 1 + 1 file changed, 1 insertion(+) diff --git a/source/arroost/entities/tool.js b/source/arroost/entities/tool.js index c580775..ff50564 100644 --- a/source/arroost/entities/tool.js +++ b/source/arroost/entities/tool.js @@ -14,6 +14,7 @@ export function selectTool(type) { let nearestDistance = Infinity for (const cell of iterateCells(shared.nogan)) { if (cell.type !== type) continue + if (cell.parent !== shared.level) continue const distance = distanceBetween(cell.position, pointer) if (distance < nearestDistance) { nearestDistance = distance From 833caed93dabf6526d1dfb147f8012c4905d29f0 Mon Sep 17 00:00:00 2001 From: "Lu[ke] Wilson" Date: Fri, 5 Jan 2024 08:54:18 +0000 Subject: [PATCH 09/18] dispose --- source/arroost/components/tunnel.js | 18 ++++++++++++++++-- source/arroost/entities/scene.js | 10 +++++++++- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/source/arroost/components/tunnel.js b/source/arroost/components/tunnel.js index 2979052..3c1f78a 100644 --- a/source/arroost/components/tunnel.js +++ b/source/arroost/components/tunnel.js @@ -56,6 +56,17 @@ export class Tunnel extends Component { */ static inViewInfiniteTunnels = new Set() + static purgeOtherLevelInfiniteTunnels() { + for (const tunnel of Tunnel.inViewInfiniteTunnels) { + const cell = getCell(shared.nogan, tunnel.id) + if (!cell) throw new Error(`Tunnel: Can't find cell ${tunnel.id}`) + if (cell.parent !== shared.level) { + tunnel.entity.dispose() + Tunnel.inViewInfiniteTunnels.delete(tunnel) + } + } + } + /** * @param {Operation[]} operations */ @@ -229,10 +240,11 @@ export class Tunnel extends Component { /** * @param {CellId | WireId} id * @param {Map} store + * @param {boolean} quiet */ - static delete(id, store = Tunnel.tunnels) { + static delete(id, store = Tunnel.tunnels, quiet = false) { const tunnel = Tunnel.get(id, store) - if (!tunnel) throw new Error(`Tunnel: Can't find tunnel ${id} to delete`) + if (!tunnel && !quiet) throw new Error(`Tunnel: Can't find tunnel ${id} to delete`) store.delete(id) if (store === Tunnel.tunnels) { @@ -478,3 +490,5 @@ export const WIRE_CONSTRUCTOR = ({ id, colour, timing, source, target, preview } preview, }) } + +window["Tunnel"] = Tunnel diff --git a/source/arroost/entities/scene.js b/source/arroost/entities/scene.js index 15731a5..de1237f 100644 --- a/source/arroost/entities/scene.js +++ b/source/arroost/entities/scene.js @@ -396,6 +396,7 @@ export class Scene extends Entity { this.setCameraCenter(position) this.infiniteTarget.get()?.infinite.state.set("none") this.infiniteTarget.set(null) + Tunnel.purgeOtherLevelInfiniteTunnels() checkUnderPointer() // this.recreateSceneLayers() // shared.level = tunnel.id @@ -414,6 +415,11 @@ export class Scene extends Entity { let cellToComeOutOf = oldLevelCell.id // If we're at the top level, just find any cell on the top level if (shared.level === 0) { + // Purge everything, because we're gonna remake it + shared.level = NaN + Tunnel.purgeOtherLevelInfiniteTunnels() + shared.level = 0 + for (const cell of iterateCells(shared.nogan)) { if (cell.id === 0) continue if (cell.parent === 0) { @@ -429,6 +435,7 @@ export class Scene extends Entity { const { center } = this.bounds.get() const cell = getCell(shared.nogan, cellToComeOutOf) if (!cell) { + console.warn("Couldn't find cell to come out of") return // throw new Error("Couldn't find cell to come out of") } @@ -438,6 +445,7 @@ export class Scene extends Entity { const zoom = (ZOOMING_OUT_THRESHOLD + zoomDiff) * PARENT_SCALE this.dom.transform.scale.set([zoom, zoom]) this.setCameraCenter(position) + Tunnel.purgeOtherLevelInfiniteTunnels() this.dealWithInfinites() } @@ -486,7 +494,7 @@ export class Scene extends Entity { } else { this.layer.cell.append(entity.dom) if (entity.infinite) { - // entity.infinite.background?.dom.style.sendToBack() + entity.infinite.background?.dom.style.sendToBack() // entity.infinite.dom?.style.bringToFront() entity.dom.style.bringToFront() } From 8600b8574a2515534c07f4a55d3720557007eab2 Mon Sep 17 00:00:00 2001 From: "Lu[ke] Wilson" Date: Fri, 5 Jan 2024 08:59:08 +0000 Subject: [PATCH 10/18] purge tunnels --- source/arroost/components/tunnel.js | 2 +- source/arroost/entities/scene.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/arroost/components/tunnel.js b/source/arroost/components/tunnel.js index 3c1f78a..b027171 100644 --- a/source/arroost/components/tunnel.js +++ b/source/arroost/components/tunnel.js @@ -265,7 +265,7 @@ export class Tunnel extends Component { dispose() { super.dispose() const store = this.isPreview ? Tunnel.tunnelPreviews : Tunnel.tunnels - Tunnel.delete(this.id, store) + Tunnel.delete(this.id, store, true) } /** diff --git a/source/arroost/entities/scene.js b/source/arroost/entities/scene.js index de1237f..1a95186 100644 --- a/source/arroost/entities/scene.js +++ b/source/arroost/entities/scene.js @@ -414,7 +414,7 @@ export class Scene extends Entity { let cellToComeOutOf = oldLevelCell.id // If we're at the top level, just find any cell on the top level - if (shared.level === 0) { + if (shared.level === 0 && oldLevelCell.id === 0) { // Purge everything, because we're gonna remake it shared.level = NaN Tunnel.purgeOtherLevelInfiniteTunnels() @@ -429,6 +429,7 @@ export class Scene extends Entity { } } + Tunnel.purgeOtherLevelInfiniteTunnels() this.recreateSceneLayers() this.rebuildWorldFromNogan() @@ -445,7 +446,6 @@ export class Scene extends Entity { const zoom = (ZOOMING_OUT_THRESHOLD + zoomDiff) * PARENT_SCALE this.dom.transform.scale.set([zoom, zoom]) this.setCameraCenter(position) - Tunnel.purgeOtherLevelInfiniteTunnels() this.dealWithInfinites() } From 611234c1db0d839fec3c505e6b54dcaa062e1317 Mon Sep 17 00:00:00 2001 From: "Lu[ke] Wilson" Date: Fri, 5 Jan 2024 09:19:18 +0000 Subject: [PATCH 11/18] purge more tunnels --- source/arroost/components/dom.js | 2 +- source/arroost/components/tunnel.js | 9 +++++++++ source/arroost/entities/scene.js | 3 +-- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/source/arroost/components/dom.js b/source/arroost/components/dom.js index 01e346e..470784b 100644 --- a/source/arroost/components/dom.js +++ b/source/arroost/components/dom.js @@ -153,7 +153,7 @@ export class Dom extends Component { this.use(() => { const outOfView = this.outOfView.get() - container.style.display = outOfView ? "block" : "block" + container.style.display = outOfView ? "hidden" : "block" }, [this.outOfView, this.forceInView]) const element = this.getElement() diff --git a/source/arroost/components/tunnel.js b/source/arroost/components/tunnel.js index b027171..014ff4d 100644 --- a/source/arroost/components/tunnel.js +++ b/source/arroost/components/tunnel.js @@ -57,6 +57,15 @@ export class Tunnel extends Component { static inViewInfiniteTunnels = new Set() static purgeOtherLevelInfiniteTunnels() { + for (const [key, tunnel] of Tunnel.tunnels) { + const cell = getCell(shared.nogan, tunnel.id) + if (!cell) throw new Error(`Tunnel: Can't find cell ${tunnel.id}`) + if (cell.parent !== shared.level) { + tunnel.entity.dispose() + Tunnel.tunnels.delete(key) + } + } + for (const tunnel of Tunnel.inViewInfiniteTunnels) { const cell = getCell(shared.nogan, tunnel.id) if (!cell) throw new Error(`Tunnel: Can't find cell ${tunnel.id}`) diff --git a/source/arroost/entities/scene.js b/source/arroost/entities/scene.js index 1a95186..aabba93 100644 --- a/source/arroost/entities/scene.js +++ b/source/arroost/entities/scene.js @@ -383,8 +383,8 @@ export class Scene extends Entity { shared.level = tunnel.id + Tunnel.purgeOtherLevelInfiniteTunnels() this.recreateSceneLayers() - this.rebuildWorldFromNogan() const { center } = this.bounds.get() @@ -396,7 +396,6 @@ export class Scene extends Entity { this.setCameraCenter(position) this.infiniteTarget.get()?.infinite.state.set("none") this.infiniteTarget.set(null) - Tunnel.purgeOtherLevelInfiniteTunnels() checkUnderPointer() // this.recreateSceneLayers() // shared.level = tunnel.id From 84fa6fabf6a581a07f54fbf3f7f8962f31433bdc Mon Sep 17 00:00:00 2001 From: "Lu[ke] Wilson" Date: Fri, 5 Jan 2024 09:59:44 +0000 Subject: [PATCH 12/18] only tick wires if parent firing --- source/nogan/nogan.js | 27 +++++++++++++---- source/nogan/nogan.test.js | 61 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 5 deletions(-) diff --git a/source/nogan/nogan.js b/source/nogan/nogan.js index 75ebbe3..6094cb9 100644 --- a/source/nogan/nogan.js +++ b/source/nogan/nogan.js @@ -1334,12 +1334,13 @@ export const fullFireCell = ( /** * Clone a nogan, ending all fires of cells whose parents are firing. * @param {Nogan} nogan + * @param {GetPeakMemo | undefined} memo * @returns {{ * projection: Nogan, * operations: Operation[], * }} */ -export const getProjection = (nogan) => { +export const getProjection = (nogan, memo = undefined) => { const projection = getClone(nogan) const operations = [] @@ -1356,7 +1357,7 @@ export const getProjection = (nogan) => { if (!cell.fire.blue && !cell.fire.red && !cell.fire.green) continue // Don't unfire the cell if its parent isn't firing - if (!isRoot(parent) && !isPeakFiring(nogan, { id: parent })) continue + if (!isRoot(parent) && !isPeakFiring(nogan, { id: parent, memo })) continue cell.fire = createFire() const unfiredOperation = c({ type: "unfired", id: cell.id }) @@ -1465,6 +1466,18 @@ export const getPeak = ( const from = timing === 1 ? past : future // First, let's try to look in the known future/past + // But wait! only if my parent is firing + const cell = getCell(nogan, id) + if (!cell) throw new Error(`Couldn't find cell ${id} to get peak`) + const { parent } = cell + if ( + !isRoot(parent) && + !isPeakFiring(nogan, { id: parent, past, future, memo, timing: getFlippedTiming(timing) }) + ) { + return createPeak({ colour }) + } + + // Parent is firing, so let's look in the known future/past! const [next, ...rest] = to if (next) { const peak = getPeakNow(next, { @@ -1479,7 +1492,7 @@ export const getPeak = ( } // Otherwise, let's prepare to imagine the future/past - const { projection } = getProjection(nogan) + const { projection } = getProjection(nogan, memo) // But wait! // Are we stuck in a loop? @@ -1571,12 +1584,16 @@ export const isFiring = (nogan, { id }) => { * @param {Nogan} nogan * @param {{ * id: CellId, + * timing?: Timing, + * past?: Nogan[], + * future?: Nogan[], + * memo?: GetPeakMemo, * }} options * @returns {boolean} */ -export const isPeakFiring = (nogan, { id }) => { +export const isPeakFiring = (nogan, options) => { for (const colour of PULSE_COLOURS) { - const peak = getPeak(nogan, { id, colour }) + const peak = getPeak(nogan, options) if (peak.result) return true } return false diff --git a/source/nogan/nogan.test.js b/source/nogan/nogan.test.js index f5a992a..7235e5c 100644 --- a/source/nogan/nogan.test.js +++ b/source/nogan/nogan.test.js @@ -1723,3 +1723,64 @@ describe("memoisation", () => { assertEquals(operations.length, 3) // Should have fired all three slots }) }) + +describe("infinity", () => { + it("deals with wires inside cells", () => { + const nogan = createNogan() + const cell1 = createCell(nogan, { type: "slot" }) + const cell2 = createCell(nogan, { type: "slot" }) + createWire(nogan, { source: cell1.id, target: cell2.id, timing: 1 }) + createWire(nogan, { source: cell2.id, target: cell1.id, timing: 1 }) + + const child1 = createCell(nogan, { type: "slot", parent: cell1.id }) + const child2 = createCell(nogan, { type: "slot", parent: cell1.id }) + createWire(nogan, { source: child1.id, target: child2.id, timing: 1 }) + + const advanced0 = getAdvanced(nogan).advanced + const cell1after0 = getCell(advanced0, cell1.id) + const cell2after0 = getCell(advanced0, cell2.id) + const child1after0 = getCell(advanced0, child1.id) + const child2after0 = getCell(advanced0, child2.id) + + assertEquals(cell1after0?.fire.blue, null) + assertEquals(cell2after0?.fire.blue, null) + assertEquals(child1after0?.fire.blue, null) + assertEquals(child2after0?.fire.blue, null) + + fireCell(nogan, { id: child1.id }) + + assertEquals(cell1.fire.blue, null) + assertEquals(cell2.fire.blue, null) + assertEquals(child1.fire.blue, { type: "raw" }) + assertEquals(child2.fire.blue, null) + + const advanced1 = getAdvanced(nogan).advanced + const cell1after1 = getCell(advanced1, cell1.id) + const cell2after1 = getCell(advanced1, cell2.id) + const child1after1 = getCell(advanced1, child1.id) + const child2after1 = getCell(advanced1, child2.id) + + assertEquals(cell1after1?.fire.blue, null) + assertEquals(cell2after1?.fire.blue, null) + assertEquals(child1after1?.fire.blue, { type: "raw" }) + assertEquals(child2after1?.fire.blue, null) + + fireCell(nogan, { id: cell1.id }) + + assertEquals(cell1.fire.blue, { type: "raw" }) + assertEquals(cell2.fire.blue, null) + assertEquals(child1.fire.blue, { type: "raw" }) + assertEquals(child2.fire.blue, null) + + const advanced2 = getAdvanced(nogan).advanced + const cell1after2 = getCell(advanced2, cell1.id) + const cell2after2 = getCell(advanced2, cell2.id) + const child1after2 = getCell(advanced2, child1.id) + const child2after2 = getCell(advanced2, child2.id) + + assertEquals(cell1after2?.fire.blue, null) + assertEquals(cell2after2?.fire.blue, { type: "raw" }) + assertEquals(child1after2?.fire.blue, null) + assertEquals(child2after2?.fire.blue, { type: "raw" }) + }) +}) From da819d8d35f7daa690d36008770d08463af0673b Mon Sep 17 00:00:00 2001 From: "Lu[ke] Wilson" Date: Fri, 5 Jan 2024 10:12:35 +0000 Subject: [PATCH 13/18] fuck yeah timing children --- source/nogan/nogan.js | 50 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/source/nogan/nogan.js b/source/nogan/nogan.js index 6094cb9..a134ade 100644 --- a/source/nogan/nogan.js +++ b/source/nogan/nogan.js @@ -1467,15 +1467,21 @@ export const getPeak = ( // First, let's try to look in the known future/past // But wait! only if my parent is firing - const cell = getCell(nogan, id) - if (!cell) throw new Error(`Couldn't find cell ${id} to get peak`) - const { parent } = cell - if ( - !isRoot(parent) && - !isPeakFiring(nogan, { id: parent, past, future, memo, timing: getFlippedTiming(timing) }) - ) { - return createPeak({ colour }) - } + // const cell = getCell(nogan, id) + // if (!cell) throw new Error(`Couldn't find cell ${id} to get peak`) + // const { parent } = cell + // if ( + // !isRoot(parent) && + // !isPeakFiring(nogan, { + // id: parent, + // past, + // future, + // memo, + // timing: getFlippedTiming(timing), + // }) + // ) { + // return createPeak({ colour }) + // } // Parent is firing, so let's look in the known future/past! const [next, ...rest] = to @@ -1549,6 +1555,24 @@ const getPeakNow = (nogan, { id, colour, past, future, memo = new GetPeakMemo() }) if (!inputPeak.result) continue + + // Check if the input's parent is firing + const inputCell = getCell(nogan, wire.source) + if (!inputCell) throw new Error(`Couldn't find input cell ${wire.source}`) + const { parent } = inputCell + if ( + !isRoot(parent) && + !isPeakFiring(nogan, { + id: parent, + timing: getFlippedTiming(wire.timing), + past, + future, + memo, + }) + ) { + continue + } + peak = getBehavedPeak({ nogan, source: wire.source, @@ -1593,7 +1617,7 @@ export const isFiring = (nogan, { id }) => { */ export const isPeakFiring = (nogan, options) => { for (const colour of PULSE_COLOURS) { - const peak = getPeak(nogan, options) + const peak = getPeak(nogan, { ...options, colour }) if (peak.result) return true } return false @@ -1656,6 +1680,12 @@ export const refresh = ( let memo = new GetPeakMemo() for (const id of iterateCellIds(snapshot)) { if (filter && !filter(id)) continue + const cell = getCell(snapshot, id) + if (!cell) throw new Error(`Couldn't find cell ${id} to refresh`) + // if (!isRoot(cell.parent) && !isPeakFiring(nogan, { id: cell.parent, memo, past, future })) { + // continue + // } + for (const colour of PULSE_COLOURS) { const peak = getPeak(snapshot, { id, From 06f9835054d9e1bdb6edf26b8bb52912c1fe43ab Mon Sep 17 00:00:00 2001 From: "Lu[ke] Wilson" Date: Fri, 5 Jan 2024 10:35:00 +0000 Subject: [PATCH 14/18] fix infinite wires --- source/arroost/components/tunnel.js | 12 ++++++------ source/arroost/entities/arrows/time.js | 18 +++++++++++++++--- source/nogan/nogan.js | 5 ++++- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/source/arroost/components/tunnel.js b/source/arroost/components/tunnel.js index 014ff4d..15cd935 100644 --- a/source/arroost/components/tunnel.js +++ b/source/arroost/components/tunnel.js @@ -229,6 +229,11 @@ export class Tunnel extends Component { } if (this.type === "cell") { + const cell = getCell(shared.nogan, this.id) + if (!cell) throw new Error(`Tunnel: Can't find cell ${this.id}`) + if (cell.type === "timing" || cell.type === "colour") { + return + } this.useCell({ dom: this.entity.dom, carry: this.entity.carry, @@ -293,16 +298,11 @@ export class Tunnel extends Component { const cell = getCell(shared.nogan, this.id) if (!cell) throw new Error(`Tunnel: Can't find cell ${this.id}`) if (equals(cell.position, position)) return + if (!equals(velocity, [0, 0])) return Tunnel.apply(() => { return moveCell(shared.nogan, { id: this.id, position, - propogate: equals(velocity, [0, 0]), - filter: (id) => { - const cell = getCell(shared.nogan, id) - if (!cell) throw new Error(`Tunnel: Can't find cell ${id}`) - return cell.type === "slot" - }, }) }) }) diff --git a/source/arroost/entities/arrows/time.js b/source/arroost/entities/arrows/time.js index cdeb667..03d2950 100644 --- a/source/arroost/entities/arrows/time.js +++ b/source/arroost/entities/arrows/time.js @@ -9,7 +9,7 @@ import { subtract, } from "../../../../libraries/habitat-import.js" import { shared } from "../../../main.js" -import { createWire } from "../../../nogan/nogan.js" +import { createWire, getCell, getWire } from "../../../nogan/nogan.js" import { Dom } from "../../components/dom.js" import { Tunnel } from "../../components/tunnel.js" import { Entity } from "../entity.js" @@ -47,6 +47,9 @@ export class ArrowOfTime extends Entity { this.target = target this.isPreview = preview + let timingId = undefined + let colourId = undefined + // Setup tunnel if (id === undefined) { const { wire, operations } = createWire(shared.nogan, { @@ -62,12 +65,21 @@ export class ArrowOfTime extends Entity { Tunnel.apply(() => operations) } else { this.tunnel = this.attach(new Tunnel(id, { entity: this, forcePreview: this.isPreview })) + const wireWire = getWire(shared.nogan, id) + for (const cellId of wireWire.cells) { + const cell = getCell(shared.nogan, cellId) + if (cell?.type === "timing") { + timingId = cellId + } else if (cell?.type === "colour") { + colourId = cellId + } + } } // Render elements this.line = this.attach(new Line()) - this.flaps = this.attach(new ArrowOfTiming({ wire: this.tunnel.id })) - this.colour = this.attach(new ArrowOfColour({ wire: this.tunnel.id })) + this.flaps = this.attach(new ArrowOfTiming({ wire: this.tunnel.id, id: timingId })) + this.colour = this.attach(new ArrowOfColour({ wire: this.tunnel.id, id: colourId })) this.dom.append(this.line.dom) if (!this.isPreview) { diff --git a/source/nogan/nogan.js b/source/nogan/nogan.js index a134ade..5084e57 100644 --- a/source/nogan/nogan.js +++ b/source/nogan/nogan.js @@ -1705,7 +1705,10 @@ export const refresh = ( // If we've changed the nogan, we need to refresh the cache // (as things might be different now) - memo = new GetPeakMemo() + + // COMMENT OUT FOR BUGS BUT HUGE PERFORMANCE INCREASE + // memo = new GetPeakMemo() + operations.push(...firedOperations) } } From 04bbd7bff347c888212301865957d56142276d41 Mon Sep 17 00:00:00 2001 From: "Lu[ke] Wilson" Date: Fri, 5 Jan 2024 10:43:10 +0000 Subject: [PATCH 15/18] zoom out forever --- source/arroost/components/infinite.js | 29 +++++++++------------------ source/arroost/entities/scene.js | 26 ++++++++++++++++++++++-- 2 files changed, 33 insertions(+), 22 deletions(-) diff --git a/source/arroost/components/infinite.js b/source/arroost/components/infinite.js index e37d2e1..c0beed9 100644 --- a/source/arroost/components/infinite.js +++ b/source/arroost/components/infinite.js @@ -1,4 +1,4 @@ -import { BLACK, RED, scale } from "../../../libraries/habitat-import.js" +import { BLACK, RED, rotate, scale } from "../../../libraries/habitat-import.js" import { shared } from "../../main.js" import { Dragging } from "../machines/input.js" import { Component } from "./component.js" @@ -177,19 +177,8 @@ export class Infinite extends Component { const distance = FULL * 2 const angle = Math.random() * Math.PI * 2 - // Three points of an equilateral triangle /** @type {[number, number][]} */ - const positions = [ - [distance * Math.cos(angle), distance * Math.sin(angle)], - [ - distance * Math.cos(angle + (2 * Math.PI) / 3), - distance * Math.sin(angle + (2 * Math.PI) / 3), - ], - [ - distance * Math.cos(angle + (4 * Math.PI) / 3), - distance * Math.sin(angle + (4 * Math.PI) / 3), - ], - ] + const positions = [rotate([distance, 0], angle), rotate([-distance, 0], angle)] const entity1 = new ArrowOfCreation({ position: positions[0], @@ -207,13 +196,13 @@ export class Infinite extends Component { cellEntities.push(entity2) this.previews.add(entity2) - const entity3 = new ArrowOfDestruction({ - position: positions[2], - preview: true, - level: newLevel, - }) - cellEntities.push(entity3) - this.previews.add(entity3) + // const entity3 = new ArrowOfDestruction({ + // position: positions[2], + // preview: true, + // level: newLevel, + // }) + // cellEntities.push(entity3) + // this.previews.add(entity3) } const background = new Ellipse() diff --git a/source/arroost/entities/scene.js b/source/arroost/entities/scene.js index aabba93..93af141 100644 --- a/source/arroost/entities/scene.js +++ b/source/arroost/entities/scene.js @@ -9,6 +9,7 @@ import { distanceBetween, equals, fireEvent, + rotate, scale, subtract, use, @@ -23,12 +24,21 @@ import { Transform } from "../components/transform.js" import { CELL_CONSTRUCTORS, Tunnel, WIRE_CONSTRUCTOR } from "../components/tunnel.js" import { CHILD_SCALE, + FULL, PARENT_SCALE, ZOOMING_IN_THRESHOLD, ZOOMING_OUT_THRESHOLD, ZOOM_IN_THRESHOLD, } from "../unit.js" -import { c, getCell, getTemplate, iterateCells, iterateWires, t } from "../../nogan/nogan.js" +import { + c, + createCell, + getCell, + getTemplate, + iterateCells, + iterateWires, + t, +} from "../../nogan/nogan.js" import { Infinite } from "../components/infinite.js" import { checkUnderPointer, triggerSomethingHasMoved } from "../machines/hover.js" import { Marker } from "./debug/marker.js" @@ -419,13 +429,25 @@ export class Scene extends Entity { Tunnel.purgeOtherLevelInfiniteTunnels() shared.level = 0 + const newCell = createCell(shared.nogan, { + type: "creation", + }) + + cellToComeOutOf = newCell.id + for (const cell of iterateCells(shared.nogan)) { if (cell.id === 0) continue + if (cell.id === newCell.id) continue if (cell.parent === 0) { - cellToComeOutOf = cell.id + cell.parent = newCell.id break } } + + // createCell(shared.nogan, { + // type: "connection", + // position: rotate([FULL * 2, 0], Math.random() * Math.PI * 2), + // }) } Tunnel.purgeOtherLevelInfiniteTunnels() From 28676f6fddbbead73f1b42dfc7458bf1ca0680c3 Mon Sep 17 00:00:00 2001 From: TodePond Date: Fri, 5 Jan 2024 17:21:18 +0000 Subject: [PATCH 16/18] merge --- source/clock.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source/clock.js b/source/clock.js index 7a7314c..7ad53d0 100644 --- a/source/clock.js +++ b/source/clock.js @@ -4,7 +4,7 @@ import { GREY_BLACK, shared } from "./main.js" import { getAdvanced } from "./nogan/nogan.js" class Clock { - bpm = 120 + bpm = 160 /** @type {"buildup" | "aftermath"} */ phase = "buildup" @@ -13,6 +13,10 @@ class Clock { queue = [] count = 0 + setBpm(bpm) { + this.bpm = bpm + Tone.Transport.bpm.value = bpm + } start() { const metronome = new Tone.PluckSynth().toDestination() From dd8760936ff6588833b094bd07e8ae5b07915f0e Mon Sep 17 00:00:00 2001 From: "Lu[ke] Wilson" Date: Wed, 10 Jan 2024 23:10:51 +0000 Subject: [PATCH 17/18] inverse --- assets/berd-cursor-inverse.png | Bin 0 -> 1492 bytes assets/berd-cursor-inverse.svg | 4 ++ source/arroost/components/style.js | 19 ++++-- source/arroost/cursor.js | 6 +- source/arroost/entities/arrows/colour.js | 2 +- source/arroost/entities/arrows/dummy.js | 2 +- source/arroost/entities/arrows/noise.js | 2 +- source/arroost/entities/arrows/reality.js | 2 +- source/arroost/entities/arrows/recording.js | 2 +- source/arroost/entities/arrows/shared.js | 4 +- source/arroost/entities/arrows/slot.js | 2 +- source/arroost/entities/arrows/timing.js | 2 +- source/arroost/entities/arrows/typing.js | 2 +- source/arroost/entities/scene.js | 3 +- source/clock.js | 2 +- source/main.js | 4 +- source/theme.js | 72 ++++++++++++++++++++ 17 files changed, 110 insertions(+), 20 deletions(-) create mode 100644 assets/berd-cursor-inverse.png create mode 100644 assets/berd-cursor-inverse.svg create mode 100644 source/theme.js diff --git a/assets/berd-cursor-inverse.png b/assets/berd-cursor-inverse.png new file mode 100644 index 0000000000000000000000000000000000000000..907878f20e66b7e3e59d5316d0e96b40dd990b42 GIT binary patch literal 1492 zcmds%|3A|S9LL|=#}Z35%0;79M`^XxoLtU)$zhTto8`ME31v?C66!OzFh$pOUDUYJ zDRIfSjPm6Zk;}pZN41<$TPokO*c@{1-?$&1ujenXpPxbxcV``KLu~-iVY)baE*kxh zrArpKi4okkC|r!Evjdd0livdnvY3wcUhx5=qJ6Co_N;k&_UX}bQU>R;j;A2Kd~*I! zl$Oa$Pfz{f&h}Ku(=bjiEnqQ7chzBC zjT2A#X&Xi(FYOQ6!npRA@#`+HQXyT+EBTx(z{uOG3!k zv)``6J_(b1l72@DaO$PiR`fgGeBYh3MZUL@0w|4U0If~Z^iT^WDde%+aM)cej_^zj zt+~yl`4&8HQ_yyvs~`S`;JlD~0VkvISchx(Jr6`q(5&)OGk6qDNc2@DpA*O8DTfa*>?* z?vc^_E6V+QIwSII@uLM_`t*Q>%JX3X`LO$g^w0FJlkLriAEkh)` zLdFhOVZp9u?!98Tx`LY6jIhZQ1&v}eWs3=HN5pJVq0gQO=jhZ5YbsjzB*FI0wg9IW zL;jIzpSY+EbJ&$ffgsiFe(%U`_ccYFgV!a=P4<@pdoP3!?2U{_XdRd)y&CEnXfEgN z^f2#qe?#sUD$b|U5i?bw&GJz90Kn=Kq_jNal5FR0(p~K;se^86P|)?`40fhsX-&iik1}*^hR$&w@Bi z_sEX%o$w*rl`8%i+}!tPW^EVorlr$D+}iZ{#v_Tdwz#Zf(SQ^?b%h(IUWl4+z8mxcL zO=UfbANcNhN}2zv4eV_A}e z;AqGyIz)u6ebm(ETXmCFbX=^Zo%cpfAKc2fFWUR1mSK93Y03~B(?Og2Pd;&LSoHzm za@ctOXmm8I<~RJamMWFriSUY1i_&@XC+!g*ME~UEF3I^EG%dvTH%Xf}p_*%l+3An@ z#?Tq!HjF}c=bW(v5j74CZX|190)=X&4}3N!>M1B-YSEC^iNBF{DBD~UXMS_WM)0>j zq-6cFQEsEQO;|1kbkx4`a!G7C2fp6$KnJozW{)G+=O&nykE4{waagE_n7=Gbtc5O{ z`LF>*bP8yoF`A+_Z^BAwH{#I(SKEPA99EOW0-WqM?%gB{_kTXjodqWYK40jwyMHm$ N!2I6bvBV)L + + + \ No newline at end of file diff --git a/source/arroost/components/style.js b/source/arroost/components/style.js index 1c4c14b..ddd412b 100644 --- a/source/arroost/components/style.js +++ b/source/arroost/components/style.js @@ -1,9 +1,10 @@ -import { glue, GREY, use } from "../../../libraries/habitat-import.js" +import { BLACK, glue, GREY, use } from "../../../libraries/habitat-import.js" import { shared } from "../../main.js" +import { theme } from "../../theme.js" import { Component } from "./component.js" import { Dom } from "./dom.js" -export const Style = class extends Component { +export class Style extends Component { static highestZIndex = 0 static lowestZIndex = 0 @@ -57,9 +58,15 @@ export const Style = class extends Component { /** @type {Signal} */ opacity = this.use(null) - static SHADOW = "0px 4px 8px rgba(0, 0, 0, 0.25), 0px 0px 4px rgba(0, 0, 0, 0.15)" - static SHADOW_FILTER = - "drop-shadow(0px 4px 8px rgba(0, 0, 0, 0.25)) drop-shadow(0px 0px 4px rgba(0, 0, 0, 0.15))" + static SHADOW_COLOUR = theme.get() === "dark" ? "0, 0, 0" : "0, 0, 20" + static SHADOW_OPACITY = theme.get() === "dark" ? 0.25 : 0.03 + + static SHADOW = `0px 4px 8px rgba(${Style.SHADOW_COLOUR}, ${ + Style.SHADOW_OPACITY + }), 0px 0px 4px rgba(${Style.SHADOW_COLOUR}, ${Style.SHADOW_OPACITY * 0.6})` + static SHADOW_FILTER = `drop-shadow(0px 4px 8px rgba(${Style.SHADOW_COLOUR}, ${ + Style.SHADOW_OPACITY + })) drop-shadow(0px 0px 4px rgba(${Style.SHADOW_COLOUR}, ${Style.SHADOW_OPACITY * 0.6}))` /** * @param {SVGElement} element @@ -153,3 +160,5 @@ export const Style = class extends Component { this.zIndex.set(zIndex) } } + +window["Style"] = Style diff --git a/source/arroost/cursor.js b/source/arroost/cursor.js index a07eb2f..e1007d2 100644 --- a/source/arroost/cursor.js +++ b/source/arroost/cursor.js @@ -1,5 +1,6 @@ import { use } from "../../libraries/habitat-import.js" import { shared } from "../main.js" +import { theme } from "../theme.js" export function useCursor() { use(() => { @@ -12,7 +13,10 @@ export function useCursor() { } case "berd": { - const path = "/assets/berd-cursor.svg" + const path = + theme.get() === "dark" + ? "/assets/berd-cursor.svg" + : "/assets/berd-cursor-inverse.svg" document.body.style.cursor = `url(${path}) 0 20, auto` return } diff --git a/source/arroost/entities/arrows/colour.js b/source/arroost/entities/arrows/colour.js index ce3fbdd..a98727c 100644 --- a/source/arroost/entities/arrows/colour.js +++ b/source/arroost/entities/arrows/colour.js @@ -8,7 +8,7 @@ import { WHITE, equals, } from "../../../../libraries/habitat-import.js" -import { GREY_SILVER, shared } from "../../../main.js" +import { shared } from "../../../main.js" import { createCell, createWire, diff --git a/source/arroost/entities/arrows/dummy.js b/source/arroost/entities/arrows/dummy.js index d5e6df8..05a3165 100644 --- a/source/arroost/entities/arrows/dummy.js +++ b/source/arroost/entities/arrows/dummy.js @@ -8,7 +8,7 @@ import { WHITE, equals, } from "../../../../libraries/habitat-import.js" -import { GREY_SILVER, shared } from "../../../main.js" +import { shared } from "../../../main.js" import { createCell, fireCell, diff --git a/source/arroost/entities/arrows/noise.js b/source/arroost/entities/arrows/noise.js index 11a2ff5..e6d0696 100644 --- a/source/arroost/entities/arrows/noise.js +++ b/source/arroost/entities/arrows/noise.js @@ -5,7 +5,7 @@ import { Input } from "../../components/input.js" import { setCellStyles } from "./shared.js" import { ArrowOfRecording } from "./recording.js" import { RectangleHtml } from "../shapes/rectangle-html.js" -import { GREY_SILVER, shared } from "../../../main.js" +import { shared } from "../../../main.js" import { GREY } from "../../../../libraries/habitat-import.js" import { FIFTH, FULL, HALF, TENTH, THIRD } from "../../unit.js" diff --git a/source/arroost/entities/arrows/reality.js b/source/arroost/entities/arrows/reality.js index 3d24b74..3be7617 100644 --- a/source/arroost/entities/arrows/reality.js +++ b/source/arroost/entities/arrows/reality.js @@ -8,7 +8,7 @@ import { WHITE, equals, } from "../../../../libraries/habitat-import.js" -import { GREY_SILVER, shared } from "../../../main.js" +import { shared } from "../../../main.js" import { createCell, fireCell, diff --git a/source/arroost/entities/arrows/recording.js b/source/arroost/entities/arrows/recording.js index 212158e..37c69ab 100644 --- a/source/arroost/entities/arrows/recording.js +++ b/source/arroost/entities/arrows/recording.js @@ -10,7 +10,7 @@ import { equals, subtract, } from "../../../../libraries/habitat-import.js" -import { GREY_SILVER, MIDDLE_C, shared } from "../../../main.js" +import { MIDDLE_C, shared } from "../../../main.js" import { SharedResource, createCell, diff --git a/source/arroost/entities/arrows/shared.js b/source/arroost/entities/arrows/shared.js index 3849ee9..af4da2b 100644 --- a/source/arroost/entities/arrows/shared.js +++ b/source/arroost/entities/arrows/shared.js @@ -1,5 +1,5 @@ import { WHITE, BLACK, GREY, SILVER } from "../../../../libraries/habitat-import.js" -import { GREY_SILVER } from "../../../main.js" +import { GREY_SILVER, theme } from "../../../theme.js" import { Dom } from "../../components/dom.js" import { Infinite } from "../../components/infinite.js" import { Input } from "../../components/input.js" @@ -41,7 +41,7 @@ export const setCellStyles = ({ }) back.style.shadow.set(true) - back.style.stroke.set("rgba(0, 0, 0, 0.25)") + back.style.stroke.set(theme.get() === "dark" ? "rgba(0, 0, 0, 0.25)" : "rgba(0, 0, 20, 0.02)") back.style.strokeWidth.set(2) // back.style.pointerEvents.set(infinite?.isPreview ? "none" : "all") diff --git a/source/arroost/entities/arrows/slot.js b/source/arroost/entities/arrows/slot.js index 47f003a..a823f5a 100644 --- a/source/arroost/entities/arrows/slot.js +++ b/source/arroost/entities/arrows/slot.js @@ -8,7 +8,7 @@ import { WHITE, equals, } from "../../../../libraries/habitat-import.js" -import { GREY_SILVER, shared } from "../../../main.js" +import { shared } from "../../../main.js" import { createCell, fireCell, diff --git a/source/arroost/entities/arrows/timing.js b/source/arroost/entities/arrows/timing.js index 40d69e2..e1da4d5 100644 --- a/source/arroost/entities/arrows/timing.js +++ b/source/arroost/entities/arrows/timing.js @@ -8,7 +8,7 @@ import { WHITE, equals, } from "../../../../libraries/habitat-import.js" -import { GREY_SILVER, shared } from "../../../main.js" +import { shared } from "../../../main.js" import { createCell, createWire, diff --git a/source/arroost/entities/arrows/typing.js b/source/arroost/entities/arrows/typing.js index b2e08dc..4dd4c35 100644 --- a/source/arroost/entities/arrows/typing.js +++ b/source/arroost/entities/arrows/typing.js @@ -8,7 +8,7 @@ import { WHITE, equals, } from "../../../../libraries/habitat-import.js" -import { GREY_SILVER, shared } from "../../../main.js" +import { shared } from "../../../main.js" import { createCell, fireCell, diff --git a/source/arroost/entities/scene.js b/source/arroost/entities/scene.js index 93af141..ec47c87 100644 --- a/source/arroost/entities/scene.js +++ b/source/arroost/entities/scene.js @@ -1,4 +1,4 @@ -import { GREY_SILVER, shared } from "../../main.js" +import { shared } from "../../main.js" import { Entity } from "./entity.js" import { Dom } from "../components/dom.js" import { @@ -44,6 +44,7 @@ import { checkUnderPointer, triggerSomethingHasMoved } from "../machines/hover.j import { Marker } from "./debug/marker.js" import { ArrowOfTiming } from "./arrows/timing.js" import { ArrowOfColour } from "./arrows/colour.js" +import { GREY_SILVER } from "../../theme.js" const ZOOM_FRICTION = 0.75 diff --git a/source/clock.js b/source/clock.js index 7ad53d0..fec7bb0 100644 --- a/source/clock.js +++ b/source/clock.js @@ -1,6 +1,6 @@ import { BLACK, GREY, VOID } from "../libraries/habitat-import.js" import { Tunnel } from "./arroost/components/tunnel.js" -import { GREY_BLACK, shared } from "./main.js" +import { shared } from "./main.js" import { getAdvanced } from "./nogan/nogan.js" class Clock { diff --git a/source/main.js b/source/main.js index f3e3972..6833d07 100644 --- a/source/main.js +++ b/source/main.js @@ -22,6 +22,7 @@ import { getZoomer } from "./arroost/input/zoomer.js" import { clock } from "./clock.js" import { registerImporters } from "./arroost/machines/import.js" import { useCursor } from "./arroost/cursor.js" +import { useTheme } from "./theme.js" //======// // Tone // @@ -35,8 +36,7 @@ window["print"] = print window["dir"] = console.dir.bind(console) registerMethods() -export const GREY_SILVER = new Colour(83, 101, 147) -export const GREY_BLACK = new Colour(31, 39, 54) +useTheme() //==============// // Setup Engine // diff --git a/source/theme.js b/source/theme.js new file mode 100644 index 0000000..0731db1 --- /dev/null +++ b/source/theme.js @@ -0,0 +1,72 @@ +import { + add, + BLACK, + Colour, + COLOURS, + GREY, + SILVER, + use, + WHITE, +} from "../libraries/habitat-import.js" + +export const GREY_SILVER = new Colour(83, 101, 147) +export const GREY_BLACK = new Colour(31, 39, 54) + +/** @type {Signal<"light" | "dark">} */ +export const theme = use("light") + +const BASE = { + WHITE, + BLACK, + GREY, + GREY_SILVER, + GREY_BLACK, + SILVER, +} + +window["BASE"] = BASE + +const DARK = { + WHITE: [...WHITE], + BLACK: [...BLACK], + GREY: [...GREY], + GREY_SILVER: [...GREY_SILVER], + GREY_BLACK: [...GREY_BLACK], +} + +const LIGHT = { + WHITE: [...BLACK], + BLACK: [...new Colour(255, 255, 255)], + GREY: [...SILVER], + GREY_SILVER: [...SILVER], + GREY_BLACK: [...SILVER], +} + +export function useTheme() { + addEventListener("keydown", (event) => { + if (event.key === "Enter") { + theme.set(theme.get() === "light" ? "dark" : "light") + } + }) + + use(() => { + switch (theme.get()) { + case "light": { + for (const key in LIGHT) { + BASE[key][0] = LIGHT[key][0] + BASE[key][1] = LIGHT[key][1] + BASE[key][2] = LIGHT[key][2] + } + break + } + case "dark": { + for (const key in DARK) { + BASE[key][0] = DARK[key][0] + BASE[key][1] = DARK[key][1] + BASE[key][2] = DARK[key][2] + } + break + } + } + }, [theme]) +} From 4e4decfbd7004cf73d205251b8a26484e8a06acf Mon Sep 17 00:00:00 2001 From: TodePond Date: Thu, 11 Jan 2024 22:41:57 +0000 Subject: [PATCH 18/18] sizing --- source/arroost/components/infinite.js | 2 +- source/arroost/entities/arrows/slot.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/arroost/components/infinite.js b/source/arroost/components/infinite.js index c0beed9..bb328f0 100644 --- a/source/arroost/components/infinite.js +++ b/source/arroost/components/infinite.js @@ -76,7 +76,7 @@ export class Infinite extends Component { // const parentBlur = lerp([0, 20], t, EASE.easeInOutExpo) this.dom?.style.opacity.set(childOpacity) - this.parent?.style.opacity.set(parentOpacity) + // this.parent?.style.opacity.set(parentOpacity) // this.dom?.style.blur.set(childBlur) // this.parent?.style.blur.set(parentBlur) diff --git a/source/arroost/entities/arrows/slot.js b/source/arroost/entities/arrows/slot.js index a823f5a..567944d 100644 --- a/source/arroost/entities/arrows/slot.js +++ b/source/arroost/entities/arrows/slot.js @@ -70,8 +70,8 @@ export class ArrowOfSlot extends Entity { this.dom.append(this.front.dom) // Style elements - this.back.dom.transform.scale.set([2 / 3, 2 / 3]) - this.front.dom.transform.scale.set([1 / 3, 1 / 3]) + this.back.dom.transform.scale.set([1, 1]) + this.front.dom.transform.scale.set([1 / 2, 1 / 2]) setCellStyles({ back: this.back.dom, front: this.front.dom,