\ No newline at end of file
diff --git a/src/ui/SolutionList.svelte b/src/ui/SolutionList.svelte
index 00df79b..a72399a 100644
--- a/src/ui/SolutionList.svelte
+++ b/src/ui/SolutionList.svelte
@@ -20,5 +20,6 @@
\ No newline at end of file
diff --git a/src/ui/SolveButton.svelte b/src/ui/SolveButton.svelte
index 3a2f6bc..cb55a9a 100644
--- a/src/ui/SolveButton.svelte
+++ b/src/ui/SolveButton.svelte
@@ -1,6 +1,7 @@
-
\ No newline at end of file
diff --git a/src/ui/Stage.svelte b/src/ui/Stage.svelte
index ae227af..0fb41a2 100644
--- a/src/ui/Stage.svelte
+++ b/src/ui/Stage.svelte
@@ -1,5 +1,5 @@
-
- {#if $activeSolution !== null}
+
+ {#if $showingSolution && ($activeSolution !== null)}
+ {:else if !$showingSolution}
+
+
+
{/if}
@@ -49,6 +69,11 @@
flex: 0 1 auto;
display: inline-block;
}
+ @media (max-width: 1200px) {
+ .soln2d-container {
+ display: none;
+ }
+ }
.container {
flex: 1 1 auto;
display: flex;
@@ -57,5 +82,6 @@
justify-content: space-evenly;
text-align: center;
align-items: center;
+ overflow: hidden;
}
\ No newline at end of file
diff --git a/src/ui/threedee/PolycubeScene.ts b/src/ui/threedee/PolycubeScene.ts
index c196a41..7c98f6c 100644
--- a/src/ui/threedee/PolycubeScene.ts
+++ b/src/ui/threedee/PolycubeScene.ts
@@ -21,8 +21,10 @@ export default class PolycubeScene {
private canvas: HTMLCanvasElement;
private loadedCb: () => void = () => {};
private loaded: boolean = false;
+ private windowDims: {width: number, height: number};
- constructor() {
+ constructor(windowDims?: {width: number, height: number}) {
+ this.windowDims = windowDims ?? {width: DEFAULT_WIDTH, height: DEFAULT_HEIGHT};
this.init().then(() => this.loadedCb()).catch(e => console.log(e));
}
@@ -56,12 +58,24 @@ export default class PolycubeScene {
}
mount(el: HTMLDivElement) {
- this.canvas.width = DEFAULT_WIDTH;
- this.canvas.height = DEFAULT_HEIGHT;
+ this.updateDims(this.windowDims);
+ el.append(this.canvas);
+ }
+
+ updateDims(windowDims: {width: number, height: number}) {
+ this.windowDims.width = windowDims.width;
+ this.windowDims.height = windowDims.height;
+ this.canvas.width = this.windowDims.width;
+ this.canvas.height = this.windowDims.height;
this.camera.aspect = this.canvas.width / this.canvas.height;
this.camera.updateProjectionMatrix();
this.renderer.setSize(this.canvas.width, this.canvas.height);
- el.append(this.canvas);
+ }
+
+ resetDims() {
+ this.windowDims.width = DEFAULT_WIDTH;
+ this.windowDims.height = DEFAULT_HEIGHT;
+ this.updateDims(this.windowDims);
}
onLoaded(cb: () => void) {
diff --git a/src/ui/threedee/RotationControl.ts b/src/ui/threedee/RotationControl.ts
index fc45967..98242e3 100644
--- a/src/ui/threedee/RotationControl.ts
+++ b/src/ui/threedee/RotationControl.ts
@@ -1,4 +1,5 @@
import type * as THREE from 'three';
+import {MOUSE} from "three";
interface Fliable {
flyBy(factor: number);
@@ -17,6 +18,10 @@ export default class RotationControls {
private start: THREE.Euler;
private fliables: Fliable[];
private hovered: boolean = false;
+ private scrolling: boolean = false;
+ private lastTouch: {x: number, y: number} = {x: 0, y: 0};
+ private lastScroll1: {x: number, y: number} = {x: 0, y: 0};
+ private lastScroll2: {x: number, y: number} = {x: 0, y: 0};
constructor(object: THREE.Object3D, fliables: Fliable[], camera: THREE.Camera, element: HTMLCanvasElement) {
this.object = object;
@@ -28,23 +33,29 @@ export default class RotationControls {
this.xAxis = this.xAxis.clone().cross(this.yAxis.clone());
this.start = this.object.rotation.clone();
+ this.element.addEventListener('touchstart', (ev) => this.handleTouchStart(ev));
+ this.element.addEventListener("touchcancel", (ev) => this.handleTouchEnd(ev));
+ window.addEventListener('touchmove', (ev) => this.handleTouchMove(ev));
+ window.addEventListener('touchend', (ev) => this.handleTouchEnd(ev));
+ this.element.addEventListener('wheel', (ev) => this.handleScroll(ev));
this.element.addEventListener('mouseover', () => this.hovered = true);
this.element.addEventListener('mouseout', () => this.hovered = false);
- this.element.addEventListener('wheel', (ev) => this.handleScroll(ev));
- this.element.addEventListener('mousedown', (event) => {
- if (event.button === 1) {
- this.object.setRotationFromEuler(this.start);
- }
- if (!this.dragging) {
- this.lastX = event.x;
- this.lastY = event.y;
- this.dragging = true;
- }
- });
+ this.element.addEventListener('mousedown', (ev) => this.handleMouseDown(ev));
window.addEventListener('mousemove', (ev) => this.handleMove(ev));
window.addEventListener('mouseup', () => this.dragging = false);
}
+ private handleMouseDown(event: MouseEvent) {
+ if (event.button === 1) {
+ this.object.setRotationFromEuler(this.start);
+ }
+ if (!this.dragging) {
+ this.lastX = event.x;
+ this.lastY = event.y;
+ this.dragging = true;
+ }
+ }
+
private handleMove(event: MouseEvent) {
if (this.dragging) {
const xDiff = event.movementX * RotationControls.ROTATION_FACTOR;
@@ -63,6 +74,56 @@ export default class RotationControls {
}
}
+ private handleTouchMove(event: TouchEvent) {
+ if (this.dragging) {
+ const newTouchX = event.touches.item(0).clientX;
+ const newTouchY = event.touches.item(0).clientY;
+ const touchDiffX = newTouchX - this.lastTouch.x;
+ const touchDiffY = newTouchY - this.lastTouch.y;
+ const xDiff = touchDiffX * RotationControls.ROTATION_FACTOR;
+ const yDiff = touchDiffY * RotationControls.ROTATION_FACTOR;
+ this.object.rotateOnAxis(this.yAxis, xDiff);
+ this.object.rotateOnWorldAxis(this.xAxis, yDiff);
+ this.lastTouch.x = newTouchX;
+ this.lastTouch.y = newTouchY;
+ } else if (this.scrolling) {
+ if (this.flyingEnabled && this.hovered) {
+ const newTouchX1 = event.touches.item(0).clientX;
+ const newTouchX2 = event.touches.item(1).clientX;
+ const newTouchY1 = event.touches.item(0).clientY;
+ const newTouchY2 = event.touches.item(1).clientY;
+ const lastDist = Math.sqrt((this.lastScroll1.x - this.lastScroll2.x) ** 2 + (this.lastScroll1.y - this.lastScroll2.y) ** 2);
+ const newDist = Math.sqrt((newTouchX1 - newTouchX2) ** 2 + (newTouchY1 - newTouchY2) ** 2)
+ const delta = newDist - lastDist;
+ for (const fliable of this.fliables) {
+ const direction = delta / Math.abs(delta);
+ fliable.flyBy(direction / 10);
+ }
+ }
+ }
+ }
+
+ private handleTouchStart(event: TouchEvent) {
+ if (event.touches.length === 1) {
+ this.lastTouch.x = event.touches.item(0).clientX;
+ this.lastTouch.y = event.touches.item(0).clientY;
+ this.dragging = true;
+ } else if (event.touches.length === 2) {
+ this.lastScroll1.x = event.touches.item(0).clientX;
+ this.lastScroll1.y = event.touches.item(0).clientY;
+ this.lastScroll2.x = event.touches.item(1).clientX;
+ this.lastScroll2.y = event.touches.item(1).clientY;
+ this.scrolling = true;
+ }
+ this.hovered = true;
+ }
+
+ private handleTouchEnd(event: TouchEvent) {
+ this.dragging = false;
+ this.scrolling = false;
+ this.hovered = false;
+ }
+
enableFly() {
this.flyingEnabled = true;
}