First 'release'L

This commit is contained in:
Daniel Ledda
2021-07-04 14:00:28 +02:00
parent c950631b5e
commit 0f3696b497
10 changed files with 245 additions and 144 deletions

61
.idea/workspace.xml generated
View File

@@ -26,41 +26,15 @@
</component> </component>
<component name="ChangeListManager"> <component name="ChangeListManager">
<list default="true" id="70635ef7-86ab-4681-b98d-dc8e4999995b" name="Default Changelist" comment=""> <list default="true" id="70635ef7-86ab-4681-b98d-dc8e4999995b" name="Default Changelist" comment="">
<change afterPath="$PROJECT_DIR$/src/desktop/build.js" afterDir="false" /> <change afterPath="$PROJECT_DIR$/src/ui/IncDecNum.svelte" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/desktop/main.js" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/desktop/preload.js" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/solver/js/SomaSolver.ts" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/solver/js/VoxelSpaceBoolean.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.gitignore" beforeDir="false" afterPath="$PROJECT_DIR$/.gitignore" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" /> <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/package-lock.json" beforeDir="false" afterPath="$PROJECT_DIR$/package-lock.json" afterDir="false" />
<change beforePath="$PROJECT_DIR$/package.json" beforeDir="false" afterPath="$PROJECT_DIR$/package.json" afterDir="false" /> <change beforePath="$PROJECT_DIR$/package.json" beforeDir="false" afterPath="$PROJECT_DIR$/package.json" afterDir="false" />
<change beforePath="$PROJECT_DIR$/public/index.html" beforeDir="false" afterPath="$PROJECT_DIR$/public/index.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/public/solver/SomaSolution.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/solver/js/SomaSolution.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/public/solver/SomaSolver.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/public/solver/VoxelSpace.js" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/public/solver/main.js" beforeDir="false" afterPath="$PROJECT_DIR$/public/solver/main.js" afterDir="false" />
<change beforePath="$PROJECT_DIR$/public/solver/main.wasm" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/src/SomaSolution.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/SomaSolution.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/SomaSolver.ts" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/src/VoxelSpace.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/VoxelSpaceBigInt.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/solver/asconfig.json" beforeDir="false" afterPath="$PROJECT_DIR$/src/solver/wasm/asconfig.json" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/solver/assembly/SomaSolution.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/solver/wasm/assembly/SomaSolution.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/solver/assembly/SomaSolver.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/solver/wasm/assembly/SomaSolver.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/solver/assembly/VoxelSpace.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/solver/wasm/assembly/VoxelSpace.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/solver/assembly/index.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/solver/wasm/assembly/index.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/solver/assembly/tsconfig.json" beforeDir="false" afterPath="$PROJECT_DIR$/src/solver/wasm/assembly/tsconfig.json" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/solver/index.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/solver/wasm/index.js" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/solver/package-lock.json" beforeDir="false" afterPath="$PROJECT_DIR$/src/solver/wasm/package-lock.json" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/solver/package.json" beforeDir="false" afterPath="$PROJECT_DIR$/src/solver/wasm/package.json" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/store.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/store.ts" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/store.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/store.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/ui/CubeInput.svelte" beforeDir="false" afterPath="$PROJECT_DIR$/src/ui/CubeInput.svelte" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/ui/App.svelte" beforeDir="false" afterPath="$PROJECT_DIR$/src/ui/App.svelte" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/ui/Interactor.svelte" beforeDir="false" afterPath="$PROJECT_DIR$/src/ui/Interactor.svelte" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/ui/Sidebar.svelte" beforeDir="false" afterPath="$PROJECT_DIR$/src/ui/Sidebar.svelte" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/ui/Sidebar.svelte" beforeDir="false" afterPath="$PROJECT_DIR$/src/ui/Sidebar.svelte" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/ui/Solution2D.svelte" beforeDir="false" afterPath="$PROJECT_DIR$/src/ui/Solution2D.svelte" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/ui/SolutionViewer.svelte" beforeDir="false" afterPath="$PROJECT_DIR$/src/ui/SolutionViewer.svelte" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/ui/SolutionViewer.svelte" beforeDir="false" afterPath="$PROJECT_DIR$/src/ui/SolutionViewer.svelte" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/ui/threedee/PolycubeMesh.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/ui/threedee/PolycubeMesh.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/ui/threedee/PolycubeScene.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/ui/threedee/PolycubeScene.ts" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/ui/threedee/PolycubeScene.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/ui/threedee/PolycubeScene.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/tsconfig.json" beforeDir="false" afterPath="$PROJECT_DIR$/tsconfig.json" afterDir="false" />
</list> </list>
<option name="SHOW_DIALOG" value="false" /> <option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" /> <option name="HIGHLIGHT_CONFLICTS" value="true" />
@@ -78,6 +52,7 @@
<option value="HTML File" /> <option value="HTML File" />
<option value="JavaScript File" /> <option value="JavaScript File" />
<option value="TypeScript File" /> <option value="TypeScript File" />
<option value="IncDecNum.svelte" />
</list> </list>
</option> </option>
</component> </component>
@@ -171,7 +146,8 @@
<workItem from="1624862787465" duration="3754000" /> <workItem from="1624862787465" duration="3754000" />
<workItem from="1624953370630" duration="10086000" /> <workItem from="1624953370630" duration="10086000" />
<workItem from="1625293881668" duration="18235000" /> <workItem from="1625293881668" duration="18235000" />
<workItem from="1625330866437" duration="2495000" /> <workItem from="1625330866437" duration="4956000" />
<workItem from="1625389803555" duration="9379000" />
</task> </task>
<servers /> <servers />
</component> </component>
@@ -179,27 +155,10 @@
<option name="version" value="3" /> <option name="version" value="3" />
<option name="exactExcludedFiles"> <option name="exactExcludedFiles">
<list> <list>
<option value="$PROJECT_DIR$/src/solver/js/SomaSolver.js" />
<option value="$PROJECT_DIR$/src/SomaSolution.js" />
<option value="$PROJECT_DIR$/src/SomaSolution.js" />
<option value="$PROJECT_DIR$/src/solver/js/SomaSolver.js" />
<option value="$PROJECT_DIR$/src/VoxelSpaceBigInt.js" />
<option value="$PROJECT_DIR$/src/VoxelSpaceBoolean.js" />
<option value="$PROJECT_DIR$/src/SomaSolution.js" />
<option value="$PROJECT_DIR$/src/VoxelSpaceBigInt.js" />
<option value="$PROJECT_DIR$/src/VoxelSpaceBoolean.js" />
<option value="$PROJECT_DIR$/src/SomaSolution.js" />
<option value="$PROJECT_DIR$/src/VoxelSpaceBigInt.js" />
<option value="$PROJECT_DIR$/src/VoxelSpaceBoolean.js" />
<option value="$PROJECT_DIR$/src/SomaSolution.js" />
<option value="$PROJECT_DIR$/src/solver/js/SomaSolver.js" />
<option value="$PROJECT_DIR$/src/VoxelSpaceBigInt.js" />
<option value="$PROJECT_DIR$/src/VoxelSpaceBoolean.js" />
<option value="$PROJECT_DIR$/src/SomaSolution.js" />
<option value="$PROJECT_DIR$/src/solver/js/VoxelSpaceBoolean.js" />
<option value="$PROJECT_DIR$/src/solver/js/SomaSolution.js" /> <option value="$PROJECT_DIR$/src/solver/js/SomaSolution.js" />
<option value="$PROJECT_DIR$/src/solver/js/SomaSolver.js" /> <option value="$PROJECT_DIR$/src/solver/js/SomaSolver.js" />
<option value="$PROJECT_DIR$/src/solver/js/main.js" /> <option value="$PROJECT_DIR$/src/solver/js/main.js" />
<option value="$PROJECT_DIR$/src/solver/js/VoxelSpaceBoolean.js" />
</list> </list>
</option> </option>
</component> </component>
@@ -275,11 +234,11 @@
<screen x="0" y="27" width="1920" height="1053" /> <screen x="0" y="27" width="1920" height="1053" />
</state> </state>
<state x="834" y="395" width="250" height="278" key="jetbrains.javascript.buildTools.run-task-popup/1920.0.1920.1080/0.27.1920.1053@0.27.1920.1053" timestamp="1623671403065" /> <state x="834" y="395" width="250" height="278" key="jetbrains.javascript.buildTools.run-task-popup/1920.0.1920.1080/0.27.1920.1053@0.27.1920.1053" timestamp="1623671403065" />
<state x="1248" y="245" key="run.anything.popup" timestamp="1625305747628"> <state x="624" y="245" key="run.anything.popup" timestamp="1625390874883">
<screen x="0" y="27" width="3840" height="1053" /> <screen x="0" y="27" width="1920" height="1053" />
</state> </state>
<state x="1248" y="245" key="run.anything.popup/0.27.3840.1053@0.27.3840.1053" timestamp="1625305747628" /> <state x="1248" y="245" key="run.anything.popup/0.27.3840.1053@0.27.3840.1053" timestamp="1625305747628" />
<state x="624" y="245" key="run.anything.popup/1920.0.1920.1080/0.27.1920.1053@0.27.1920.1053" timestamp="1624805204463" /> <state x="624" y="245" key="run.anything.popup/1920.0.1920.1080/0.27.1920.1053@0.27.1920.1053" timestamp="1625390874883" />
<state x="755" y="405" width="400" height="284" key="scopes" timestamp="1621932851405"> <state x="755" y="405" width="400" height="284" key="scopes" timestamp="1621932851405">
<screen x="0" y="27" width="1920" height="1053" /> <screen x="0" y="27" width="1920" height="1053" />
</state> </state>

View File

@@ -51,6 +51,7 @@
"./public/**", "./public/**",
"./src/desktop${/*}" "./src/desktop${/*}"
], ],
"icon": "./public/resources/soma_icon.png",
"directories": { "directories": {
"output": "desktop-dist" "output": "desktop-dist"
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

View File

@@ -3,9 +3,10 @@ import { get } from 'svelte/store';
import SomaSolution from "./SomaSolution"; import SomaSolution from "./SomaSolution";
import VoxelSpaceBigInt from "./VoxelSpaceBigInt"; import VoxelSpaceBigInt from "./VoxelSpaceBigInt";
import type {DimensionDef} from "./VoxelSpaceBoolean"; import type {DimensionDef} from "./VoxelSpaceBoolean";
import PolycubeScene from "./ui/threedee/PolycubeScene";
const MAX_DIMS = 20; export const MAX_DIMS = 20;
const MIN_DIMS = 1; export const MIN_DIMS = 1;
export const solving = writable(false); export const solving = writable(false);
export const debug = writable(false); export const debug = writable(false);
@@ -29,11 +30,19 @@ export const isMinPolycubes = derived(
polycubes, polycubes,
($polycubes: VoxelSpaceBigInt[]) => $polycubes.length <= 1 ($polycubes: VoxelSpaceBigInt[]) => $polycubes.length <= 1
); );
export const cubeScene = new PolycubeScene();
function dimStore(init: number) { function dimStore(init: number) {
const dimStore = writable(init); const dimStore = writable(init);
return { return {
subscribe: dimStore.subscribe, subscribe: dimStore.subscribe,
inc() {
dimStore.set(get(dimStore) + 1);
},
dec() {
dimStore.set(get(dimStore) - 1);
},
set(dim: number) { set(dim: number) {
if (dim > MAX_DIMS || dim < MIN_DIMS) { if (dim > MAX_DIMS || dim < MIN_DIMS) {
return; return;

View File

@@ -38,20 +38,12 @@
color: white; color: white;
background: #333333; background: #333333;
} }
@media(max-width: 1600px) {
.solutionBodyContainer {
width: 100%;
}
.sidebarContainer {
width: 20%;
}
}
@media(max-width: 1200px) { @media(max-width: 1200px) {
.solutionBodyContainer { .solutionBodyContainer {
width: 100%; width: calc(100% - 18em);
} }
.sidebarContainer { .sidebarContainer {
width: 15em; width: 18em;
} }
} }
</style> </style>

48
src/ui/IncDecNum.svelte Normal file
View File

@@ -0,0 +1,48 @@
<script lang="ts">
export let up: () => void;
export let down: () => void;
export let val: number;
export let upDisabled: boolean;
export let title: string;
export let downDisabled: boolean;
</script>
<div class="container">
{#if title}
<p class="title">{title}</p>
{/if}
<div class="controls">
<button on:click={down} disabled={downDisabled}>-</button>
<p class="val">{val}</p>
<button on:click={up} disabled={upDisabled}>+</button>
</div>
</div>
<style>
.container {
margin: 0 0.5em 0 0.5em;
display: inline-block;
}
.title {
margin-bottom: 0;
}
.val {
font-weight: bold;
margin-left: 0.2em;
margin-right: 0.2em;
}
.controls {
margin-top: 0;
}
.controls > * {
display: inline-block;
}
button:hover:not(:disabled) {
cursor: pointer;
background-color: #c1c1c1;
}
button:disabled {
color: #a7a7a7;
background-color: #616161;
}
</style>

View File

@@ -3,26 +3,84 @@
import CubeInput from "./CubeInput.svelte"; import CubeInput from "./CubeInput.svelte";
import SolutionViewer from "./SolutionViewer.svelte"; import SolutionViewer from "./SolutionViewer.svelte";
$: numCubes = $polycubes.length; $: numCubes = $polycubes.length;
let showInput = true;
let smallViewport = true;
function onMediaChange() {
smallViewport = queryListWidth.matches || queryListHeight.matches;
}
const queryListWidth = window.matchMedia("(max-width: 1200px)");
const queryListHeight = window.matchMedia("(max-height: 920px)");
queryListWidth.addEventListener("change", onMediaChange);
queryListHeight.addEventListener("change", onMediaChange);
onMediaChange();
</script> </script>
<div class="viewport"> <div class="viewport">
<div class="input-container"> {#if smallViewport}
{#each {length: numCubes} as _, cubeNo} <div class="tabs">
<div class="cube-input"> <div class="tab" class:selected={showInput} on:click="{() => showInput = true}">Input</div>
<div class="padder"> <div class="tab" class:selected={!showInput} on:click="{() => showInput = false}">3D</div>
<CubeInput </div>
cubeNo={cubeNo} {#if showInput}
/> <div class="input-container">
</div> {#each {length: numCubes} as _, cubeNo}
<div class="cube-input">
<div class="padder">
<CubeInput
cubeNo={cubeNo}
/>
</div>
</div>
{/each}
</div> </div>
{/each} {:else}
</div> <div class="threedee">
<div class="threedee"> <SolutionViewer/>
<SolutionViewer/> </div>
</div> {/if}
{:else}
<div class="input-container">
{#each {length: numCubes} as _, cubeNo}
<div class="cube-input">
<div class="padder">
<CubeInput
cubeNo={cubeNo}
/>
</div>
</div>
{/each}
</div>
<div class="threedee">
<SolutionViewer/>
</div>
{/if}
</div> </div>
<style> <style>
.tabs {
height: 3em;
flex: 0 1 auto;
display: flex;
cursor: pointer;
}
.tab {
flex: 1;
border: solid black;
text-align: center;
border-width: 0 1px 1px 1px;
background-color: #555555;
line-height: 3em;
transition: background-color 100ms;
}
.tab:hover {
background-color: #999999;
}
.tab.selected {
background-color: grey;
border-width: 1px 0 0 0;
}
.threedee { .threedee {
flex: 1 1 auto; flex: 1 1 auto;
display: flex; display: flex;
@@ -38,16 +96,17 @@
margin: auto; margin: auto;
} }
.input-container { .input-container {
flex: 0 1 fit-content; flex: 1 1 auto;
overflow-x: scroll; overflow-x: scroll;
display: flex; display: flex;
flex-flow: row; flex-flow: row;
} }
.viewport { .viewport {
overflow: scroll;
display: flex; display: flex;
height: 100%; height: 100%;
align-content: center; align-content: center;
justify-content: center; justify-content: flex-start;
flex-direction: column; flex-direction: column;
} }
</style> </style>

View File

@@ -4,10 +4,17 @@
isMinPolycubes, isMinPolycubes,
polycubes, polycubes,
solutions, solutions,
colorFromIndex, solving,
activeSolution, showingSolution, totalVolume, somaDimX, somaDimY, somaDimZ, debug totalVolume,
somaDimX,
somaDimY,
somaDimZ,
MAX_DIMS,
MIN_DIMS,
solve
} from "../store"; } from "../store";
import SolutionList from "./SolutionList.svelte"; import SolutionList from "./SolutionList.svelte";
import IncDecNum from "./IncDecNum.svelte";
$: numCubes = $polycubes.length; $: numCubes = $polycubes.length;
$: cubes = $polycubes; $: cubes = $polycubes;
@@ -40,21 +47,30 @@
<div class="option"> <div class="option">
<p>Dimensions:</p> <p>Dimensions:</p>
<div class="choice"> <div class="choice">
X <IncDecNum
<input title="X"
type="number" val="{$somaDimX}"
value="3" upDisabled="{$somaDimX >= MAX_DIMS}"
on:input={(e) => somaDimX.set(e.target.valueAsNumber)}/> up="{() => somaDimX.set($somaDimX + 1)}"
Y downDisabled="{$somaDimX <= MIN_DIMS}"
<input down="{() => somaDimX.set($somaDimX - 1)}"
type="number" />
value="3" <IncDecNum
on:input={(e) => somaDimY.set(e.target.valueAsNumber)}/> title="Y"
Z val="{$somaDimY}"
<input upDisabled="{$somaDimY >= MAX_DIMS}"
type="number" up="{() => somaDimY.set($somaDimY + 1)}"
value="3" downDisabled="{$somaDimY <= MIN_DIMS}"
on:input={(e) => somaDimZ.set(e.target.valueAsNumber)}/> down="{() => somaDimY.set($somaDimY - 1)}"
/>
<IncDecNum
title="Z"
val="{$somaDimZ}"
upDisabled="{$somaDimZ >= MAX_DIMS}"
up="{() => somaDimZ.set($somaDimZ + 1)}"
downDisabled="{$somaDimZ <= MIN_DIMS}"
down="{() => somaDimZ.set($somaDimZ - 1)}"
/>
{#if $totalVolume > 32} {#if $totalVolume > 32}
<p class="warn">The total number of units exceeds 32. Attempting to solve puzzles with more than 32 units results in significantly slower computation time.</p> <p class="warn">The total number of units exceeds 32. Attempting to solve puzzles with more than 32 units results in significantly slower computation time.</p>
{/if} {/if}
@@ -64,9 +80,13 @@
<div class="option"> <div class="option">
<p>Cubes:</p> <p>Cubes:</p>
<div class="choice"> <div class="choice">
<button on:click={polycubes.removeCube} disabled={$isMinPolycubes}>-</button> <IncDecNum
<p>{numCubes}</p> down="{polycubes.removeCube}"
<button on:click={polycubes.addCube} disabled={$isMaxPolycubes}>+</button> downDisabled="{$isMinPolycubes}"
up="{polycubes.addCube}"
upDisabled="{$isMaxPolycubes}"
val="{numCubes}"
/>
</div> </div>
</div> </div>
@@ -75,8 +95,8 @@
class="solve" class="solve"
on:click={solve} on:click={solve}
title="{genTooltip(enoughSubcubes, noEmpties, size)}" title="{genTooltip(enoughSubcubes, noEmpties, size)}"
disabled="{solving || !readyToSolve}"> disabled="{$solving || !readyToSolve}">
{solving ? "Solving..." : "Solve!"} {$solving ? "Solving..." : "Solve!"}
</button> </button>
</div> </div>
</div> </div>
@@ -95,7 +115,7 @@
.choice { .choice {
display: block; display: block;
text-align: center; text-align: center;
margin-top: 1em; margin-top: 0.5em;
} }
input { input {
display: inline-block; display: inline-block;
@@ -108,14 +128,6 @@
color: white; color: white;
background-color: #ff3e00; background-color: #ff3e00;
} }
button:hover:not(:disabled) {
cursor: pointer;
background-color: #c1c1c1;
}
button:disabled {
color: #a7a7a7;
background-color: #616161;
}
button.solve { button.solve {
width: auto; width: auto;
color: white; color: white;
@@ -124,6 +136,7 @@
border-radius: 0.5em; border-radius: 0.5em;
border-style: none; border-style: none;
margin: 0; margin: 0;
cursor: pointer;
} }
button.solve:disabled { button.solve:disabled {
width: auto; width: auto;
@@ -151,8 +164,8 @@
padding-bottom: 0; padding-bottom: 0;
} }
.widgets > * { .widgets > * {
padding-top: 1em; padding-top: 0.5em;
padding-bottom: 1em; padding-bottom: 0.5em;
} }
h1 { h1 {
margin: 0; margin: 0;

View File

@@ -1,38 +1,35 @@
<script lang="ts"> <script lang="ts">
import PolycubeScene from "./threedee/PolycubeScene"; import PolycubeScene from "./threedee/PolycubeScene";
import {onMount} from "svelte"; import {onMount} from "svelte";
import {polycubes, selectedCube, solutions, activeSolution, showingSolution, somaDimX, somaDimY, somaDimZ} from "../store"; import {polycubes, selectedCube, solutions, activeSolution, showingSolution, cubeScene} from "../store";
import Solution2D from "./Solution2D.svelte"; import Solution2D from "./Solution2D.svelte";
import VoxelSpaceBoolean from "../VoxelSpaceBoolean";
$: cube = $polycubes[$selectedCube]; $: cube = $polycubes[$selectedCube];
$: soln = $solutions[$activeSolution]; $: soln = $solutions[$activeSolution];
let el: HTMLCanvasElement; let el: HTMLDivElement;
let scene: PolycubeScene; let scene: PolycubeScene;
let loaded: boolean = false; let loaded: boolean = false;
const canvasStyle: Partial<CSSStyleDeclaration> = {
borderRadius: "1em",
};
onMount(() => { onMount(() => {
scene = new PolycubeScene(el, () => loaded = true, console.log); cubeScene.onLoaded(() => {
cubeScene.mount(el);
Object.assign((el.children.item(0) as HTMLElement).style, canvasStyle);
loaded = true;
});
}); });
window.getPermutations = () => {
const newCube: VoxelSpaceBoolean = cube.clone() as VoxelSpaceBoolean;
(newCube as VoxelSpaceBoolean).cullEmptySpace();
return (newCube as VoxelSpaceBoolean).getAllPermutationsInPrism($somaDimX, $somaDimY, $somaDimZ);
}
window.showRot = (rot: VoxelSpaceBoolean) => {
scene?.showPolycube(rot);
}
$: { $: {
if (loaded) { if (loaded) {
if ($showingSolution) { if ($showingSolution) {
const colorMap = {}; const colorMap = {};
$polycubes.forEach((polycube, i) => colorMap[i] = polycube.color); $polycubes.forEach((polycube, i) => colorMap[i] = polycube.color);
scene?.showSolution(soln); cubeScene.showSolution(soln);
} else { } else {
scene?.showPolycube(cube); cubeScene.showPolycube(cube);
} }
} }
} }
@@ -44,11 +41,7 @@
<Solution2D/> <Solution2D/>
</div> </div>
{/if} {/if}
<canvas <div class="stage" bind:this={el}></div>
bind:this={el}
width="640"
height="480"
></canvas>
</div> </div>
<style> <style>
@@ -58,10 +51,7 @@
align-items: center; align-items: center;
} }
.soln2d-container { .soln2d-container {
flex: 0 1 auto;
display: inline-block; display: inline-block;
} }
canvas {
display: inline-block;
border-radius: 1em;
}
</style> </style>

View File

@@ -6,34 +6,44 @@ import type VoxelSpaceBoolean from "../../VoxelSpaceBoolean";
import type VoxelSpaceBigInt from "../../VoxelSpaceBigInt"; import type VoxelSpaceBigInt from "../../VoxelSpaceBigInt";
import GeometryManager from "./GeometryManager"; import GeometryManager from "./GeometryManager";
const DEFAULT_WIDTH = 640;
const DEFAULT_HEIGHT = 480;
export default class PolycubeScene { export default class PolycubeScene {
private renderer: THREE.WebGLRenderer; private renderer: THREE.WebGLRenderer;
private camera: THREE.Camera; private camera: THREE.PerspectiveCamera;
private mainScene: THREE.Scene; private mainScene: THREE.Scene;
private polycubeMeshes: PolycubeMesh[] = []; private polycubeMeshes: PolycubeMesh[] = [];
private controls: RotationControl; private controls: RotationControl;
private light: THREE.Light; private light: THREE.Light;
private cubeScene: THREE.Scene; private cubeScene: THREE.Scene;
private geomManager: GeometryManager; private geomManager: GeometryManager;
private canvas: HTMLCanvasElement;
private loadedCb: () => void = () => {};
private loaded: boolean = false;
constructor(el: HTMLCanvasElement, onReady: () => any, onError: (err: Error) => any) { constructor() {
this.init(el).then(onReady).catch(onError); this.init().then(() => this.loadedCb()).catch(e => console.log(e));
} }
private async init(el: HTMLCanvasElement) { private async init() {
this.renderer = new THREE.WebGLRenderer({canvas: el, antialias: true}); this.canvas = document.createElement("canvas");
this.setupCamera(el.clientWidth / el.clientHeight); this.canvas.width = 0;
this.canvas.height = 0;
this.renderer = new THREE.WebGLRenderer({canvas: this.canvas, antialias: true});
this.setupCamera(this.canvas.clientWidth / this.canvas.clientHeight);
this.setupLight(); this.setupLight();
this.mainScene = new THREE.Scene(); this.mainScene = new THREE.Scene();
this.cubeScene = new THREE.Scene(); this.cubeScene = new THREE.Scene();
this.mainScene.add(this.cubeScene, this.camera, this.light); this.mainScene.add(this.cubeScene, this.camera, this.light);
this.cubeScene.rotateX(Math.PI/4); this.cubeScene.rotateX(Math.PI/4);
this.cubeScene.rotateY(Math.PI/4); this.cubeScene.rotateY(Math.PI/4);
this.controls = new RotationControl(this.cubeScene, this.polycubeMeshes, this.camera, el); this.controls = new RotationControl(this.cubeScene, this.polycubeMeshes, this.camera, this.canvas);
this.geomManager = await new GeometryManager('../resources/', () => { this.geomManager = await new GeometryManager('../resources/', () => {
requestAnimationFrame((timestamp) => this.render(timestamp)); requestAnimationFrame((timestamp) => this.render(timestamp));
}); });
PolycubeMesh.setManager(this.geomManager); PolycubeMesh.setManager(this.geomManager);
this.loaded = true;
} }
private setupCamera(aspect: number) { private setupCamera(aspect: number) {
@@ -45,6 +55,26 @@ export default class PolycubeScene {
this.camera.lookAt(0, 0, 0); this.camera.lookAt(0, 0, 0);
} }
mount(el: HTMLDivElement) {
this.canvas.width = DEFAULT_WIDTH;
this.canvas.height = DEFAULT_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);
}
onLoaded(cb: () => void) {
if (this.loaded) {
cb();
}
this.loadedCb = cb;
}
isLoaded(): boolean {
return this.loaded;
}
showPolycube(voxelSpace: VoxelSpaceBoolean) { showPolycube(voxelSpace: VoxelSpaceBoolean) {
this.controls.disableFly(); this.controls.disableFly();
this.clearScene(); this.clearScene();