Skip to content

Commit

Permalink
Implemented shared graph templates, but loading not working
Browse files Browse the repository at this point in the history
  • Loading branch information
newcat committed Mar 12, 2024
1 parent 2ec8e6c commit c9ed56b
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 17 deletions.
7 changes: 7 additions & 0 deletions src/globalState.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { ref } from "vue";
import { defineStore } from "pinia";
import { IGraphTemplateState } from "baklavajs";
import { BaklavaEvent } from "@baklavajs/events";

import { ITimelineState, useTimeline } from "@/timeline";
import { ILibraryState, useLibrary } from "./library";
import { useGraphTemplateSync } from "./graph";
import { TICKS_PER_BEAT } from "./constants";
import { StageState, useStage } from "./stage";

Expand All @@ -26,6 +28,7 @@ export interface SavedState {
resolution: number;
snapUnits: number;
bridgeUrl: string;
graphTemplates: IGraphTemplateState[];
}

export const useGlobalState = defineStore("globalState", () => {
Expand All @@ -43,6 +46,7 @@ export const useGlobalState = defineStore("globalState", () => {
const stage = useStage();
const library = useLibrary();
const timeline = useTimeline();
const graphTemplates = useGraphTemplateSync();

const events = {
positionSetByUser: new BaklavaEvent<void, undefined>(undefined),
Expand All @@ -69,6 +73,7 @@ export const useGlobalState = defineStore("globalState", () => {
stage: stage.save(),
timeline: timeline.save(),
library: library.save(),
graphTemplates: graphTemplates.save(),
bpm: bpm.value,
fps: fps.value,
volume: volume.value,
Expand All @@ -83,6 +88,7 @@ export const useGlobalState = defineStore("globalState", () => {
async function load(raw: string) {
const data: SavedState = JSON.parse(raw) as SavedState;
stage.load(data.stage);
graphTemplates.load(data.graphTemplates ?? []);
await library.load(data.library);
timeline.load(data.timeline);
bpm.value = data.bpm ?? defaults.bpm;
Expand Down Expand Up @@ -110,6 +116,7 @@ export const useGlobalState = defineStore("globalState", () => {
snapUnits,
metronome,
bridgeUrl,
graphTemplates,
timeline,
events,
reset,
Expand Down
3 changes: 0 additions & 3 deletions src/graph/editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,6 @@ export class BaklavaEditor {
this.editor.graphEvents.addConnection.subscribe(this, () => this.updateNodeInterfaceTypes());
this.editor.graphEvents.removeConnection.subscribe(this, () => this.updateNodeInterfaceTypes());

// TODO: Remove after next Baklava upgrade
this.enginePlugin.calculateOrder();

this.enginePlugin.events.afterRun.subscribe(this, (r) => {
applyResult(r, this.editor);
});
Expand Down
16 changes: 15 additions & 1 deletion src/graph/graph.libraryItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { IEditorState } from "baklavajs";
import { LibraryItem, LibraryItemType } from "@/library";
import { BaklavaEditor } from "./editor";
import { KeyframeManager, InterfaceKeyframes } from "./keyframes/KeyframeManager";
import { useGlobalState } from "@/globalState";

export interface GraphLibraryItemState {
graph: IEditorState;
Expand All @@ -15,6 +16,11 @@ export class GraphLibraryItem extends LibraryItem<GraphLibraryItemState> {
public editor = new BaklavaEditor();
public keyframeManager = new KeyframeManager(this);

public constructor() {
super();
useGlobalState().graphTemplates.registerTarget(this.editor.editor);
}

public override save() {
return {
graph: this.editor.editor.save(),
Expand All @@ -23,7 +29,15 @@ export class GraphLibraryItem extends LibraryItem<GraphLibraryItemState> {
}

public override load(state: GraphLibraryItemState) {
this.editor.editor.load(state.graph);
const warnings = this.editor.editor.load(state.graph);
if (warnings.length > 0) {
console.warn("Warnings while loading graph:", warnings);
}
this.keyframeManager.keyframes = new Map(Object.entries(state.keyframes));
}

public override destroy(): Promise<void> {
useGlobalState().graphTemplates.unregisterTarget(this.editor.editor);
return Promise.resolve();
}
}
95 changes: 95 additions & 0 deletions src/graph/graphTemplateSync.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { Editor, GraphTemplate, IGraphTemplateState } from "baklavajs";

export function useGraphTemplateSync() {
const token = Symbol("useGraphTemplateSync");
const targets: Editor[] = [];
const templates = new Map<string, IGraphTemplateState>();
let updating = false;

function registerTarget(target: Editor) {
targets.push(target);
target.events.addGraphTemplate.subscribe(token, (template) => {
updateTemplate(template.save());
});
target.events.removeGraphTemplate.subscribe(token, (template) => {
removeTemplate(template.id);
});
target.graphTemplateEvents.updated.subscribe(token, (_, template) => {
updateTemplate(template.save());
});
target.graphTemplateEvents.nameChanged.subscribe(token, (_, template) => {
updateTemplate(template.save());
});
for (const template of templates.values()) {
if (target.graphTemplates.find((t) => t.id === template.id)) {
continue;
}

const newTemplate = new GraphTemplate(template, target);
newTemplate.id = template.id;
target.addGraphTemplate(newTemplate);
}
}

function unregisterTarget(target: Editor) {
const index = targets.indexOf(target);
if (index !== -1) {
targets.splice(index, 1);

const target = targets[index];
target.events.addGraphTemplate.unsubscribe(token);
target.events.removeGraphTemplate.unsubscribe(token);
target.graphTemplateEvents.updated.unsubscribe(token);
target.graphTemplateEvents.nameChanged.unsubscribe(token);
}
}

function save() {
return Array.from(templates.values());
}

function load(state: IGraphTemplateState[]) {
for (const template of state) {
updateTemplate(template);
}
}

function updateTemplate(template: IGraphTemplateState) {
if (updating) {
return;
}

updating = true;
templates.set(template.id, template);
for (const target of targets) {
const targetTemplate = target.graphTemplates.find((t) => t.id === template.id);
if (targetTemplate) {
targetTemplate.update(template);
targetTemplate.name = template.name;
} else {
const newTemplate = new GraphTemplate(template, target);
newTemplate.id = template.id;
target.addGraphTemplate(newTemplate);
}
}
updating = false;
}

function removeTemplate(id: string) {
if (updating) {
return;
}

updating = true;
templates.delete(id);
for (const target of targets) {
const targetTemplate = target.graphTemplates.find((t) => t.id === id);
if (targetTemplate) {
target.removeGraphTemplate(targetTemplate);
}
}
updating = false;
}

return { registerTarget, unregisterTarget, save, load };
}
1 change: 1 addition & 0 deletions src/graph/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from "./editor";
export * from "./graph.libraryItem";
export * from "./types";
export * from "./graphTemplateSync";
export { default as GraphEditor } from "./GraphEditor.vue";
30 changes: 17 additions & 13 deletions src/timeline/timelineProcessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { INote, PatternLibraryItem } from "@/pattern";
import { ICalculationData } from "@/graph";
import { useGlobalState } from "@/globalState";
import { useStage } from "@/stage/stage";
import { BaseFixture } from "@/stage";

export class TimelineProcessor {
public trackValues = new Map<string, number | INote[]>(); // maps trackId -> value
Expand Down Expand Up @@ -91,7 +92,7 @@ export class TimelineProcessor {

const audioData = this.audioProcessor!.getAudioData();

const uncontrolledFixtures = new Set(this.stage.fixtures.values());
const uncontrolledFixtures = new Set(this.stage.fixtures.values()) as Set<BaseFixture>;
const calculationData: ICalculationData = {
resolution: this.globalState.resolution,
fps: this.globalState.fps,
Expand All @@ -105,21 +106,10 @@ export class TimelineProcessor {
for (const g of graphs) {
try {
const results = await this.processGraph(g, unit, calculationData);

if (g.libraryItem.error) {
g.libraryItem.error = "";
}

results.forEach((intfValues) => {
if (!intfValues.has("fixtureId")) {
return;
}
const fixture = this.stage.fixtures.get(intfValues.get("fixtureId"));
if (fixture) {
uncontrolledFixtures.delete(fixture);
fixture.setValue(intfValues.get("data"));
}
});
this.applyGraphResults(results, uncontrolledFixtures);
} catch (err) {
console.error(err);
g.libraryItem.error = String(err);
Expand Down Expand Up @@ -192,4 +182,18 @@ export class TimelineProcessor {
const notes = np.getNotesAt(unit - item.start);
this.trackValues.set(item.trackId, notes);
}

private applyGraphResults(results: CalculationResult, uncontrolledFixtures: Set<BaseFixture>): void {
for (const nodeResults of results.values()) {
if (nodeResults.has("_calculationResults")) {
this.applyGraphResults(nodeResults.get("_calculationResults") as CalculationResult, uncontrolledFixtures);
} else if (nodeResults.has("fixtureId")) {
const fixture = this.stage.fixtures.get(nodeResults.get("fixtureId"));
if (fixture) {
uncontrolledFixtures.delete(fixture as BaseFixture);
fixture.setValue(nodeResults.get("data"));
}
}
}
}
}

0 comments on commit c9ed56b

Please sign in to comment.