migrate to vite working
This commit is contained in:
@@ -1,94 +0,0 @@
|
||||
type ContextStore = Record<string, any>;
|
||||
|
||||
const defaultContext: ContextStore = {};
|
||||
const contextStack: ContextStore[] = [defaultContext];
|
||||
|
||||
const debug = JSON.parse(localStorage.getItem("debug") || "false");
|
||||
|
||||
export function setDefaultContext(context: ContextStore) {
|
||||
Object.assign(defaultContext, context);
|
||||
}
|
||||
|
||||
export function withContext<T>(context: ContextStore, fn: () => T): T {
|
||||
contextStack.push(context);
|
||||
try {
|
||||
return fn();
|
||||
} finally {
|
||||
contextStack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
export const ctx = new Proxy(
|
||||
{},
|
||||
{
|
||||
get(_, prop: string) {
|
||||
for (let i = contextStack.length - 1; i >= 0; i--) {
|
||||
if (prop in contextStack[i]) return contextStack[i][prop];
|
||||
}
|
||||
if (prop in defaultContext) return defaultContext[prop];
|
||||
throw new Error(`Context variable '${prop}' is not defined.`);
|
||||
},
|
||||
},
|
||||
) as Record<string, unknown>;
|
||||
|
||||
export function getContext() {
|
||||
return ctx;
|
||||
}
|
||||
export function getContextItem<T>(prop: string): T {
|
||||
return ctx[prop] as T;
|
||||
}
|
||||
export function getContextItemOrDefault<T>(prop: string, defaultValue: T): T {
|
||||
try {
|
||||
return ctx[prop] as T;
|
||||
} catch {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
export function setContextItem<T>(prop: string, value: T) {
|
||||
Object.assign(contextStack[contextStack.length - 1] ?? defaultContext, {
|
||||
[prop]: value,
|
||||
});
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
setInterval(() => {
|
||||
let ctxEl = document.getElementById("context");
|
||||
if (!ctxEl) {
|
||||
ctxEl = document.createElement("div");
|
||||
ctxEl.id = "context";
|
||||
document.body.append(ctxEl);
|
||||
}
|
||||
ctxEl.innerHTML = "";
|
||||
const div = document.createElement("div");
|
||||
const pre = document.createElement("pre");
|
||||
const h3 = document.createElement("h3");
|
||||
h3.textContent = "Default";
|
||||
div.append(h3);
|
||||
pre.textContent = safeStringify(defaultContext);
|
||||
div.append(pre);
|
||||
ctxEl.append(div);
|
||||
for (const [idx, ctx] of contextStack.entries()) {
|
||||
const div = document.createElement("div");
|
||||
const pre = document.createElement("pre");
|
||||
const h3 = document.createElement("h3");
|
||||
h3.textContent = "CTX " + idx;
|
||||
div.append(h3);
|
||||
pre.textContent = safeStringify(ctx);
|
||||
div.append(pre);
|
||||
ctxEl.append(div);
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
function safeStringify(obj: any) {
|
||||
const seen = new WeakSet();
|
||||
return JSON.stringify(obj, (key, value) => {
|
||||
if (typeof value === "object" && value !== null) {
|
||||
if (seen.has(value)) {
|
||||
return "[Circular]"; // Replace circular references
|
||||
}
|
||||
seen.add(value);
|
||||
}
|
||||
return value;
|
||||
}, 2);
|
||||
}
|
115
lib/input.ts
115
lib/input.ts
@@ -1,115 +0,0 @@
|
||||
import { Vector, ZoomableDoodler } from "@bearmetal/doodler";
|
||||
import { getContextItem } from "./context.ts";
|
||||
|
||||
function mouseButtonToString(button: number) {
|
||||
switch (button) {
|
||||
case 0:
|
||||
return "left";
|
||||
case 1:
|
||||
return "middle";
|
||||
case 2:
|
||||
return "right";
|
||||
}
|
||||
}
|
||||
|
||||
function mouseButtonToNumber(button: string) {
|
||||
switch (button) {
|
||||
case "left":
|
||||
return 0;
|
||||
case "middle":
|
||||
return 1;
|
||||
case "right":
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
export class InputManager {
|
||||
private keyStates: Map<string, boolean> = new Map();
|
||||
private mouseStates: Map<string, boolean> = new Map();
|
||||
private mouseLocation: { x: number; y: number } = { x: 0, y: 0 };
|
||||
private mouseDelta: { x: number; y: number } = { x: 0, y: 0 };
|
||||
|
||||
private keyEvents: Map<string, () => void> = new Map();
|
||||
private mouseEvents: Map<string, () => void> = new Map();
|
||||
|
||||
constructor() {
|
||||
document.addEventListener("keydown", (e) => {
|
||||
this.keyStates.set(e.key, true);
|
||||
this.keyEvents.get(e.key)?.call(e);
|
||||
});
|
||||
document.addEventListener("keyup", (e) => {
|
||||
this.keyStates.set(e.key, false);
|
||||
});
|
||||
document.addEventListener("mousedown", (e) => {
|
||||
const button = mouseButtonToString(e.button);
|
||||
if (!button) throw "Mouse button not found: " + e.button;
|
||||
this.mouseStates.set(button, true);
|
||||
this.mouseEvents.get(button)?.call(e);
|
||||
});
|
||||
document.addEventListener("mouseup", (e) => {
|
||||
const button = mouseButtonToString(e.button);
|
||||
if (!button) throw "Mouse button not found: " + e.button;
|
||||
this.mouseStates.set(button, false);
|
||||
});
|
||||
|
||||
self.addEventListener("mousemove", (e) => {
|
||||
this.mouseLocation = { x: e.clientX, y: e.clientY };
|
||||
this.mouseDelta = {
|
||||
x: e.movementX,
|
||||
y: e.movementY,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
getKeyState(key: string) {
|
||||
return this.keyStates.get(key);
|
||||
}
|
||||
getMouseState(key: string) {
|
||||
return this.mouseStates.get(key);
|
||||
}
|
||||
getMouseLocation() {
|
||||
if (getContextItem("doodler") instanceof ZoomableDoodler) {
|
||||
return getContextItem<ZoomableDoodler>("doodler").screenToWorld(
|
||||
this.mouseLocation.x,
|
||||
this.mouseLocation.y,
|
||||
);
|
||||
}
|
||||
return this.mouseLocation;
|
||||
}
|
||||
getMouseLocationV() {
|
||||
if (getContextItem("doodler") instanceof ZoomableDoodler) {
|
||||
return new Vector(
|
||||
getContextItem<ZoomableDoodler>("doodler").screenToWorld(
|
||||
this.mouseLocation.x,
|
||||
this.mouseLocation.y,
|
||||
),
|
||||
);
|
||||
}
|
||||
return new Vector(this.mouseLocation);
|
||||
}
|
||||
getMouseDelta() {
|
||||
return this.mouseDelta;
|
||||
}
|
||||
|
||||
onKey(key: string, cb: () => void) {
|
||||
this.keyEvents.set(key, cb);
|
||||
}
|
||||
onMouse(key: string, cb: () => void) {
|
||||
this.mouseEvents.set(key, cb);
|
||||
}
|
||||
|
||||
offKey(key: string) {
|
||||
const events = this.keyEvents.get(key);
|
||||
this.keyEvents.delete(key);
|
||||
return events;
|
||||
}
|
||||
offMouse(key: string) {
|
||||
this.mouseEvents.delete(key);
|
||||
}
|
||||
|
||||
onNumberKey(arg0: (arg: number) => void) {
|
||||
for (let i = 0; i < 10; i++) {
|
||||
this.onKey(i.toString(), () => arg0(i));
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,38 +0,0 @@
|
||||
export class ResourceManager {
|
||||
private resources: Map<string, unknown> = new Map();
|
||||
private statuses: Map<string, Promise<boolean>> = new Map();
|
||||
|
||||
get<T>(name: string): T {
|
||||
if (!this.resources.has(name)) {
|
||||
throw new Error(`Resource ${name} not found`);
|
||||
}
|
||||
return this.resources.get(name) as T;
|
||||
}
|
||||
|
||||
set(name: string, value: unknown) {
|
||||
if (typeof (value as EventSource).addEventListener === "function") {
|
||||
this.statuses.set(
|
||||
name,
|
||||
new Promise((resolve) => {
|
||||
const onload = () => {
|
||||
this.resources.set(name, value);
|
||||
resolve(true);
|
||||
(value as EventSource).removeEventListener("load", onload);
|
||||
};
|
||||
(value as EventSource).addEventListener("load", onload);
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
console.warn("Resource added was not a loadable resource");
|
||||
}
|
||||
this.resources.set(name, value);
|
||||
}
|
||||
|
||||
delete(name: string) {
|
||||
this.resources.delete(name);
|
||||
}
|
||||
|
||||
ready() {
|
||||
return Promise.all(Array.from(this.statuses.values()));
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user