@opendaw/studio-core 0.0.10 → 0.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/EffectFactories.d.ts +38 -0
- package/dist/EffectFactories.d.ts.map +1 -0
- package/dist/EffectFactories.js +163 -0
- package/dist/EffectFactory.d.ts +13 -0
- package/dist/EffectFactory.d.ts.map +1 -0
- package/dist/EffectFactory.js +1 -0
- package/dist/InstrumentBox.d.ts +3 -0
- package/dist/InstrumentBox.d.ts.map +1 -0
- package/dist/InstrumentBox.js +1 -0
- package/dist/InstrumentFactories.d.ts +15 -0
- package/dist/InstrumentFactories.d.ts.map +1 -0
- package/dist/{Instruments.js → InstrumentFactories.js} +31 -69
- package/dist/InstrumentFactory.d.ts +11 -0
- package/dist/InstrumentFactory.d.ts.map +1 -0
- package/dist/InstrumentFactory.js +1 -0
- package/dist/InstrumentOptions.d.ts +8 -0
- package/dist/InstrumentOptions.d.ts.map +1 -0
- package/dist/InstrumentOptions.js +1 -0
- package/dist/InstrumentProduct.d.ts +8 -0
- package/dist/InstrumentProduct.d.ts.map +1 -0
- package/dist/InstrumentProduct.js +1 -0
- package/dist/Project.d.ts +3 -1
- package/dist/Project.d.ts.map +1 -1
- package/dist/Project.js +7 -59
- package/dist/ProjectApi.d.ts +44 -0
- package/dist/ProjectApi.d.ts.map +1 -0
- package/dist/ProjectApi.js +217 -0
- package/dist/ProjectMigration.d.ts +5 -0
- package/dist/ProjectMigration.d.ts.map +1 -0
- package/dist/ProjectMigration.js +60 -0
- package/dist/index.d.ts +8 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -3
- package/dist/processors.js +2 -2
- package/dist/processors.js.map +3 -3
- package/dist/workers.js +2 -2
- package/dist/workers.js.map +4 -4
- package/package.json +16 -16
- package/dist/Effects.d.ts +0 -154
- package/dist/Effects.d.ts.map +0 -1
- package/dist/Effects.js +0 -166
- package/dist/Instruments.d.ts +0 -35
- package/dist/Instruments.d.ts.map +0 -1
- package/dist/Modifier.d.ts +0 -21
- package/dist/Modifier.d.ts.map +0 -1
- package/dist/Modifier.js +0 -168
@@ -0,0 +1,217 @@
|
|
1
|
+
import { assert, Option, panic, Strings, UUID } from "@opendaw/lib-std";
|
2
|
+
import { AudioUnitType } from "@opendaw/studio-enums";
|
3
|
+
import { AudioBusBox, AudioUnitBox, NoteClipBox, NoteEventBox, NoteEventCollectionBox, NoteRegionBox, TrackBox, ValueClipBox, ValueEventCollectionBox, ValueRegionBox } from "@opendaw/studio-boxes";
|
4
|
+
import { AudioUnitBoxAdapter, IconSymbol, NoteEventBoxAdapter, TrackType } from "@opendaw/studio-adapters";
|
5
|
+
import { ColorCodes } from "./ColorCodes";
|
6
|
+
import { PPQN } from "@opendaw/lib-dsp";
|
7
|
+
export class ProjectApi {
|
8
|
+
static AudioUnitOrdering = {
|
9
|
+
[AudioUnitType.Instrument]: 0,
|
10
|
+
[AudioUnitType.Aux]: 1,
|
11
|
+
[AudioUnitType.Bus]: 2,
|
12
|
+
[AudioUnitType.Output]: 3
|
13
|
+
};
|
14
|
+
#project;
|
15
|
+
constructor(project) { this.#project = project; }
|
16
|
+
createInstrument({ create, defaultIcon, defaultName, trackType }, { name, icon, index } = {}) {
|
17
|
+
const { boxGraph, boxAdapters, rootBoxAdapter, userEditingManager } = this.#project;
|
18
|
+
const existingNames = rootBoxAdapter.audioUnits.adapters()
|
19
|
+
.map(adapter => adapter.input.getValue().match({
|
20
|
+
none: () => "Untitled",
|
21
|
+
some: adapter => adapter.labelField.getValue()
|
22
|
+
}));
|
23
|
+
const audioUnitBox = this.#createAudioUnit(AudioUnitType.Instrument, index);
|
24
|
+
const audioUnitBoxAdapter = boxAdapters.adapterFor(audioUnitBox, AudioUnitBoxAdapter);
|
25
|
+
const uniqueName = Strings.getUniqueName(existingNames, name ?? defaultName);
|
26
|
+
const iconSymbol = icon ?? defaultIcon;
|
27
|
+
const instrumentBox = create(boxGraph, audioUnitBoxAdapter, uniqueName, iconSymbol);
|
28
|
+
const trackBox = TrackBox.create(boxGraph, UUID.generate(), box => {
|
29
|
+
box.index.setValue(0);
|
30
|
+
box.type.setValue(trackType);
|
31
|
+
box.tracks.refer(audioUnitBoxAdapter.tracksField);
|
32
|
+
box.target.refer(audioUnitBoxAdapter.audioUnitBoxAdapter().box);
|
33
|
+
});
|
34
|
+
userEditingManager.audioUnit.edit(audioUnitBox.editing);
|
35
|
+
return { audioUnitBox, instrumentBox, trackBox };
|
36
|
+
}
|
37
|
+
createEffect(host, factory, newIndex) {
|
38
|
+
let chain;
|
39
|
+
let field;
|
40
|
+
if (factory.type === "audio") {
|
41
|
+
chain = host.audioEffects.adapters();
|
42
|
+
field = host.audioEffects.field();
|
43
|
+
}
|
44
|
+
else if (factory.type === "midi") {
|
45
|
+
chain = host.midiEffects.adapters();
|
46
|
+
field = host.midiEffects.field();
|
47
|
+
}
|
48
|
+
else {
|
49
|
+
return panic(`Unknown factory type: ${factory.type}`);
|
50
|
+
}
|
51
|
+
const box = factory.create(this.#project, field, newIndex);
|
52
|
+
for (let index = newIndex; index < chain.length; index++) {
|
53
|
+
chain[index].indexField.setValue(index + 1);
|
54
|
+
}
|
55
|
+
return box;
|
56
|
+
}
|
57
|
+
createAudioBus(name, icon, type, color) {
|
58
|
+
console.debug(`createAudioBus '${name}', type: ${type}, color: ${color}`);
|
59
|
+
const { rootBox, boxGraph } = this.#project;
|
60
|
+
assert(rootBox.audioBusses.isAttached(), "rootBox not attached");
|
61
|
+
const uuid = UUID.generate();
|
62
|
+
const audioBusBox = AudioBusBox.create(boxGraph, uuid, box => {
|
63
|
+
box.collection.refer(rootBox.audioBusses);
|
64
|
+
box.label.setValue(name);
|
65
|
+
box.icon.setValue(IconSymbol.toName(icon));
|
66
|
+
box.color.setValue(color);
|
67
|
+
});
|
68
|
+
const audioUnitBox = this.#createAudioUnit(type);
|
69
|
+
TrackBox.create(boxGraph, UUID.generate(), box => {
|
70
|
+
box.tracks.refer(audioUnitBox.tracks);
|
71
|
+
box.target.refer(audioUnitBox);
|
72
|
+
box.index.setValue(0);
|
73
|
+
box.type.setValue(TrackType.Undefined);
|
74
|
+
});
|
75
|
+
audioBusBox.output.refer(audioUnitBox.input);
|
76
|
+
return audioBusBox;
|
77
|
+
}
|
78
|
+
createNoteTrack(adapter, index = 0) {
|
79
|
+
return this.#createTrack(adapter, TrackType.Notes, index);
|
80
|
+
}
|
81
|
+
createAudioTrack(adapter, index = 0) {
|
82
|
+
return this.#createTrack(adapter, TrackType.Audio, index);
|
83
|
+
}
|
84
|
+
createAutomationTrack(adapter, index = 0) {
|
85
|
+
return this.#createTrack(adapter, TrackType.Value, index);
|
86
|
+
}
|
87
|
+
createClip(trackBox, clipIndex, { name, hue } = {}) {
|
88
|
+
const { boxGraph } = this.#project;
|
89
|
+
const type = trackBox.type.getValue();
|
90
|
+
switch (type) {
|
91
|
+
case TrackType.Notes: {
|
92
|
+
const events = NoteEventCollectionBox.create(boxGraph, UUID.generate());
|
93
|
+
return Option.wrap(NoteClipBox.create(boxGraph, UUID.generate(), box => {
|
94
|
+
box.index.setValue(clipIndex);
|
95
|
+
box.label.setValue(name ?? "Notes");
|
96
|
+
box.hue.setValue(hue ?? ColorCodes.forTrackType(type));
|
97
|
+
box.mute.setValue(false);
|
98
|
+
box.duration.setValue(PPQN.Bar);
|
99
|
+
box.clips.refer(trackBox.clips);
|
100
|
+
box.events.refer(events.owners);
|
101
|
+
}));
|
102
|
+
}
|
103
|
+
case TrackType.Value: {
|
104
|
+
const events = ValueEventCollectionBox.create(boxGraph, UUID.generate());
|
105
|
+
return Option.wrap(ValueClipBox.create(boxGraph, UUID.generate(), box => {
|
106
|
+
box.index.setValue(clipIndex);
|
107
|
+
box.label.setValue(name ?? "CV");
|
108
|
+
box.hue.setValue(hue ?? ColorCodes.forTrackType(type));
|
109
|
+
box.mute.setValue(false);
|
110
|
+
box.duration.setValue(PPQN.Bar);
|
111
|
+
box.events.refer(events.owners);
|
112
|
+
box.clips.refer(trackBox.clips);
|
113
|
+
}));
|
114
|
+
}
|
115
|
+
}
|
116
|
+
return Option.None;
|
117
|
+
}
|
118
|
+
createRegion(trackBox, position, duration, { name, hue } = {}) {
|
119
|
+
const { boxGraph } = this.#project;
|
120
|
+
const type = trackBox.type.getValue();
|
121
|
+
switch (type) {
|
122
|
+
case TrackType.Notes: {
|
123
|
+
const events = NoteEventCollectionBox.create(boxGraph, UUID.generate());
|
124
|
+
return Option.wrap(NoteRegionBox.create(boxGraph, UUID.generate(), box => {
|
125
|
+
box.position.setValue(Math.max(position, 0));
|
126
|
+
box.label.setValue(name ?? "Notes");
|
127
|
+
box.hue.setValue(hue ?? ColorCodes.forTrackType(type));
|
128
|
+
box.mute.setValue(false);
|
129
|
+
box.duration.setValue(duration);
|
130
|
+
box.loopDuration.setValue(PPQN.Bar);
|
131
|
+
box.events.refer(events.owners);
|
132
|
+
box.regions.refer(trackBox.regions);
|
133
|
+
}));
|
134
|
+
}
|
135
|
+
case TrackType.Value: {
|
136
|
+
const events = ValueEventCollectionBox.create(boxGraph, UUID.generate());
|
137
|
+
return Option.wrap(ValueRegionBox.create(boxGraph, UUID.generate(), box => {
|
138
|
+
box.position.setValue(Math.max(position, 0));
|
139
|
+
box.label.setValue(name ?? "Automation");
|
140
|
+
box.hue.setValue(hue ?? ColorCodes.forTrackType(type));
|
141
|
+
box.mute.setValue(false);
|
142
|
+
box.duration.setValue(duration);
|
143
|
+
box.loopDuration.setValue(PPQN.Bar);
|
144
|
+
box.events.refer(events.owners);
|
145
|
+
box.regions.refer(trackBox.regions);
|
146
|
+
}));
|
147
|
+
}
|
148
|
+
}
|
149
|
+
return Option.None;
|
150
|
+
}
|
151
|
+
createNoteEvent({ owner, position, duration, velocity, pitch, chance, cent }) {
|
152
|
+
const { boxAdapters, boxGraph } = this.#project;
|
153
|
+
return boxAdapters.adapterFor(NoteEventBox.create(boxGraph, UUID.generate(), box => {
|
154
|
+
box.position.setValue(position);
|
155
|
+
box.duration.setValue(duration);
|
156
|
+
box.velocity.setValue(velocity ?? 1.0);
|
157
|
+
box.pitch.setValue(pitch);
|
158
|
+
box.chance.setValue(chance ?? 100.0);
|
159
|
+
box.cent.setValue(cent ?? 0.0);
|
160
|
+
box.events.refer(owner.events.targetVertex
|
161
|
+
.unwrap("Owner has no event-collection").box
|
162
|
+
.asBox(NoteEventCollectionBox).events);
|
163
|
+
}), NoteEventBoxAdapter);
|
164
|
+
}
|
165
|
+
deleteAudioUnit(adapter) {
|
166
|
+
const { rootBoxAdapter } = this.#project;
|
167
|
+
const adapters = rootBoxAdapter.audioUnits.adapters();
|
168
|
+
const boxIndex = adapter.indexField.getValue();
|
169
|
+
const deleteIndex = adapters.indexOf(adapter);
|
170
|
+
console.debug(`deleteAudioUnit adapter: ${adapter.toString()}, deleteIndex: ${deleteIndex}, indexField: ${boxIndex}`);
|
171
|
+
if (deleteIndex === -1) {
|
172
|
+
return panic(`Cannot delete ${adapter}. Does not exist.`);
|
173
|
+
}
|
174
|
+
if (deleteIndex !== boxIndex) {
|
175
|
+
console.debug("indices", adapters.map(x => x.box.index.getValue()).join(", "));
|
176
|
+
return panic(`Cannot delete ${adapter}. Wrong index.`);
|
177
|
+
}
|
178
|
+
for (let index = deleteIndex + 1; index < adapters.length; index++) {
|
179
|
+
adapters[index].indexField.setValue(index - 1);
|
180
|
+
}
|
181
|
+
adapter.box.delete();
|
182
|
+
}
|
183
|
+
#createAudioUnit(type, index) {
|
184
|
+
const { boxGraph, rootBox, rootBoxAdapter, masterBusBox } = this.#project;
|
185
|
+
const insertIndex = index ?? this.#pushAudioUnitsIndices(rootBoxAdapter, type, 1);
|
186
|
+
console.debug(`createAudioUnit type: ${type}, insertIndex: ${insertIndex}`);
|
187
|
+
return AudioUnitBox.create(boxGraph, UUID.generate(), box => {
|
188
|
+
box.collection.refer(rootBox.audioUnits);
|
189
|
+
box.output.refer(masterBusBox.input);
|
190
|
+
box.index.setValue(insertIndex);
|
191
|
+
box.type.setValue(type);
|
192
|
+
});
|
193
|
+
}
|
194
|
+
#createTrack(adapter, trackType, index = 0) {
|
195
|
+
return TrackBox.create(this.#project.boxGraph, UUID.generate(), box => {
|
196
|
+
box.index.setValue(index);
|
197
|
+
box.type.setValue(trackType);
|
198
|
+
box.tracks.refer(adapter.tracksField);
|
199
|
+
box.target.refer(adapter.audioUnitBoxAdapter().box);
|
200
|
+
});
|
201
|
+
}
|
202
|
+
#pushAudioUnitsIndices(rootBoxAdapter, type, count = 1) {
|
203
|
+
const adapters = rootBoxAdapter.audioUnits.adapters();
|
204
|
+
const order = ProjectApi.AudioUnitOrdering[type];
|
205
|
+
let index = 0 | 0;
|
206
|
+
for (; index < adapters.length; index++) {
|
207
|
+
if (ProjectApi.AudioUnitOrdering[adapters[index].type] > order) {
|
208
|
+
break;
|
209
|
+
}
|
210
|
+
}
|
211
|
+
const insertIndex = index;
|
212
|
+
while (index < adapters.length) {
|
213
|
+
adapters[index].indexField.setValue(count + index++);
|
214
|
+
}
|
215
|
+
return insertIndex;
|
216
|
+
}
|
217
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"ProjectMigration.d.ts","sourceRoot":"","sources":["../src/ProjectMigration.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,cAAc,EAAC,MAAM,0BAA0B,CAAA;AAUvD,qBAAa,gBAAgB;IACzB,MAAM,CAAC,OAAO,CAAC,EAAC,QAAQ,EAAE,cAAc,EAAC,EAAE,cAAc,CAAC,QAAQ,GAAG,IAAI;CAoD5E"}
|
@@ -0,0 +1,60 @@
|
|
1
|
+
import { GrooveShuffleBox, ValueEventCurveBox } from "@opendaw/studio-boxes";
|
2
|
+
import { asInstanceOf, UUID } from "@opendaw/lib-std";
|
3
|
+
export class ProjectMigration {
|
4
|
+
static migrate({ boxGraph, mandatoryBoxes }) {
|
5
|
+
const { rootBox } = mandatoryBoxes;
|
6
|
+
if (rootBox.groove.targetAddress.isEmpty()) {
|
7
|
+
console.debug("Migrate to global GrooveShuffleBox");
|
8
|
+
boxGraph.beginTransaction();
|
9
|
+
rootBox.groove.refer(GrooveShuffleBox.create(boxGraph, UUID.generate()));
|
10
|
+
boxGraph.endTransaction();
|
11
|
+
}
|
12
|
+
const globalShuffle = asInstanceOf(rootBox.groove.targetVertex.unwrap(), GrooveShuffleBox).label;
|
13
|
+
if (globalShuffle.getValue() !== "Groove Shuffle") {
|
14
|
+
boxGraph.beginTransaction();
|
15
|
+
globalShuffle.setValue("Groove Shuffle");
|
16
|
+
boxGraph.endTransaction();
|
17
|
+
}
|
18
|
+
// TODO We can remove this when we delete all not-migrated, local(!) project files from my machine
|
19
|
+
boxGraph.boxes().forEach(box => box.accept({
|
20
|
+
visitZeitgeistDeviceBox: (box) => {
|
21
|
+
if (box.groove.targetAddress.isEmpty()) {
|
22
|
+
console.debug("Migrate 'ZeitgeistDeviceBox' to GrooveShuffleBox");
|
23
|
+
boxGraph.beginTransaction();
|
24
|
+
box.groove.refer(rootBox.groove.targetVertex.unwrap());
|
25
|
+
boxGraph.endTransaction();
|
26
|
+
}
|
27
|
+
},
|
28
|
+
visitValueEventBox: (eventBox) => {
|
29
|
+
const slope = eventBox.slope.getValue();
|
30
|
+
if (isNaN(slope)) {
|
31
|
+
return;
|
32
|
+
} // already migrated, nothing to do
|
33
|
+
if (slope === 0.0) { // never set
|
34
|
+
console.debug("Migrate 'ValueEventBox'");
|
35
|
+
boxGraph.beginTransaction();
|
36
|
+
eventBox.slope.setValue(NaN);
|
37
|
+
boxGraph.endTransaction();
|
38
|
+
}
|
39
|
+
else if (eventBox.interpolation.getValue() === 1) { // linear
|
40
|
+
if (slope === 0.5) {
|
41
|
+
console.debug("Migrate 'ValueEventBox' to linear");
|
42
|
+
boxGraph.beginTransaction();
|
43
|
+
eventBox.slope.setValue(NaN);
|
44
|
+
boxGraph.endTransaction();
|
45
|
+
}
|
46
|
+
else {
|
47
|
+
console.debug("Migrate 'ValueEventBox' to new ValueEventCurveBox");
|
48
|
+
boxGraph.beginTransaction();
|
49
|
+
ValueEventCurveBox.create(boxGraph, UUID.generate(), box => {
|
50
|
+
box.event.refer(eventBox.interpolation);
|
51
|
+
box.slope.setValue(slope);
|
52
|
+
});
|
53
|
+
eventBox.slope.setValue(NaN);
|
54
|
+
boxGraph.endTransaction();
|
55
|
+
}
|
56
|
+
}
|
57
|
+
}
|
58
|
+
}));
|
59
|
+
}
|
60
|
+
}
|
package/dist/index.d.ts
CHANGED
@@ -8,14 +8,19 @@ export * from "./samples/MainThreadSampleManager";
|
|
8
8
|
export * from "./samples/SampleProvider";
|
9
9
|
export * from "./ColorCodes";
|
10
10
|
export * from "./Colors";
|
11
|
-
export * from "./
|
11
|
+
export * from "./EffectFactory";
|
12
|
+
export * from "./EffectFactories";
|
12
13
|
export * from "./Engine";
|
13
14
|
export * from "./EngineFacade";
|
14
15
|
export * from "./EngineWorklet";
|
15
|
-
export * from "./
|
16
|
+
export * from "./InstrumentBox";
|
17
|
+
export * from "./InstrumentFactories";
|
18
|
+
export * from "./InstrumentFactory";
|
19
|
+
export * from "./InstrumentOptions";
|
20
|
+
export * from "./InstrumentProduct";
|
16
21
|
export * from "./Mixer";
|
17
|
-
export * from "./Modifier";
|
18
22
|
export * from "./Project";
|
23
|
+
export * from "./ProjectApi";
|
19
24
|
export * from "./ProjectEnv";
|
20
25
|
export * from "./Wav";
|
21
26
|
export * from "./WorkerAgents";
|
package/dist/index.d.ts.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAA;AACjC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AAExC,cAAc,uBAAuB,CAAA;AACrC,cAAc,yBAAyB,CAAA;AACvC,cAAc,kCAAkC,CAAA;AAChD,cAAc,mCAAmC,CAAA;AACjD,cAAc,0BAA0B,CAAA;AAExC,cAAc,cAAc,CAAA;AAC5B,cAAc,UAAU,CAAA;AACxB,cAAc,
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAA;AACjC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AAExC,cAAc,uBAAuB,CAAA;AACrC,cAAc,yBAAyB,CAAA;AACvC,cAAc,kCAAkC,CAAA;AAChD,cAAc,mCAAmC,CAAA;AACjD,cAAc,0BAA0B,CAAA;AAExC,cAAc,cAAc,CAAA;AAC5B,cAAc,UAAU,CAAA;AACxB,cAAc,iBAAiB,CAAA;AAC/B,cAAc,mBAAmB,CAAA;AACjC,cAAc,UAAU,CAAA;AACxB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,uBAAuB,CAAA;AACrC,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,SAAS,CAAA;AACvB,cAAc,WAAW,CAAA;AACzB,cAAc,cAAc,CAAA;AAC5B,cAAc,cAAc,CAAA;AAC5B,cAAc,OAAO,CAAA;AACrB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,YAAY,CAAA"}
|
package/dist/index.js
CHANGED
@@ -8,14 +8,19 @@ export * from "./samples/MainThreadSampleManager";
|
|
8
8
|
export * from "./samples/SampleProvider";
|
9
9
|
export * from "./ColorCodes";
|
10
10
|
export * from "./Colors";
|
11
|
-
export * from "./
|
11
|
+
export * from "./EffectFactory";
|
12
|
+
export * from "./EffectFactories";
|
12
13
|
export * from "./Engine";
|
13
14
|
export * from "./EngineFacade";
|
14
15
|
export * from "./EngineWorklet";
|
15
|
-
export * from "./
|
16
|
+
export * from "./InstrumentBox";
|
17
|
+
export * from "./InstrumentFactories";
|
18
|
+
export * from "./InstrumentFactory";
|
19
|
+
export * from "./InstrumentOptions";
|
20
|
+
export * from "./InstrumentProduct";
|
16
21
|
export * from "./Mixer";
|
17
|
-
export * from "./Modifier";
|
18
22
|
export * from "./Project";
|
23
|
+
export * from "./ProjectApi";
|
19
24
|
export * from "./ProjectEnv";
|
20
25
|
export * from "./Wav";
|
21
26
|
export * from "./WorkerAgents";
|