Added video support to SystemView.

This commit is contained in:
Leon Styhre 2022-02-19 21:22:46 +01:00
parent 77beb39801
commit 29514d4db9
3 changed files with 224 additions and 9 deletions

View file

@ -36,13 +36,17 @@ SystemView::SystemView()
, mUpdatedGameCount {false} , mUpdatedGameCount {false}
, mViewNeedsReload {true} , mViewNeedsReload {true}
, mLegacyMode {false} , mLegacyMode {false}
, mHoldingKey {false}
, mNavigated {false}
{ {
setSize(Renderer::getScreenWidth(), Renderer::getScreenHeight()); setSize(Renderer::getScreenWidth(), Renderer::getScreenHeight());
mCarousel = std::make_unique<CarouselComponent>(); mCarousel = std::make_unique<CarouselComponent>();
mCarousel->setCursorChangedCallback([&](const CursorState& state) { onCursorChanged(state); }); mCarousel->setCursorChangedCallback([&](const CursorState& state) { onCursorChanged(state); });
mCarousel->setCancelTransitionsCallback( mCarousel->setCancelTransitionsCallback([&] {
[&] { ViewController::getInstance()->cancelViewTransitions(); }); ViewController::getInstance()->cancelViewTransitions();
mNavigated = true;
});
populate(); populate();
} }
@ -68,8 +72,12 @@ void SystemView::goToSystem(SystemData* system, bool animate)
selector->setNeedsRefresh(); selector->setNeedsRefresh();
} }
for (auto& video : mSystemElements[mCarousel->getCursor()].videoComponents)
video->setStaticVideo();
updateGameSelectors(); updateGameSelectors();
updateGameCount(); updateGameCount();
startViewVideos();
if (!animate) if (!animate)
finishSystemAnimation(0); finishSystemAnimation(0);
@ -77,7 +85,11 @@ void SystemView::goToSystem(SystemData* system, bool animate)
bool SystemView::input(InputConfig* config, Input input) bool SystemView::input(InputConfig* config, Input input)
{ {
mNavigated = false;
if (input.value != 0) { if (input.value != 0) {
mHoldingKey = true;
if (config->getDeviceId() == DEVICE_KEYBOARD && input.value && input.id == SDLK_r && if (config->getDeviceId() == DEVICE_KEYBOARD && input.value && input.id == SDLK_r &&
SDL_GetModState() & KMOD_LCTRL && Settings::getInstance()->getBool("Debug")) { SDL_GetModState() & KMOD_LCTRL && Settings::getInstance()->getBool("Debug")) {
LOG(LogDebug) << "SystemView::input(): Reloading all"; LOG(LogDebug) << "SystemView::input(): Reloading all";
@ -87,6 +99,7 @@ bool SystemView::input(InputConfig* config, Input input)
if (config->isMappedTo("a", input)) { if (config->isMappedTo("a", input)) {
mCarousel->stopScrolling(); mCarousel->stopScrolling();
pauseViewVideos();
ViewController::getInstance()->goToGamelist(mCarousel->getSelected()); ViewController::getInstance()->goToGamelist(mCarousel->getSelected());
NavigationSounds::getInstance().playThemeNavigationSound(SELECTSOUND); NavigationSounds::getInstance().playThemeNavigationSound(SELECTSOUND);
return true; return true;
@ -111,6 +124,9 @@ bool SystemView::input(InputConfig* config, Input input)
return true; return true;
} }
} }
else {
mHoldingKey = false;
}
return mCarousel->input(config, input); return mCarousel->input(config, input);
} }
@ -118,6 +134,10 @@ bool SystemView::input(InputConfig* config, Input input)
void SystemView::update(int deltaTime) void SystemView::update(int deltaTime)
{ {
mCarousel->update(deltaTime); mCarousel->update(deltaTime);
for (auto& video : mSystemElements[mCarousel->getCursor()].videoComponents)
video->update(deltaTime);
GuiComponent::update(deltaTime); GuiComponent::update(deltaTime);
} }
@ -126,7 +146,14 @@ void SystemView::render(const glm::mat4& parentTrans)
if (mCarousel->getNumEntries() == 0) if (mCarousel->getNumEntries() == 0)
return; // Nothing to render. return; // Nothing to render.
renderElements(parentTrans, false); bool fade {false};
if (mNavigated && mCarousel->isAnimationPlaying(0) &&
Settings::getInstance()->getString("TransitionStyle") == "fade")
fade = true;
if (!fade)
renderElements(parentTrans, false);
glm::mat4 trans {getTransform() * parentTrans}; glm::mat4 trans {getTransform() * parentTrans};
// During fade transitions draw a black rectangle above all elements placed below the carousel. // During fade transitions draw a black rectangle above all elements placed below the carousel.
@ -187,7 +214,11 @@ void SystemView::onCursorChanged(const CursorState& /*state*/)
selector->setNeedsRefresh(); selector->setNeedsRefresh();
} }
for (auto& video : mSystemElements[cursor].videoComponents)
video->setStaticVideo();
updateGameSelectors(); updateGameSelectors();
startViewVideos();
updateHelpPrompts(); updateHelpPrompts();
int scrollVelocity {mCarousel->getScrollingVelocity()}; int scrollVelocity {mCarousel->getScrollingVelocity()};
@ -368,10 +399,17 @@ void SystemView::populate()
elements.imageComponents.back()->setDefaultZIndex(30.0f); elements.imageComponents.back()->setDefaultZIndex(30.0f);
elements.imageComponents.back()->applyTheme(theme, "system", element.first, elements.imageComponents.back()->applyTheme(theme, "system", element.first,
ThemeFlags::ALL); ThemeFlags::ALL);
if (elements.imageComponents.back()->getThemeImageTypes().size() != 0)
elements.imageComponents.back()->setScrollHide(true);
elements.children.emplace_back(elements.imageComponents.back().get()); elements.children.emplace_back(elements.imageComponents.back().get());
} }
else if (element.second.type == "video") {
elements.videoComponents.emplace_back(
std::make_unique<VideoFFmpegComponent>());
elements.videoComponents.back()->setDefaultZIndex(30.0f);
elements.videoComponents.back()->setStaticVideo();
elements.videoComponents.back()->applyTheme(theme, "system", element.first,
ThemeFlags::ALL);
elements.children.emplace_back(elements.videoComponents.back().get());
}
else if (element.second.type == "text") { else if (element.second.type == "text") {
if (element.second.has("systemdata") && if (element.second.has("systemdata") &&
element.second.get<std::string>("systemdata").substr(0, 9) == element.second.get<std::string>("systemdata").substr(0, 9) ==
@ -440,8 +478,6 @@ void SystemView::populate()
} }
} }
updateGameSelectors();
if (mCarousel->getNumEntries() == 0) { if (mCarousel->getNumEntries() == 0) {
// Something is wrong, there is not a single system to show, check if UI mode is not full. // Something is wrong, there is not a single system to show, check if UI mode is not full.
if (!UIModeController::getInstance()->isUIModeFull()) { if (!UIModeController::getInstance()->isUIModeFull()) {
@ -533,15 +569,19 @@ void SystemView::updateGameSelectors()
gameSelector = mSystemElements[cursor].gameSelectors.front().get(); gameSelector = mSystemElements[cursor].gameSelectors.front().get();
LOG(LogWarning) << "SystemView::updateGameSelectors(): Multiple gameselector " LOG(LogWarning) << "SystemView::updateGameSelectors(): Multiple gameselector "
"elements defined but image element does not state which one to " "elements defined but image element does not state which one to "
"use, so selecting first entry"; "use, selecting first entry";
} }
else { else {
for (auto& selector : mSystemElements[cursor].gameSelectors) { for (auto& selector : mSystemElements[cursor].gameSelectors) {
if (selector->getSelectorName() == imageSelector) if (selector->getSelectorName() == imageSelector)
gameSelector = selector.get(); gameSelector = selector.get();
} }
if (gameSelector == nullptr) if (gameSelector == nullptr) {
LOG(LogWarning)
<< "SystemView::updateGameSelectors(): Invalid gameselector \""
<< imageSelector << "\" defined for image element, selecting first entry";
gameSelector = mSystemElements[cursor].gameSelectors.front().get(); gameSelector = mSystemElements[cursor].gameSelectors.front().get();
}
} }
} }
else { else {
@ -632,6 +672,156 @@ void SystemView::updateGameSelectors()
} }
} }
for (auto& video : mSystemElements[cursor].videoComponents) {
// If a static video has been set, then don't attempt to find a gameselector entry.
if (video->hasStaticVideo())
continue;
GameSelectorComponent* gameSelector {nullptr};
if (multipleSelectors) {
const std::string& videoSelector {video->getThemeGameSelector()};
if (videoSelector == "") {
gameSelector = mSystemElements[cursor].gameSelectors.front().get();
LOG(LogWarning) << "SystemView::updateGameSelectors(): Multiple gameselector "
"elements defined but video element does not state which one to "
"use, selecting first entry";
}
else {
for (auto& selector : mSystemElements[cursor].gameSelectors) {
if (selector->getSelectorName() == videoSelector)
gameSelector = selector.get();
}
if (gameSelector == nullptr) {
LOG(LogWarning)
<< "SystemView::updateGameSelectors(): Invalid gameselector \""
<< videoSelector << "\" defined for video element, selecting first entry";
gameSelector = mSystemElements[cursor].gameSelectors.front().get();
}
}
}
else {
gameSelector = mSystemElements[cursor].gameSelectors.front().get();
}
gameSelector->refreshGames();
std::vector<FileData*> games {gameSelector->getGames()};
if (!games.empty()) {
if (!video->setVideo(games.front()->getVideoPath()))
video->setDefaultVideo();
}
}
for (auto& video : mSystemElements[cursor].videoComponents) {
if (video->getThemeImageTypes().size() == 0)
continue;
GameSelectorComponent* gameSelector {nullptr};
if (multipleSelectors) {
const std::string& imageSelector {video->getThemeGameSelector()};
if (imageSelector == "") {
gameSelector = mSystemElements[cursor].gameSelectors.front().get();
LOG(LogWarning) << "SystemView::updateGameSelectors(): Multiple gameselector "
"elements defined but video element does not state which one to "
"use, selecting first entry";
}
else {
for (auto& selector : mSystemElements[cursor].gameSelectors) {
if (selector->getSelectorName() == imageSelector)
gameSelector = selector.get();
}
if (gameSelector == nullptr) {
LOG(LogWarning)
<< "SystemView::updateGameSelectors(): Invalid gameselector \""
<< imageSelector << "\" defined for video element, selecting first entry";
gameSelector = mSystemElements[cursor].gameSelectors.front().get();
}
}
}
else {
gameSelector = mSystemElements[cursor].gameSelectors.front().get();
}
gameSelector->refreshGames();
std::vector<FileData*> games {gameSelector->getGames()};
if (!games.empty()) {
std::string path;
for (auto& imageType : video->getThemeImageTypes()) {
if (imageType == "image") {
path = games.front()->getImagePath();
if (path != "") {
video->setImage(path);
break;
}
}
else if (imageType == "miximage") {
path = games.front()->getMiximagePath();
if (path != "") {
video->setImage(path);
break;
}
}
else if (imageType == "marquee") {
path = games.front()->getMarqueePath();
if (path != "") {
video->setImage(path);
break;
}
}
else if (imageType == "screenshot") {
path = games.front()->getScreenshotPath();
if (path != "") {
video->setImage(path);
break;
}
}
else if (imageType == "titlescreen") {
path = games.front()->getTitleScreenPath();
if (path != "") {
video->setImage(path);
break;
}
}
else if (imageType == "cover") {
path = games.front()->getCoverPath();
if (path != "") {
video->setImage(path);
break;
}
}
else if (imageType == "backcover") {
path = games.front()->getBackCoverPath();
if (path != "") {
video->setImage(path);
break;
}
}
else if (imageType == "3dbox") {
path = games.front()->get3DBoxPath();
if (path != "") {
video->setImage(path);
break;
}
}
else if (imageType == "fanart") {
path = games.front()->getFanArtPath();
if (path != "") {
video->setImage(path);
break;
}
}
else if (imageType == "thumbnail") {
path = games.front()->getThumbnailPath();
if (path != "") {
video->setImage(path);
break;
}
}
}
// This is needed so the default image is set if no game media was found.
if (path == "" && video->getThemeImageTypes().size() > 0)
video->setImage("");
}
else {
video->setImage("");
}
}
for (auto& text : mSystemElements[cursor].textComponents) { for (auto& text : mSystemElements[cursor].textComponents) {
if (text->getThemeMetadata() == "") if (text->getThemeMetadata() == "")
continue; continue;

View file

@ -66,6 +66,28 @@ public:
CarouselComponent::CarouselType getCarouselType() { return mCarousel->getType(); } CarouselComponent::CarouselType getCarouselType() { return mCarousel->getType(); }
SystemData* getFirstSystem() { return mCarousel->getFirst(); } SystemData* getFirstSystem() { return mCarousel->getFirst(); }
void startViewVideos() override
{
for (auto& video : mSystemElements[mCarousel->getCursor()].videoComponents)
video->startVideoPlayer();
}
void stopViewVideos() override
{
for (auto& video : mSystemElements[mCarousel->getCursor()].videoComponents)
video->stopVideoPlayer();
}
void pauseViewVideos() override
{
for (auto& video : mSystemElements[mCarousel->getCursor()].videoComponents) {
video->pauseVideoPlayer();
}
}
void muteViewVideos() override
{
for (auto& video : mSystemElements[mCarousel->getCursor()].videoComponents)
video->muteVideoPlayer();
}
void onThemeChanged(const std::shared_ptr<ThemeData>& theme); void onThemeChanged(const std::shared_ptr<ThemeData>& theme);
std::vector<HelpPrompt> getHelpPrompts() override; std::vector<HelpPrompt> getHelpPrompts() override;
@ -92,6 +114,8 @@ private:
bool mUpdatedGameCount; bool mUpdatedGameCount;
bool mViewNeedsReload; bool mViewNeedsReload;
bool mLegacyMode; bool mLegacyMode;
bool mHoldingKey;
bool mNavigated;
}; };
#endif // ES_APP_VIEWS_SYSTEM_VIEW_H #endif // ES_APP_VIEWS_SYSTEM_VIEW_H

View file

@ -110,6 +110,7 @@ std::map<std::string, std::map<std::string, ThemeData::ElementPropertyType>>
{"default", PATH}, {"default", PATH},
{"defaultImage", PATH}, {"defaultImage", PATH},
{"imageType", STRING}, {"imageType", STRING},
{"gameselector", STRING},
{"interpolation", STRING}, {"interpolation", STRING},
{"pillarboxes", BOOLEAN}, {"pillarboxes", BOOLEAN},
{"scanlines", BOOLEAN}, {"scanlines", BOOLEAN},