First 'release'L
This commit is contained in:
61
.idea/workspace.xml
generated
61
.idea/workspace.xml
generated
@@ -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>
|
||||||
|
|||||||
@@ -51,6 +51,7 @@
|
|||||||
"./public/**",
|
"./public/**",
|
||||||
"./src/desktop${/*}"
|
"./src/desktop${/*}"
|
||||||
],
|
],
|
||||||
|
"icon": "./public/resources/soma_icon.png",
|
||||||
"directories": {
|
"directories": {
|
||||||
"output": "desktop-dist"
|
"output": "desktop-dist"
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
public/resources/soma_icon.png
Normal file
BIN
public/resources/soma_icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 37 KiB |
13
src/store.ts
13
src/store.ts
@@ -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;
|
||||||
|
|||||||
@@ -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
48
src/ui/IncDecNum.svelte
Normal 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>
|
||||||
@@ -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>
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -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>
|
||||||
@@ -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();
|
||||||
|
|||||||
Reference in New Issue
Block a user