feat: allow to edit the print layout
Merge branch 'movable-print'
This commit is contained in:
commit
381d497a15
@ -1 +1,2 @@
|
|||||||
export const browser = true;
|
export const browser = true;
|
||||||
|
export const dev = true;
|
||||||
|
1
fake/app/paths.js
Normal file
1
fake/app/paths.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
export const base = "";
|
@ -18,9 +18,6 @@
|
|||||||
"@sveltejs/adapter-static": "^1.0.0-next.28",
|
"@sveltejs/adapter-static": "^1.0.0-next.28",
|
||||||
"@sveltejs/kit": "^1.0.0-next.288",
|
"@sveltejs/kit": "^1.0.0-next.288",
|
||||||
"@sveltejs/vite-plugin-svelte": "^1.0.0-next.38",
|
"@sveltejs/vite-plugin-svelte": "^1.0.0-next.38",
|
||||||
"@vitebook/client": "^0.23.2",
|
|
||||||
"@vitebook/core": "^0.23.2",
|
|
||||||
"@vitebook/theme-default": "^0.23.2",
|
|
||||||
"eslint": "^8.10.0",
|
"eslint": "^8.10.0",
|
||||||
"eslint-config-prettier": "^8.4.0",
|
"eslint-config-prettier": "^8.4.0",
|
||||||
"eslint-plugin-svelte3": "^3.4.1",
|
"eslint-plugin-svelte3": "^3.4.1",
|
||||||
@ -28,13 +25,12 @@
|
|||||||
"prettier-plugin-svelte": "^2.6.0",
|
"prettier-plugin-svelte": "^2.6.0",
|
||||||
"standard-version": "^9.3.2",
|
"standard-version": "^9.3.2",
|
||||||
"storybook-builder-vite": "0.1.21",
|
"storybook-builder-vite": "0.1.21",
|
||||||
"svelte": "^3.46.4",
|
"svelte": "^3.46.4"
|
||||||
"vite": "^2.7.0"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@storybook/addon-essentials": "^6.4.19",
|
"@storybook/addon-essentials": "^6.4.19",
|
||||||
"@storybook/addon-svelte-csf": "^1.1.0",
|
"@storybook/addon-svelte-csf": "^1.1.0",
|
||||||
"@storybook/svelte": "^6.4.19",
|
"@storybook/svelte": "^6.4.21",
|
||||||
"@sveltejs/adapter-node": "^1.0.0-next.0",
|
"@sveltejs/adapter-node": "^1.0.0-next.0",
|
||||||
"chota": "^0.8.0",
|
"chota": "^0.8.0",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
|
@ -1,4 +1,12 @@
|
|||||||
<div>
|
<div
|
||||||
|
use:movable={{
|
||||||
|
disabled: !isMovable,
|
||||||
|
}}
|
||||||
|
on:translate={({ detail: translate }) => {
|
||||||
|
ship.dispatch.setUITransform({ system: "hull", translate });
|
||||||
|
}}
|
||||||
|
style:transform={hull?.uiTransform}
|
||||||
|
>
|
||||||
{#each rows as row, i (i)}
|
{#each rows as row, i (i)}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{#each row as threshold, j (j)}
|
{#each row as threshold, j (j)}
|
||||||
@ -13,10 +21,18 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { base } from '$app/paths';
|
import { base } from "$app/paths";
|
||||||
|
import { getContext } from "svelte";
|
||||||
|
|
||||||
|
import { movable } from "../../MainSystems/movable.js";
|
||||||
|
|
||||||
export let shipMass = 0;
|
export let shipMass = 0;
|
||||||
export let rating = 0;
|
export let rating = 0;
|
||||||
export let advanced = false;
|
export let advanced = false;
|
||||||
|
export let hull = {};
|
||||||
|
export let isMovable = false;
|
||||||
|
|
||||||
|
const ship = getContext("ship");
|
||||||
|
|
||||||
let nbr_rows;
|
let nbr_rows;
|
||||||
$: nbr_rows = advanced ? 3 : 4;
|
$: nbr_rows = advanced ? 3 : 4;
|
||||||
@ -50,9 +66,9 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.row {
|
.row {
|
||||||
margin-bottom: 0.5em;
|
margin-bottom: 0.5em;
|
||||||
}
|
}
|
||||||
.cell {
|
.cell {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-right: 0.5em;
|
margin-right: 0.5em;
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
<div>
|
<div>
|
||||||
<Armour armour={structure.armour} />
|
<Armour armour={structure.armour} />
|
||||||
<Integrity
|
<Integrity
|
||||||
|
{isMovable}
|
||||||
|
hull={structure?.hull}
|
||||||
rating={structure.hull.rating}
|
rating={structure.hull.rating}
|
||||||
advanced={structure.hull.advanced}
|
advanced={structure.hull.advanced}
|
||||||
{ship_mass}
|
{ship_mass}
|
||||||
@ -13,4 +15,5 @@
|
|||||||
|
|
||||||
export let structure = {};
|
export let structure = {};
|
||||||
export let ship_mass = 0;
|
export let ship_mass = 0;
|
||||||
|
export let isMovable = false;
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,28 +1,33 @@
|
|||||||
<div class="main_systems">
|
<div class="main_systems">
|
||||||
{#if ftl !== "none"}
|
{#if ftl !== "none"}
|
||||||
<img
|
<img
|
||||||
bind:this={targetFTL}
|
|
||||||
class="ftl"
|
class="ftl"
|
||||||
src="{base}/icons/ftl-drive.svg"
|
src="{base}/icons/ftl-drive.svg"
|
||||||
alt="ftl drive"
|
alt="ftl drive"
|
||||||
|
use:movable={{
|
||||||
|
disabled: !isMovable,
|
||||||
|
}}
|
||||||
|
on:translate={({ detail: translate }) => {
|
||||||
|
ship.dispatch.setUITransform({ system: "ftl", translate });
|
||||||
|
}}
|
||||||
|
style:transform={ftl?.uiTransform}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{#if movable}
|
|
||||||
<Movable target={targetFTL} />
|
|
||||||
{/if}
|
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if engine > 0}
|
{#if engine > 0}
|
||||||
<div
|
<div
|
||||||
bind:this={targetEngine}
|
|
||||||
class="thrust"
|
class="thrust"
|
||||||
style="background-image: url({base}/icons/standard-drive.svg);"
|
style="background-image: url({base}/icons/standard-drive.svg);"
|
||||||
|
use:movable={{
|
||||||
|
disabled: !isMovable,
|
||||||
|
}}
|
||||||
|
on:translate={({ detail: translate }) => {
|
||||||
|
ship.dispatch.setUITransform({ system: "drive", translate });
|
||||||
|
}}
|
||||||
|
style:transform={drive?.uiTransform}
|
||||||
>
|
>
|
||||||
{engine}
|
{engine}
|
||||||
</div>
|
</div>
|
||||||
{#if movable}
|
|
||||||
<Movable target={targetEngine} />
|
|
||||||
{/if}
|
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<img
|
<img
|
||||||
@ -30,20 +35,36 @@
|
|||||||
src="{base}/icons/internal-systems.svg"
|
src="{base}/icons/internal-systems.svg"
|
||||||
alt="internal systems"
|
alt="internal systems"
|
||||||
bind:this={targetInternal}
|
bind:this={targetInternal}
|
||||||
|
use:movable={{
|
||||||
|
disabled: !isMovable,
|
||||||
|
}}
|
||||||
|
on:translate={({ detail: translate }) => {
|
||||||
|
ship.dispatch.setUITransform({ system: "internalSystems", translate });
|
||||||
|
}}
|
||||||
|
style:transform={structure?.uiTransform}
|
||||||
/>
|
/>
|
||||||
{#if movable}
|
|
||||||
<Movable target={targetInternal} />
|
|
||||||
{/if}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { getContext } from "svelte";
|
||||||
import { base } from "$app/paths";
|
import { base } from "$app/paths";
|
||||||
|
|
||||||
import Movable from "./Movable.svelte";
|
import Movable from "./Movable.svelte";
|
||||||
|
import { movable } from "./movable.js";
|
||||||
|
|
||||||
export let ftl = "none";
|
export let ftl = "none";
|
||||||
export let engine = 0;
|
export let engine = 0;
|
||||||
export let movable = false;
|
export let isMovable = false;
|
||||||
|
export let structure = {};
|
||||||
|
export let drive = {};
|
||||||
|
|
||||||
|
let internalTranslate = "translate(50px,50px)";
|
||||||
|
|
||||||
|
const ship = getContext("ship");
|
||||||
|
|
||||||
|
let frame = {
|
||||||
|
translate: [0, 0],
|
||||||
|
};
|
||||||
|
|
||||||
let targetFTL;
|
let targetFTL;
|
||||||
let targetInternal;
|
let targetInternal;
|
||||||
|
64
src/lib/components/Output/Print/MainSystems/movable.js
Normal file
64
src/lib/components/Output/Print/MainSystems/movable.js
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
import VanillaMoveable, { PROPERTIES, EVENTS } from "moveable";
|
||||||
|
import { camelize, isUndefined } from "@daybrush/utils";
|
||||||
|
|
||||||
|
function createMoveable(node, options) {
|
||||||
|
let translate = [0, 0];
|
||||||
|
|
||||||
|
options = {
|
||||||
|
originDraggable: true,
|
||||||
|
originRelative: true,
|
||||||
|
draggable: true,
|
||||||
|
throttleDrag: 0,
|
||||||
|
zoom: 1,
|
||||||
|
origin: false,
|
||||||
|
onDrag(e) {
|
||||||
|
translate = e.beforeTranslate;
|
||||||
|
node.dispatchEvent(new CustomEvent("translate", { detail: translate }));
|
||||||
|
},
|
||||||
|
target: node,
|
||||||
|
...options,
|
||||||
|
};
|
||||||
|
|
||||||
|
const moveable = new VanillaMoveable(document.body, options);
|
||||||
|
|
||||||
|
EVENTS.forEach((name) => {
|
||||||
|
const onName = camelize(`on ${name}`);
|
||||||
|
moveable.on(name, (e) => {
|
||||||
|
const result = options[onName] && options[onName](e);
|
||||||
|
const result2 = node.dispatchEvent(new CustomEvent(name, { detail: e }));
|
||||||
|
|
||||||
|
return !isUndefined(result)
|
||||||
|
? result
|
||||||
|
: !isUndefined(result2)
|
||||||
|
? result2
|
||||||
|
: undefined;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return moveable;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function movable(node, options) {
|
||||||
|
let moveable = options.disabled ? undefined : createMoveable(options);
|
||||||
|
|
||||||
|
const destroy = () => {
|
||||||
|
if (!moveable) return;
|
||||||
|
moveable.destroy();
|
||||||
|
moveable = undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
const update = async (params) => {
|
||||||
|
if (params.disabled) {
|
||||||
|
destroy();
|
||||||
|
} else {
|
||||||
|
if (!moveable) {
|
||||||
|
moveable = createMoveable(node, params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
destroy,
|
||||||
|
update,
|
||||||
|
};
|
||||||
|
}
|
@ -1,15 +1,16 @@
|
|||||||
<Meta title="Output/Print" component={Print} argTypes={{
|
<Meta
|
||||||
ship: {
|
title="Output/Print"
|
||||||
type: 'object',
|
component={Print}
|
||||||
defaultValue: sample
|
argTypes={{
|
||||||
}
|
isMovable: { defaultValue: false },
|
||||||
}} />
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
<Story name="Primary" args={{}} />
|
<Story name="Primary" args={{}} />
|
||||||
|
|
||||||
<Template let:args>
|
<Template let:args>
|
||||||
<div style="width: 50em">
|
<div style="width: 50em; positive: relative;">
|
||||||
<Print ship={sample}/>
|
<Print ship={$shipState} {...args} />
|
||||||
</div>
|
</div>
|
||||||
</Template>
|
</Template>
|
||||||
|
|
||||||
@ -17,7 +18,16 @@
|
|||||||
import { Meta, Template, Story } from "@storybook/addon-svelte-csf";
|
import { Meta, Template, Story } from "@storybook/addon-svelte-csf";
|
||||||
import { action } from "@storybook/addon-actions";
|
import { action } from "@storybook/addon-actions";
|
||||||
|
|
||||||
import sample from './sample.js';
|
import { setContext } from "svelte";
|
||||||
|
|
||||||
import Print from './index.svelte';
|
import sample from "./sample.js";
|
||||||
|
import shipStore from "$lib/store/ship.js";
|
||||||
|
|
||||||
|
const ship = shipStore(sample);
|
||||||
|
|
||||||
|
setContext("ship", ship);
|
||||||
|
|
||||||
|
const shipState = ship.state;
|
||||||
|
|
||||||
|
import Print from "./index.svelte";
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,14 +1,27 @@
|
|||||||
<div>
|
<div
|
||||||
{#each range(1,firecons) as firecon}
|
style:transform={uiTransform}
|
||||||
|
use:movable={{
|
||||||
|
disabled: !isMovable,
|
||||||
|
ship,
|
||||||
|
system: "firecons",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{#each range(1, stations) as firecon}
|
||||||
<img class="firecon" src="{base}/icons/firecon.svg" alt="firecon" />
|
<img class="firecon" src="{base}/icons/firecon.svg" alt="firecon" />
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { base } from '$app/paths';
|
import { base } from "$app/paths";
|
||||||
import {range} from "$lib/utils.js";
|
import { range } from "$lib/utils.js";
|
||||||
|
import { getContext } from "svelte";
|
||||||
|
import { movable } from "../../movable.js";
|
||||||
|
|
||||||
export let firecons = 0;
|
export let stations = 0;
|
||||||
|
export let isMovable = false;
|
||||||
|
export let uiTransform = "";
|
||||||
|
|
||||||
|
const ship = getContext("ship");
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@ -1,18 +1,33 @@
|
|||||||
<div>
|
<div
|
||||||
{#each range(1,standard) as i}
|
use:movable={{
|
||||||
|
disabled: !isMovable,
|
||||||
|
}}
|
||||||
|
on:translate={({ detail: translate }) => {
|
||||||
|
ship.dispatch.setUITransform({ system: "screens", translate });
|
||||||
|
}}
|
||||||
|
style:transform={uiTransform}
|
||||||
|
>
|
||||||
|
{#each range(1, standard) as i}
|
||||||
<img src="{base}/icons/screen.svg" alt="screen" />
|
<img src="{base}/icons/screen.svg" alt="screen" />
|
||||||
{/each}
|
{/each}
|
||||||
{#each range(1,advanced) as i}
|
{#each range(1, advanced) as i}
|
||||||
<img src="{base}/icons/screen-advanced.svg" alt="advanced screen" />
|
<img src="{base}/icons/screen-advanced.svg" alt="advanced screen" />
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { base } from '$app/paths';
|
import { base } from "$app/paths";
|
||||||
import {range} from "$lib/utils.js";
|
import { range } from "$lib/utils.js";
|
||||||
|
import { getContext } from "svelte";
|
||||||
|
|
||||||
|
import { movable } from "../../MainSystems/movable.js";
|
||||||
|
|
||||||
export let standard = 0;
|
export let standard = 0;
|
||||||
export let advanced = 0;
|
export let advanced = 0;
|
||||||
|
export let uiTransform = "";
|
||||||
|
export let isMovable = false;
|
||||||
|
|
||||||
|
const ship = getContext("ship");
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<Firecons {firecons} />
|
<Firecons {isMovable} {...firecons} />
|
||||||
|
|
||||||
<Screens {...screens} />
|
<Screens {isMovable} {...screens} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
export let firecons = 0;
|
export let firecons = 0;
|
||||||
export let screens = {};
|
export let screens = {};
|
||||||
|
export let isMovable = false;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@ -1,4 +1,11 @@
|
|||||||
<div>
|
<div
|
||||||
|
style:transform={uiTransform}
|
||||||
|
use:movable={{
|
||||||
|
disabled: !isMovable,
|
||||||
|
ship,
|
||||||
|
system: ["weapon", id],
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Arcs selected={arcs} size="40">
|
<Arcs selected={arcs} size="40">
|
||||||
<text x="50%" y="50%">
|
<text x="50%" y="50%">
|
||||||
{weaponClass}
|
{weaponClass}
|
||||||
@ -7,9 +14,15 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { getContext } from "svelte";
|
||||||
|
import { movable } from "../../movable.js";
|
||||||
import Arcs from "$lib/components/ShipEdit/Weaponry/Weapon/Arcs.svelte";
|
import Arcs from "$lib/components/ShipEdit/Weaponry/Weapon/Arcs.svelte";
|
||||||
export let weaponClass = 1;
|
export let weaponClass = 1;
|
||||||
export let arcs = [];
|
export let arcs = [];
|
||||||
|
export let uiTransform = "";
|
||||||
|
export let isMovable = false;
|
||||||
|
export let id = -1;
|
||||||
|
const ship = getContext("ship");
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@ -1,17 +1,22 @@
|
|||||||
<div class="weapons">
|
<div class="weapons">
|
||||||
<div class="beams">
|
<div class="beams">
|
||||||
{#each beams as beam}
|
{#each beams as beam}
|
||||||
<Beam {...beam} />
|
<Beam {isMovable} {...beam} />
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Beam from "./Beam/index.svelte";
|
import Beam from "./Beam/index.svelte";
|
||||||
|
import { getContext } from "svelte";
|
||||||
|
import { movable } from "../movable.js";
|
||||||
export let weapons = [];
|
export let weapons = [];
|
||||||
|
export let isMovable = false;
|
||||||
|
|
||||||
let beams = [];
|
let beams = [];
|
||||||
$: beams = weapons.filter(({ type }) => type === "beam");
|
$: beams = weapons.filter(({ type }) => type === "beam");
|
||||||
|
|
||||||
|
const ship = getContext("ship");
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
<div class="notice">
|
<div class="notice">
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" bind:checked={movable} /> enable wiggletron (<i
|
<input type="checkbox" bind:checked={isMovable} /> edit layout
|
||||||
>alpha feature</i
|
|
||||||
>)
|
|
||||||
</label>
|
</label>
|
||||||
|
<button class="button error" on:click={resetLayout}>reset layout</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="print-output">
|
<div class="print-output">
|
||||||
@ -15,26 +14,34 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="section-2">
|
<div class="section-2">
|
||||||
<Hull structure={ship.structure} shipMass={ship.identification.mass} />
|
<Hull
|
||||||
|
structure={ship.structure}
|
||||||
|
shipMass={ship.identification.mass}
|
||||||
|
{isMovable}
|
||||||
|
/>
|
||||||
|
|
||||||
<Systems
|
<Systems
|
||||||
firecons={ship.weaponry.firecons.nbr}
|
{isMovable}
|
||||||
|
firecons={ship.weaponry.firecons}
|
||||||
screens={ship.structure.screens}
|
screens={ship.structure.screens}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Weapons weapons={ship.weaponry.weapons} />
|
<Weapons {isMovable} weapons={ship.weaponry.weapons} />
|
||||||
|
|
||||||
<MainSystems
|
<MainSystems
|
||||||
{movable}
|
{isMovable}
|
||||||
ftl={ship?.propulsion?.ftl}
|
ftl={ship?.propulsion?.ftl}
|
||||||
engine={ship?.propulsion?.drive?.rating}
|
engine={ship?.propulsion?.drive?.rating}
|
||||||
|
drive={ship?.propulsion?.drive}
|
||||||
|
structure={ship?.structure}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="notice">Printing this page will only prints the ship sheet.</div>
|
<div class="notice">Printing this page will only prints the ship sheet.</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { getContext } from "svelte";
|
||||||
import Identification from "./Identification/index.svelte";
|
import Identification from "./Identification/index.svelte";
|
||||||
import MainSystems from "./MainSystems/index.svelte";
|
import MainSystems from "./MainSystems/index.svelte";
|
||||||
import Hull from "./Hull/index.svelte";
|
import Hull from "./Hull/index.svelte";
|
||||||
@ -42,7 +49,14 @@
|
|||||||
import Systems from "./Systems/index.svelte";
|
import Systems from "./Systems/index.svelte";
|
||||||
|
|
||||||
export let ship = {};
|
export let ship = {};
|
||||||
let movable = false;
|
export let isMovable = false;
|
||||||
|
|
||||||
|
const { dispatch } = getContext("ship");
|
||||||
|
|
||||||
|
const resetLayout = () => {
|
||||||
|
isMovable = false;
|
||||||
|
dispatch.resetLayout();
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@ -64,6 +78,10 @@
|
|||||||
font-style: italic;
|
font-style: italic;
|
||||||
margin-top: 1em;
|
margin-top: 1em;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
|
display: flex;
|
||||||
|
justify-content: end;
|
||||||
|
align-items: center;
|
||||||
|
gap: 3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media print {
|
@media print {
|
||||||
|
76
src/lib/components/Output/Print/movable.js
Normal file
76
src/lib/components/Output/Print/movable.js
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
import VanillaMoveable, { PROPERTIES, EVENTS } from "moveable";
|
||||||
|
import { camelize, isUndefined } from "@daybrush/utils";
|
||||||
|
|
||||||
|
function createMoveable(node, options) {
|
||||||
|
let translate = [0, 0];
|
||||||
|
|
||||||
|
let ship = options.ship;
|
||||||
|
let system = options.system;
|
||||||
|
delete options.ship;
|
||||||
|
delete options.system;
|
||||||
|
|
||||||
|
if (Array.isArray(system)) {
|
||||||
|
system = { system: system[0], systemId: system[1] };
|
||||||
|
} else {
|
||||||
|
system = { system };
|
||||||
|
}
|
||||||
|
|
||||||
|
options = {
|
||||||
|
originDraggable: true,
|
||||||
|
originRelative: true,
|
||||||
|
draggable: true,
|
||||||
|
throttleDrag: 0,
|
||||||
|
zoom: 1,
|
||||||
|
origin: false,
|
||||||
|
onDrag(e) {
|
||||||
|
translate = e.beforeTranslate;
|
||||||
|
node.dispatchEvent(new CustomEvent("translate", { detail: translate }));
|
||||||
|
ship.dispatch.setUITransform({ ...system, translate });
|
||||||
|
},
|
||||||
|
target: node,
|
||||||
|
...options,
|
||||||
|
};
|
||||||
|
|
||||||
|
const moveable = new VanillaMoveable(document.body, options);
|
||||||
|
|
||||||
|
EVENTS.forEach((name) => {
|
||||||
|
const onName = camelize(`on ${name}`);
|
||||||
|
moveable.on(name, (e) => {
|
||||||
|
const result = options[onName] && options[onName](e);
|
||||||
|
const result2 = node.dispatchEvent(new CustomEvent(name, { detail: e }));
|
||||||
|
|
||||||
|
return !isUndefined(result)
|
||||||
|
? result
|
||||||
|
: !isUndefined(result2)
|
||||||
|
? result2
|
||||||
|
: undefined;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return moveable;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function movable(node, options) {
|
||||||
|
let moveable = options.disabled ? undefined : createMoveable(options);
|
||||||
|
|
||||||
|
const destroy = () => {
|
||||||
|
if (!moveable) return;
|
||||||
|
moveable.destroy();
|
||||||
|
moveable = undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
const update = async (params) => {
|
||||||
|
if (params.disabled) {
|
||||||
|
destroy();
|
||||||
|
} else {
|
||||||
|
if (!moveable) {
|
||||||
|
moveable = createMoveable(node, params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
destroy,
|
||||||
|
update,
|
||||||
|
};
|
||||||
|
}
|
@ -11,48 +11,96 @@ import weaponry from "./weaponry/index.js";
|
|||||||
import { screensReqsReaction } from "./structure/screens.js";
|
import { screensReqsReaction } from "./structure/screens.js";
|
||||||
|
|
||||||
const dux = new Updux({
|
const dux = new Updux({
|
||||||
subduxes: {
|
subduxes: {
|
||||||
identification,
|
identification,
|
||||||
propulsion,
|
propulsion,
|
||||||
structure,
|
structure,
|
||||||
carrier,
|
carrier,
|
||||||
weaponry,
|
weaponry,
|
||||||
},
|
},
|
||||||
initial: {
|
initial: {
|
||||||
reqs: { cost: 0, mass: 10, usedMass: 0 },
|
reqs: { cost: 0, mass: 10, usedMass: 0 },
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
setShipReqs: null,
|
setShipReqs: null,
|
||||||
},
|
setUITransform: null,
|
||||||
|
resetLayout: null,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function resetUITransform(thing) {
|
||||||
|
if (typeof thing !== "object") return thing;
|
||||||
|
|
||||||
|
return u.map(
|
||||||
|
(v, k) => (k === "uiTransform" ? "" : resetUITransform(v)),
|
||||||
|
thing
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
dux.setMutation("resetLayout", () => resetUITransform);
|
||||||
|
|
||||||
dux.setMutation("setShipMass", (mass) => u({ reqs: { mass } }));
|
dux.setMutation("setShipMass", (mass) => u({ reqs: { mass } }));
|
||||||
dux.setMutation('setShipReqs', reqs => u({reqs}));
|
dux.setMutation("setShipReqs", (reqs) => u({ reqs }));
|
||||||
|
|
||||||
|
dux.setMutation("setUITransform", ({ system, systemId, translate }) => {
|
||||||
|
const transform = translate
|
||||||
|
? `translate(${translate[0]}px,${translate[1]}px)`
|
||||||
|
: "";
|
||||||
|
|
||||||
|
switch (system) {
|
||||||
|
case "firecons":
|
||||||
|
return u.updateIn("weaponry.firecons.uiTransform", transform);
|
||||||
|
|
||||||
|
case "weapon":
|
||||||
|
return u.updateIn(
|
||||||
|
"weaponry.weapons",
|
||||||
|
u.map(u.if(({ id }) => id === systemId, u({ uiTransform: transform })))
|
||||||
|
);
|
||||||
|
|
||||||
|
case "screens":
|
||||||
|
return u.updateIn("structure.screens.uiTransform", transform);
|
||||||
|
|
||||||
|
case "hull":
|
||||||
|
return u.updateIn("structure.hull.uiTransform", transform);
|
||||||
|
|
||||||
|
case "internalSystems":
|
||||||
|
const path = "structure.uiTransform";
|
||||||
|
return u.updateIn(path, transform);
|
||||||
|
|
||||||
|
case "ftl":
|
||||||
|
return u.updateIn("propulsion.ftl.uiTransform", transform);
|
||||||
|
|
||||||
|
case "drive":
|
||||||
|
return u.updateIn("propulsion.drive.uiTransform", transform);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return (state) => state;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
dux.addReaction(calculateDriveReqs);
|
dux.addReaction(calculateDriveReqs);
|
||||||
dux.addReaction(ftlReqsReaction);
|
dux.addReaction(ftlReqsReaction);
|
||||||
dux.addReaction(screensReqsReaction);
|
dux.addReaction(screensReqsReaction);
|
||||||
|
|
||||||
dux.addReaction( (store) => (state) => {
|
dux.addReaction((store) => (state) => {
|
||||||
let cost = 0;
|
let cost = 0;
|
||||||
let mass = 0;
|
let mass = 0;
|
||||||
|
|
||||||
let subsystems = Object.values(state);
|
let subsystems = Object.values(state);
|
||||||
|
|
||||||
while(subsystems.length>0) {
|
while (subsystems.length > 0) {
|
||||||
const subsystem = subsystems.shift();
|
const subsystem = subsystems.shift();
|
||||||
if( typeof subsystem !== 'object' ) continue;
|
if (typeof subsystem !== "object") continue;
|
||||||
|
|
||||||
if( subsystem.reqs ) {
|
if (subsystem.reqs) {
|
||||||
cost += subsystem.reqs.cost;
|
cost += subsystem.reqs.cost;
|
||||||
mass += subsystem.reqs.mass;
|
mass += subsystem.reqs.mass;
|
||||||
}
|
|
||||||
|
|
||||||
subsystems.push( ...Object.values(subsystem));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
store.dispatch.setShipReqs({cost,usedMass: mass});
|
subsystems.push(...Object.values(subsystem));
|
||||||
|
}
|
||||||
|
|
||||||
|
store.dispatch.setShipReqs({ cost, usedMass: mass });
|
||||||
});
|
});
|
||||||
|
|
||||||
export default dux;
|
export default dux;
|
||||||
|
@ -10,35 +10,32 @@ const dux = new Updux({
|
|||||||
subduxes: { reqs },
|
subduxes: { reqs },
|
||||||
initial: {
|
initial: {
|
||||||
type: "none",
|
type: "none",
|
||||||
|
uiTransform: "",
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
setFtl: null,
|
setFtl: null,
|
||||||
setFtlReqs: null,
|
setFtlReqs: null,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
export default dux;
|
export default dux;
|
||||||
|
|
||||||
dux.setMutation( 'setFtl', type => u({type}) );
|
dux.setMutation("setFtl", (type) => u({ type }));
|
||||||
dux.setMutation( 'setFtlReqs', reqs => u({reqs}) );
|
dux.setMutation("setFtlReqs", (reqs) => u({ reqs }));
|
||||||
|
|
||||||
export function calcFtlReqs(type,shipMass) {
|
export function calcFtlReqs(type, shipMass) {
|
||||||
if(type==="none") return { cost: 0, mass: 0 };
|
if (type === "none") return { cost: 0, mass: 0 };
|
||||||
|
|
||||||
const mass = Math.ceil(shipMass / 10);
|
const mass = Math.ceil(shipMass / 10);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
mass,
|
mass,
|
||||||
cost: mass * ( type === 'advanced' ? 3 : 2 ),
|
cost: mass * (type === "advanced" ? 3 : 2),
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// needs to be at the top level
|
// needs to be at the top level
|
||||||
export const ftlReqsReaction = store =>
|
export const ftlReqsReaction = (store) =>
|
||||||
createSelector(
|
createSelector(
|
||||||
[
|
[(ship) => ship.propulsion.ftl.type, (ship) => ship.reqs.mass],
|
||||||
(ship) => ship.propulsion.ftl.type,
|
(type, shipMass) => store.dispatch.setFtlReqs(calcFtlReqs(type, shipMass))
|
||||||
(ship) => ship.reqs.mass,
|
);
|
||||||
],
|
|
||||||
(type,shipMass) =>
|
|
||||||
store.dispatch.setFtlReqs(calcFtlReqs(type,shipMass))
|
|
||||||
);
|
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
import { Updux } from 'updux';
|
import { Updux } from "updux";
|
||||||
|
|
||||||
import hull from './hull.js';
|
import hull from "./hull.js";
|
||||||
import screens from './screens.js';
|
import screens from "./screens.js";
|
||||||
import cargo from './cargo.js';
|
import cargo from "./cargo.js";
|
||||||
import armor from './armor.js';
|
import armor from "./armor.js";
|
||||||
import streamlining from './streamlining.js';
|
import streamlining from "./streamlining.js";
|
||||||
|
|
||||||
const dux = new Updux({
|
const dux = new Updux({
|
||||||
subduxes: { hull, screens, cargo, streamlining, armor }
|
subduxes: { hull, screens, cargo, streamlining, armor },
|
||||||
|
initial: {
|
||||||
|
uiTransform: "",
|
||||||
|
},
|
||||||
});
|
});
|
||||||
export default dux;
|
export default dux;
|
||||||
|
|
||||||
|
@ -8,36 +8,33 @@ import { initial } from "lodash";
|
|||||||
let composeEnhancers = compose;
|
let composeEnhancers = compose;
|
||||||
|
|
||||||
if (dev && browser && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) {
|
if (dev && browser && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) {
|
||||||
composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__;
|
composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default () => {
|
export default (initialState = undefined) => {
|
||||||
|
if (browser) {
|
||||||
|
const i = localStorage.getItem("ship");
|
||||||
|
|
||||||
let initialState = undefined;
|
if (i) initialState = JSON.parse(localStorage.getItem("ship"));
|
||||||
|
}
|
||||||
|
|
||||||
if( browser ) {
|
const duxStore = shipDux.createStore(initialState, (mw) =>
|
||||||
const i =localStorage.getItem('ship');
|
composeEnhancers(applyMiddleware(mw))
|
||||||
|
);
|
||||||
|
|
||||||
if(i) initialState = JSON.parse(localStorage.getItem('ship'));
|
let previous;
|
||||||
}
|
const state = readable(duxStore.getState(), (set) => {
|
||||||
|
duxStore.subscribe(() => {
|
||||||
const duxStore = shipDux.createStore(initialState, (mw) =>
|
if (previous === duxStore.getState()) return;
|
||||||
composeEnhancers(applyMiddleware(mw))
|
previous = duxStore.getState();
|
||||||
);
|
set(previous);
|
||||||
|
if (browser) localStorage.setItem("ship", JSON.stringify(previous));
|
||||||
let previous;
|
|
||||||
const state = readable(duxStore.getState(), (set) => {
|
|
||||||
duxStore.subscribe(() => {
|
|
||||||
if (previous === duxStore.getState()) return;
|
|
||||||
previous = duxStore.getState();
|
|
||||||
set(previous);
|
|
||||||
if( browser ) localStorage.setItem('ship', JSON.stringify(previous));
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
dispatch: duxStore.dispatch,
|
dispatch: duxStore.dispatch,
|
||||||
state,
|
state,
|
||||||
shipMass: derived(state, (state) => state.reqs.mass),
|
shipMass: derived(state, (state) => state.reqs.mass),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user