feat: add theming support
This commit is contained in:
@ -8,6 +8,7 @@ uniform vec2 dimensions;
|
||||
uniform vec3 camPos;
|
||||
uniform vec2 zoomLimits;
|
||||
uniform vec3 backgroundColor;
|
||||
uniform vec3 lineColor;
|
||||
|
||||
float grid(float x, float y, float divisions, float thickness) {
|
||||
x = fract(x * divisions);
|
||||
@ -92,7 +93,7 @@ void main(void) {
|
||||
float c = mix(large, small, min(nz*2.0+0.05, 1.0));
|
||||
c = mix(c, xsmall, max(min((nz-0.3)/0.7, 1.0), 0.0));
|
||||
|
||||
vec3 color = mix(backgroundColor, vec3(1.0), c*0.5);
|
||||
vec3 color = mix(backgroundColor, lineColor, c);
|
||||
|
||||
gl_FragColor = vec4(color, 1.0);
|
||||
}
|
||||
|
@ -1,52 +1,61 @@
|
||||
<script lang="ts">
|
||||
import { T } from '@threlte/core';
|
||||
import { T } from "@threlte/core";
|
||||
|
||||
import BackgroundVert from './Background.vert';
|
||||
import BackgroundFrag from './Background.frag';
|
||||
import { colors } from '../graph/stores.js';
|
||||
import BackgroundVert from "./Background.vert";
|
||||
import BackgroundFrag from "./Background.frag";
|
||||
import { colors } from "../graph/stores.js";
|
||||
import { Color } from "three";
|
||||
|
||||
export let minZoom = 4;
|
||||
export let maxZoom = 150;
|
||||
export let minZoom = 4;
|
||||
export let maxZoom = 150;
|
||||
|
||||
export let cameraPosition: [number, number, number] = [0, 1, 0];
|
||||
export let cameraPosition: [number, number, number] = [0, 1, 0];
|
||||
|
||||
export let width = globalThis?.innerWidth || 100;
|
||||
export let height = globalThis?.innerHeight || 100;
|
||||
export let width = globalThis?.innerWidth || 100;
|
||||
export let height = globalThis?.innerHeight || 100;
|
||||
|
||||
let bw = 2;
|
||||
let bh = 2;
|
||||
let bw = 2;
|
||||
let bh = 2;
|
||||
|
||||
$: if (width && height) {
|
||||
bw = width / cameraPosition[2];
|
||||
bh = height / cameraPosition[2];
|
||||
}
|
||||
$: if (width && height) {
|
||||
bw = width / cameraPosition[2];
|
||||
bh = height / cameraPosition[2];
|
||||
}
|
||||
</script>
|
||||
|
||||
<T.Group position.x={cameraPosition[0]} position.z={cameraPosition[1]} position.y={-1.0}>
|
||||
<T.Mesh rotation.x={-Math.PI / 2} position.y={0.2} scale.x={bw} scale.y={bh}>
|
||||
<T.PlaneGeometry args={[1, 1]} />
|
||||
<T.ShaderMaterial
|
||||
transparent
|
||||
vertexShader={BackgroundVert}
|
||||
fragmentShader={BackgroundFrag}
|
||||
uniforms={{
|
||||
camPos: {
|
||||
value: [0, 1, 0]
|
||||
},
|
||||
backgroundColor: {
|
||||
value: [0, 0, 0]
|
||||
},
|
||||
zoomLimits: {
|
||||
value: [2, 50]
|
||||
},
|
||||
dimensions: {
|
||||
value: [100, 100]
|
||||
}
|
||||
}}
|
||||
uniforms.camPos.value={cameraPosition}
|
||||
uniforms.backgroundColor.value={$colors.backgroundColorDarker}
|
||||
uniforms.zoomLimits.value={[minZoom, maxZoom]}
|
||||
uniforms.dimensions.value={[width, height]}
|
||||
/>
|
||||
</T.Mesh>
|
||||
<T.Group
|
||||
position.x={cameraPosition[0]}
|
||||
position.z={cameraPosition[1]}
|
||||
position.y={-1.0}
|
||||
>
|
||||
<T.Mesh rotation.x={-Math.PI / 2} position.y={0.2} scale.x={bw} scale.y={bh}>
|
||||
<T.PlaneGeometry args={[1, 1]} />
|
||||
<T.ShaderMaterial
|
||||
transparent
|
||||
vertexShader={BackgroundVert}
|
||||
fragmentShader={BackgroundFrag}
|
||||
uniforms={{
|
||||
camPos: {
|
||||
value: [0, 1, 0],
|
||||
},
|
||||
backgroundColor: {
|
||||
value: new Color(0x171717),
|
||||
},
|
||||
lineColor: {
|
||||
value: new Color(0x111111),
|
||||
},
|
||||
zoomLimits: {
|
||||
value: [2, 50],
|
||||
},
|
||||
dimensions: {
|
||||
value: [100, 100],
|
||||
},
|
||||
}}
|
||||
uniforms.camPos.value={cameraPosition}
|
||||
uniforms.backgroundColor.value={$colors.layer0}
|
||||
uniforms.lineColor.value={$colors.layer2}
|
||||
uniforms.zoomLimits.value={[minZoom, maxZoom]}
|
||||
uniforms.dimensions.value={[width, height]}
|
||||
/>
|
||||
</T.Mesh>
|
||||
</T.Group>
|
||||
|
@ -1,12 +1,9 @@
|
||||
<script context="module" lang="ts">
|
||||
const color = new Color(0x202020);
|
||||
color.convertLinearToSRGB();
|
||||
|
||||
const color2 = color.clone();
|
||||
color2.convertSRGBToLinear();
|
||||
import { colors } from "../graph/stores";
|
||||
import { get } from "svelte/store";
|
||||
|
||||
const circleMaterial = new MeshBasicMaterial({
|
||||
color,
|
||||
color: get(colors).outline,
|
||||
toneMapped: false,
|
||||
});
|
||||
|
||||
@ -24,7 +21,6 @@
|
||||
import { T } from "@threlte/core";
|
||||
import { MeshLineMaterial } from "@threlte/extras";
|
||||
import { BufferGeometry, MeshBasicMaterial, Vector3 } from "three";
|
||||
import { Color } from "three/src/math/Color.js";
|
||||
import { CubicBezierCurve } from "three/src/extras/curves/CubicBezierCurve.js";
|
||||
import { Vector2 } from "three/src/math/Vector2.js";
|
||||
import { createEdgeGeometry } from "./createEdgeGeometry.js";
|
||||
@ -59,7 +55,7 @@
|
||||
const length = Math.floor(
|
||||
Math.sqrt(Math.pow(new_x, 2) + Math.pow(new_y, 2)) / 4,
|
||||
);
|
||||
samples = Math.min(Math.max(10, length), 60);
|
||||
samples = Math.min(Math.max(10, length), 60) * 2;
|
||||
|
||||
curve.v0.set(0, 0);
|
||||
curve.v1.set(mid.x, 0);
|
||||
@ -102,11 +98,6 @@
|
||||
|
||||
{#if geometry}
|
||||
<T.Mesh position.x={from.x} position.z={from.y} position.y={0.1} {geometry}>
|
||||
<MeshLineMaterial
|
||||
width={4}
|
||||
attenuate={false}
|
||||
color={color2}
|
||||
toneMapped={false}
|
||||
/>
|
||||
<MeshLineMaterial width={3} attenuate={false} color={$colors.outline} />
|
||||
</T.Mesh>
|
||||
{/if}
|
||||
|
@ -435,7 +435,6 @@ export class GraphManager extends EventEmitter<{ "save": Graph, "result": any, "
|
||||
save() {
|
||||
if (this.currentUndoGroup) return;
|
||||
const state = this.serialize();
|
||||
console.log(state);
|
||||
this.history.save(state);
|
||||
this.emit("save", state);
|
||||
logger.log("saving graphs", state);
|
||||
|
@ -1,6 +1,11 @@
|
||||
<script lang="ts">
|
||||
import { animate, lerp, snapToGrid } from "../helpers/index.js";
|
||||
import { LinearSRGBColorSpace } from "three";
|
||||
import {
|
||||
LinearSRGBColorSpace,
|
||||
LinearToneMapping,
|
||||
NoToneMapping,
|
||||
SRGBColorSpace,
|
||||
} from "three";
|
||||
import { Canvas } from "@threlte/core";
|
||||
import type { OrthographicCamera } from "three";
|
||||
import Background from "../background/Background.svelte";
|
||||
@ -750,12 +755,7 @@
|
||||
on:keydown={handleKeyDown}
|
||||
on:mousedown={handleMouseDown}
|
||||
>
|
||||
<Canvas
|
||||
shadows={false}
|
||||
renderMode="on-demand"
|
||||
colorManagementEnabled={false}
|
||||
colorSpace={LinearSRGBColorSpace}
|
||||
>
|
||||
<Canvas shadows={false} renderMode="on-demand" colorManagementEnabled={false}>
|
||||
<Camera bind:camera position={cameraPosition} />
|
||||
|
||||
<Background {cameraPosition} {maxZoom} {minZoom} {width} {height} />
|
||||
|
@ -11,9 +11,11 @@ export const possibleSockets: Writable<Socket[]> = writable([]);
|
||||
export const possibleSocketIds: Writable<Set<string> | null> = writable(null);
|
||||
|
||||
export const colors = writable({
|
||||
backgroundColorDarker: new Color().setStyle("#101010"),
|
||||
backgroundColor: new Color().setStyle("#151515"),
|
||||
backgroundColorLighter: new Color().setStyle("#202020")
|
||||
layer0: new Color().setStyle("#060606"),
|
||||
layer1: new Color().setStyle("#171717"),
|
||||
layer2: new Color().setStyle("#2D2D2D"),
|
||||
layer3: new Color().setStyle("#A6A6A6"),
|
||||
outline: new Color().setStyle("#000000"),
|
||||
});
|
||||
|
||||
if ("getComputedStyle" in globalThis) {
|
||||
@ -23,19 +25,32 @@ if ("getComputedStyle" in globalThis) {
|
||||
function updateColors() {
|
||||
|
||||
const style = getComputedStyle(body);
|
||||
const backgroundColorDarker = style.getPropertyValue("--background-color-darker");
|
||||
const backgroundColor = style.getPropertyValue("--background-color");
|
||||
const backgroundColorLighter = style.getPropertyValue("--background-color-lighter");
|
||||
const layer0 = style.getPropertyValue("--layer-0");
|
||||
const layer1 = style.getPropertyValue("--layer-1");
|
||||
const layer2 = style.getPropertyValue("--layer-2");
|
||||
const layer3 = style.getPropertyValue("--layer-3");
|
||||
const outline = style.getPropertyValue("--outline");
|
||||
|
||||
colors.update(col => {
|
||||
col.backgroundColorDarker.setStyle(backgroundColorDarker);
|
||||
col.backgroundColor.setStyle(backgroundColor);
|
||||
col.backgroundColorLighter.setStyle(backgroundColorLighter);
|
||||
col.layer0.setStyle(layer0);
|
||||
col.layer0.convertLinearToSRGB();
|
||||
col.layer1.setStyle(layer1);
|
||||
col.layer1.convertLinearToSRGB();
|
||||
col.layer2.setStyle(layer2);
|
||||
col.layer2.convertLinearToSRGB();
|
||||
col.layer3.setStyle(layer3);
|
||||
col.layer3.convertLinearToSRGB();
|
||||
col.outline.setStyle(outline);
|
||||
col.outline.convertLinearToSRGB();
|
||||
return col;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
updateColors();
|
||||
|
||||
window.onload = updateColors;
|
||||
|
||||
body.addEventListener("transitionstart", () => {
|
||||
updateColors();
|
||||
})
|
||||
|
@ -4,6 +4,7 @@
|
||||
import NodeHeader from "./NodeHeader.svelte";
|
||||
import NodeParameter from "./NodeParameter.svelte";
|
||||
import { activeNodeId, selectedNodes } from "../graph/stores.js";
|
||||
import { colors } from "../graph/stores";
|
||||
import { T } from "@threlte/core";
|
||||
import { Color, type Mesh } from "three";
|
||||
import NodeFrag from "./Node.frag";
|
||||
@ -25,7 +26,6 @@
|
||||
|
||||
const zOffset = (node.tmp?.random || 0) * 0.5;
|
||||
const zLimit = 2 - zOffset;
|
||||
$: visible = inView && z > zLimit;
|
||||
|
||||
const parameters = Object.entries(type?.inputs || {})
|
||||
.filter((p) => p[1].type !== "seed")
|
||||
@ -49,13 +49,6 @@
|
||||
node.tmp.mesh = meshRef;
|
||||
updateNodePosition(node);
|
||||
});
|
||||
|
||||
const colorDark = new Color();
|
||||
colorDark.setStyle("#151515");
|
||||
//colorDark.();
|
||||
|
||||
const colorBright = new Color("#202020");
|
||||
//colorBright.convertLinearToSRGB();
|
||||
</script>
|
||||
|
||||
<T.Mesh
|
||||
@ -72,8 +65,8 @@
|
||||
fragmentShader={NodeFrag}
|
||||
transparent
|
||||
uniforms={{
|
||||
uColorBright: { value: colorBright },
|
||||
uColorDark: { value: colorDark },
|
||||
uColorBright: { value: new Color("#171717") },
|
||||
uColorDark: { value: new Color("#151515") },
|
||||
uSelectedColor: { value: new Color("#9d5f28") },
|
||||
uActiveColor: { value: new Color("white") },
|
||||
uSelected: { value: false },
|
||||
@ -84,6 +77,8 @@
|
||||
}}
|
||||
uniforms.uSelected.value={isSelected}
|
||||
uniforms.uActive.value={isActive}
|
||||
uniforms.uColorBright.value={$colors.layer2}
|
||||
uniforms.uColorDark.value={$colors.layer1}
|
||||
uniforms.uStrokeWidth.value={(7 - z) / 3}
|
||||
/>
|
||||
</T.Mesh>
|
||||
@ -122,7 +117,7 @@
|
||||
z-index: 1;
|
||||
opacity: calc((var(--cz) - 2.5) / 3.5);
|
||||
font-weight: 300;
|
||||
--stroke: var(--background-color-lighter);
|
||||
--stroke: var(--outline);
|
||||
--stroke-width: 2px;
|
||||
}
|
||||
|
||||
|
@ -1,129 +1,137 @@
|
||||
<script lang="ts">
|
||||
import { createNodePath } from '../helpers/index.js';
|
||||
import type { Node, Socket } from '@nodes/types';
|
||||
import { getContext } from 'svelte';
|
||||
import { createNodePath } from "../helpers/index.js";
|
||||
import type { Node, Socket } from "@nodes/types";
|
||||
import { getContext } from "svelte";
|
||||
|
||||
export let node: Node;
|
||||
export let node: Node;
|
||||
|
||||
const setDownSocket = getContext<(socket: Socket) => void>('setDownSocket');
|
||||
const getSocketPosition =
|
||||
getContext<(node: Node, index: number) => [number, number]>('getSocketPosition');
|
||||
const setDownSocket = getContext<(socket: Socket) => void>("setDownSocket");
|
||||
const getSocketPosition =
|
||||
getContext<(node: Node, index: number) => [number, number]>(
|
||||
"getSocketPosition",
|
||||
);
|
||||
|
||||
function handleMouseDown(event: MouseEvent) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
setDownSocket({
|
||||
node,
|
||||
index: 0,
|
||||
position: getSocketPosition(node, 0)
|
||||
});
|
||||
}
|
||||
function handleMouseDown(event: MouseEvent) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
setDownSocket({
|
||||
node,
|
||||
index: 0,
|
||||
position: getSocketPosition(node, 0),
|
||||
});
|
||||
}
|
||||
|
||||
const cornerTop = 10;
|
||||
const rightBump = !!node?.tmp?.type?.outputs?.length;
|
||||
const aspectRatio = 0.25;
|
||||
const cornerTop = 10;
|
||||
const rightBump = !!node?.tmp?.type?.outputs?.length;
|
||||
const aspectRatio = 0.25;
|
||||
|
||||
const path = createNodePath({
|
||||
depth: 4,
|
||||
height: 24,
|
||||
y: 50,
|
||||
cornerTop,
|
||||
rightBump,
|
||||
aspectRatio
|
||||
});
|
||||
const pathDisabled = createNodePath({
|
||||
depth: 0,
|
||||
height: 15,
|
||||
y: 50,
|
||||
cornerTop,
|
||||
rightBump,
|
||||
aspectRatio
|
||||
});
|
||||
const pathHover = createNodePath({
|
||||
depth: 5,
|
||||
height: 30,
|
||||
y: 50,
|
||||
cornerTop,
|
||||
rightBump,
|
||||
aspectRatio
|
||||
});
|
||||
const path = createNodePath({
|
||||
depth: 4,
|
||||
height: 24,
|
||||
y: 50,
|
||||
cornerTop,
|
||||
rightBump,
|
||||
aspectRatio,
|
||||
});
|
||||
const pathDisabled = createNodePath({
|
||||
depth: 0,
|
||||
height: 15,
|
||||
y: 50,
|
||||
cornerTop,
|
||||
rightBump,
|
||||
aspectRatio,
|
||||
});
|
||||
const pathHover = createNodePath({
|
||||
depth: 5,
|
||||
height: 30,
|
||||
y: 50,
|
||||
cornerTop,
|
||||
rightBump,
|
||||
aspectRatio,
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="wrapper" data-node-id={node.id}>
|
||||
<div class="content">
|
||||
{node.type.split('/').pop()}
|
||||
</div>
|
||||
<div class="click-target" role="button" tabindex="0" on:mousedown={handleMouseDown} />
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 100 100"
|
||||
width="100"
|
||||
height="100"
|
||||
preserveAspectRatio="none"
|
||||
style={`
|
||||
<div class="content">
|
||||
{node.type.split("/").pop()}
|
||||
</div>
|
||||
<div
|
||||
class="click-target"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
on:mousedown={handleMouseDown}
|
||||
/>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 100 100"
|
||||
width="100"
|
||||
height="100"
|
||||
preserveAspectRatio="none"
|
||||
style={`
|
||||
--path: path("${path}");
|
||||
--hover-path: path("${pathHover}");
|
||||
`}
|
||||
>
|
||||
<path vector-effect="non-scaling-stroke" stroke="white" stroke-width="0.1"></path>
|
||||
</svg>
|
||||
>
|
||||
<path vector-effect="non-scaling-stroke" stroke="white" stroke-width="0.1"
|
||||
></path>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.wrapper {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
}
|
||||
.wrapper {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.click-target {
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
top: 50%;
|
||||
transform: translateX(50%) translateY(-50%);
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
z-index: 100;
|
||||
border-radius: 50%;
|
||||
/* background: red; */
|
||||
/* opacity: 0.2; */
|
||||
}
|
||||
.click-target {
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
top: 50%;
|
||||
transform: translateX(50%) translateY(-50%);
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
z-index: 100;
|
||||
border-radius: 50%;
|
||||
/* background: red; */
|
||||
/* opacity: 0.2; */
|
||||
}
|
||||
|
||||
.click-target:hover + svg path {
|
||||
d: var(--hover-path);
|
||||
}
|
||||
.click-target:hover + svg path {
|
||||
d: var(--hover-path);
|
||||
}
|
||||
|
||||
svg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: -1;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: visible;
|
||||
}
|
||||
svg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: -1;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
svg path {
|
||||
stroke-width: 0.2px;
|
||||
transition:
|
||||
d 0.3s ease,
|
||||
fill 0.3s ease;
|
||||
fill: var(--background-color-lighter);
|
||||
stroke: var(--stroke);
|
||||
stroke-width: var(--stroke-width);
|
||||
d: var(--path);
|
||||
}
|
||||
svg path {
|
||||
stroke-width: 0.2px;
|
||||
transition:
|
||||
d 0.3s ease,
|
||||
fill 0.3s ease;
|
||||
fill: var(--layer-2);
|
||||
stroke: var(--stroke);
|
||||
stroke-width: var(--stroke-width);
|
||||
d: var(--path);
|
||||
}
|
||||
|
||||
.content {
|
||||
font-size: 1em;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: 20px;
|
||||
height: 100%;
|
||||
}
|
||||
.content {
|
||||
font-size: 1em;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: 20px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
svg:hover path {
|
||||
d: var(--hover-path) !important;
|
||||
}
|
||||
svg:hover path {
|
||||
d: var(--hover-path) !important;
|
||||
}
|
||||
</style>
|
||||
|
@ -175,7 +175,7 @@
|
||||
transition:
|
||||
d 0.3s ease,
|
||||
fill 0.3s ease;
|
||||
fill: var(--background-color);
|
||||
fill: var(--layer-1);
|
||||
stroke: var(--stroke);
|
||||
stroke-width: var(--stroke-width);
|
||||
d: var(--path);
|
||||
|
Reference in New Issue
Block a user