Skip to content

Commit 5e977d8

Browse files
committed
Update singer in visual editor
1 parent e35b68a commit 5e977d8

4 files changed

Lines changed: 147 additions & 2 deletions

File tree

src/plugins/audiovisualizer/qml/AudioThumbnail.qml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ Item {
3434

3535
Rectangle {
3636
color: Theme.backgroundQuaternaryColor
37-
x: Math.min(d.viewportOffset * d.width / (d.clipViewModel?.length ?? 0) + 8, d.width - width - 8)
37+
x: Math.min(Math.max(8, d.viewportOffset * d.width / (d.clipViewModel?.length ?? 0) + 8), d.width - width - 8)
3838
anchors.bottom: parent.bottom
3939
anchors.bottomMargin: 4
4040
width: label.implicitWidth + 8

src/plugins/visualeditor/internal/addon/ArrangementAddOn.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ namespace VisualEditor::Internal {
7474
}
7575

7676
QQmlComponent *ArrangementAddOn::audioThumbnailComponent() {
77+
// TODO multiple thumbnail components
7778
return qobject_cast<QQmlComponent *>(Core::RuntimeInterface::instance()->getFirstObject("org.diffscope.visualeditor.audiothumbnailcomponent"));
7879
}
7980

src/plugins/visualeditor/qml/ArrangementViewThumbnail.qml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,4 +110,14 @@ Item {
110110
anchors.fill: parent
111111
}
112112
}
113-
}
113+
114+
ClipSingerLayer {
115+
anchors.fill: parent
116+
clipViewModel: d.clipViewModel
117+
visualVisible: d.visualVisible
118+
projectViewModelContext: d.projectViewModelContext
119+
viewportOffset: d.arrangementPanelInterface?.timeViewModel
120+
? d.arrangementPanelInterface.timeViewModel.start - d.clipViewModel.position
121+
: 0
122+
}
123+
}
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
import QtQml
2+
import QtQuick
3+
import QtQuick.Controls
4+
5+
import SVSCraft
6+
import SVSCraft.UIComponents
7+
8+
import dev.sjimo.ScopicFlow
9+
10+
import DiffScope.DspxModel as DspxModel
11+
import DiffScope.Core
12+
13+
Item {
14+
id: d
15+
16+
readonly property string sourcesPickerModelMimeType: "application/x.diffscope.sourcespickermodel"
17+
18+
required property ClipViewModel clipViewModel
19+
required property bool visualVisible
20+
required property ProjectViewModelContext projectViewModelContext
21+
required property double viewportOffset
22+
23+
readonly property QtObject documentClip: projectViewModelContext?.getClipDocumentItemFromViewItem(clipViewModel) ?? null
24+
readonly property QtObject singingClip: documentClip?.type === DspxModel.Clip.Singing ? documentClip : null
25+
readonly property var singerIds: flattenSingerIds(clipSingerIdProvider.singerTree)
26+
readonly property string singerName: {
27+
if (!singingClip?.sources || singerIds.length === 0)
28+
return qsTr("No singer")
29+
if (singerIds.length > 1)
30+
return qsTr("Mixed singer")
31+
return singerInfoProvider.info.name || singerIds[0]
32+
}
33+
34+
visible: singingClip !== null
35+
clip: true
36+
37+
function flattenSingerIds(tree) {
38+
if (!tree || typeof tree.length !== "number")
39+
return []
40+
41+
let result = []
42+
for (let index = 0; index < tree.length; ++index) {
43+
const singer = tree[index]
44+
if (typeof singer === "string") {
45+
if (singer !== "")
46+
result.push(singer)
47+
} else {
48+
result = result.concat(flattenSingerIds(singer))
49+
}
50+
}
51+
return result
52+
}
53+
54+
ClipSingerIdProvider {
55+
id: clipSingerIdProvider
56+
sources: d.singingClip?.sources ?? null
57+
}
58+
59+
SingerInfoProvider {
60+
id: singerInfoProvider
61+
registry: CoreInterface.singerRegistry
62+
architectureId: clipSingerIdProvider.architectureId
63+
singerId: d.singerIds.length === 1 ? d.singerIds[0] : ""
64+
}
65+
66+
SourcesPickerModel {
67+
id: sourcesPickerModel
68+
}
69+
70+
EditSourcesScenario {
71+
id: editSourcesScenario
72+
window: d.projectViewModelContext?.windowHandle?.window ?? null
73+
document: d.projectViewModelContext?.windowHandle?.projectDocumentContext?.document ?? null
74+
}
75+
76+
DropArea {
77+
id: singerDropArea
78+
anchors.fill: parent
79+
keys: [d.sourcesPickerModelMimeType]
80+
onDropped: drop => {
81+
if (!d.singingClip) {
82+
drop.accepted = false
83+
return
84+
}
85+
const data = drop.getDataAsArrayBuffer(d.sourcesPickerModelMimeType)
86+
if (!sourcesPickerModel.deserialize(data)) {
87+
drop.accepted = false
88+
return
89+
}
90+
editSourcesScenario.applySources(sourcesPickerModel, [d.singingClip])
91+
drop.acceptProposedAction()
92+
}
93+
}
94+
95+
Rectangle {
96+
id: dropBackground
97+
anchors.fill: parent
98+
visible: singerDropArea.containsDrag
99+
color: Theme.backgroundQuaternaryColor
100+
opacity: 0
101+
SequentialAnimation {
102+
running: singerDropArea.containsDrag
103+
loops: Animation.Infinite
104+
NumberAnimation {
105+
target: dropBackground
106+
property: "opacity"
107+
from: 0
108+
to: 0.5
109+
duration: Theme.visualEffectAnimationDuration
110+
easing.type: Easing.InOutCubic
111+
}
112+
113+
NumberAnimation {
114+
target: dropBackground
115+
property: "opacity"
116+
from: 0.5
117+
to: 0
118+
duration: Theme.visualEffectAnimationDuration
119+
easing.type: Easing.InOutCubic
120+
}
121+
}
122+
}
123+
124+
Label {
125+
id: singerNameLabel
126+
x: Math.min(Math.max(8, d.viewportOffset * d.width / (d.clipViewModel?.length ?? 0) + 8), d.width - width - 8)
127+
anchors.bottom: parent.bottom
128+
anchors.bottomMargin: 4
129+
color: Theme.foregroundPrimaryColor
130+
elide: Text.ElideRight
131+
font: Theme.font
132+
text: singerDropArea.containsDrag ? qsTr("Drop to set singer") : d.singerName
133+
}
134+
}

0 commit comments

Comments
 (0)