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

キャラクター並び替えダイアログ: speakerUuidが異なる場合にstyleIdの重複を許容する #754

Merged
Merged
Changes from all commits
Commits
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
46 changes: 27 additions & 19 deletions src/components/CharacterOrderDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
]"
@click="
selectCharacter(speakerUuid);
togglePlayOrStop(selectedStyles[speakerUuid], 0);
togglePlayOrStop(speakerUuid, selectedStyles[speakerUuid], 0);
"
>
<div class="character-item-inner">
Expand Down Expand Up @@ -124,6 +124,7 @@
outline
:icon="
playing != undefined &&
speakerUuid === playing.speakerUuid &&
selectedStyles[speakerUuid].styleId ===
playing.styleId &&
voiceSampleIndex === playing.index
Expand All @@ -137,6 +138,7 @@
@click.stop="
selectCharacter(speakerUuid);
togglePlayOrStop(
speakerUuid,
selectedStyles[speakerUuid],
voiceSampleIndex
);
Expand Down Expand Up @@ -236,21 +238,14 @@ export default defineComponent({
const sampleCharacterOrder = ref<string[]>([]);

// 選択中のスタイル
const selectedStyleIndexes = ref(
Object.fromEntries(
props.characterInfos.map((characterInfo) => [
characterInfo.metas.speakerUuid,
0,
])
)
);
const selectedStyleIndexes = ref<Record<string, number>>({});
const selectedStyles = computed(() => {
const map: { [key: string]: StyleInfo } = {};
props.characterInfos.forEach((characterInfo) => {
const selectedStyleIndex: number | undefined =
selectedStyleIndexes.value[characterInfo.metas.speakerUuid];
Comment on lines +245 to +246
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

同上で、undefinedになる可能性が無いのであれば| undefinedは逆に混乱しちゃうかなと感じました。
(もしくはここはundefinedableだったりする・・・?)

Copy link
Member Author

@aoirint aoirint Mar 26, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

こちらについては、selectedStyleIndexはundefinedになる可能性があります。

このPRの変更前の実装では、selectedStyleIndexesにはprops.characterInfosに基づく初期値が設定されていましたが、このPRでは、初期値を空objectに変更しています。
その結果、selectedStyleIndexを更新する処理であるrollStyleIndexが一度も実行されていないキャラクターは、selectedStyleIndexがundefinedであるようになっています。

styleIdの重複許容に対して余計な差分が入っていてわかりにくく申し訳ないですが、これは複数エンジン対応時を想定した挙動の修正です。

従来の実装では、props.characerInfosが後で(初回setup呼び出し後に)書き換えられたとき、selectedStyleIndexesの値が再計算されない(refの初期値または変更された値が維持される)ため、書き換え後に新しく含まれるようになったキャラクターについてのみ、selectedStyleIndexがundefinedになる形でした。
setup実行時のprops.characterInfosの値によらず、挙動をそろえるためにselectedStyleIndexの初期値をundefinedに統一しています。

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

なるほどです!!

より良く意図を反映できるコードを思いつきました!!
たぶんなのですが、objectにキーがない場合にundefinedになる感じですよね。
であれば、キーの有無で処理を分岐させるのが一番意図が伝わりやすいかも…?

(でもまあここのコードはここでしか使われないので、正直どちらでもそこまで問題ないかなとも思いました…!)

map[characterInfo.metas.speakerUuid] =
characterInfo.metas.styles[
selectedStyleIndexes.value[characterInfo.metas.speakerUuid]
];
characterInfo.metas.styles[selectedStyleIndex ?? 0];
});
return map;
});
Expand Down Expand Up @@ -315,18 +310,23 @@ export default defineComponent({
const isHoverableItem = ref(true);

// 音声再生
const playing = ref<{ styleId: number; index: number }>();
const playing =
ref<{ speakerUuid: string; styleId: number; index: number }>();

const audio = new Audio();
audio.volume = 0.5;
audio.onended = () => stop();

const play = ({ styleId, voiceSamplePaths }: StyleInfo, index: number) => {
const play = (
speakerUuid: string,
{ styleId, voiceSamplePaths }: StyleInfo,
index: number
) => {
if (audio.src !== "") stop();

audio.src = voiceSamplePaths[index];
audio.play();
playing.value = { styleId, index };
playing.value = { speakerUuid, styleId, index };
};
const stop = () => {
if (audio.src === "") return;
Expand All @@ -337,13 +337,18 @@ export default defineComponent({
};

// 再生していたら停止、再生していなかったら再生
const togglePlayOrStop = (styleInfo: StyleInfo, index: number) => {
const togglePlayOrStop = (
speakerUuid: string,
styleInfo: StyleInfo,
index: number
) => {
if (
playing.value === undefined ||
speakerUuid !== playing.value.speakerUuid ||
styleInfo.styleId !== playing.value.styleId ||
index !== playing.value.index
) {
play(styleInfo, index);
play(speakerUuid, styleInfo, index);
} else {
stop();
}
Expand All @@ -353,14 +358,17 @@ export default defineComponent({
const rollStyleIndex = (speakerUuid: string, diff: number) => {
// 0 <= index <= length に収める
const length = characterInfosMap.value[speakerUuid].metas.styles.length;
let styleIndex = selectedStyleIndexes.value[speakerUuid] + diff;
const selectedStyleIndex: number | undefined =
selectedStyleIndexes.value[speakerUuid];

let styleIndex = (selectedStyleIndex ?? 0) + diff;
styleIndex = styleIndex < 0 ? length - 1 : styleIndex % length;
selectedStyleIndexes.value[speakerUuid] = styleIndex;

// 音声を再生する。同じstyleIndexだったら停止する。
const selectedStyleInfo =
characterInfosMap.value[speakerUuid].metas.styles[styleIndex];
togglePlayOrStop(selectedStyleInfo, 0);
togglePlayOrStop(speakerUuid, selectedStyleInfo, 0);
};

// ドラッグ中かどうか
Expand Down