Compare commits
1 Commits
vite-lib-t
...
renderer
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ec0723ac88 |
35
main.typ
35
main.typ
@@ -1,35 +0,0 @@
|
||||
#let put(x, y, z, ..args) = {
|
||||
(
|
||||
"p",
|
||||
str(x),
|
||||
str(y),
|
||||
str(z),
|
||||
..args.pos().map(str),
|
||||
..args.named().pairs().map((u, v) => str(u) + "=" + str(v)),
|
||||
).join(" ")
|
||||
}
|
||||
|
||||
#html.html({
|
||||
html.head({
|
||||
html.link(rel: "stylesheet", href: "./mc-diorama.css")
|
||||
html.script(src: "./mc-diorama.mjs", type: "module")
|
||||
})
|
||||
html.body({
|
||||
html.main([
|
||||
= hello world
|
||||
])
|
||||
|
||||
html.elem("mc-diorama", {
|
||||
html.elem("mc-camera")
|
||||
html.elem(
|
||||
"mc-world",
|
||||
"
|
||||
p 0 0 0 stone;
|
||||
p 0 0 1 piston facing=up extended=false &
|
||||
|
||||
p 1 0 0 redstone_block;
|
||||
",
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
40
package-lock.json
generated
40
package-lock.json
generated
@@ -1,14 +1,14 @@
|
||||
{
|
||||
"name": "mc-diorama",
|
||||
"version": "0.1.0",
|
||||
"name": "wireless",
|
||||
"version": "0.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "mc-diorama",
|
||||
"version": "0.1.0",
|
||||
"name": "wireless",
|
||||
"version": "0.0.0",
|
||||
"devDependencies": {
|
||||
"vite": "^8.1.3"
|
||||
"vite": "^8.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@emnapi/core": {
|
||||
@@ -167,6 +167,9 @@
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"libc": [
|
||||
"glibc"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -184,6 +187,9 @@
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"libc": [
|
||||
"musl"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -201,6 +207,9 @@
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"libc": [
|
||||
"glibc"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -218,6 +227,9 @@
|
||||
"s390x"
|
||||
],
|
||||
"dev": true,
|
||||
"libc": [
|
||||
"glibc"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -235,6 +247,9 @@
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"libc": [
|
||||
"glibc"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -252,6 +267,9 @@
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"libc": [
|
||||
"musl"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -535,6 +553,9 @@
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"libc": [
|
||||
"glibc"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -556,6 +577,9 @@
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"libc": [
|
||||
"musl"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -577,6 +601,9 @@
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"libc": [
|
||||
"glibc"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -598,6 +625,9 @@
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"libc": [
|
||||
"musl"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
|
||||
21
package.json
21
package.json
@@ -1,13 +1,14 @@
|
||||
{
|
||||
"name": "mc-diorama",
|
||||
"version": "0.1.0",
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"module": "./dist/mc-diorama.es.js",
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/mc-diorama.es.js"
|
||||
}
|
||||
"name": "wireless",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"devDependencies": {
|
||||
"vite": "^8.1.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,6 +190,7 @@ mc-diorama {
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
touch-action: none;
|
||||
|
||||
& .track-inner {
|
||||
position: relative;
|
||||
|
||||
@@ -8,7 +8,7 @@ import {SpacetimeController} from './controller.js';
|
||||
window.mcEngine = new Engine();
|
||||
document.body.appendChild(window.mcEngine.canvas)
|
||||
|
||||
class MCWorldElement extends HTMLElement {
|
||||
export class MCWorldElement extends HTMLElement {
|
||||
connectedCallback() {
|
||||
if (this.world) return;
|
||||
// Read text content directly, allowing inline scripting
|
||||
@@ -17,7 +17,7 @@ class MCWorldElement extends HTMLElement {
|
||||
}
|
||||
}
|
||||
|
||||
class MCFrameElement extends HTMLElement {
|
||||
export class MCFrameElement extends HTMLElement {
|
||||
connectedCallback() {
|
||||
// Use a microtask to ensure children are parsed
|
||||
setTimeout(() => this.init(), 0);
|
||||
@@ -42,7 +42,7 @@ class MCFrameElement extends HTMLElement {
|
||||
}
|
||||
}
|
||||
|
||||
class MCDioramaElement extends HTMLElement {
|
||||
export class MCDioramaElement extends HTMLElement {
|
||||
connectedCallback() {
|
||||
setTimeout(() => this.init(), 0);
|
||||
}
|
||||
|
||||
@@ -230,6 +230,111 @@ export class SpacetimeController {
|
||||
this.syncUI();
|
||||
}
|
||||
});
|
||||
|
||||
// --- MOBILE TOUCH LOGIC ("Wait and See" Scroll vs Camera) ---
|
||||
|
||||
this.touchEngaged = false;
|
||||
this.touchTimer = null;
|
||||
this.touchStartPos = new Map();
|
||||
this.lastTouchPos = new Map();
|
||||
|
||||
this.canvas.addEventListener('touchstart', (e) => {
|
||||
if (!this.hasSpatial) return;
|
||||
|
||||
for (let i = 0; i < e.changedTouches.length; i++) {
|
||||
const t = e.changedTouches[i];
|
||||
this.touchStartPos.set(t.identifier, {x: t.clientX, y: t.clientY});
|
||||
this.lastTouchPos.set(t.identifier, {x: t.clientX, y: t.clientY});
|
||||
}
|
||||
|
||||
clearTimeout(this.touchTimer);
|
||||
|
||||
// Instantly engage if multi-touch (pinch/pan). No wait required!
|
||||
if (e.touches.length >= 2) {
|
||||
this.touchEngaged = true;
|
||||
this.hasDragged = true;
|
||||
if (e.cancelable) e.preventDefault();
|
||||
} else {
|
||||
// Single touch: wait to see if it's a page scroll
|
||||
this.touchEngaged = false;
|
||||
this.touchTimer = setTimeout(() => {
|
||||
this.touchEngaged = true;
|
||||
this.hasDragged = true;
|
||||
}, 200);
|
||||
}
|
||||
}, {passive: false});
|
||||
|
||||
this.canvas.addEventListener('touchmove', (e) => {
|
||||
if (!this.hasSpatial) return;
|
||||
|
||||
if (!this.touchEngaged) {
|
||||
// Check if they are swiping quickly before the timer completes (1 finger).
|
||||
let maxDist = 0;
|
||||
for (let i = 0; i < e.touches.length; i++) {
|
||||
const t = e.touches[i];
|
||||
const start = this.touchStartPos.get(t.identifier);
|
||||
if (start) {
|
||||
maxDist = Math.max(maxDist, Math.hypot(t.clientX - start.x, t.clientY - start.y));
|
||||
}
|
||||
}
|
||||
if (maxDist > 10) clearTimeout(this.touchTimer);
|
||||
return; // Let the browser scroll the page
|
||||
}
|
||||
|
||||
// --- CAMERA IS ENGAGED ---
|
||||
if (e.cancelable) e.preventDefault(); // Block native pinch-zoom and scrolling
|
||||
this.hasDragged = true;
|
||||
|
||||
if (e.touches.length === 1) {
|
||||
// 1 Finger: Orbit
|
||||
const t = e.touches[0];
|
||||
const last = this.lastTouchPos.get(t.identifier);
|
||||
if (last) {
|
||||
this.orbit(t.clientX - last.x, t.clientY - last.y);
|
||||
notifyCameraChange();
|
||||
}
|
||||
this.lastTouchPos.set(t.identifier, {x: t.clientX, y: t.clientY});
|
||||
} else if (e.touches.length === 2) {
|
||||
// 2 Fingers: Pan and Zoom
|
||||
const t1 = e.touches[0];
|
||||
const t2 = e.touches[1];
|
||||
const l1 = this.lastTouchPos.get(t1.identifier);
|
||||
const l2 = this.lastTouchPos.get(t2.identifier);
|
||||
|
||||
if (l1 && l2) {
|
||||
// Zoom (Pinch distance delta)
|
||||
const lastDist = Math.hypot(l1.x - l2.x, l1.y - l2.y);
|
||||
const currentDist = Math.hypot(t1.clientX - t2.clientX, t1.clientY - t2.clientY);
|
||||
this.zoomRatio(lastDist / currentDist);
|
||||
|
||||
// Pan (Center point delta)
|
||||
const lastCx = (l1.x + l2.x) / 2;
|
||||
const lastCy = (l1.y + l2.y) / 2;
|
||||
const cx = (t1.clientX + t2.clientX) / 2;
|
||||
const cy = (t1.clientY + t2.clientY) / 2;
|
||||
this.pan(cx - lastCx, cy - lastCy);
|
||||
|
||||
notifyCameraChange();
|
||||
}
|
||||
this.lastTouchPos.set(t1.identifier, {x: t1.clientX, y: t1.clientY});
|
||||
this.lastTouchPos.set(t2.identifier, {x: t2.clientX, y: t2.clientY});
|
||||
}
|
||||
}, {passive: false});
|
||||
|
||||
const handleTouchEnd = (e) => {
|
||||
for (let i = 0; i < e.changedTouches.length; i++) {
|
||||
const t = e.changedTouches[i];
|
||||
this.touchStartPos.delete(t.identifier);
|
||||
this.lastTouchPos.delete(t.identifier);
|
||||
}
|
||||
if (e.touches.length === 0) {
|
||||
clearTimeout(this.touchTimer);
|
||||
this.touchEngaged = false;
|
||||
}
|
||||
};
|
||||
|
||||
this.canvas.addEventListener('touchend', handleTouchEnd);
|
||||
this.canvas.addEventListener('touchcancel', handleTouchEnd);
|
||||
}
|
||||
|
||||
// --- TEMPORAL CONTROL ---
|
||||
@@ -273,19 +378,26 @@ export class SpacetimeController {
|
||||
onDrag(pct);
|
||||
};
|
||||
|
||||
wrapper.addEventListener('mousedown', (e) => {
|
||||
wrapper.addEventListener('pointerdown', (e) => {
|
||||
wrapper.setPointerCapture(e.pointerId);
|
||||
isTrackDragging = true;
|
||||
this.playMode = 'paused';
|
||||
update(e);
|
||||
});
|
||||
|
||||
window.addEventListener('mousemove', (e) => {
|
||||
wrapper.addEventListener('pointermove', (e) => {
|
||||
if (isTrackDragging) update(e);
|
||||
});
|
||||
|
||||
window.addEventListener('mouseup', () => {
|
||||
isTrackDragging = false;
|
||||
});
|
||||
const stopDrag = (e) => {
|
||||
if (isTrackDragging) {
|
||||
isTrackDragging = false;
|
||||
wrapper.releasePointerCapture(e.pointerId);
|
||||
}
|
||||
};
|
||||
|
||||
wrapper.addEventListener('pointerup', stopDrag);
|
||||
wrapper.addEventListener('pointercancel', stopDrag);
|
||||
}
|
||||
|
||||
bindTimelineEvents() {
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
import './components.js';
|
||||
import './components.css';
|
||||
@@ -54,10 +54,10 @@ export class TextureHandler {
|
||||
|
||||
const drawMissing = () => {
|
||||
const half = this.cellSize / 2;
|
||||
this.ctx.fillStyle = '#666666FF'; // Gray
|
||||
this.ctx.fillStyle = '#33333366'; // Gray
|
||||
this.ctx.fillRect(pos.x, pos.y, half, half);
|
||||
this.ctx.fillRect(pos.x + half, pos.y + half, half, half);
|
||||
this.ctx.fillStyle = '#333333FF'; // Black
|
||||
this.ctx.fillStyle = '#00000066'; // Black
|
||||
this.ctx.fillRect(pos.x + half, pos.y, half, half);
|
||||
this.ctx.fillRect(pos.x, pos.y + half, half, half);
|
||||
};
|
||||
|
||||
@@ -36,7 +36,7 @@ export class World {
|
||||
capturedInitialState = true;
|
||||
};
|
||||
|
||||
const lines = script.split(/\n|;|(?<=&)/).map(l => l.trim()).filter(l => l && !l.startsWith('#'));
|
||||
const lines = script.split('\n').map(l => l.trim()).filter(l => l && !l.startsWith('#'));
|
||||
|
||||
let currentBatch = [];
|
||||
|
||||
|
||||
@@ -1,13 +1,3 @@
|
||||
import {dirname, resolve} from 'node:path'
|
||||
import {defineConfig} from 'vite'
|
||||
|
||||
export default defineConfig({
|
||||
build: {
|
||||
lib: {
|
||||
entry: resolve(import.meta.dirname, 'src/lib.js'),
|
||||
name: 'mc-diorama',
|
||||
fileName: 'mc-diorama',
|
||||
formats: ['es']
|
||||
}
|
||||
}
|
||||
});
|
||||
export default {
|
||||
base: "/secret-knowledge/",
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user