import {
audio,
wait,
defineVQTimeline,
say,
still,
standeeDefaultImage,
standeeFacingDirection,
standeeImage,
standeeShake,
standeeVerticalOffset,
type VQCustomTimelineEvent,
type VQStandeeFacingDirectionEvent,
type VQStandeeImageEvent,
type VQStandeeShakeEvent,
type VQStandeeVerticalOffsetEvent,
type VQSpeechEvent,
type VQTimelineEvent,
type VQTimelineInputEvent,
} from "../../lib/VQRemotionLib/timeline";
import type {CharacterId, VoicevoxVoice} from "./characters";
export {characters, initialVisibleCharacters} from "./characters";
export type {CharacterDefinition, CharacterId, VoicevoxVoice} from "./characters";
export const compositionTitle = "ずんだもんの持論";
export type ShowOptions = Readonly<{
caption?: string;
durationSeconds?: number;
}>;
export type SpeechEvent = VQSpeechEvent<CharacterId, VoicevoxVoice>;
export type ShowEvent = VQCustomTimelineEvent<
"show",
{
character: CharacterId;
caption?: string;
durationSeconds?: number;
}
>;
export type HideTitleEvent = VQCustomTimelineEvent<
"hideTitle",
{
id: string;
}
>;
export type TimelineEvent = VQTimelineEvent<
CharacterId,
VoicevoxVoice,
| ShowEvent
| HideTitleEvent
| VQStandeeFacingDirectionEvent<CharacterId>
| VQStandeeImageEvent<CharacterId>
| VQStandeeShakeEvent<CharacterId>
| VQStandeeVerticalOffsetEvent<CharacterId>
>;
export type TimelineInputEvent = VQTimelineInputEvent<
CharacterId,
VoicevoxVoice,
| ShowEvent
| HideTitleEvent
| VQStandeeFacingDirectionEvent<CharacterId>
| VQStandeeImageEvent<CharacterId>
| VQStandeeShakeEvent<CharacterId>
| VQStandeeVerticalOffsetEvent<CharacterId>
>;
// 用途: キャラクターを画面に登場させ、任意の説明字幕を表示する。
// 使用方法: timeline 内で show("sayo", {caption: "小夜が登場!"}) のように呼び出す。
// オプションや引数詳細: durationSeconds を省略すると timing.ts の既定秒数で表示する。
export const show = (
character: CharacterId,
options: ShowOptions = {}
): ShowEvent => ({
type: "show",
character,
...options,
});
export const hideTitle = (id: string): HideTitleEvent => ({
type: "hideTitle",
id,
});
export const timeline = defineVQTimeline([
still("zundamon-jiron-background-001", "image/still/nc238325_living_day.jpg", {
fit: "cover",
}),
audio("zundamon-jiron-bgm-001", "audio/common_bgm/saturn-3-music-rockabye-baby-music-box-lullaby-loopable-527146.mp3", {
playback: "loop",
volume: 0.2,
}),
say("zundamon-jiron-zunda-001", "zundamon", "ふー、着替えて落ち着いたのだ。"),
say("zundamon-jiron-zunda-002", "zundamon", "やっぱり寮ではこのスタイルが一番なのだ。"),
hideTitle("zundamon-jiron-hide-title-001"),
standeeVerticalOffset("zundamon-jiron-zunda-y-001", "zundamon", -20),
audio("zundamon-jiron-sound-effect-001", "audio/common_soundeffect/Door 6_5 Open.wav",
{
playback: "once",
durationSeconds: 1.5,
}
),
show("sayo", { }),
say("zundamon-jiron-sayo-001", "sayo", "あ、ずんだもんだ。"),
standeeFacingDirection("zundamon-jiron-zunda-facing-001", "zundamon", "right"),
say("zundamon-jiron-sayo-002", "sayo", "あったかくなってきたにしても、おむつ一枚はちょっとラフすぎない?"),
say("zundamon-jiron-zunda-003", "zundamon", "そんなことないのだ!これが夏のベストスタイルなのだ!"),
say("zundamon-jiron-zunda-004", "zundamon", "小夜もこのスタイルにしてみればいいのだ。たぶん似合うし、快適なのだ!"),
say("zundamon-jiron-sayo-003", "sayo", "えー、小夜はいいかな。なんか、清潔かどうか気になるし…。"),
standeeImage("zundamon-jiron-zunda-image-001", "zundamon", "image/zundamon-ohnegus-rework-baby/36-round-eyes-small-a.png", {
lipSync: false,
}),
say("zundamon-jiron-zunda-005", "zundamon", "それは偏見なのだ!"),
say("zundamon-jiron-zunda-006", "zundamon", "考えてみるのだ。紙おむつは常に新品をあてることになるから、むしろ清潔なのだ!"),
say("zundamon-jiron-zunda-007", "zundamon", "毎回おろしたての下着を身につけるようなものなのだ。洗濯して使い続ける下着よりも清潔なのは明らかなのだ。"),
say("zundamon-jiron-sayo-004", "sayo", "うーん、そう言われると確かにそうかも…。"),
standeeDefaultImage("zundamon-jiron-zunda-image-002", "zundamon"),
say("zundamon-jiron-zunda-008", "zundamon", "わかったのだ?だからみんなもこのスタイルを試してみるといいのだ!"),
say("zundamon-jiron-sayo-005", "sayo", "言ってることは、たぶん間違ってないんだけど……。\n清潔なのは「穿いた直後」だけじゃない?",
{
readAs: "いってることは、たぶんまちがってないんだけど……。\nせいけつなのは、はいたちょくごだけじゃない?",
}
),
standeeImage("zundamon-jiron-zunda-image-003", "zundamon", "image/zundamon-ohnegus-rework-baby/45-nnaa-n.png", {
lipSync: false,
}),
say("zundamon-jiron-zunda-009", "zundamon", "うっ…!"),
audio("zundamon-jiron-sound-effect-002", "audio/common_soundeffect/nc174220_osikko7.mp3",
{
playback: "once",
durationSeconds: 10.0,
}
),
standeeShake("zundamon-jiron-zunda-shake-001", "zundamon", {
durationSeconds: 2.0,
amplitudeX: 9,
amplitudeY: 6,
frequencyHz: 16,
}),
wait(2.0),
standeeDefaultImage("zundamon-jiron-zunda-image-004", "zundamon"),
say("zundamon-jiron-zunda-010", "zundamon", "……ちょうどいま、清潔じゃなくなったのだ。"),
say("zundamon-jiron-sayo-006", "sayo", "そうだね…。"),
standeeImage("zundamon-jiron-sayo-image-001", "sayo", "image/sayo_by_sayonaka/variants/sayo_006_embarrassed.png", {
lipSync: false,
}),
say("zundamon-jiron-sayo-007", "sayo", "(……でも、漏らさずに使うなら、ずんだもんが言うこともわかるかも?)"),
say("zundamon-jiron-zunda-011", "zundamon", "こまめに替えれば大丈夫なのだ!\nなので、小夜もおむつスタイルを試してみるといいのだ!"),
standeeDefaultImage("zundamon-jiron-sayo-image-002", "sayo"),
say("zundamon-jiron-sayo-008", "sayo", "考えておくね。\nずんだもんは早くおむつ替えてね。"),
say("zundamon-jiron-zunda-012", "zundamon", "そうするのだ!"),
wait(4.0),
] satisfies readonly TimelineInputEvent[]);