diff --git a/distribution/openrct2.d.ts b/distribution/openrct2.d.ts index 550f5e969d..c7b34b847a 100644 --- a/distribution/openrct2.d.ts +++ b/distribution/openrct2.d.ts @@ -2205,6 +2205,16 @@ declare global { */ commands: TitleSequenceCommand[]; + /** + * Whether the title sequence is currently playing. + */ + readonly isPlaying: boolean; + + /** + * The current command the title sequence is on if playing. + */ + readonly position: number | null; + addPark(path: string, fileName: string): void; /** @@ -2217,6 +2227,22 @@ declare global { * Deletes this title sequence from disc. */ delete(): void; + + /** + * Play the title sequence. + */ + play(): void; + + /** + * Seek to a specific command in the sequence. + * @param position The index of the command to seek to. + */ + seek(position: number): void; + + /** + * Stops playing the title sequence. + */ + stop(): void; } interface TitleSequencePark { diff --git a/src/openrct2-ui/scripting/ScTitleSequence.hpp b/src/openrct2-ui/scripting/ScTitleSequence.hpp index cb8e4413e6..c35abd1c46 100644 --- a/src/openrct2-ui/scripting/ScTitleSequence.hpp +++ b/src/openrct2-ui/scripting/ScTitleSequence.hpp @@ -13,13 +13,16 @@ # include # include +# include # include # include # include # include # include +# include # include # include +# include # include namespace OpenRCT2::Scripting @@ -387,6 +390,69 @@ namespace OpenRCT2::Scripting _path = {}; } + bool isPlaying_get() const + { + auto index = GetManagerIndex(); + return index && title_is_previewing_sequence() && *index == title_get_current_sequence(); + } + + DukValue position_get() const + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + if (isPlaying_get()) + { + auto* player = static_cast(title_get_sequence_player()); + if (player != nullptr) + { + return ToDuk(ctx, player->GetCurrentPosition()); + } + } + return ToDuk(ctx, nullptr); + } + + void play() + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + auto index = GetManagerIndex(); + if (index && !title_is_previewing_sequence() || *index != title_get_current_sequence()) + { + if (!title_preview_sequence(*index)) + { + duk_error(ctx, DUK_ERR_ERROR, "Failed to load title sequence"); + } + else if (!(gScreenFlags & SCREEN_FLAGS_TITLE_DEMO)) + { + gPreviewingTitleSequenceInGame = true; + } + } + } + + void seek(int32_t position) + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + if (isPlaying_get()) + { + auto* player = static_cast(title_get_sequence_player()); + try + { + player->Seek(position); + player->Update(); + } + catch (...) + { + duk_error(ctx, DUK_ERR_ERROR, "Failed to seek"); + } + } + } + + void stop() + { + if (isPlaying_get()) + { + title_stop_previewing_sequence(); + } + } + public: static void Register(duk_context* ctx) { @@ -396,9 +462,15 @@ namespace OpenRCT2::Scripting dukglue_register_property(ctx, &ScTitleSequence::isReadOnly_get, nullptr, "isReadOnly"); dukglue_register_property(ctx, &ScTitleSequence::parks_get, nullptr, "parks"); dukglue_register_property(ctx, &ScTitleSequence::commands_get, &ScTitleSequence::commands_set, "commands"); + dukglue_register_property(ctx, &ScTitleSequence::isPlaying_get, nullptr, "isPlaying"); + dukglue_register_property(ctx, &ScTitleSequence::position_get, nullptr, "position"); dukglue_register_method(ctx, &ScTitleSequence::addPark, "addPark"); dukglue_register_method(ctx, &ScTitleSequence::clone, "clone"); dukglue_register_method(ctx, &ScTitleSequence::delete_, "delete"); + + dukglue_register_method(ctx, &ScTitleSequence::play, "play"); + dukglue_register_method(ctx, &ScTitleSequence::seek, "seek"); + dukglue_register_method(ctx, &ScTitleSequence::stop, "stop"); } private: diff --git a/src/openrct2/title/TitleScreen.cpp b/src/openrct2/title/TitleScreen.cpp index 626c7e2a86..d9361acc79 100644 --- a/src/openrct2/title/TitleScreen.cpp +++ b/src/openrct2/title/TitleScreen.cpp @@ -298,6 +298,11 @@ bool TitleScreen::TryLoadSequence(bool loadPreview) { if (_loadedTitleSequenceId != _currentSequence || loadPreview) { + if (_sequencePlayer == nullptr) + { + _sequencePlayer = GetContext()->GetUiContext()->GetTitleSequencePlayer(); + } + size_t numSequences = TitleSequenceManager::GetCount(); if (numSequences > 0) {