Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ソング:マルチトラック機能を追加 #1971

Closed
wants to merge 121 commits into from
Closed
Show file tree
Hide file tree
Changes from 117 commits
Commits
Show all changes
121 commits
Select commit Hold shift + click to select a range
f6e3a1e
Add: サイドバーだけ追加
sevenc-nanashi Mar 31, 2024
4be70c0
Add: トラックリストを追加
sevenc-nanashi Apr 1, 2024
5e6a26a
Add: 合成できるように
sevenc-nanashi Apr 1, 2024
2f69b46
Improve: 表示を良い感じに
sevenc-nanashi Apr 1, 2024
26ac882
Change: TrackList -> SideBar
sevenc-nanashi Apr 1, 2024
5a3a929
Add: panとvolumeを追加
sevenc-nanashi Apr 1, 2024
d192708
Fix: エラーを修正
sevenc-nanashi Apr 1, 2024
d1fe5bb
Add: 削除ボタンを追加
sevenc-nanashi Apr 2, 2024
5f8890a
Add: ミュート/ソロを追加
sevenc-nanashi Apr 2, 2024
e285d6c
Improve: 元に戻す対象を選べるように
sevenc-nanashi Apr 2, 2024
2b00dc0
Add: パン・音量を実装
sevenc-nanashi Apr 2, 2024
40060b0
Fix: Undoした時に壊れるのを修正
sevenc-nanashi Apr 2, 2024
ca38167
Add: オフラインレダリングを実装
sevenc-nanashi Apr 2, 2024
7cac55d
Add: プロジェクト読み込みを追加
sevenc-nanashi Apr 2, 2024
c99c228
Fix: インポート周りを修正
sevenc-nanashi Apr 2, 2024
249cad2
Add: 複数書き出しを追加
sevenc-nanashi Apr 2, 2024
b757270
Change: サイドバーではエンジンのアイコンを出さないように
sevenc-nanashi Apr 2, 2024
28e00bc
Fix: 型エラーを修正
sevenc-nanashi Apr 2, 2024
04151c4
Fix: 使われないengineIconsを削除
sevenc-nanashi Apr 2, 2024
bcd6d97
Fix: 使われてた
sevenc-nanashi Apr 2, 2024
102099a
Change: non-null assertionをやめる
sevenc-nanashi Apr 2, 2024
d8baec6
Fix: uiLocked中はボタンを無効化
sevenc-nanashi Apr 2, 2024
501e4d6
Change: TrackIdベースにする
sevenc-nanashi Apr 6, 2024
24e8b9c
Change: シンセとかの持ち方を変える
sevenc-nanashi Apr 6, 2024
c3f278a
Fix: 左の余白を復活
sevenc-nanashi Apr 6, 2024
42cfcd5
Add: トラックの並び替えを追加
sevenc-nanashi Apr 6, 2024
ffcb205
Add: dragのカーソルを出す様に
sevenc-nanashi Apr 6, 2024
bf65900
Fix: シンガーがリセットされるのを修正
sevenc-nanashi Apr 6, 2024
6ee80bd
Fix: Nemo Engineだと動かないのを修正
sevenc-nanashi Apr 7, 2024
05b7d10
Merge: main -> add/multi-track
sevenc-nanashi Apr 7, 2024
2387022
Merge: remote -> local
sevenc-nanashi Apr 7, 2024
eca0bf3
Change: 日本語を変更
sevenc-nanashi Apr 7, 2024
47da6be
Merge: main -> add/multi-track
sevenc-nanashi Apr 9, 2024
a223900
Add: DefaultMapにドキュメントを追加
sevenc-nanashi Apr 12, 2024
3543909
Change: ソング周りのテストを移動
sevenc-nanashi Apr 12, 2024
8e802ac
Change: sidebarOpen -> sidebarOpened
sevenc-nanashi Apr 12, 2024
6d899fc
Code: 良い感じに空行を足す
sevenc-nanashi Apr 12, 2024
dde8090
Code: CSSも良い感じにする
sevenc-nanashi Apr 12, 2024
f81634a
Change: Record<string, string> -> Record<EngineId, string>
sevenc-nanashi Apr 12, 2024
37d8cbc
Merge: main -> add/multi-track
sevenc-nanashi Apr 12, 2024
e7cdd9c
Fix: 生成まわりを修正
sevenc-nanashi Apr 12, 2024
0089b78
Update: テストを更新
sevenc-nanashi Apr 12, 2024
cfedc02
Change: getOverlappingNoteIdsがMapを受け取るようにする
sevenc-nanashi Apr 12, 2024
8d6c820
Change: PitchLineがtrackIdを持たないようにする
sevenc-nanashi Apr 12, 2024
e7b1389
Fix: エディタ切り替えするとバグるのを修正Z
sevenc-nanashi Apr 13, 2024
b3056dc
Fix: ミュート中のトラックは出力しないように
sevenc-nanashi Apr 13, 2024
9054c1b
Add: 影を追加
sevenc-nanashi Apr 13, 2024
4e0b5ca
Change: surfaceにする
sevenc-nanashi Apr 13, 2024
66b34a0
Improve: 選択中のトラックのボタンの表示を改善
sevenc-nanashi Apr 13, 2024
9c2828d
Merge: main -> add/multi-track
sevenc-nanashi Apr 13, 2024
750a188
Change: InactiveNote -> ShadowNote
sevenc-nanashi Apr 14, 2024
876020e
Improve: ShadowNoteを見やすく
sevenc-nanashi Apr 14, 2024
9f05797
Add: SideBarとかを分解
sevenc-nanashi Apr 14, 2024
01366a0
Improve: 見た目を調整
sevenc-nanashi Apr 14, 2024
416f036
Change: 色を変更
sevenc-nanashi Apr 14, 2024
ec5a081
Add: ソロ解除ボタンを追加
sevenc-nanashi Apr 14, 2024
9136c89
Fix: 枠線の色を修正
sevenc-nanashi Apr 14, 2024
54c2f1a
Merge: main -> add/multi-track
sevenc-nanashi Apr 15, 2024
d033631
Update: prettier、eslint、node、npmを更新 (#1992)
sevenc-nanashi Apr 17, 2024
879fa9f
Merge: main -> add/multi-track
sevenc-nanashi Apr 18, 2024
a5acae2
Fix: マージミス
sevenc-nanashi Apr 18, 2024
680efd5
Fix: マージミス
sevenc-nanashi Apr 18, 2024
0828ba4
Add: リサイズできるように
sevenc-nanashi Apr 18, 2024
98e3af2
Improve: ボタンの見た目を良い感じに
sevenc-nanashi Apr 18, 2024
dbf5a13
Change: ボタンの見た目を変更
sevenc-nanashi Apr 19, 2024
86234bf
Change: アイコンクリックでキャラを変えられるように
sevenc-nanashi Apr 19, 2024
d481644
Fix: 一括歌詞入力を修正
sevenc-nanashi Apr 19, 2024
24e6408
Add: トラック名を追加
sevenc-nanashi Apr 20, 2024
7753213
Fix: プロジェクト読み込みを修正
sevenc-nanashi Apr 20, 2024
63e959e
Improve: z-indexを設定
sevenc-nanashi Apr 20, 2024
a97419c
Change: トラック作成ボタンを移動
sevenc-nanashi Apr 20, 2024
d410d5f
Improve: ヒットボックスを改善
sevenc-nanashi Apr 20, 2024
859e5bf
Add: ミュートアイコンを追加
sevenc-nanashi Apr 20, 2024
e4734ae
Add: delayを追加
sevenc-nanashi Apr 20, 2024
6dcada7
Change: テキストにしてみる
sevenc-nanashi Apr 21, 2024
c6be71e
Fix: テストを修正
sevenc-nanashi Apr 21, 2024
761dd57
Add: MIDIトラックを新しいトラックに置くように
sevenc-nanashi Apr 25, 2024
2d9dac5
Improve: 上のレンダリングの表示を改善
sevenc-nanashi Apr 25, 2024
cae218f
Change: USTインポートを他と揃える
sevenc-nanashi Apr 25, 2024
f710b04
Merge: main -> add/multi-track
sevenc-nanashi Apr 29, 2024
499ec8e
Update: Pitch以外対応
sevenc-nanashi Apr 29, 2024
e26064f
Add: Pitchをとりあえず対応
sevenc-nanashi Apr 29, 2024
72244b9
Add: Pitchをちゃんと対応
sevenc-nanashi Apr 29, 2024
27f9016
Change: 関数を移動
sevenc-nanashi Apr 29, 2024
0281838
Change: Score#notes -> Score#parts
sevenc-nanashi Apr 29, 2024
de0888c
Merge: main -> add/multi-track
sevenc-nanashi Apr 30, 2024
2761159
Delete: ワークアラウンドを削除
sevenc-nanashi Apr 30, 2024
4e0a3a2
Change: Partにする#
sevenc-nanashi Apr 30, 2024
0f5e403
Change: trackRefs -> tracks
sevenc-nanashi Apr 30, 2024
4b3934e
Fix: DELETE_TRACKでPhraseも消すようにする
sevenc-nanashi Apr 30, 2024
c4bcb7d
Revert: package-lock.jsonをrevert
sevenc-nanashi May 1, 2024
e1f495e
Fix: hasでチェックする
sevenc-nanashi May 2, 2024
92a0aaa
Update: zodを更新
sevenc-nanashi May 2, 2024
a7ddedc
Revert: package.jsonの変更をやめる
sevenc-nanashi May 2, 2024
1fb83b6
Change: trackIdの持ち方を変える
sevenc-nanashi May 2, 2024
4c9011c
Delete: 不要なnull-safe operatorを削除
sevenc-nanashi May 2, 2024
f0f7094
Code: コメントを改善
sevenc-nanashi May 2, 2024
96d908c
Add: エラーがundefinedの時のコメントを追加
sevenc-nanashi May 2, 2024
4d43272
Change: トラック毎 -> トラックごと
sevenc-nanashi May 2, 2024
8d33f61
Delete: exportしないように
sevenc-nanashi May 2, 2024
2df8afc
Change: ミュートはミュートで値を持つようにする
sevenc-nanashi May 2, 2024
91bc02c
Fix: readonlyを外す
sevenc-nanashi May 2, 2024
63ca949
Update: マイグレーション周りを更新
sevenc-nanashi May 2, 2024
81ea5d1
Fix: テストを修正
sevenc-nanashi May 2, 2024
784caec
Refactor: calcRenderDurationの処理を改善
sevenc-nanashi May 2, 2024
ff3b135
Change: isMuteをなくす
sevenc-nanashi May 3, 2024
14e089f
Change: CREATE_TRACKにする
sevenc-nanashi May 3, 2024
6d57503
Add: 読み込みが終わったらRENDERする
sevenc-nanashi May 3, 2024
ae83270
Add: TODOコメントを追加
sevenc-nanashi May 4, 2024
e159948
Merge: main -> add/multi-track
sevenc-nanashi May 9, 2024
1eabad6
WIP: 良い感じにマージ
sevenc-nanashi May 9, 2024
699b35f
Fix: 同時に変更するように
sevenc-nanashi May 11, 2024
0255fd5
Delete: mergeMaps.tsを削除
sevenc-nanashi May 11, 2024
b37055d
Change: calcRenderDurationの依存を変える
sevenc-nanashi May 11, 2024
e623435
Change: Undo対象の選択方法を変える
sevenc-nanashi May 11, 2024
3bb09ad
Revert: 別のPRの変更が入ってたので削除
sevenc-nanashi May 11, 2024
f84c546
Fix: 日本語を修正
sevenc-nanashi May 11, 2024
2c1f668
Merge: main -> add/multi-track
sevenc-nanashi May 16, 2024
7b394dd
Fix: 保存忘れ
sevenc-nanashi May 16, 2024
a512e0b
Fix: 解消忘れ
sevenc-nanashi May 16, 2024
2bbfaab
Delete: とりあえずPARAOUTを削除
sevenc-nanashi May 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/components/Dialog/ImportMidiDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
placeholder="MIDIファイルを選択してください"
@input="handleMidiFileChange"
/>
<!-- TODO: 複数選択して複数のトラックとしてインポートできるようにする -->
<QSelect
v-if="midi"
v-model="selectedTrack"
Expand Down
104 changes: 104 additions & 0 deletions src/components/Dialog/SettingDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,54 @@
>
</QBtn>
</QCardActions>

<QCardActions class="q-px-md bg-surface">
<div>
ソング:「元に戻す」機能の対象にするトラックのパラメータ
</div>
<div
aria-label="パン、音量、ミュート、ソロ、名前のうち、「元に戻す」機能の対象にするパラメータを選べます。"
>
<QIcon name="help_outline" size="sm" class="help-hover-icon">
<QTooltip
:delay="500"
anchor="center right"
self="center left"
transition-show="jump-right"
transition-hide="jump-left"
>
名前変更、パン、音量、ミュート、ソロ、名前のうち、「元に戻す」機能の対象にするパラメータを選べます。
</QTooltip>
</QIcon>
</div>
<QSpace />
<QSelect
v-model="songUndoableTrackControl"
padding="xs md"
unelevated
emit-value
multiple
color="background"
text-color="display"
toggle-color="primary"
toggle-text-color="display-on-primary"
:options="songUndoableTrackControlOptions"
:display-value="songUndoableTrackControlDisplayValue"
>
<template #option="{ itemProps, opt, selected }">
<QItem v-ripple v-bind="itemProps" clickable>
<QItemSection avatar>
<QIcon v-if="selected" name="check" color="display" />
</QItemSection>
<QItemSection class="text-display">
<QItemLabel>
{{ opt.label }}
</QItemLabel>
</QItemSection>
</QItem>
</template>
</QSelect>
</QCardActions>
</QCard>
<!-- Saving Card -->
<QCard flat class="setting-card">
Expand Down Expand Up @@ -1087,6 +1135,62 @@ const isDefaultConfirmedTips = computed(() => {
return Object.values(confirmedTips).every((v) => !v);
});

// トラック操作のUndo対象
type SongUndoableTrackControl =
keyof RootMiscSettingType["songUndoableTrackControl"];
const songUndoableTrackControlOptions: {
label: string;
value: SongUndoableTrackControl;
}[] = [
{
label: "名前",
value: "name",
},
{
label: "パン、音量",
value: "panVolume",
},
{
label: "ミュート、ソロ",
value: "soloMute",
},
];
const songUndoableTrackControlDisplayValue = computed(() => {
const labels = Object.entries(store.state.songUndoableTrackControl)
.filter((v) => v[1])
.map((v) => {
const option = songUndoableTrackControlOptions.find(
(option) => option.value === v[0],
);
if (!option) {
throw new Error("Invalid songUndoableTrackControl value");
}
return option.label;
});
if (labels.length === 0) {
return "(なし)";
}
return labels.join("、");
});

const songUndoableTrackControl = computed({
get: () =>
Object.entries(store.state.songUndoableTrackControl)
.filter((v) => v[1])
.map((v) => v[0] as SongUndoableTrackControl),
set: (songUndoableTrackControl: SongUndoableTrackControl[]) => {
store.dispatch("SET_ROOT_MISC_SETTING", {
key: "songUndoableTrackControl",
value: Object.fromEntries(
Object.keys(store.state.songUndoableTrackControl).map((key) => [
key,
songUndoableTrackControl.includes(key as SongUndoableTrackControl),
]),
) as Record<SongUndoableTrackControl, boolean>,
});
},
});

// 外観
const currentThemeNameComputed = computed({
get: () => store.state.themeSetting.currentTheme,
Expand Down
10 changes: 9 additions & 1 deletion src/components/ErrorBoundary.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,15 @@ onMounted(() => {
}
Hiroshiba marked this conversation as resolved.
Show resolved Hide resolved
};
window.addEventListener("error", (event: ErrorEvent) => {
logError(event.error);
if (event.error) {
logError(event.error);
} else {
logError(
new Error(
`Unknown error at ${event.filename}:${event.lineno}:${event.colno}`,
),
);
}
});
window.addEventListener("unhandledrejection", handlePromiseRejectionEvent);
window.addEventListener("rejectionhandled", handlePromiseRejectionEvent);
Expand Down
241 changes: 241 additions & 0 deletions src/components/Sing/CharacterMenuButton/CharacterSelectMenu.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
<template>
<QMenu
class="character-menu"
transition-show="none"
transition-hide="none"
touch-position
>
<QList>
<QItem
v-for="(characterInfo, characterIndex) in userOrderedCharacterInfos"
:key="characterIndex"
class="q-pa-none"
>
<QBtnGroup flat class="col full-width">
<QBtn
v-close-popup
flat
no-caps
class="col-grow"
:class="
characterInfo.metas.speakerUuid === selectedSpeakerUuid &&
'selected-character-item'
"
@click="
changeStyleId(
characterInfo.metas.speakerUuid,
getDefaultStyle(characterInfo.metas.speakerUuid).styleId,
)
"
@mouseover="reassignSubMenuOpen(-1)"
@mouseleave="reassignSubMenuOpen.cancel()"
>
<SingerIcon
class="q-mr-md"
rounded
:style="getDefaultStyle(characterInfo.metas.speakerUuid)"
:show-engine-icon="isMultipleEngine"
:engine-icons="engineIcons"
/>
<div>{{ characterInfo.metas.speakerName }}</div>
</QBtn>

<!-- スタイルが2つ以上あるものだけ、スタイル選択ボタンを表示する-->
<template v-if="characterInfo.metas.styles.length >= 2">
<QSeparator vertical />

<div
class="flex items-center q-px-sm q-py-none cursor-pointer"
:class="
subMenuOpenFlags[characterIndex] && 'opened-character-item'
"
@mouseover="reassignSubMenuOpen(characterIndex)"
@mouseleave="reassignSubMenuOpen.cancel()"
>
<QIcon name="keyboard_arrow_right" color="grey-6" size="sm" />

<QMenu
v-model="subMenuOpenFlags[characterIndex]"
no-parent-event
anchor="top end"
self="top start"
transition-show="none"
transition-hide="none"
class="character-menu"
>
<QList>
<QItem
v-for="(style, styleIndex) in characterInfo.metas.styles"
:key="styleIndex"
v-close-popup
clickable
active-class="selected-character-item"
:active="style.styleId === selectedStyleId"
@click="
changeStyleId(
characterInfo.metas.speakerUuid,
style.styleId,
)
"
>
<SingerIcon
class="q-mr-md"
rounded
:style="style"
:show-engine-icon="isMultipleEngine"
:engine-icons="engineIcons"
/>
<QItemSection v-if="style.styleName">
{{ characterInfo.metas.speakerName }} ({{
getStyleDescription(style)
}})
</QItemSection>
<QItemSection v-else>{{
characterInfo.metas.speakerName
}}</QItemSection>
</QItem>
</QList>
</QMenu>
</div>
</template>
</QBtnGroup>
</QItem>
</QList>
</QMenu>
</template>

<script lang="ts">
export default {
name: "CharacterMenuButton",
};
</script>
<script setup lang="ts">
import { computed, ref } from "vue";
import { debounce } from "quasar";
import { useStore } from "@/store";
import { base64ImageToUri } from "@/helpers/imageHelper";
import { SpeakerId, StyleId, TrackId } from "@/type/preload";
import { getStyleDescription } from "@/sing/viewHelper";
import SingerIcon from "@/components/Sing/SingerIcon.vue";

const store = useStore();
const props = defineProps<{
trackId: TrackId;
}>();

const userOrderedCharacterInfos = computed(() => {
return store.getters.USER_ORDERED_CHARACTER_INFOS("singerLike");
});

const subMenuOpenFlags = ref(
[...Array(userOrderedCharacterInfos.value?.length)].map(() => false),
);

const reassignSubMenuOpen = debounce((idx: number) => {
if (subMenuOpenFlags.value[idx]) return;
const arr = [...Array(userOrderedCharacterInfos.value?.length)].map(
() => false,
);
arr[idx] = true;
subMenuOpenFlags.value = arr;
}, 100);

const changeStyleId = (speakerUuid: SpeakerId, styleId: StyleId) => {
const engineId = store.state.engineIds.find((_engineId) =>
(store.state.characterInfos[_engineId] ?? []).some(
(characterInfo) =>
characterInfo.metas.speakerUuid === speakerUuid &&
characterInfo.metas.styles.some((style) => style.styleId === styleId),
),
);
if (engineId == undefined)
throw new Error(
`No engineId for target character style (speakerUuid == ${speakerUuid}, styleId == ${styleId})`,
);

store.dispatch("COMMAND_SET_SINGER", {
trackId: props.trackId,
singer: { engineId, styleId },
withRelated: true,
});
};

const getDefaultStyle = (speakerUuid: string) => {
// FIXME: 同一キャラが複数エンジンにまたがっているとき、順番が先のエンジンが必ず選択される
const characterInfo = userOrderedCharacterInfos.value?.find(
(info) => info.metas.speakerUuid === speakerUuid,
);

// ここで取得されるcharacterInfoには、ソングエディタ向けのスタイルのみ含まれるので、
// その中の最初のスタイルをソングエディタにおける仮のデフォルトスタイルとする
// TODO: ソングエディタ向けのデフォルトスタイルをどうするか考える
const defaultStyleId = characterInfo?.metas.styles[0].styleId;

const defaultStyle = characterInfo?.metas.styles.find(
(style) => style.styleId === defaultStyleId,
);

if (defaultStyle == undefined) throw new Error("defaultStyle == undefined");

return defaultStyle;
};

const selectedCharacterInfo = computed(() => {
const singer = store.getters.SELECTED_TRACK.singer;
if (userOrderedCharacterInfos.value == undefined || !singer) {
return undefined;
}
return store.getters.CHARACTER_INFO(singer.engineId, singer.styleId);
});

const selectedSpeakerUuid = computed(() => {
return selectedCharacterInfo.value?.metas.speakerUuid;
});

const selectedStyleId = computed(
() =>
selectedCharacterInfo.value?.metas.styles.find(
(style) =>
style.styleId === store.getters.SELECTED_TRACK.singer?.styleId &&
style.engineId === store.getters.SELECTED_TRACK.singer?.engineId,
)?.styleId,
);

// 複数エンジン
const isMultipleEngine = computed(() => store.state.engineIds.length > 1);

const engineIcons = computed(() =>
Object.fromEntries(
store.state.engineIds.map((engineId) => [
engineId,
base64ImageToUri(store.state.engineManifests[engineId].icon),
]),
),
);
</script>

<style scoped lang="scss">
@use "@/styles/variables" as vars;
@use "@/styles/colors" as colors;

.character-menu {
.q-item {
color: colors.$display;
}
.q-btn-group {
> .q-btn:first-child > :deep(.q-btn__content) {
justify-content: flex-start;
}
> div:last-child:hover {
background-color: rgba(colors.$primary-rgb, 0.1);
}
}
.engine-icon {
position: absolute;
width: 13px;
height: 13px;
bottom: -6px;
right: -6px;
}
}
</style>
Loading
Loading