Skip to content

Commit

Permalink
More work on subgraph portal UI
Browse files Browse the repository at this point in the history
 * Allow renaming subgraphs
  • Loading branch information
Ameobea committed Feb 11, 2024
1 parent 422ff6a commit 46cce6e
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 7 deletions.
6 changes: 6 additions & 0 deletions engine/engine/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,12 @@ pub fn set_active_subgraph_id(subgraph_id: &str) {
vcm.set_active_subgraph(uuid, false);
}

#[wasm_bindgen]
pub fn rename_subgraph(subgraph_id: &str, new_name: String) {
let uuid = Uuid::from_str(subgraph_id).expect("Invalid UUID string passed to `rename_subgraph`!");
get_vcm().rename_subgraph(uuid, new_name);
}

#[wasm_bindgen]
pub fn undo_view_change() { get_vcm().undo_view_change(); }

Expand Down
12 changes: 12 additions & 0 deletions engine/engine/src/view_context/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,18 @@ impl ViewContextManager {
);
}

pub fn rename_subgraph(&mut self, subgraph_id: Uuid, new_name: String) {
let subgraph = self
.subgraphs_by_id
.get_mut(&subgraph_id)
.expect("Tried to rename a subgraph that doesn't exist. This should never happen.");
subgraph.name = new_name;
js::set_subgraphs(
&self.active_subgraph_id.to_string(),
&serde_json::to_string(&self.subgraphs_by_id).unwrap(),
);
}

fn set_view(&mut self, subgraph_id: Uuid, vc_id: Uuid) -> Result<(), ()> {
if self.subgraphs_by_id.contains_key(&subgraph_id)
&& self.contexts.iter().any(|vc| vc.id == vc_id)
Expand Down
4 changes: 4 additions & 0 deletions src/graphEditor/nodes/CustomAudio/FMSynthFx/FMSynthFxNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ export class FMSynthFxNode implements ForeignNode {
getProps: () => ({
store: this.store,
onChange: (ix: number, newState: Partial<Effect> | null) => this.handleChange(ix, newState),
commitAll: () => {
const state = get(this.store);
state.effects.forEach((effect, effectIx) => this.commitEffect(effectIx, effect));
},
}),
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,17 @@
import type { AdsrParams } from 'src/graphEditor/nodes/CustomAudio/FMSynth';
import type { FMSynthFxState } from 'src/graphEditor/nodes/CustomAudio/FMSynthFx/FMSynthFxNode';
import type { Effect } from 'src/fmSynth/Effect';
import { UnreachableError } from 'src/util';
export let store: Writable<FMSynthFxState>;
export let onChange: (ix: number, newState: Partial<Effect> | null) => void;
export let commitAll: () => void;
let state: (Effect | null)[] = $store.effects;
$: state = $store.effects;
const setOperatorEffects = (newOperatorEffects: (Effect | null)[]) => {
throw new UnreachableError('Should never set operator-specific fx in FMSynthFxSmallView');
const setOperatorEffects = (newFx: (Effect | null)[]) => {
store.set({ effects: newFx });
commitAll();
};
let adsrs: AdsrParams[] = []; // TODO
let onAdsrChange: AdsrChangeHandler = (adsrIx: number, newParams: AdsrParams) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ export class SubgraphPortalNode implements ForeignNode {
public registeredOutputs: Writable<PortMap> = writable({});
private placeholderInput: PlaceholderInput;
private placeholderOutput: PlaceholderOutput;
public lgNode?: LGraphNode;

static typeName = 'Subgraph Portal';
static manuallyCreatable = false;
Expand Down Expand Up @@ -212,6 +213,14 @@ export class SubgraphPortalNode implements ForeignNode {
},
renamePort: (side: 'input' | 'output', oldName: string, newName: string) =>
void this.renamePort(side, oldName, newName),
setSubgraphName: (newSubgraphName: string) => {
getEngine()!.rename_subgraph(this.rxSubgraphID, newSubgraphName);
if (this.lgNode) {
this.lgNode.title = newSubgraphName;
this.lgNode.graph?.setDirtyCanvas(true, false);
}
},
rxSubgraphID: this.rxSubgraphID,
}),
});
this.cleanupSmallView = mkSvelteContainerCleanupHelper({ preserveRoot: true });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,32 @@
import type { PortMap } from 'src/graphEditor/nodes/CustomAudio/Subgraph/SubgraphPortalNode';
import type { Writable } from 'svelte/store';
import PortList from './PortList.svelte';
import EditableInstanceName from 'src/midiEditor/EditableInstanceName.svelte';
import { svelteStoreFromRedux } from 'src/svelteUtils';
export let inputs: Writable<PortMap>;
export let outputs: Writable<PortMap>;
export let renamePort: (side: 'input' | 'output', oldName: string, newName: string) => void;
export let deletePort: (ports: Writable<PortMap>, name: string) => void;
export let setSubgraphName: (newName: string) => void;
export let rxSubgraphID: string;
const subgraphName = svelteStoreFromRedux(
state => state.viewContextManager.subgraphsByID[rxSubgraphID]?.name
);
</script>

<div class="root">
<div class="subgraph-name">
<EditableInstanceName
left={0}
--position="relative"
--font-size="18px"
--icon-font-size="22px"
name={$subgraphName}
setName={setSubgraphName}
/>
</div>
<PortList
title="Inputs"
ports={inputs}
Expand All @@ -30,4 +48,13 @@
flex-direction: column;
flex: 1;
}
.subgraph-name {
display: flex;
align-items: center;
justify-content: center;
border-bottom: 1px solid #333;
padding-bottom: 2px;
font-weight: bold;
}
</style>
4 changes: 2 additions & 2 deletions src/midiEditor/EditableInstanceName.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
class="edit-name"
style="visibility: {nameWrapperHovered && !isEditingName
? 'visible'
: 'hidden'}; font-size: 16px;"
: 'hidden'}; font-size: var(--icon-font-size, 16px);"
on:click={e => {
e.stopPropagation();
isEditingName = true;
Expand Down Expand Up @@ -88,7 +88,7 @@
Oxygen Mono,
Menlo,
monospace;
font-size: 13px;
font-size: var(--font-size, 13px);
}
.edit-name {
Expand Down
33 changes: 31 additions & 2 deletions src/svelteUtils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import React, { type JSXElementConstructor, type ReactElement, type RefObject } from 'react';
import type { Unsubscribe as ReduxUnsubscribe, Store } from 'redux';
import type { SvelteComponent } from 'svelte';
import type { Writable } from 'svelte/store';
import { getState, store, type ReduxStore } from 'src/redux';
import { onDestroy, type SvelteComponent } from 'svelte';
import { writable, type Writable } from 'svelte/store';

import type { Subscriber, Unsubscriber, Updater } from 'svelte/store';

Expand Down Expand Up @@ -157,6 +158,34 @@ export function buildSvelteReduxStoreBridge<State, Slice>(
return { set, update, subscribe };
}

/**
* Subscribes to a Redux store using the provided `selector` and returns the result as a Svelte store.
*
* Automatically unsubscribes from the Redux store when the Svelte component is destroyed.
*
* NOTE: The provided `selector` must remain static.
*/
export function svelteStoreFromRedux<Slice>(
selector: (state: ReduxStore) => Slice
): Writable<Slice> {
let lastSlice = selector(getState());
const svelteStore = writable(lastSlice);

const unsub = store.subscribe(() => {
const slice = selector(getState());
if (slice === lastSlice) {
return;
}
lastSlice = slice;

svelteStore.set(slice);
});

onDestroy(() => void unsub());

return svelteStore;
}

export type SveltePropTypesOf<Comp> =
Comp extends SvelteComponent<infer Props>
? Props
Expand Down

0 comments on commit 46cce6e

Please sign in to comment.