@opendaw/studio-core 0.0.100 → 0.0.102
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/AssetService.js +2 -2
- package/dist/EffectFactories.d.ts +2 -0
- package/dist/EffectFactories.d.ts.map +1 -1
- package/dist/EffectFactories.js +44 -24
- package/dist/Engine.d.ts +5 -0
- package/dist/Engine.d.ts.map +1 -1
- package/dist/EngineFacade.d.ts +5 -0
- package/dist/EngineFacade.d.ts.map +1 -1
- package/dist/EngineFacade.js +23 -2
- package/dist/EngineWorklet.d.ts +5 -0
- package/dist/EngineWorklet.d.ts.map +1 -1
- package/dist/EngineWorklet.js +107 -11
- package/dist/HRClockWorker.d.ts +7 -0
- package/dist/HRClockWorker.d.ts.map +1 -0
- package/dist/HRClockWorker.js +54 -0
- package/dist/OfflineEngineRenderer.d.ts.map +1 -1
- package/dist/OfflineEngineRenderer.js +6 -2
- package/dist/RecordingWorklet.d.ts +2 -1
- package/dist/RecordingWorklet.d.ts.map +1 -1
- package/dist/RecordingWorklet.js +9 -1
- package/dist/Storage.d.ts.map +1 -1
- package/dist/Storage.js +1 -0
- package/dist/StudioPreferences.d.ts +9 -0
- package/dist/StudioPreferences.d.ts.map +1 -1
- package/dist/StudioSettings.d.ts +14 -0
- package/dist/StudioSettings.d.ts.map +1 -1
- package/dist/StudioSettings.js +19 -2
- package/dist/capture/CaptureAudio.d.ts +3 -1
- package/dist/capture/CaptureAudio.d.ts.map +1 -1
- package/dist/capture/CaptureAudio.js +51 -29
- package/dist/capture/MonitoringMode.d.ts +2 -0
- package/dist/capture/MonitoringMode.d.ts.map +1 -0
- package/dist/capture/MonitoringMode.js +1 -0
- package/dist/capture/RecordAudio.d.ts.map +1 -1
- package/dist/capture/RecordAudio.js +1 -0
- package/dist/capture/index.d.ts +1 -0
- package/dist/capture/index.d.ts.map +1 -1
- package/dist/capture/index.js +1 -0
- package/dist/dawproject/DawProjectImporter.d.ts.map +1 -1
- package/dist/dawproject/DawProjectImporter.js +4 -0
- package/dist/processors.js +24 -24
- package/dist/processors.js.map +4 -4
- package/dist/project/Project.d.ts +7 -1
- package/dist/project/Project.d.ts.map +1 -1
- package/dist/project/Project.js +58 -8
- package/dist/project/ProjectApi.d.ts +1 -1
- package/dist/project/ProjectApi.d.ts.map +1 -1
- package/dist/project/ProjectApi.js +17 -3
- package/dist/project/ProjectMigration.d.ts.map +1 -1
- package/dist/project/ProjectMigration.js +3 -2
- package/dist/project/audio/AudioContentFactory.d.ts +5 -0
- package/dist/project/audio/AudioContentFactory.d.ts.map +1 -1
- package/dist/project/audio/AudioContentFactory.js +13 -0
- package/dist/project/migration/MigrateNeuralAmpDeviceBox.d.ts +4 -0
- package/dist/project/migration/MigrateNeuralAmpDeviceBox.d.ts.map +1 -0
- package/dist/project/migration/MigrateNeuralAmpDeviceBox.js +29 -0
- package/dist/project/migration/index.d.ts +1 -0
- package/dist/project/migration/index.d.ts.map +1 -1
- package/dist/project/migration/index.js +1 -0
- package/dist/ui/{generic → clipboard}/ClipboardManager.d.ts +3 -3
- package/dist/ui/clipboard/ClipboardManager.d.ts.map +1 -0
- package/dist/ui/clipboard/ClipboardManager.js +147 -0
- package/dist/ui/clipboard/ClipboardUtils.d.ts +12 -0
- package/dist/ui/clipboard/ClipboardUtils.d.ts.map +1 -0
- package/dist/ui/clipboard/ClipboardUtils.js +94 -0
- package/dist/ui/{generic → clipboard}/ContextMenu.d.ts +1 -1
- package/dist/ui/clipboard/ContextMenu.d.ts.map +1 -0
- package/dist/ui/{generic → clipboard}/ContextMenu.js +1 -1
- package/dist/ui/clipboard/types/AudioUnitsClipboardHandler.d.ts +18 -0
- package/dist/ui/clipboard/types/AudioUnitsClipboardHandler.d.ts.map +1 -0
- package/dist/ui/clipboard/types/AudioUnitsClipboardHandler.js +215 -0
- package/dist/ui/clipboard/types/DevicesClipboardHandler.d.ts +18 -0
- package/dist/ui/clipboard/types/DevicesClipboardHandler.d.ts.map +1 -0
- package/dist/ui/clipboard/types/DevicesClipboardHandler.js +188 -0
- package/dist/ui/clipboard/types/NotesClipboardHandler.d.ts +21 -0
- package/dist/ui/clipboard/types/NotesClipboardHandler.d.ts.map +1 -0
- package/dist/ui/clipboard/types/NotesClipboardHandler.js +72 -0
- package/dist/ui/clipboard/types/RegionsClipboardHandler.d.ts +24 -0
- package/dist/ui/clipboard/types/RegionsClipboardHandler.d.ts.map +1 -0
- package/dist/ui/clipboard/types/RegionsClipboardHandler.js +137 -0
- package/dist/ui/clipboard/types/ValuesClipboardHandler.d.ts +22 -0
- package/dist/ui/clipboard/types/ValuesClipboardHandler.d.ts.map +1 -0
- package/dist/ui/clipboard/types/ValuesClipboardHandler.js +135 -0
- package/dist/ui/index.d.ts +14 -3
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/index.js +14 -3
- package/dist/ui/menu/MenuItems.d.ts.map +1 -0
- package/dist/ui/timeline/RegionClipResolver.d.ts +5 -1
- package/dist/ui/timeline/RegionClipResolver.d.ts.map +1 -1
- package/dist/ui/timeline/RegionClipResolver.js +5 -1
- package/dist/ui/timeline/RegionKeepExistingResolver.d.ts +34 -0
- package/dist/ui/timeline/RegionKeepExistingResolver.d.ts.map +1 -0
- package/dist/ui/timeline/RegionKeepExistingResolver.js +171 -0
- package/dist/ui/timeline/RegionOverlapResolver.d.ts +33 -0
- package/dist/ui/timeline/RegionOverlapResolver.d.ts.map +1 -0
- package/dist/ui/timeline/RegionOverlapResolver.js +79 -0
- package/dist/ui/timeline/RegionPushExistingResolver.d.ts +31 -0
- package/dist/ui/timeline/RegionPushExistingResolver.d.ts.map +1 -0
- package/dist/ui/timeline/RegionPushExistingResolver.js +159 -0
- package/dist/ui/timeline/TimelineFocus.d.ts +14 -0
- package/dist/ui/timeline/TimelineFocus.d.ts.map +1 -0
- package/dist/ui/timeline/TimelineFocus.js +45 -0
- package/dist/ui/timeline/TrackResolver.d.ts +11 -0
- package/dist/ui/timeline/TrackResolver.d.ts.map +1 -0
- package/dist/ui/timeline/TrackResolver.js +5 -0
- package/dist/workers-main.js +1 -1
- package/dist/workers-main.js.map +3 -3
- package/package.json +62 -62
- package/dist/ui/generic/ClipboardManager.d.ts.map +0 -1
- package/dist/ui/generic/ClipboardManager.js +0 -77
- package/dist/ui/generic/ContextMenu.d.ts.map +0 -1
- package/dist/ui/generic/MenuItems.d.ts.map +0 -1
- /package/dist/ui/{generic → menu}/MenuItems.d.ts +0 -0
- /package/dist/ui/{generic → menu}/MenuItems.js +0 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { ByteArrayInput, ByteArrayOutput, Option } from "@opendaw/lib-std";
|
|
2
|
+
import { Pointers } from "@opendaw/studio-enums";
|
|
3
|
+
import { NoteEventBox } from "@opendaw/studio-boxes";
|
|
4
|
+
import { NoteEventBoxAdapter } from "@opendaw/studio-adapters";
|
|
5
|
+
import { ClipboardUtils } from "../ClipboardUtils";
|
|
6
|
+
export var NotesClipboard;
|
|
7
|
+
(function (NotesClipboard) {
|
|
8
|
+
const encodeMetadata = (min, max) => {
|
|
9
|
+
const output = ByteArrayOutput.create();
|
|
10
|
+
output.writeFloat(min);
|
|
11
|
+
output.writeFloat(max);
|
|
12
|
+
return output.toArrayBuffer();
|
|
13
|
+
};
|
|
14
|
+
const decodeMetadata = (buffer) => {
|
|
15
|
+
const input = new ByteArrayInput(buffer);
|
|
16
|
+
return { min: input.readFloat(), max: input.readFloat() };
|
|
17
|
+
};
|
|
18
|
+
NotesClipboard.createHandler = ({ getEnabled, getPosition, setPosition, editing, selection, targetAddress, boxGraph, boxAdapters }) => {
|
|
19
|
+
const copyNotes = () => {
|
|
20
|
+
const selected = selection.selected();
|
|
21
|
+
if (selected.length === 0) {
|
|
22
|
+
return Option.None;
|
|
23
|
+
}
|
|
24
|
+
const min = selected.reduce((acc, { position }) => Math.min(acc, position), Number.POSITIVE_INFINITY);
|
|
25
|
+
const max = selected.reduce((acc, { complete }) => Math.max(acc, complete), Number.NEGATIVE_INFINITY);
|
|
26
|
+
const eventBoxes = selected.map(adapter => adapter.box);
|
|
27
|
+
const dependencies = eventBoxes.flatMap(box => Array.from(boxGraph.dependenciesOf(box, {
|
|
28
|
+
alwaysFollowMandatory: true,
|
|
29
|
+
excludeBox: (dep) => dep.ephemeral
|
|
30
|
+
}).boxes));
|
|
31
|
+
const allBoxes = [...eventBoxes, ...dependencies];
|
|
32
|
+
const data = ClipboardUtils.serializeBoxes(allBoxes, encodeMetadata(min, max));
|
|
33
|
+
setPosition(max);
|
|
34
|
+
return Option.wrap({ type: "notes", data });
|
|
35
|
+
};
|
|
36
|
+
return {
|
|
37
|
+
canCopy: () => getEnabled() && selection.nonEmpty(),
|
|
38
|
+
canCut: () => getEnabled() && selection.nonEmpty(),
|
|
39
|
+
canPaste: (entry) => getEnabled() && entry.type === "notes",
|
|
40
|
+
copy: copyNotes,
|
|
41
|
+
cut: () => {
|
|
42
|
+
const result = copyNotes();
|
|
43
|
+
result.ifSome(() => editing.modify(() => selection.selected().forEach(adapter => adapter.box.delete())));
|
|
44
|
+
return result;
|
|
45
|
+
},
|
|
46
|
+
paste: (entry) => {
|
|
47
|
+
if (entry.type !== "notes" || !getEnabled()) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const position = getPosition();
|
|
51
|
+
const { min, max } = decodeMetadata(ClipboardUtils.extractMetadata(entry.data));
|
|
52
|
+
const positionOffset = Math.max(0, position) - min;
|
|
53
|
+
editing.modify(() => {
|
|
54
|
+
selection.deselectAll();
|
|
55
|
+
const boxes = ClipboardUtils.deserializeBoxes(entry.data, boxGraph, {
|
|
56
|
+
mapPointer: pointer => pointer.pointerType === Pointers.NoteEvents
|
|
57
|
+
? Option.wrap(targetAddress)
|
|
58
|
+
: Option.None,
|
|
59
|
+
modifyBox: box => {
|
|
60
|
+
if (box instanceof NoteEventBox) {
|
|
61
|
+
box.position.setValue(box.position.getValue() + positionOffset);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
const noteEventBoxes = boxes.filter((box) => box instanceof NoteEventBox);
|
|
66
|
+
selection.select(...noteEventBoxes.map(box => boxAdapters.adapterFor(box, NoteEventBoxAdapter)));
|
|
67
|
+
setPosition(Math.max(0, position) + (max - min));
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
})(NotesClipboard || (NotesClipboard = {}));
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Option, Procedure, Provider, Selection } from "@opendaw/lib-std";
|
|
2
|
+
import { BoxEditing, BoxGraph } from "@opendaw/lib-box";
|
|
3
|
+
import { ppqn } from "@opendaw/lib-dsp";
|
|
4
|
+
import { AnyRegionBoxAdapter, BoxAdapters, TrackBoxAdapter } from "@opendaw/studio-adapters";
|
|
5
|
+
import { ClipboardEntry, ClipboardHandler } from "../ClipboardManager";
|
|
6
|
+
import { RegionOverlapResolver } from "../../timeline/RegionOverlapResolver";
|
|
7
|
+
type ClipboardRegions = ClipboardEntry<"regions">;
|
|
8
|
+
export declare namespace RegionsClipboard {
|
|
9
|
+
type Context = {
|
|
10
|
+
readonly getEnabled: Provider<boolean>;
|
|
11
|
+
readonly getPosition: Provider<ppqn>;
|
|
12
|
+
readonly setPosition: Procedure<ppqn>;
|
|
13
|
+
readonly editing: BoxEditing;
|
|
14
|
+
readonly selection: Selection<AnyRegionBoxAdapter>;
|
|
15
|
+
readonly boxGraph: BoxGraph;
|
|
16
|
+
readonly boxAdapters: BoxAdapters;
|
|
17
|
+
readonly getTracks: Provider<ReadonlyArray<TrackBoxAdapter>>;
|
|
18
|
+
readonly getFocusedTrack: Provider<Option<TrackBoxAdapter>>;
|
|
19
|
+
readonly overlapResolver: RegionOverlapResolver;
|
|
20
|
+
};
|
|
21
|
+
const createHandler: ({ getEnabled, getPosition, setPosition, editing, selection, boxGraph, boxAdapters, getTracks, getFocusedTrack, overlapResolver }: Context) => ClipboardHandler<ClipboardRegions>;
|
|
22
|
+
}
|
|
23
|
+
export {};
|
|
24
|
+
//# sourceMappingURL=RegionsClipboardHandler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RegionsClipboardHandler.d.ts","sourceRoot":"","sources":["../../../../src/ui/clipboard/types/RegionsClipboardHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAO,MAAM,kBAAkB,CAAA;AAC9G,OAAO,EAAM,UAAU,EAAE,QAAQ,EAAC,MAAM,kBAAkB,CAAA;AAC1D,OAAO,EAAC,IAAI,EAAC,MAAM,kBAAkB,CAAA;AAErC,OAAO,EACH,mBAAmB,EACnB,WAAW,EAEX,eAAe,EAGlB,MAAM,0BAA0B,CAAA;AACjC,OAAO,EAAC,cAAc,EAAE,gBAAgB,EAAC,MAAM,qBAAqB,CAAA;AAEpE,OAAO,EAAC,qBAAqB,EAAC,MAAM,sCAAsC,CAAA;AAE1E,KAAK,gBAAgB,GAAG,cAAc,CAAC,SAAS,CAAC,CAAA;AAcjD,yBAAiB,gBAAgB,CAAC;IAC9B,KAAY,OAAO,GAAG;QAClB,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAA;QACtC,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAA;QACpC,QAAQ,CAAC,WAAW,EAAE,SAAS,CAAC,IAAI,CAAC,CAAA;QACrC,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAA;QAC5B,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC,mBAAmB,CAAC,CAAA;QAClD,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;QAC3B,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAA;QACjC,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,aAAa,CAAC,eAAe,CAAC,CAAC,CAAA;QAC5D,QAAQ,CAAC,eAAe,EAAE,QAAQ,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAA;QAC3D,QAAQ,CAAC,eAAe,EAAE,qBAAqB,CAAA;KAClD,CAAA;IA+BM,MAAM,aAAa,GAAI,kIAWG,OAAO,KAAG,gBAAgB,CAAC,gBAAgB,CAgG3E,CAAA;CACJ"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { ByteArrayInput, ByteArrayOutput, Option, UUID } from "@opendaw/lib-std";
|
|
2
|
+
import { Pointers } from "@opendaw/studio-enums";
|
|
3
|
+
import { RegionAdapters, UnionBoxTypes } from "@opendaw/studio-adapters";
|
|
4
|
+
import { ClipboardUtils } from "../ClipboardUtils";
|
|
5
|
+
export var RegionsClipboard;
|
|
6
|
+
(function (RegionsClipboard) {
|
|
7
|
+
const encodeMetadata = (metadata) => {
|
|
8
|
+
const output = ByteArrayOutput.create();
|
|
9
|
+
output.writeFloat(metadata.minPosition);
|
|
10
|
+
output.writeFloat(metadata.maxPosition);
|
|
11
|
+
output.writeInt(metadata.tracks.length);
|
|
12
|
+
for (const track of metadata.tracks) {
|
|
13
|
+
output.writeBytes(new Int8Array(track.uuid));
|
|
14
|
+
output.writeInt(track.offset);
|
|
15
|
+
output.writeInt(track.type);
|
|
16
|
+
}
|
|
17
|
+
return output.toArrayBuffer();
|
|
18
|
+
};
|
|
19
|
+
const decodeMetadata = (buffer) => {
|
|
20
|
+
const input = new ByteArrayInput(buffer);
|
|
21
|
+
const minPosition = input.readFloat();
|
|
22
|
+
const maxPosition = input.readFloat();
|
|
23
|
+
const count = input.readInt();
|
|
24
|
+
const tracks = [];
|
|
25
|
+
for (let i = 0; i < count; i++) {
|
|
26
|
+
const uuid = new Uint8Array(16);
|
|
27
|
+
input.readBytes(new Int8Array(uuid.buffer));
|
|
28
|
+
const offset = input.readInt();
|
|
29
|
+
const type = input.readInt();
|
|
30
|
+
tracks.push({ uuid, offset, type });
|
|
31
|
+
}
|
|
32
|
+
return { minPosition, maxPosition, tracks };
|
|
33
|
+
};
|
|
34
|
+
RegionsClipboard.createHandler = ({ getEnabled, getPosition, setPosition, editing, selection, boxGraph, boxAdapters, getTracks, getFocusedTrack, overlapResolver }) => {
|
|
35
|
+
const copyRegions = () => {
|
|
36
|
+
const selected = selection.selected();
|
|
37
|
+
if (selected.length === 0) {
|
|
38
|
+
return Option.None;
|
|
39
|
+
}
|
|
40
|
+
const allTracks = getTracks();
|
|
41
|
+
const trackIndexMap = new Map();
|
|
42
|
+
allTracks.forEach((track, index) => trackIndexMap.set(track, index));
|
|
43
|
+
const sourceTracks = selected.flatMap(region => region.trackBoxAdapter.match({ some: track => [track], none: () => [] }));
|
|
44
|
+
if (sourceTracks.length === 0) {
|
|
45
|
+
return Option.None;
|
|
46
|
+
}
|
|
47
|
+
const sourceTrackIndices = sourceTracks
|
|
48
|
+
.map(track => trackIndexMap.get(track))
|
|
49
|
+
.filter((index) => index !== undefined);
|
|
50
|
+
const minTrackIndex = Math.min(...sourceTrackIndices);
|
|
51
|
+
const uniqueTracks = UUID.newSet(track => track.uuid);
|
|
52
|
+
sourceTracks.forEach(track => uniqueTracks.add(track));
|
|
53
|
+
const trackInfos = uniqueTracks.values().map(track => ({
|
|
54
|
+
uuid: track.uuid,
|
|
55
|
+
offset: (trackIndexMap.get(track) ?? 0) - minTrackIndex,
|
|
56
|
+
type: track.type
|
|
57
|
+
}));
|
|
58
|
+
const minPosition = Math.min(...selected.map(region => region.position));
|
|
59
|
+
const maxPosition = Math.max(...selected.map(region => region.complete));
|
|
60
|
+
const regionBoxes = selected.map(region => region.box);
|
|
61
|
+
const dependencies = regionBoxes.flatMap(box => Array.from(boxGraph.dependenciesOf(box, {
|
|
62
|
+
alwaysFollowMandatory: true,
|
|
63
|
+
stopAtResources: true,
|
|
64
|
+
excludeBox: (dep) => dep.ephemeral
|
|
65
|
+
}).boxes));
|
|
66
|
+
const allBoxes = [...regionBoxes, ...dependencies];
|
|
67
|
+
const metadata = { minPosition, maxPosition, tracks: trackInfos };
|
|
68
|
+
const data = ClipboardUtils.serializeBoxes(allBoxes, encodeMetadata(metadata));
|
|
69
|
+
setPosition(maxPosition);
|
|
70
|
+
return Option.wrap({ type: "regions", data });
|
|
71
|
+
};
|
|
72
|
+
return {
|
|
73
|
+
canCopy: () => getEnabled() && selection.nonEmpty(),
|
|
74
|
+
canCut: () => getEnabled() && selection.nonEmpty(),
|
|
75
|
+
canPaste: (entry) => getEnabled() && entry.type === "regions",
|
|
76
|
+
copy: copyRegions,
|
|
77
|
+
cut: () => {
|
|
78
|
+
const result = copyRegions();
|
|
79
|
+
result.ifSome(() => editing.modify(() => selection.selected().forEach(region => region.box.delete())));
|
|
80
|
+
return result;
|
|
81
|
+
},
|
|
82
|
+
paste: (entry) => {
|
|
83
|
+
if (entry.type !== "regions" || !getEnabled()) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
const position = getPosition();
|
|
87
|
+
const metadata = decodeMetadata(ClipboardUtils.extractMetadata(entry.data));
|
|
88
|
+
const positionOffset = Math.max(0, position) - metadata.minPosition;
|
|
89
|
+
const allTracks = getTracks();
|
|
90
|
+
const focusedTrack = getFocusedTrack();
|
|
91
|
+
if (focusedTrack.isEmpty() || allTracks.length === 0) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const focusedTrackIndex = allTracks.indexOf(focusedTrack.unwrap());
|
|
95
|
+
if (focusedTrackIndex === -1) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const sourceTrackToTarget = UUID.newSet(entry => entry.uuid);
|
|
99
|
+
for (const trackInfo of metadata.tracks) {
|
|
100
|
+
const targetIndex = focusedTrackIndex + trackInfo.offset;
|
|
101
|
+
const targetTrack = allTracks[targetIndex];
|
|
102
|
+
if (!targetTrack || targetTrack.type !== trackInfo.type) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
sourceTrackToTarget.add({ uuid: trackInfo.uuid, target: targetTrack });
|
|
106
|
+
}
|
|
107
|
+
editing.modify(() => {
|
|
108
|
+
selection.deselectAll();
|
|
109
|
+
const pastePosition = Math.max(0, position);
|
|
110
|
+
const pasteComplete = pastePosition + (metadata.maxPosition - metadata.minPosition);
|
|
111
|
+
const overlapSolvers = sourceTrackToTarget.values()
|
|
112
|
+
.map(({ target }) => overlapResolver.fromRange(target, pastePosition, pasteComplete));
|
|
113
|
+
const boxes = ClipboardUtils.deserializeBoxes(entry.data, boxGraph, {
|
|
114
|
+
mapPointer: (pointer, address) => {
|
|
115
|
+
if (pointer.pointerType === Pointers.RegionCollection) {
|
|
116
|
+
return address.flatMap(addr => sourceTrackToTarget.opt(addr.uuid)
|
|
117
|
+
.map(({ target }) => target.box.regions.address));
|
|
118
|
+
}
|
|
119
|
+
return Option.None;
|
|
120
|
+
},
|
|
121
|
+
modifyBox: (box) => {
|
|
122
|
+
if (UnionBoxTypes.isRegionBox(box)) {
|
|
123
|
+
const regionBox = UnionBoxTypes.asRegionBox(box);
|
|
124
|
+
regionBox.position.setValue(regionBox.position.getValue() + positionOffset);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
overlapSolvers.forEach(solver => solver());
|
|
129
|
+
const regionBoxes = boxes.filter(UnionBoxTypes.isRegionBox);
|
|
130
|
+
const adapters = regionBoxes.map(box => RegionAdapters.for(boxAdapters, box));
|
|
131
|
+
selection.select(...adapters);
|
|
132
|
+
setPosition(pasteComplete);
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
};
|
|
137
|
+
})(RegionsClipboard || (RegionsClipboard = {}));
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Procedure, Provider, Selection } from "@opendaw/lib-std";
|
|
2
|
+
import { Address, BoxEditing, BoxGraph } from "@opendaw/lib-box";
|
|
3
|
+
import { ppqn } from "@opendaw/lib-dsp";
|
|
4
|
+
import { BoxAdapters, ValueEventBoxAdapter, ValueEventCollectionBoxAdapter } from "@opendaw/studio-adapters";
|
|
5
|
+
import { ClipboardEntry, ClipboardHandler } from "../ClipboardManager";
|
|
6
|
+
type ClipboardValues = ClipboardEntry<"values">;
|
|
7
|
+
export declare namespace ValuesClipboard {
|
|
8
|
+
type Context = {
|
|
9
|
+
readonly getEnabled: Provider<boolean>;
|
|
10
|
+
readonly getPosition: Provider<ppqn>;
|
|
11
|
+
readonly setPosition: Procedure<ppqn>;
|
|
12
|
+
readonly editing: BoxEditing;
|
|
13
|
+
readonly selection: Selection<ValueEventBoxAdapter>;
|
|
14
|
+
readonly collection: ValueEventCollectionBoxAdapter;
|
|
15
|
+
readonly targetAddress: Address;
|
|
16
|
+
readonly boxGraph: BoxGraph;
|
|
17
|
+
readonly boxAdapters: BoxAdapters;
|
|
18
|
+
};
|
|
19
|
+
const createHandler: ({ getEnabled, getPosition, setPosition, editing, selection, collection, targetAddress, boxGraph, boxAdapters }: Context) => ClipboardHandler<ClipboardValues>;
|
|
20
|
+
}
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=ValuesClipboardHandler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ValuesClipboardHandler.d.ts","sourceRoot":"","sources":["../../../../src/ui/clipboard/types/ValuesClipboardHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0C,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAC,MAAM,kBAAkB,CAAA;AACxG,OAAO,EAAC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAC,MAAM,kBAAkB,CAAA;AAC9D,OAAO,EAAC,IAAI,EAAC,MAAM,kBAAkB,CAAA;AAGrC,OAAO,EAAC,WAAW,EAAE,oBAAoB,EAAE,8BAA8B,EAAC,MAAM,0BAA0B,CAAA;AAC1G,OAAO,EAAC,cAAc,EAAE,gBAAgB,EAAC,MAAM,qBAAqB,CAAA;AAGpE,KAAK,eAAe,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAA;AAE/C,yBAAiB,eAAe,CAAC;IAC7B,KAAY,OAAO,GAAG;QAClB,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAA;QACtC,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAA;QACpC,QAAQ,CAAC,WAAW,EAAE,SAAS,CAAC,IAAI,CAAC,CAAA;QACrC,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAA;QAC5B,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC,oBAAoB,CAAC,CAAA;QACnD,QAAQ,CAAC,UAAU,EAAE,8BAA8B,CAAA;QACnD,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAA;QAC/B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;QAC3B,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAA;KACpC,CAAA;IAEM,MAAM,aAAa,GAAI,gHAUG,OAAO,KAAG,gBAAgB,CAAC,eAAe,CAsE1E,CAAA;CAyDJ"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { ByteArrayInput, ByteArrayOutput, Option } from "@opendaw/lib-std";
|
|
2
|
+
import { Pointers } from "@opendaw/studio-enums";
|
|
3
|
+
import { ValueEventBox } from "@opendaw/studio-boxes";
|
|
4
|
+
import { ValueEventBoxAdapter } from "@opendaw/studio-adapters";
|
|
5
|
+
import { ClipboardUtils } from "../ClipboardUtils";
|
|
6
|
+
export var ValuesClipboard;
|
|
7
|
+
(function (ValuesClipboard) {
|
|
8
|
+
ValuesClipboard.createHandler = ({ getEnabled, getPosition, setPosition, editing, selection, collection, targetAddress, boxGraph, boxAdapters }) => {
|
|
9
|
+
const copyValues = () => {
|
|
10
|
+
const selected = selection.selected();
|
|
11
|
+
if (selected.length === 0) {
|
|
12
|
+
return Option.None;
|
|
13
|
+
}
|
|
14
|
+
const sorted = selected.slice().sort((a, b) => {
|
|
15
|
+
const positionDiff = a.position - b.position;
|
|
16
|
+
return positionDiff !== 0 ? positionDiff : a.index - b.index;
|
|
17
|
+
});
|
|
18
|
+
const min = sorted[0].position;
|
|
19
|
+
const max = sorted[sorted.length - 1].position;
|
|
20
|
+
const eventBoxes = sorted.map(adapter => adapter.box);
|
|
21
|
+
const dependencies = eventBoxes.flatMap(box => Array.from(boxGraph.dependenciesOf(box, {
|
|
22
|
+
alwaysFollowMandatory: true,
|
|
23
|
+
excludeBox: dep => dep.ephemeral
|
|
24
|
+
}).boxes));
|
|
25
|
+
const allBoxes = [...eventBoxes, ...dependencies];
|
|
26
|
+
const data = ClipboardUtils.serializeBoxes(allBoxes, encodeMetadata(min, max));
|
|
27
|
+
setPosition(max);
|
|
28
|
+
return Option.wrap({ type: "values", data });
|
|
29
|
+
};
|
|
30
|
+
return {
|
|
31
|
+
canCopy: () => getEnabled() && selection.nonEmpty(),
|
|
32
|
+
canCut: () => getEnabled() && selection.nonEmpty(),
|
|
33
|
+
canPaste: (entry) => getEnabled() && entry.type === "values",
|
|
34
|
+
copy: copyValues,
|
|
35
|
+
cut: () => {
|
|
36
|
+
const result = copyValues();
|
|
37
|
+
result.ifSome(() => editing.modify(() => selection.selected().forEach(adapter => adapter.box.delete())));
|
|
38
|
+
return result;
|
|
39
|
+
},
|
|
40
|
+
paste: (entry) => {
|
|
41
|
+
if (entry.type !== "values" || !getEnabled()) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const position = getPosition();
|
|
45
|
+
const { min, max } = decodeMetadata(ClipboardUtils.extractMetadata(entry.data));
|
|
46
|
+
const positionOffset = Math.max(0, position) - min;
|
|
47
|
+
const pastedMin = min + positionOffset;
|
|
48
|
+
const pastedMax = max + positionOffset;
|
|
49
|
+
editing.modify(() => {
|
|
50
|
+
selection.deselectAll();
|
|
51
|
+
const existingAdapters = [];
|
|
52
|
+
for (const adapter of collection.events.asArray()) {
|
|
53
|
+
if (pastedMin < adapter.position && adapter.position < pastedMax) {
|
|
54
|
+
adapter.box.delete();
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
existingAdapters.push(adapter);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const boxes = ClipboardUtils.deserializeBoxes(entry.data, boxGraph, {
|
|
61
|
+
mapPointer: pointer => pointer.pointerType === Pointers.ValueEvents
|
|
62
|
+
? Option.wrap(targetAddress)
|
|
63
|
+
: Option.None,
|
|
64
|
+
modifyBox: box => {
|
|
65
|
+
if (box instanceof ValueEventBox) {
|
|
66
|
+
box.position.setValue(box.position.getValue() + positionOffset);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
const valueEventBoxes = boxes.filter((box) => box instanceof ValueEventBox);
|
|
71
|
+
const pastedAdapters = valueEventBoxes.map(box => boxAdapters.adapterFor(box, ValueEventBoxAdapter));
|
|
72
|
+
const deleted = resolveIndexConflicts(existingAdapters, pastedAdapters, pastedMin, pastedMax);
|
|
73
|
+
selection.select(...pastedAdapters.filter(adapter => !deleted.has(adapter)));
|
|
74
|
+
setPosition(pastedMax);
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
const encodeMetadata = (min, max) => {
|
|
80
|
+
const output = ByteArrayOutput.create();
|
|
81
|
+
output.writeFloat(min);
|
|
82
|
+
output.writeFloat(max);
|
|
83
|
+
return output.toArrayBuffer();
|
|
84
|
+
};
|
|
85
|
+
const decodeMetadata = (buffer) => {
|
|
86
|
+
const input = new ByteArrayInput(buffer);
|
|
87
|
+
return { min: input.readFloat(), max: input.readFloat() };
|
|
88
|
+
};
|
|
89
|
+
// At pastedMin: push all pasted after existing → keep first (existing, index 0) and last (pasted, index 1)
|
|
90
|
+
// At pastedMax: unshift all pasted before existing → keep first (pasted, index 0) and last (existing, index 1)
|
|
91
|
+
// Delete middle events at each boundary. Returns the set of deleted pasted adapters.
|
|
92
|
+
const resolveIndexConflicts = (existingAdapters, pastedAdapters, pastedMin, pastedMax) => {
|
|
93
|
+
const deleted = new Set();
|
|
94
|
+
const sortedPasted = pastedAdapters.slice().sort((a, b) => {
|
|
95
|
+
const positionDiff = a.position - b.position;
|
|
96
|
+
return positionDiff !== 0 ? positionDiff : a.index - b.index;
|
|
97
|
+
});
|
|
98
|
+
if (sortedPasted.length === 0) {
|
|
99
|
+
return deleted;
|
|
100
|
+
}
|
|
101
|
+
const existingAtMin = existingAdapters.filter(adapter => adapter.position === pastedMin);
|
|
102
|
+
const existingAtMax = existingAdapters.filter(adapter => adapter.position === pastedMax);
|
|
103
|
+
const pastedAtMin = sortedPasted.filter(adapter => adapter.position === pastedMin);
|
|
104
|
+
const pastedAtMax = sortedPasted.filter(adapter => adapter.position === pastedMax);
|
|
105
|
+
// At pastedMin: existing first, then all pasted pushed after
|
|
106
|
+
const combinedAtMin = [...existingAtMin, ...pastedAtMin];
|
|
107
|
+
if (combinedAtMin.length > 1) {
|
|
108
|
+
for (let i = 1; i < combinedAtMin.length - 1; i++) {
|
|
109
|
+
const adapter = combinedAtMin[i];
|
|
110
|
+
adapter.box.delete();
|
|
111
|
+
if (pastedAtMin.includes(adapter)) {
|
|
112
|
+
deleted.add(adapter);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
combinedAtMin[0].box.index.setValue(0);
|
|
116
|
+
combinedAtMin[combinedAtMin.length - 1].box.index.setValue(1);
|
|
117
|
+
}
|
|
118
|
+
// At pastedMax: all pasted first (unshifted), then existing after
|
|
119
|
+
if (pastedMax !== pastedMin) {
|
|
120
|
+
const combinedAtMax = [...pastedAtMax, ...existingAtMax];
|
|
121
|
+
if (combinedAtMax.length > 1) {
|
|
122
|
+
for (let i = 1; i < combinedAtMax.length - 1; i++) {
|
|
123
|
+
const adapter = combinedAtMax[i];
|
|
124
|
+
adapter.box.delete();
|
|
125
|
+
if (pastedAtMax.includes(adapter)) {
|
|
126
|
+
deleted.add(adapter);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
combinedAtMax[0].box.index.setValue(0);
|
|
130
|
+
combinedAtMax[combinedAtMax.length - 1].box.index.setValue(1);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return deleted;
|
|
134
|
+
};
|
|
135
|
+
})(ValuesClipboard || (ValuesClipboard = {}));
|
package/dist/ui/index.d.ts
CHANGED
|
@@ -1,8 +1,19 @@
|
|
|
1
|
-
export * from "./
|
|
2
|
-
export * from "./
|
|
3
|
-
export * from "./
|
|
1
|
+
export * from "./clipboard/ClipboardManager";
|
|
2
|
+
export * from "./clipboard/ClipboardUtils";
|
|
3
|
+
export * from "./clipboard/ContextMenu";
|
|
4
|
+
export * from "./clipboard/types/AudioUnitsClipboardHandler";
|
|
5
|
+
export * from "./clipboard/types/DevicesClipboardHandler";
|
|
6
|
+
export * from "./clipboard/types/NotesClipboardHandler";
|
|
7
|
+
export * from "./clipboard/types/RegionsClipboardHandler";
|
|
8
|
+
export * from "./clipboard/types/ValuesClipboardHandler";
|
|
9
|
+
export * from "./menu/MenuItems";
|
|
4
10
|
export * from "./timeline/RegionClipResolver";
|
|
11
|
+
export * from "./timeline/RegionKeepExistingResolver";
|
|
5
12
|
export * from "./timeline/RegionModifyStrategies";
|
|
13
|
+
export * from "./timeline/RegionOverlapResolver";
|
|
14
|
+
export * from "./timeline/RegionPushExistingResolver";
|
|
15
|
+
export * from "./timeline/TrackResolver";
|
|
6
16
|
export * from "./timeline/TimeGrid";
|
|
17
|
+
export * from "./timeline/TimelineFocus";
|
|
7
18
|
export * from "./timeline/TimelineRange";
|
|
8
19
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/ui/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":"AAAA,cAAc,4BAA4B,CAAA;AAC1C,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":"AAAA,cAAc,8BAA8B,CAAA;AAC5C,cAAc,4BAA4B,CAAA;AAC1C,cAAc,yBAAyB,CAAA;AACvC,cAAc,8CAA8C,CAAA;AAC5D,cAAc,2CAA2C,CAAA;AACzD,cAAc,yCAAyC,CAAA;AACvD,cAAc,2CAA2C,CAAA;AACzD,cAAc,0CAA0C,CAAA;AACxD,cAAc,kBAAkB,CAAA;AAChC,cAAc,+BAA+B,CAAA;AAC7C,cAAc,uCAAuC,CAAA;AACrD,cAAc,mCAAmC,CAAA;AACjD,cAAc,kCAAkC,CAAA;AAChD,cAAc,uCAAuC,CAAA;AACrD,cAAc,0BAA0B,CAAA;AACxC,cAAc,qBAAqB,CAAA;AACnC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA"}
|
package/dist/ui/index.js
CHANGED
|
@@ -1,7 +1,18 @@
|
|
|
1
|
-
export * from "./
|
|
2
|
-
export * from "./
|
|
3
|
-
export * from "./
|
|
1
|
+
export * from "./clipboard/ClipboardManager";
|
|
2
|
+
export * from "./clipboard/ClipboardUtils";
|
|
3
|
+
export * from "./clipboard/ContextMenu";
|
|
4
|
+
export * from "./clipboard/types/AudioUnitsClipboardHandler";
|
|
5
|
+
export * from "./clipboard/types/DevicesClipboardHandler";
|
|
6
|
+
export * from "./clipboard/types/NotesClipboardHandler";
|
|
7
|
+
export * from "./clipboard/types/RegionsClipboardHandler";
|
|
8
|
+
export * from "./clipboard/types/ValuesClipboardHandler";
|
|
9
|
+
export * from "./menu/MenuItems";
|
|
4
10
|
export * from "./timeline/RegionClipResolver";
|
|
11
|
+
export * from "./timeline/RegionKeepExistingResolver";
|
|
5
12
|
export * from "./timeline/RegionModifyStrategies";
|
|
13
|
+
export * from "./timeline/RegionOverlapResolver";
|
|
14
|
+
export * from "./timeline/RegionPushExistingResolver";
|
|
15
|
+
export * from "./timeline/TrackResolver";
|
|
6
16
|
export * from "./timeline/TimeGrid";
|
|
17
|
+
export * from "./timeline/TimelineFocus";
|
|
7
18
|
export * from "./timeline/TimelineRange";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MenuItems.d.ts","sourceRoot":"","sources":["../../../src/ui/menu/MenuItems.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,6 +2,7 @@ import { Exec, int } from "@opendaw/lib-std";
|
|
|
2
2
|
import { Event, ppqn } from "@opendaw/lib-dsp";
|
|
3
3
|
import { AnyRegionBoxAdapter, TrackBoxAdapter } from "@opendaw/studio-adapters";
|
|
4
4
|
import { RegionModifyStrategies } from "./RegionModifyStrategies";
|
|
5
|
+
import { TrackResolver } from "./TrackResolver";
|
|
5
6
|
export type ClipTask = {
|
|
6
7
|
type: "delete";
|
|
7
8
|
region: AnyRegionBoxAdapter;
|
|
@@ -24,7 +25,10 @@ interface Mask extends Event {
|
|
|
24
25
|
}
|
|
25
26
|
export declare class RegionClipResolver {
|
|
26
27
|
#private;
|
|
27
|
-
static fromSelection(tracks: ReadonlyArray<TrackBoxAdapter>, adapters: ReadonlyArray<AnyRegionBoxAdapter>, strategy: RegionModifyStrategies, deltaIndex?: int):
|
|
28
|
+
static fromSelection(tracks: ReadonlyArray<TrackBoxAdapter>, adapters: ReadonlyArray<AnyRegionBoxAdapter>, strategy: RegionModifyStrategies, deltaIndex?: int): {
|
|
29
|
+
postProcess: Exec;
|
|
30
|
+
trackResolver: TrackResolver;
|
|
31
|
+
};
|
|
28
32
|
static fromRange(track: TrackBoxAdapter, position: ppqn, complete: ppqn): Exec;
|
|
29
33
|
static validateTracks(tracks: ReadonlyArray<TrackBoxAdapter>): void;
|
|
30
34
|
static validateTrack(track: TrackBoxAdapter): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RegionClipResolver.d.ts","sourceRoot":"","sources":["../../../src/ui/timeline/RegionClipResolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,IAAI,EAAE,GAAG,EAAa,MAAM,kBAAkB,CAAA;AACzE,OAAO,EAAC,KAAK,EAAmB,IAAI,EAAW,MAAM,kBAAkB,CAAA;AACvE,OAAO,EACH,mBAAmB,EAGnB,eAAe,EAGlB,MAAM,0BAA0B,CAAA;AACjC,OAAO,EAAC,sBAAsB,EAAC,MAAM,0BAA0B,CAAA;
|
|
1
|
+
{"version":3,"file":"RegionClipResolver.d.ts","sourceRoot":"","sources":["../../../src/ui/timeline/RegionClipResolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,IAAI,EAAE,GAAG,EAAa,MAAM,kBAAkB,CAAA;AACzE,OAAO,EAAC,KAAK,EAAmB,IAAI,EAAW,MAAM,kBAAkB,CAAA;AACvE,OAAO,EACH,mBAAmB,EAGnB,eAAe,EAGlB,MAAM,0BAA0B,CAAA;AACjC,OAAO,EAAC,sBAAsB,EAAC,MAAM,0BAA0B,CAAA;AAC/D,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAA;AAE7C,MAAM,MAAM,QAAQ,GAAG;IACnB,IAAI,EAAE,QAAQ,CAAA;IACd,MAAM,EAAE,mBAAmB,CAAA;CAC9B,GAAG;IACA,IAAI,EAAE,UAAU,CAAA;IAChB,MAAM,EAAE,mBAAmB,CAAA;IAC3B,KAAK,EAAE,IAAI,CAAA;IACX,GAAG,EAAE,IAAI,CAAA;CACZ,GAAG;IACA,IAAI,EAAE,OAAO,CAAA;IACb,MAAM,EAAE,mBAAmB,CAAA;IAC3B,QAAQ,EAAE,IAAI,CAAA;CACjB,GAAG;IACA,IAAI,EAAE,UAAU,CAAA;IAChB,MAAM,EAAE,mBAAmB,CAAA;IAC3B,QAAQ,EAAE,IAAI,CAAA;CACjB,CAAA;AAED,UAAU,IAAK,SAAQ,KAAK;IAAE,QAAQ,EAAE,IAAI,CAAA;CAAC;AAO7C,qBAAa,kBAAkB;;IAC3B,MAAM,CAAC,aAAa,CAAC,MAAM,EAAE,aAAa,CAAC,eAAe,CAAC,EACtC,QAAQ,EAAE,aAAa,CAAC,mBAAmB,CAAC,EAC5C,QAAQ,EAAE,sBAAsB,EAChC,UAAU,GAAE,GAAO,GAAG;QAAE,WAAW,EAAE,IAAI,CAAC;QAAC,aAAa,EAAE,aAAa,CAAA;KAAE;IAe9F,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,GAAG,IAAI;IAO9E,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,aAAa,CAAC,eAAe,CAAC,GAAG,IAAI;IAInE,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI;IAuBlD,MAAM,CAAC,gBAAgB,CAAC,KAAK,EAAE,aAAa,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,IAAI,CAAC;gBAuC5D,QAAQ,EAAE,sBAAsB,EAAE,MAAM,EAAE,eAAe;IAMrE,OAAO,CAAC,MAAM,EAAE,mBAAmB,GAAG,IAAI;IAK1C,YAAY,CAAC,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,GAAG,IAAI;CA+ErD"}
|
|
@@ -2,6 +2,7 @@ import { asDefined, assert, mod, panic } from "@opendaw/lib-std";
|
|
|
2
2
|
import { EventCollection, TimeBase } from "@opendaw/lib-dsp";
|
|
3
3
|
import { AudioRegionBoxAdapter, RegionEditing, TrackType, UnionAdapterTypes } from "@opendaw/studio-adapters";
|
|
4
4
|
import { RegionModifyStrategies } from "./RegionModifyStrategies";
|
|
5
|
+
import { TrackResolver } from "./TrackResolver";
|
|
5
6
|
// AudioRegions in absolute time-domain are allowed to overlap. Their duration changes when the tempo changes,
|
|
6
7
|
// but we do not truncate them to keep the original durations.
|
|
7
8
|
const allowOverlap = (region) => region instanceof AudioRegionBoxAdapter && region.timeBase !== TimeBase.Musical;
|
|
@@ -14,7 +15,10 @@ export class RegionClipResolver {
|
|
|
14
15
|
.addMask(adapter);
|
|
15
16
|
});
|
|
16
17
|
const tasks = Array.from(clipResolvers.values()).flatMap(resolver => resolver.#createSolver());
|
|
17
|
-
return
|
|
18
|
+
return {
|
|
19
|
+
postProcess: () => tasks.forEach(task => task()),
|
|
20
|
+
trackResolver: TrackResolver.Identity
|
|
21
|
+
};
|
|
18
22
|
}
|
|
19
23
|
static fromRange(track, position, complete) {
|
|
20
24
|
// IdentityIncludeOrigin will include selected regions
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Exec, int } from "@opendaw/lib-std";
|
|
2
|
+
import { ppqn } from "@opendaw/lib-dsp";
|
|
3
|
+
import { AnyRegionBoxAdapter, BoxAdapters, TrackBoxAdapter } from "@opendaw/studio-adapters";
|
|
4
|
+
import { RegionModifyStrategies } from "./RegionModifyStrategies";
|
|
5
|
+
import { ProjectApi } from "../../project";
|
|
6
|
+
import { TrackResolver } from "./TrackResolver";
|
|
7
|
+
/**
|
|
8
|
+
* Resolver for "keep-existing" overlap behavior.
|
|
9
|
+
* When overlap is detected, the INCOMING (selected/moved/copied) region moves to a track below.
|
|
10
|
+
* Existing regions stay in place.
|
|
11
|
+
*/
|
|
12
|
+
export declare class RegionKeepExistingResolver {
|
|
13
|
+
#private;
|
|
14
|
+
/**
|
|
15
|
+
* For selection-based operations (move, resize, copy).
|
|
16
|
+
* Returns:
|
|
17
|
+
* - postProcess: function to call AFTER changes are applied (handles moves)
|
|
18
|
+
* - trackResolver: function to get target track for copies (use BEFORE creating copy)
|
|
19
|
+
*
|
|
20
|
+
* NOTE: Track resolution is lazy - target tracks are computed when trackResolver is called
|
|
21
|
+
* or when postProcess runs. This is necessary because creating new tracks requires being
|
|
22
|
+
* inside a transaction.
|
|
23
|
+
*/
|
|
24
|
+
static fromSelection(tracks: ReadonlyArray<TrackBoxAdapter>, adapters: ReadonlyArray<AnyRegionBoxAdapter>, strategy: RegionModifyStrategies, deltaIndex: int, projectApi: ProjectApi, boxAdapters: BoxAdapters): {
|
|
25
|
+
postProcess: Exec;
|
|
26
|
+
trackResolver: TrackResolver;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* For range-based operations (drop, duplicate).
|
|
30
|
+
* Returns the target track to use for creation (may be different from original if overlap exists).
|
|
31
|
+
*/
|
|
32
|
+
static resolveTargetTrack(track: TrackBoxAdapter, position: ppqn, complete: ppqn, projectApi: ProjectApi, boxAdapters: BoxAdapters): TrackBoxAdapter;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=RegionKeepExistingResolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RegionKeepExistingResolver.d.ts","sourceRoot":"","sources":["../../../src/ui/timeline/RegionKeepExistingResolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAE,GAAG,EAAC,MAAM,kBAAkB,CAAA;AAC1C,OAAO,EAAC,IAAI,EAAC,MAAM,kBAAkB,CAAA;AACrC,OAAO,EAAC,mBAAmB,EAAE,WAAW,EAAE,eAAe,EAAY,MAAM,0BAA0B,CAAA;AAErG,OAAO,EAAC,sBAAsB,EAAC,MAAM,0BAA0B,CAAA;AAC/D,OAAO,EAAC,UAAU,EAAC,MAAM,eAAe,CAAA;AACxC,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAA;AAS7C;;;;GAIG;AACH,qBAAa,0BAA0B;;IACnC;;;;;;;;;OASG;IACH,MAAM,CAAC,aAAa,CAAC,MAAM,EAAE,aAAa,CAAC,eAAe,CAAC,EACtC,QAAQ,EAAE,aAAa,CAAC,mBAAmB,CAAC,EAC5C,QAAQ,EAAE,sBAAsB,EAChC,UAAU,EAAE,GAAG,EACf,UAAU,EAAE,UAAU,EACtB,WAAW,EAAE,WAAW,GAAG;QAAE,WAAW,EAAE,IAAI,CAAC;QAAC,aAAa,EAAE,aAAa,CAAA;KAAE;IA2EnG;;;OAGG;IACH,MAAM,CAAC,kBAAkB,CAAC,KAAK,EAAE,eAAe,EACtB,QAAQ,EAAE,IAAI,EACd,QAAQ,EAAE,IAAI,EACd,UAAU,EAAE,UAAU,EACtB,WAAW,EAAE,WAAW,GAAG,eAAe;CAuDvE"}
|