Controll Stuff

This commit is contained in:
Andre Henriques 2023-07-11 12:16:59 +01:00
parent 35b37fdd7d
commit 292a1f1a95
14 changed files with 541 additions and 78 deletions

View File

@ -33,6 +33,7 @@
"dependencies": {
"@types/three": "^0.153.0",
"postcss": "^8.4.25",
"postcss-nesting": "^12.0.0",
"sass": "^1.63.6",
"svelte-cubed": "^0.2.1",
"three": "^0.154.0"

View File

@ -11,6 +11,9 @@ dependencies:
postcss:
specifier: ^8.4.25
version: 8.4.25
postcss-nesting:
specifier: ^12.0.0
version: 12.0.0(postcss@8.4.25)
sass:
specifier: ^1.63.6
version: 1.63.6
@ -89,6 +92,15 @@ packages:
'@jridgewell/trace-mapping': 0.3.18
dev: true
/@csstools/selector-specificity@3.0.0(postcss-selector-parser@6.0.13):
resolution: {integrity: sha512-hBI9tfBtuPIi885ZsZ32IMEU/5nlZH/KOVYJCOh7gyMxaVLGmLedYqFN6Ui1LXkI8JlC8IsuC0rF0btcRZKd5g==}
engines: {node: ^14 || ^16 || >=18}
peerDependencies:
postcss-selector-parser: ^6.0.13
dependencies:
postcss-selector-parser: 6.0.13
dev: false
/@esbuild/android-arm64@0.18.11:
resolution: {integrity: sha512-snieiq75Z1z5LJX9cduSAjUr7vEI1OdlzFPMw0HH5YI7qQHDd3qs+WZoMrWYDsfRJSq36lIA6mfZBkvL46KoIw==}
engines: {node: '>=12'}
@ -842,7 +854,6 @@ packages:
resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
engines: {node: '>=4'}
hasBin: true
dev: true
/debug@4.3.4:
resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
@ -1540,6 +1551,17 @@ packages:
yaml: 1.10.2
dev: true
/postcss-nesting@12.0.0(postcss@8.4.25):
resolution: {integrity: sha512-knqwW65kxssmyIFadRSimaiRyLVRd0MdwfabesKw6XvGLwSOCJ+4zfvNQQCOOYij5obwpZzDpODuGRv2PCyiUw==}
engines: {node: ^14 || ^16 || >=18}
peerDependencies:
postcss: ^8.4
dependencies:
'@csstools/selector-specificity': 3.0.0(postcss-selector-parser@6.0.13)
postcss: 8.4.25
postcss-selector-parser: 6.0.13
dev: false
/postcss-safe-parser@6.0.0(postcss@8.4.25):
resolution: {integrity: sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==}
engines: {node: '>=12.0'}
@ -1564,7 +1586,6 @@ packages:
dependencies:
cssesc: 3.0.0
util-deprecate: 1.0.2
dev: true
/postcss@8.4.25:
resolution: {integrity: sha512-7taJ/8t2av0Z+sQEvNzCkpDynl0tX3uJMCODi6nT3PfASC7dYCWV9aQ+uiCf+KBD4SEFcu+GvJdGdwzQ6OSjCw==}
@ -1976,7 +1997,6 @@ packages:
/util-deprecate@1.0.2:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
dev: true
/vite@4.4.2(sass@1.63.6):
resolution: {integrity: sha512-zUcsJN+UvdSyHhYa277UHhiJ3iq4hUBwHavOpsNUGsTgjBeoBlK8eDt+iT09pBq0h9/knhG/SPrZiM7cGmg7NA==}

View File

@ -1,26 +1,13 @@
<script lang="ts">
import * as Three from 'three';
import * as SC from 'svelte-cubed';
import {apply_direction, type Directions} from './Utils';
export let config: Config;
export let config: Directions;
type Config = {
directionX: number,
directionY: number,
directionZ: number,
}
function to_rad(degree: number): number {
return (Math.PI / 180) * degree;
}
$: vec = new Three.Vector3(1,0,0)
.applyAxisAngle(new Three.Vector3(1, 0, 0), to_rad(config.directionX))
.applyAxisAngle(new Three.Vector3(0, 1, 0), to_rad(config.directionY))
.applyAxisAngle(new Three.Vector3(0, 0, 1), to_rad(config.directionZ));
$: vec = apply_direction(config);
const origin = new Three.Vector3(0,0,0);
</script>
<div class="gyro">

View File

@ -23,7 +23,11 @@ class RequestsClass {
animations = {
list: (): Promise<AnimationBase[]> => this._get("animations"),
toggle: (name: string): Promise<void> => this._get(`toggle/${name}`)
toggle: (name: string): Promise<void> => this._get(`toggle/${name}`),
//TODO cahnge any
add: (data: any): Promise<void> => this._post('animation', data),
remove: (name: string): Promise<void> => this._get(`delete/${name}`),
get: (name: string): Promise<any> => this._get(`get/${name}`),
}
active(): Promise<ActiveAnimations> {

18
src/lib/Utils.ts Normal file
View File

@ -0,0 +1,18 @@
import * as Three from 'three';
export type Directions = {
directionX: number,
directionY: number,
directionZ: number,
};
function to_rad(degree: number): number {
return (Math.PI / 180) * degree;
}
export function apply_direction(direction: Directions, _vector?: Three.Vector3): Three.Vector3 {
const vector = _vector ?? new Three.Vector3(1,0,0);
return vector
.applyAxisAngle(new Three.Vector3(1, 0, 0), to_rad(direction.directionX))
.applyAxisAngle(new Three.Vector3(0, 1, 0), to_rad(direction.directionY))
.applyAxisAngle(new Three.Vector3(0, 0, 1), to_rad(direction.directionZ));
}

View File

@ -1,19 +1,34 @@
<script lang="ts">
import { onMount } from "svelte";
import { onDestroy, onMount } from "svelte";
import { Requests, type AnimationBase } from '$lib/Requests';
let animations = new Promise<AnimationBase[]>(() => {});
let active = new Promise<string[]>(() => {});
let interval: number;
onMount(async () => {
active = Promise.resolve((await Requests.active()).active_animations);
animations = Requests.animations.list();
interval = setInterval(async () => {
active = Promise.resolve((await Requests.active()).active_animations);
}, 5000);
});
onDestroy(async () => {
clearInterval(interval);
});
async function toggle(name: string) {
await Requests.animations.toggle(name)
active = Promise.resolve((await Requests.active()).active_animations);
}
async function remove(name: string) {
animations = new Promise(() => {});
await Requests.animations.remove(name)
active = Promise.resolve((await Requests.active()).active_animations);
animations = Requests.animations.list();
}
</script>
{#await animations}
@ -22,21 +37,62 @@
{#await active then activeList }
<ul>
{#each data as item }
<li>
<span style={`color: ${activeList.includes(item.name) ? 'green' : 'red'};`}>
<li class:active={activeList.includes(item.name)}>
<button on:click={() => toggle(item.name)} class="name">
<span>
{item.name}
</span>
<button on:click={() => toggle(item.name)}>
toggle
</button>
<a href="/ani/edit?id={item.id}">
<a href="/ani/edit?name={item.name}">
Edit
</a>
<button on:click={() => remove(item.name)} class="red">
Remove
</button>
</li>
{/each}
</ul>
{/await}
<a href="/ani/new">
new
</a>
{/await}
<style lang="post">
ul {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-wrap: wrap;
justify-content: center;
}
ul li.active {
box-shadow: 0 0 8px 2px #00ff00;
}
ul li {
margin: 20px;
padding: 20px;
border-radius: 20px;
box-shadow: 0 0 8px 2px #2222;
}
ul li span {
display: block;
}
ul li button {
border: none;
background: none;
cursor: pointer;
}
ul li button.name {
display: block;
width: 100%;
font-size: 2em;
height: 2em;
}
ul li a {
text-decoration: none;
color: black;
}
.red {
color: red;
}
</style>

View File

@ -13,11 +13,32 @@
Configuration
</a>
</li>
<li>
<a href="/ani/new">
New
</a>
</li>
</ul>
</header>
<style lang="post">
header {
margin: 0;
margin-bottom: 20px;
background: white;
box-shadow: 0 5px 8px 2px #2222;
}
header ul {
margin: 0;
padding: 10px;
list-style: none;
}
header ul li {
display: inline;
}
header ul li a {
text-decoration: none;
color: black;
font-size: 20px;
}
</style>

View File

@ -0,0 +1,112 @@
<script lang="ts" context="module">
export type LigthSetting = {
start?: number,
end?: number,
tags?: string,
r: number,
b: number,
g: number,
}
</script>
<script lang="ts">
import * as Three from 'three';
import * as SC from 'svelte-cubed';
import { onMount } from 'svelte';
import { setStore } from '$lib/store';
import { apply_direction } from '$lib/Utils';
export let frames: LigthSetting[];
type Led = {
tags: string[]
pos: Three.Vector3,
}
let leds: Led[] = [];
let avg: Three.Vector3;
let cam: Three.Vector3;
onMount(async () => {
await setStore.getData();
let set = await $setStore;
let pos = new Three.Vector3(0, 0, 0);
avg = new Three.Vector3(0, 0, 0);
cam = new Three.Vector3(0, 0, 0);
let avgdir = new Three.Vector3(0, 0, 0);
for (let config of set) {
let direction = apply_direction(config);
for (let i = 0; i < config.ledcount; i++) {
leds.push({
tags: config.tags === "" ? [] : config.tags.split(','),
pos: new Three.Vector3(pos.x, pos.y, pos.z),
});
pos.add(direction);
avg.add(pos);
avgdir.add(direction);
}
}
avg = avg.multiplyScalar(1/leds.length);
avgdir = avgdir.multiplyScalar(1/leds.length);
let temp = avgdir.cross(new Three.Vector3(-1, -1, -1)).normalize().multiplyScalar(50);
cam = avg.clone().add(temp);
leds = leds;
});
function apply(leds: Led[], settings: LigthSetting[]): Three.MeshStandardMaterial[] {
let colors: Three.MeshStandardMaterial[] = new Array(leds.length);
for (let i = 0; i < leds.length; i++) {
colors[i] = new Three.MeshStandardMaterial({color: 0x000000});
}
for (let set of settings) {
let mat = new Three.MeshStandardMaterial({color: new Three.Color(set.r, set.g, set.b) })
let tags = set.tags ? set.tags === "" ? [] : set.tags.split(',') : [];
if (tags.length > 0) {
for (let i = 0; i < leds.length; i++) {
for (let tag of tags) {
if (leds[i].tags.includes(tag)) {
colors[i] = mat;
}
}
}
} else {
if (set.start !== undefined && set.end !== undefined) {
for (let i = set.start; i < set.end; i++) {
colors[i] = mat;
}
}
}
}
return colors;
}
$: colors = apply(leds, frames);
</script>
{#if leds.length > 0}
<div>
<SC.Canvas antialias background={new Three.Color('papayawhip')}>
{#each colors as color,i }
<SC.Mesh
scale={0.8}
geometry={new Three.BoxGeometry()}
position={[leds[i].pos.x, leds[i].pos.y, leds[i].pos.z]}
material={color} />
{/each}
<SC.PerspectiveCamera position={[cam.x, cam.y, cam.z]} target={[avg.x, avg.y, avg.z]} />
<SC.OrbitControls target={[avg.x, avg.y, avg.z]} />
<SC.AmbientLight intensity={1} />
</SC.Canvas>
</div>
{/if}
<style lang="post">
div {
width: 400px;
height: 400px;
position: relative;
}
</style>

View File

@ -0,0 +1,252 @@
<script lang="ts">
import { goto } from '$app/navigation';
import { Requests } from '$lib/Requests';
import { onMount } from 'svelte';
import DisplayData from '../DisplayData.svelte';
type LigthSetting = {
start?: number;
end?: number;
tags?: string;
r: number;
b: number;
g: number;
};
type KeyFrame = {
duration: number;
settings: LigthSetting[];
};
type Animation = {
keyFrames: KeyFrame[];
priority?: number;
name: string;
repeat: boolean;
};
let animation: Animation = {
keyFrames: [],
priority: undefined,
name: '',
repeat: false
};
let data = new Promise<void>(() => {});
async function save() {
let remove = await Requests.animations.remove(animation.name);
console.log(remove);
let add = await Requests.animations.add(animation);
console.log(add);
goto('/');
}
onMount(async () => {
let url = new URLSearchParams(window.location.search);
let name = url.get('name');
if (name === null) {
goto('/');
return;
}
let d = await Requests.animations.get(name);
console.log(d);
if (d.code) {
goto('/');
return;
}
animation = d;
data = Promise.resolve();
});
</script>
<main>
{#await data}
Loading...
{:then}
Name: <input bind:value={animation.name} /><br />
Priority: <input bind:value={animation.priority} type="number" /><br />
Repeat: <input bind:checked={animation.repeat} type="checkbox" /><br />
<div class="list">
{#each animation.keyFrames as frame, i}
<div class="frame">
<div class="canvas">
<DisplayData frames={frame.settings} />
</div>
<div class="data">
Frame: {i}<br />
Duration: <input bind:value={frame.duration} type="number" /><br />
Settings:
<div class="settings">
{#each frame.settings as setting, j}
<div class="setting">
Tags: <input bind:value={setting.tags} />
Start: <input bind:value={setting.start} type="number" />
End: <input bind:value={setting.end} type="number" />
<br />
<div class="color">
<div
class="color-picker"
style="background-color: rgb({setting.r}, {setting.g}, {setting.b});"
/>
r:<input bind:value={setting.r} type="number" />
g: <input bind:value={setting.g} type="number" />
b: <input bind:value={setting.b} type="number" />
</div>
<button
on:click={() => {
frame.settings.splice(j, 1);
animation = animation;
}}
>
Remove
</button>
</div>
{/each}
</div>
</div>
<div class="btt">
<button
on:click={() => {
frame.settings.push({
tags: undefined,
end: undefined,
start: undefined,
b: 0,
g: 0,
r: 0
});
animation = animation;
}}
>
Add new setting
</button>
<button
on:click={() => {
animation.keyFrames.splice(i, 1);
animation = animation;
}}
>
Remove
</button>
<button
on:click={() => {
animation.keyFrames.splice(i, 0, {
...frame,
settings: frame.settings.map((a) => ({ ...a }))
});
animation = animation;
}}
>
Clone
</button><br />
{#if i > 0}
<button
on:click={() => {
let temp = animation.keyFrames[i - 1];
animation.keyFrames[i - 1] = animation.keyFrames[i];
animation.keyFrames[i] = temp;
animation.keyFrames = animation.keyFrames;
}}
>
Up
</button>
{/if}
{#if i < animation.keyFrames.length - 1}
<button
on:click={() => {
let temp = animation.keyFrames[i + 1];
animation.keyFrames[i + 1] = animation.keyFrames[i];
animation.keyFrames[i] = temp;
animation.keyFrames = animation.keyFrames;
}}
>
Down
</button>
{/if}
</div>
</div>
{/each}
</div>
<button
on:click={() => {
animation.keyFrames.push({
duration: 0,
settings: []
});
animation = animation;
}}
>
Add new frame
</button>
<button on:click={save}> Save </button>
{/await}
</main>
<style lang="scss">
main {
margin: 20px;
input {
padding: 5px 10px;
border: 0;
box-shadow: 0 0 8px 2px #2222;
margin: 2px;
border-radius: 20px;
}
.list {
margin: 20px 0;
.frame {
box-shadow: 0 0 8px 2px #2222;
padding: 20px;
border-radius: 20px;
margin-left: 10px;
display: flex;
flex-wrap: wrap;
.canvas {
display: inline-block;
border-radius: 20px;
overflow: hidden;
}
.settings {
margin: 10px 0;
.setting {
margin: 10px 0;
.color {
margin: 5px 0;
display: flex;
align-items: center;
gap: 10px;
.color-picker {
height: 1.5em;
width: 1.5em;
display: inline-block;
border: black 1px solid;
}
}
}
}
.data {
margin-left: 10px;
margin-top: 10px;
.settings {
margin-left: 10px;
}
}
.btt {
width: 100%;
margin-top: 20px;
}
}
}
}
</style>

View File

@ -1,10 +1,13 @@
<script lang="ts">
import DisplayData from "./DisplayData.svelte";
import { goto } from "$app/navigation";
import { navigating } from "$app/stores";
import { Requests } from "$lib/Requests";
import DisplayData from "../DisplayData.svelte";
type LigthSetting = {
start: number,
end: number,
tags: string,
start?: number,
end?: number,
tags?: string,
r: number,
b: number,
g: number,
@ -14,26 +17,31 @@
settings: LigthSetting[],
}
type Animation = {
key_frames: KeyFrame[],
keyFrames: KeyFrame[],
priority?: number,
name: string,
repeat: boolean,
}
let animation: Animation = {
key_frames: [],
keyFrames: [],
priority: undefined,
name: "",
repeat: false,
}
async function save() {
let add = await Requests.animations.add(animation);
goto('/');
}
</script>
Name: <input bind:value={animation.name} /><br/>
Priority: <input bind:value={animation.priority} type="number"><br/>
Repeat: <input bind:checked={animation.repeat} type="checkbox"><br/>
{#each animation.key_frames as frame, i}
{#each animation.keyFrames as frame, i}
<div class="frame">
<DisplayData frames={frame.settings} />
Frame: {i}<br/>
@ -45,9 +53,9 @@ Repeat: <input bind:checked={animation.repeat} type="checkbox"><br/>
Tags: <input bind:value={setting.tags} />
Start: <input bind:value={setting.start} type="number" />
End: <input bind:value={setting.end} type="number" />
r: <input bind:value={setting.tags} type="number" />
g: <input bind:value={setting.tags} type="number" />
b: <input bind:value={setting.tags} type="number" />
r: <input bind:value={setting.r} type="number" />
g: <input bind:value={setting.g} type="number" />
b: <input bind:value={setting.b} type="number" />
<button on:click={() => {
frame.settings.splice(j, 1);
animation = animation;
@ -59,9 +67,9 @@ Repeat: <input bind:checked={animation.repeat} type="checkbox"><br/>
</div>
<button on:click={() => {
frame.settings.push({
tags: "",
end: 0,
start: 0,
tags: undefined,
end: undefined,
start: undefined,
b: 0,
g: 0,
r: 0,
@ -71,7 +79,7 @@ Repeat: <input bind:checked={animation.repeat} type="checkbox"><br/>
Add new setting
</button>
<button on:click={() => {
animation.key_frames.splice(i, 1);
animation.keyFrames.splice(i, 1);
animation = animation;
}}>
Remove
@ -79,7 +87,7 @@ Repeat: <input bind:checked={animation.repeat} type="checkbox"><br/>
</div>
{/each}
<button on:click={() => {
animation.key_frames.push({
animation.keyFrames.push({
duration: 0,
settings: [],
});
@ -87,6 +95,9 @@ Repeat: <input bind:checked={animation.repeat} type="checkbox"><br/>
}}>
Add new frame
</button>
<button on:click={save}>
Save
</button>
<style lang="post">
.frame {

View File

@ -1,30 +0,0 @@
<script lang="ts" context="module">
export type LigthSetting = {
start: number,
end: number,
tags: string,
r: number,
b: number,
g: number,
}
</script>
<script lang="ts">
import * as Three from 'three';
import * as SC from 'svelte-cubed';
import { onMount } from 'svelte';
import { setStore } from '$lib/store';
export let frames: LigthSetting[];
onMount(async () => {
await setStore.getData();
let set = await $setStore;
const leds = [];
for (let config of set) {
console.log(config);
}
});
</script>

View File

@ -1,6 +1,7 @@
<script lang="ts">
import { onMount } from "svelte";
import Gyro from "$lib/Gyro.svelte";
import { setStore } from "$lib/store";
type Configuration = {
directionX: number,
@ -44,6 +45,7 @@
console.log(await request.json());
getData();
setStore.getData(true);
}
onMount(async () => {

View File

@ -0,0 +1,9 @@
body {
margin: 0;
padding: 0;
}
button {
border: none;
background: none;
}

View File

@ -5,7 +5,7 @@ import { vitePreprocess } from '@sveltejs/kit/vite';
const config = {
// Consult https://kit.svelte.dev/docs/integrations#preprocessors
// for more information about preprocessors
preprocess: vitePreprocess(),
preprocess: vitePreprocess({}),
kit: {
// adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.