mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-25 22:42:04 +02:00
intro rework
This commit is contained in:
@@ -664,7 +664,7 @@ void CServerHandler::endGameplay()
|
||||
}
|
||||
else
|
||||
{
|
||||
GH.curInt = CMainMenu::create().get();
|
||||
GH.curInt = CMainMenu::create(false).get();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -708,10 +708,10 @@ void CServerHandler::startCampaignScenario(HighScoreParameter param, std::shared
|
||||
else
|
||||
{
|
||||
CMM->openCampaignScreen(ourCampaign->campaignSet);
|
||||
if(!ourCampaign->getOutroVideo().empty() && CCS->videoh->open(ourCampaign->getOutroVideo(), false))
|
||||
if(!ourCampaign->getOutroVideo().empty() && CCS->videoh->open(ourCampaign->getOutroVideo(), Point(0, 0)))
|
||||
{
|
||||
CCS->musich->stopMusic();
|
||||
GH.windows().createAndPushWindow<CampaignRimVideo>(ourCampaign->getOutroVideo(), ourCampaign->getVideoRim().empty() ? ImagePath::builtin("INTRORIM") : ourCampaign->getVideoRim(), [campaignScoreCalculator, statistic](){
|
||||
GH.windows().createAndPushWindow<CampaignRimVideo>(ourCampaign->getOutroVideo(), ourCampaign->getVideoRim().empty() ? ImagePath::builtin("INTRORIM") : ourCampaign->getVideoRim(), false, [campaignScoreCalculator, statistic](){
|
||||
GH.windows().createAndPushWindow<CHighScoreInputScreen>(true, *campaignScoreCalculator, statistic);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -207,10 +207,10 @@ void ApplyOnLobbyScreenNetPackVisitor::visitLobbyUpdateState(LobbyUpdateState &
|
||||
{
|
||||
auto bonusSel = std::make_shared<CBonusSelection>();
|
||||
lobby->bonusSel = bonusSel;
|
||||
if(!handler.si->campState->conqueredScenarios().size() && !handler.si->campState->getIntroVideo().empty() && CCS->videoh->open(handler.si->campState->getIntroVideo(), false))
|
||||
if(!handler.si->campState->conqueredScenarios().size() && !handler.si->campState->getIntroVideo().empty() && CCS->videoh->open(handler.si->campState->getIntroVideo(), Point(0, 0)))
|
||||
{
|
||||
CCS->musich->stopMusic();
|
||||
GH.windows().createAndPushWindow<CampaignRimVideo>(handler.si->campState->getIntroVideo(), handler.si->campState->getVideoRim().empty() ? ImagePath::builtin("INTRORIM") : handler.si->campState->getVideoRim(), [bonusSel](){
|
||||
GH.windows().createAndPushWindow<CampaignRimVideo>(handler.si->campState->getIntroVideo(), handler.si->campState->getVideoRim().empty() ? ImagePath::builtin("INTRORIM") : handler.si->campState->getVideoRim(), false, [bonusSel](){
|
||||
if(!CSH->si->campState->getMusic().empty())
|
||||
CCS->musich->playMusic(CSH->si->campState->getMusic(), true, false);
|
||||
GH.windows().pushWindow(bonusSel);
|
||||
|
||||
@@ -59,16 +59,28 @@
|
||||
#include "../../lib/mapObjects/CGHeroInstance.h"
|
||||
|
||||
|
||||
CampaignRimVideo::CampaignRimVideo(VideoPath video, ImagePath rim, std::function<void()> closeCb)
|
||||
CampaignRimVideo::CampaignRimVideo(VideoPath video, ImagePath rim, bool showBackground, std::function<void()> closeCb)
|
||||
: CWindowObject(BORDERED), closeCb(closeCb)
|
||||
{
|
||||
OBJECT_CONSTRUCTION;
|
||||
|
||||
addUsedEvents(LCLICK | KEYBOARD);
|
||||
|
||||
pos = center(Rect(0, 0, 800, 600));
|
||||
|
||||
if(!rim.empty())
|
||||
{
|
||||
videoPlayer = std::make_shared<VideoWidgetOnce>(Point(80, 186), video, true, [this](){ exit(); });
|
||||
pos = center(Rect(0, 0, 800, 600));
|
||||
}
|
||||
else
|
||||
{
|
||||
videoPlayer = std::make_shared<VideoWidgetOnce>(Point(0, 0), video, true, [this](){ exit(); });
|
||||
pos = center(Rect(0, 0, videoPlayer->size().x, videoPlayer->size().y));
|
||||
}
|
||||
|
||||
if(showBackground)
|
||||
backgroundAroundWindow = std::make_shared<CFilledTexture>(ImagePath::builtin("DIBOXBCK"), Rect(-pos.x, -pos.y, GH.screenDimensions().x, GH.screenDimensions().y));
|
||||
|
||||
if(!rim.empty())
|
||||
setBackground(rim);
|
||||
}
|
||||
|
||||
@@ -89,6 +101,11 @@ void CampaignRimVideo::keyPressed(EShortcut key)
|
||||
exit();
|
||||
}
|
||||
|
||||
bool CampaignRimVideo::receiveEvent(const Point & position, int eventType) const
|
||||
{
|
||||
return true; // capture click also outside of window
|
||||
}
|
||||
|
||||
std::shared_ptr<CampaignState> CBonusSelection::getCampaign()
|
||||
{
|
||||
return CSH->si->campState;
|
||||
|
||||
@@ -31,20 +31,23 @@ class ISelectionScreenInfo;
|
||||
class ExtraOptionsTab;
|
||||
class VideoWidgetOnce;
|
||||
class CBonusSelection;
|
||||
class CFilledTexture;
|
||||
|
||||
|
||||
class CampaignRimVideo : public CWindowObject
|
||||
{
|
||||
std::shared_ptr<VideoWidgetOnce> videoPlayer;
|
||||
std::shared_ptr<CFilledTexture> backgroundAroundWindow;
|
||||
|
||||
std::function<void()> closeCb;
|
||||
|
||||
void exit();
|
||||
public:
|
||||
CampaignRimVideo(VideoPath video, ImagePath rim, std::function<void()> closeCb);
|
||||
CampaignRimVideo(VideoPath video, ImagePath rim, bool showBackground, std::function<void()> closeCb);
|
||||
|
||||
void clickPressed(const Point & cursorPosition) override;
|
||||
void keyPressed(EShortcut key) override;
|
||||
bool receiveEvent(const Point & position, int eventType) const override;
|
||||
};
|
||||
|
||||
/// Campaign screen where you can choose one out of three starting bonuses
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "../lobby/CSelectionBase.h"
|
||||
#include "../lobby/CLobbyScreen.h"
|
||||
#include "../media/IMusicPlayer.h"
|
||||
#include "../media/IVideoPlayer.h"
|
||||
#include "../gui/CursorHandler.h"
|
||||
#include "../windows/GUIClasses.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
@@ -117,7 +118,6 @@ void CMenuScreen::show(Canvas & to)
|
||||
|
||||
void CMenuScreen::activate()
|
||||
{
|
||||
CCS->musich->playMusic(AudioPath::builtin("Music/MainMenu"), true, true);
|
||||
CIntObject::activate();
|
||||
}
|
||||
|
||||
@@ -284,7 +284,7 @@ const JsonNode & CMainMenuConfig::getCampaigns() const
|
||||
return campaignSets;
|
||||
}
|
||||
|
||||
CMainMenu::CMainMenu()
|
||||
CMainMenu::CMainMenu(bool playVideoIntro)
|
||||
{
|
||||
pos.w = GH.screenDimensions().x;
|
||||
pos.h = GH.screenDimensions().y;
|
||||
@@ -292,6 +292,21 @@ CMainMenu::CMainMenu()
|
||||
menu = std::make_shared<CMenuScreen>(CMainMenuConfig::get().getConfig()["window"]);
|
||||
OBJECT_CONSTRUCTION;
|
||||
backgroundAroundMenu = std::make_shared<CFilledTexture>(ImagePath::builtin("DIBOXBCK"), pos);
|
||||
|
||||
if(playVideoIntro)
|
||||
{
|
||||
auto playVideo = [](std::string video, bool rim, std::function<void()> cb){
|
||||
if(CCS->videoh->open(VideoPath::builtin(video), Point(0, 0)))
|
||||
GH.windows().createAndPushWindow<CampaignRimVideo>(VideoPath::builtin(video), rim ? ImagePath::builtin("INTRORIM") : ImagePath::builtin(""), true, [cb](){ cb(); });
|
||||
else
|
||||
cb();
|
||||
};
|
||||
playVideo("3DOLOGO.SMK", false, [playVideo](){ playVideo("NWCLOGO.SMK", false, [playVideo](){ playVideo("H3INTRO.SMK", true, [](){
|
||||
CCS->musich->playMusic(AudioPath::builtin("Music/MainMenu"), true, true);
|
||||
}); }); });
|
||||
}
|
||||
else
|
||||
CCS->musich->playMusic(AudioPath::builtin("Music/MainMenu"), true, true);
|
||||
}
|
||||
|
||||
CMainMenu::~CMainMenu()
|
||||
@@ -418,10 +433,10 @@ void CMainMenu::openHighScoreScreen()
|
||||
return;
|
||||
}
|
||||
|
||||
std::shared_ptr<CMainMenu> CMainMenu::create()
|
||||
std::shared_ptr<CMainMenu> CMainMenu::create(bool playVideoIntro)
|
||||
{
|
||||
if(!CMM)
|
||||
CMM = std::shared_ptr<CMainMenu>(new CMainMenu());
|
||||
CMM = std::shared_ptr<CMainMenu>(new CMainMenu(playVideoIntro));
|
||||
|
||||
return CMM;
|
||||
}
|
||||
|
||||
@@ -142,7 +142,9 @@ class CMainMenu : public CIntObject, public IUpdateable, public std::enable_shar
|
||||
{
|
||||
std::shared_ptr<CFilledTexture> backgroundAroundMenu;
|
||||
|
||||
CMainMenu(); //Use CMainMenu::create
|
||||
std::vector<VideoPath> videoPlayList;
|
||||
|
||||
CMainMenu(bool playVideoIntro); //Use CMainMenu::create
|
||||
|
||||
public:
|
||||
std::shared_ptr<CMenuScreen> menu;
|
||||
@@ -158,7 +160,7 @@ public:
|
||||
static void openHighScoreScreen();
|
||||
void openCampaignScreen(std::string name);
|
||||
|
||||
static std::shared_ptr<CMainMenu> create();
|
||||
static std::shared_ptr<CMainMenu> create(bool playVideoIntro);
|
||||
|
||||
static std::shared_ptr<CPicture> createPicture(const JsonNode & config);
|
||||
|
||||
|
||||
@@ -14,18 +14,12 @@
|
||||
class CEmptyVideoPlayer final : public IVideoPlayer
|
||||
{
|
||||
public:
|
||||
/// Plays video on top of the screen, returns only after playback is over
|
||||
bool playIntroVideo(const VideoPath & name) override
|
||||
{
|
||||
return false;
|
||||
};
|
||||
|
||||
void playSpellbookAnimation(const VideoPath & name, const Point & position) override
|
||||
{
|
||||
}
|
||||
|
||||
/// Load video from specified path
|
||||
std::unique_ptr<IVideoInstance> open(const VideoPath & name, bool scaleToScreen) override
|
||||
std::unique_ptr<IVideoInstance> open(const VideoPath & name, const Point & scale) override
|
||||
{
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
@@ -173,13 +173,13 @@ void CVideoInstance::openVideo()
|
||||
openCodec(findVideoStream());
|
||||
}
|
||||
|
||||
void CVideoInstance::prepareOutput(bool scaleToScreenSize, bool useTextureOutput)
|
||||
void CVideoInstance::prepareOutput(Point scale, bool useTextureOutput)
|
||||
{
|
||||
//setup scaling
|
||||
if(scaleToScreenSize)
|
||||
if(scale.x > 0 && scale.y > 0)
|
||||
{
|
||||
dimensions.x = screen->w;
|
||||
dimensions.y = screen->h;
|
||||
dimensions.x = scale.x * GH.screenHandler().getScalingFactor();
|
||||
dimensions.y = scale.y * GH.screenHandler().getScalingFactor();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -575,7 +575,7 @@ std::pair<std::unique_ptr<ui8 []>, si64> CAudioInstance::extractAudio(const Vide
|
||||
return dat;
|
||||
}
|
||||
|
||||
bool CVideoPlayer::openAndPlayVideoImpl(const VideoPath & name, const Point & position, bool useOverlay, bool scale, bool stopOnKey)
|
||||
bool CVideoPlayer::openAndPlayVideoImpl(const VideoPath & name, const Point & position, bool useOverlay, bool stopOnKey)
|
||||
{
|
||||
CVideoInstance instance;
|
||||
CAudioInstance audio;
|
||||
@@ -587,7 +587,7 @@ bool CVideoPlayer::openAndPlayVideoImpl(const VideoPath & name, const Point & po
|
||||
return true;
|
||||
|
||||
instance.openVideo();
|
||||
instance.prepareOutput(scale, true);
|
||||
instance.prepareOutput(Point(0, 0), true);
|
||||
|
||||
auto lastTimePoint = boost::chrono::steady_clock::now();
|
||||
|
||||
@@ -633,17 +633,12 @@ bool CVideoPlayer::openAndPlayVideoImpl(const VideoPath & name, const Point & po
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CVideoPlayer::playIntroVideo(const VideoPath & name)
|
||||
{
|
||||
return openAndPlayVideoImpl(name, Point(0, 0), true, true, true);
|
||||
}
|
||||
|
||||
void CVideoPlayer::playSpellbookAnimation(const VideoPath & name, const Point & position)
|
||||
{
|
||||
openAndPlayVideoImpl(name, position * GH.screenHandler().getScalingFactor(), false, false, false);
|
||||
openAndPlayVideoImpl(name, position * GH.screenHandler().getScalingFactor(), false, false);
|
||||
}
|
||||
|
||||
std::unique_ptr<IVideoInstance> CVideoPlayer::open(const VideoPath & name, bool scaleToScreen)
|
||||
std::unique_ptr<IVideoInstance> CVideoPlayer::open(const VideoPath & name, const Point & scale)
|
||||
{
|
||||
auto result = std::make_unique<CVideoInstance>();
|
||||
|
||||
@@ -651,7 +646,7 @@ std::unique_ptr<IVideoInstance> CVideoPlayer::open(const VideoPath & name, bool
|
||||
return nullptr;
|
||||
|
||||
result->openVideo();
|
||||
result->prepareOutput(scaleToScreen, false);
|
||||
result->prepareOutput(scale, false);
|
||||
result->loadNextFrame(); // prepare 1st frame
|
||||
|
||||
return result;
|
||||
|
||||
@@ -80,7 +80,7 @@ class CVideoInstance final : public IVideoInstance, public FFMpegStream
|
||||
/// video playback current progress, in seconds
|
||||
double frameTime = 0.0;
|
||||
|
||||
void prepareOutput(bool scaleToScreenSize, bool useTextureOutput);
|
||||
void prepareOutput(Point scale, bool useTextureOutput);
|
||||
|
||||
public:
|
||||
~CVideoInstance();
|
||||
@@ -97,13 +97,12 @@ public:
|
||||
|
||||
class CVideoPlayer final : public IVideoPlayer
|
||||
{
|
||||
bool openAndPlayVideoImpl(const VideoPath & name, const Point & position, bool useOverlay, bool scale, bool stopOnKey);
|
||||
bool openAndPlayVideoImpl(const VideoPath & name, const Point & position, bool useOverlay, bool stopOnKey);
|
||||
void openVideoFile(CVideoInstance & state, const VideoPath & fname);
|
||||
|
||||
public:
|
||||
bool playIntroVideo(const VideoPath & name) final;
|
||||
void playSpellbookAnimation(const VideoPath & name, const Point & position) final;
|
||||
std::unique_ptr<IVideoInstance> open(const VideoPath & name, bool scaleToScreen) final;
|
||||
std::unique_ptr<IVideoInstance> open(const VideoPath & name, const Point & scale) final;
|
||||
std::pair<std::unique_ptr<ui8[]>, si64> getAudio(const VideoPath & videoToOpen) final;
|
||||
};
|
||||
|
||||
|
||||
@@ -38,14 +38,11 @@ public:
|
||||
class IVideoPlayer : boost::noncopyable
|
||||
{
|
||||
public:
|
||||
/// Plays video on top of the screen, returns only after playback is over, aborts on input event
|
||||
virtual bool playIntroVideo(const VideoPath & name) = 0;
|
||||
|
||||
/// Plays video on top of the screen, returns only after playback is over
|
||||
virtual void playSpellbookAnimation(const VideoPath & name, const Point & position) = 0;
|
||||
|
||||
/// Load video from specified path. Returns nullptr on failure
|
||||
virtual std::unique_ptr<IVideoInstance> open(const VideoPath & name, bool scaleToScreen) = 0;
|
||||
virtual std::unique_ptr<IVideoInstance> open(const VideoPath & name, const Point & scale) = 0;
|
||||
|
||||
/// Extracts audio data from provided video in wav format
|
||||
virtual std::pair<std::unique_ptr<ui8[]>, si64> getAudio(const VideoPath & videoToOpen) = 0;
|
||||
|
||||
@@ -28,7 +28,7 @@ VideoWidgetBase::~VideoWidgetBase() = default;
|
||||
|
||||
void VideoWidgetBase::playVideo(const VideoPath & fileToPlay)
|
||||
{
|
||||
videoInstance = CCS->videoh->open(fileToPlay, false);
|
||||
videoInstance = CCS->videoh->open(fileToPlay, Point(0, 0));
|
||||
if (videoInstance)
|
||||
{
|
||||
pos.w = videoInstance->size().x;
|
||||
@@ -119,6 +119,11 @@ void VideoWidgetBase::tick(uint32_t msPassed)
|
||||
}
|
||||
}
|
||||
|
||||
Point VideoWidgetBase::size()
|
||||
{
|
||||
return videoInstance->size();
|
||||
}
|
||||
|
||||
VideoWidget::VideoWidget(const Point & position, const VideoPath & prologue, const VideoPath & looped, bool playAudio)
|
||||
: VideoWidgetBase(position, prologue, playAudio)
|
||||
, loopedVideo(looped)
|
||||
|
||||
@@ -42,6 +42,8 @@ public:
|
||||
void showAll(Canvas & to) override;
|
||||
void tick(uint32_t msPassed) override;
|
||||
|
||||
Point size();
|
||||
|
||||
void setPlaybackFinishedCallback(std::function<void()>);
|
||||
};
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ CWindowObject::CWindowObject(int options_, const ImagePath & imageName):
|
||||
background(createBg(imageName, options_ & PLAYER_COLORED))
|
||||
{
|
||||
if(!(options & NEEDS_ANIMATED_BACKGROUND)) //currently workaround for highscores (currently uses window as normal control, because otherwise videos are not played in background yet)
|
||||
assert(parent == nullptr); //Safe to remove, but windows should not have parent
|
||||
//assert(parent == nullptr); //Safe to remove, but windows should not have parent
|
||||
|
||||
if(options & RCLICK_POPUP)
|
||||
CCS->curh->hide();
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "../client/render/Graphics.h"
|
||||
#include "../client/render/IRenderHandler.h"
|
||||
#include "../client/render/IScreenHandler.h"
|
||||
#include "../client/lobby/CBonusSelection.h"
|
||||
#include "../client/windows/CMessage.h"
|
||||
#include "../client/windows/InfoWindows.h"
|
||||
|
||||
@@ -65,7 +66,6 @@ static std::optional<std::string> criticalInitializationError;
|
||||
#ifndef VCMI_IOS
|
||||
void processCommand(const std::string &message);
|
||||
#endif
|
||||
void playIntro();
|
||||
[[noreturn]] static void quitApplication();
|
||||
static void mainLoop();
|
||||
|
||||
@@ -319,13 +319,6 @@ int main(int argc, char * argv[])
|
||||
init();
|
||||
#endif
|
||||
|
||||
if(!settings["session"]["headless"].Bool())
|
||||
{
|
||||
if(!vm.count("battle") && !vm.count("nointro") && settings["video"]["showIntro"].Bool())
|
||||
playIntro();
|
||||
GH.screenHandler().clearScreen();
|
||||
}
|
||||
|
||||
#ifndef VCMI_NO_THREADED_LOAD
|
||||
#ifdef VCMI_ANDROID // android loads the data quite slowly so we display native progressbar to prevent having only black screen for few seconds
|
||||
{
|
||||
@@ -379,7 +372,8 @@ int main(int argc, char * argv[])
|
||||
}
|
||||
else
|
||||
{
|
||||
auto mmenu = CMainMenu::create();
|
||||
bool playIntroVideo = !settings["session"]["headless"].Bool() && !vm.count("battle") && !vm.count("nointro") && settings["video"]["showIntro"].Bool();
|
||||
auto mmenu = CMainMenu::create(playIntroVideo);
|
||||
GH.curInt = mmenu.get();
|
||||
}
|
||||
|
||||
@@ -402,18 +396,6 @@ int main(int argc, char * argv[])
|
||||
return 0;
|
||||
}
|
||||
|
||||
//plays intro, ends when intro is over or button has been pressed (handles events)
|
||||
void playIntro()
|
||||
{
|
||||
if(!CCS->videoh->playIntroVideo(VideoPath::builtin("3DOLOGO.SMK")))
|
||||
return;
|
||||
|
||||
if (!CCS->videoh->playIntroVideo(VideoPath::builtin("NWCLOGO.SMK")))
|
||||
return;
|
||||
|
||||
CCS->videoh->playIntroVideo(VideoPath::builtin("H3INTRO.SMK"));
|
||||
}
|
||||
|
||||
static void mainLoop()
|
||||
{
|
||||
#ifndef VCMI_UNIX
|
||||
|
||||
Reference in New Issue
Block a user