Skip to content

Commit

Permalink
🖌️ Rewrote for Svelte 5 runes
Browse files Browse the repository at this point in the history
  • Loading branch information
Somfic committed Dec 18, 2023
1 parent dd58b88 commit 7113fdc
Show file tree
Hide file tree
Showing 23 changed files with 596 additions and 566 deletions.
3 changes: 1 addition & 2 deletions src-client/src/lib/components/Button.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<script lang="ts">
export let active = false;
export let padding = false;
let { active, padding } = $props<{ active?: boolean; padding?: boolean }>();
</script>

<button class:active class:padding>
Expand Down
30 changes: 15 additions & 15 deletions src-client/src/lib/components/editor/ComputedValue.svelte
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
<script lang="ts">
import { get } from 'svelte/store';
import { result, type TypeDefinition } from '$lib/nodes';
import { type TypeDefinition } from '$lib/nodes';
import Value from './Value.svelte';
import { state } from '$lib/state.svelte';
export let id: string;
export let input: boolean = false;
export let output: boolean = false;
export let type: TypeDefinition;
let {
id,
input = false,
output = false,
type
} = $props<{
id: string;
input?: boolean;
output?: boolean;
type: TypeDefinition;
}>();
let value: string | undefined = undefined;
result.subscribe((r) => {
if (r == undefined) return;
if (r.values == undefined) return;
value = r.values.find((v) => v.id == id)?.value;
});
let value = $derived(state.web?.result.values.find((v) => v.id == id)?.value);
</script>

<div class="computed" class:input class:output class:value>
<Value {type} bind:value readonly output />
<Value {type} {value} readonly output />
</div>

<style lang="scss">
Expand Down
19 changes: 7 additions & 12 deletions src-client/src/lib/components/editor/Editor.svelte
Original file line number Diff line number Diff line change
@@ -1,26 +1,20 @@
<script lang="ts">
import { Svelvet } from 'svelvet';
import EditorNode from './EditorNode.svelte';
import {
result,
structures,
type NodeInstance,
type NodeInstanceConnection,
runWeb
} from '$lib/nodes';
import { get } from 'svelte/store';
import Menu from '../menu/Menu.svelte';
import { type NodeInstanceConnection, runWeb } from '$lib/nodes';
import type { Web } from '$lib/nodes';
import Topbar from '../topbar/Topbar.svelte';
import { invokeMenu, menu } from '$lib/menu';
import { invokeMenu } from '$lib/menu';
import { createEventDispatcher } from 'svelte';
export let web: Web;
let { web } = $props<{ web: Web }>();
const dispatch = createEventDispatcher();
function connection(e: any) {
// FIXME: Make sure this is distinct
// FIXME: Make sure we don't connect to ourselves
// FIXME: Make sure we don't connect in a loop
// FIXME: Make sure we only connect types that can be casted to each other
if (
web.connections.find((c) => JSON.stringify(c) == JSON.stringify(detailToInstance(e.detail)))
)
Expand Down Expand Up @@ -74,6 +68,7 @@
on:connection={connection}
on:disconnection={disconnection}
edgeStyle="bezier"
modifier="meta"
>
{#each web.instances as instance}
<EditorNode bind:web bind:instance on:change={() => dispatch('change')} />
Expand Down
55 changes: 33 additions & 22 deletions src-client/src/lib/components/editor/EditorAnchor.svelte
Original file line number Diff line number Diff line change
@@ -1,25 +1,36 @@
<script lang="ts">
import { get } from 'svelte/store';
import {
types,
type ParameterInstance,
type NodeStructure,
type ParameterStructure
} from '$lib/nodes';
import { type ParameterInstance, type NodeStructure, type ParameterStructure } from '$lib/nodes';
import { state } from '$lib/state.svelte';
export let input: boolean = false;
export let output: boolean = false;
export let structure: NodeStructure;
export let parameter: ParameterInstance | ParameterStructure;
export let linked: boolean;
export let hovering: boolean;
export let connecting: boolean;
let {
input = false,
output = false,
structure,
parameter,
linked,
hovering,
connecting
} = $props<{
input?: boolean;
output?: boolean;
structure: NodeStructure;
parameter: ParameterInstance | ParameterStructure;
linked: boolean;
hovering: boolean;
connecting: boolean;
}>();
$: parameterType = structure.inputs
.concat(structure.outputs)
.find((i) => i.id == parameter.id)
?.type.replace('&', '');
$: typeDefinition = get(types).find((t) => t.type.replace('&', '') == parameterType)!;
let parameterType = $derived(
structure.inputs
.concat(structure.outputs)
.find((i) => i.id == parameter.id)
?.type.replace('&', '')
);
let typeDefinition = $derived(
state.workspace?.types.find((t) => t.type.replace('&', '') == parameterType)
);
</script>

<div
Expand All @@ -29,14 +40,14 @@
class:linked
class:hovering
class:connecting
style={`--type-color: ${typeDefinition.color.hex}`}
style={`--type-color: ${typeDefinition?.color.hex}`}
>
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
{#if typeDefinition.shape == 'circle'}
{#if typeDefinition?.shape == 'circle'}
<circle cx="50" cy="50" r="40" />
{:else if typeDefinition.shape == 'diamond'}
{:else if typeDefinition?.shape == 'diamond'}
<polygon points="49,1 99,49 49,99 1,49" />
{:else if typeDefinition.shape == 'square'}
{:else if typeDefinition?.shape == 'square'}
<rect x="10" y="10" width="80" height="80" />
{/if}
</svg>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
<script lang="ts">
import { get } from 'svelte/store';
import {
types,
type ParameterStructure,
typeToDefinition,
type ParameterInstance,
type NodeStructure
} from '$lib/nodes';
import { type ParameterStructure, type ParameterInstance, type NodeStructure } from '$lib/nodes';
import Value from './Value.svelte';
import { createEventDispatcher } from 'svelte';
import { state } from '$lib/state.svelte';
export let structure: NodeStructure;
export let parameter: ParameterInstance;
export let linked: boolean;
export let connecting: boolean;
let { structure, parameter, linked, connecting } = $props<{
structure: NodeStructure;
parameter: ParameterInstance;
linked: boolean;
connecting: boolean;
}>();
const dispatch = createEventDispatcher();
Expand All @@ -23,7 +20,17 @@
//e.preventDefault();
}
$: parameterType = structure.inputs.find((i) => i.id == parameter.id)?.type.replace('&', '')!;
let parameterType = $derived(
structure.inputs
.concat(structure.outputs)
.find((i) => i.id == parameter.id)
?.type.replace('&', '')
);
// FIXME: The type *could* not exist, but it shouldn't. We should probably handle this better
let typeDefinition = $derived(
state.workspace?.types.find((t) => t.type.replace('&', '') == parameterType)
)!;
</script>

<div class="default-wrapper" class:linked class:connecting>
Expand All @@ -32,7 +39,7 @@
<div class="default" on:mousedown={handleClick}>
<Value
on:change={() => dispatch('change')}
type={typeToDefinition(parameterType)}
type={typeDefinition}
bind:value={parameter.value}
input
/>
Expand Down
93 changes: 52 additions & 41 deletions src-client/src/lib/components/editor/EditorEdge.svelte
Original file line number Diff line number Diff line change
@@ -1,56 +1,67 @@
<script lang="ts">
import { Edge, type WritableEdge } from "svelvet";
import { structures, type ParameterStructure, typeToDefinition, instanceFromId } from "../../lib/nodes";
import { get } from "svelte/store";
import { blendColors } from "../../lib/color";
import { Edge, type WritableEdge } from 'svelvet';
import { type ParameterStructure, instanceFromId } from '$lib/nodes';
import { blendColors } from '$lib/color';
import { state as s } from '$lib/state.svelte';
let ref: SVGPathElement | undefined = undefined;
let edge: WritableEdge;
let ref: SVGPathElement | undefined = $state();
let edge: WritableEdge | undefined = $state();
$: source = findParameter(edge?.source.id, false);
$: target = findParameter(edge?.target.id, true);
let source = $derived(findParameter(edge?.source.id, false));
let target = $derived(findParameter(edge?.target.id, true));
$: startColor = typeToDefinition(source?.type ?? "")?.color?.hex ?? "#ffffff";
$: midwayColor = blendColors(startColor, stopColor, 0.5);
$: stopColor = typeToDefinition(target?.type ?? "")?.color?.hex ?? "#ffffff";
let sourceType = $derived(
s.workspace?.types.find((t) => t.type.replace('&', '') == source?.type.replace('&', ''))
);
$: gradientName = `gradient-${edge?.target.id ?? "default"}`;
let targetType = $derived(
s.workspace?.types.find((t) => t.type.replace('&', '') == target?.type.replace('&', ''))
);
function findParameter(id: string | null, isInput: boolean): ParameterStructure | undefined {
if (id == null) return undefined;
let startColor = $derived(sourceType?.color?.hex ?? '#ffffff');
let stopColor = $derived(targetType?.color?.hex ?? '#ffffff');
let midwayColor = $derived(blendColors(startColor, stopColor, 0.5));
let parameterId = id.split("/")[0].substring(2); // remove "A-"
let instanceId = id.split("/")[1].substring(2); // remove "N-"
let gradientName = $derived(`gradient-${edge?.target.id ?? 'default'}`);
let instance = instanceFromId(instanceId);
let structure = get(structures).find((s) => s.nodeType == instance?.nodeType);
function findParameter(
id: `A-${string}` | undefined | null,
isInput: boolean
): ParameterStructure | undefined {
if (id == null) return undefined;
if (isInput) {
return structure?.inputs.find((p) => p.id == parameterId);
} else {
return structure?.outputs.find((p) => p.id == parameterId);
}
}
let parameterId = id.split('/')[0].substring(2); // remove "A-"
let instanceId = id.split('/')[1].substring(2); // remove "N-"
let instance = instanceFromId(instanceId);
let structure = s.workspace?.structures.find((s) => s.nodeType == instance?.nodeType);
if (isInput) {
return structure?.inputs.find((p) => p.id == parameterId);
} else {
return structure?.outputs.find((p) => p.id == parameterId);
}
}
</script>

<Edge bind:edge let:path let:destroy edgeClick={() => alert("Edge clicked")}>
<!-- Define a gradient that goes from the source color to the target color -->
<defs>
<linearGradient id={gradientName} x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color={startColor} />
<stop offset="50%" stop-color={midwayColor} />
<stop offset="100%" stop-color={stopColor} />
</linearGradient>
</defs>

<path bind:this={ref} d={path} style:--gradient-name={`url(#${gradientName})`} />
<Edge bind:edge let:path let:destroy edgeClick={() => alert('Edge clicked')}>
<!-- Define a gradient that goes from the source color to the target color -->
<defs>
<linearGradient id={gradientName} x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color={startColor} />
<stop offset="50%" stop-color={midwayColor} />
<stop offset="100%" stop-color={stopColor} />
</linearGradient>
</defs>

<path bind:this={ref} d={path} style:--gradient-name={`url(#${gradientName})`} />
</Edge>

<style lang="scss">
path {
// Gradient fill based on the source and target colors
stroke: var(--gradient-name);
stroke-width: 4px;
z-index: 1;
}
path {
// Gradient fill based on the source and target colors
stroke: var(--gradient-name);
stroke-width: 4px;
z-index: 1;
}
</style>
Loading

0 comments on commit 7113fdc

Please sign in to comment.