1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-23 22:37:55 +02:00

Added VideoWidget to hide implementation details

This commit is contained in:
Ivan Savenko
2024-05-02 22:14:50 +03:00
parent d27b854cb1
commit d08c7b7b8f
20 changed files with 228 additions and 285 deletions

View File

@@ -131,6 +131,7 @@ set(client_SRCS
widgets/CArtifactsOfHeroMarket.cpp
widgets/CArtifactsOfHeroBackpack.cpp
widgets/RadialMenu.cpp
widgets/VideoWidget.cpp
widgets/markets/CAltarArtifacts.cpp
widgets/markets/CAltarCreatures.cpp
widgets/markets/CArtifactsBuying.cpp
@@ -332,6 +333,7 @@ set(client_HEADERS
widgets/CArtifactsOfHeroMarket.h
widgets/CArtifactsOfHeroBackpack.h
widgets/RadialMenu.h
widgets/VideoWidget.h
widgets/markets/CAltarArtifacts.h
widgets/markets/CAltarCreatures.h
widgets/markets/CArtifactsBuying.h

View File

@@ -26,7 +26,6 @@
#include "../gui/MouseButton.h"
#include "../gui/WindowHandler.h"
#include "../media/IMusicPlayer.h"
#include "../media/IVideoPlayer.h"
#include "../render/Canvas.h"
#include "../render/IImage.h"
#include "../render/IFont.h"
@@ -35,6 +34,7 @@
#include "../widgets/Images.h"
#include "../widgets/Slider.h"
#include "../widgets/TextControls.h"
#include "../widgets/VideoWidget.h"
#include "../widgets/GraphicalPrimitiveCanvas.h"
#include "../windows/CMessage.h"
#include "../windows/CCreatureWindow.h"
@@ -603,7 +603,7 @@ HeroInfoWindow::HeroInfoWindow(const InfoAboutHero & hero, Point * position)
}
BattleResultWindow::BattleResultWindow(const BattleResult & br, CPlayerInterface & _owner, bool allowReplay)
: owner(_owner), currentVideo(BattleResultVideo::NONE)
: owner(_owner)
{
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
@@ -705,68 +705,98 @@ BattleResultWindow::BattleResultWindow(const BattleResult & br, CPlayerInterface
}
}
}
auto resources = getResources(br);
description = std::make_shared<CTextBox>(resources.resultText.toString(), Rect(69, 203, 330, 68), 0, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE);
videoPlayer = std::make_shared<VideoWidget>(Point(107, 70), resources.prologueVideo, resources.loopedVideo);
CCS->musich->playMusic(resources.musicName, false, true);
}
BattleResultResources BattleResultWindow::getResources(const BattleResult & br)
{
//printing result description
bool weAreAttacker = !(owner.cb->getBattle(br.battleID)->battleGetMySide());
if((br.winner == 0 && weAreAttacker) || (br.winner == 1 && !weAreAttacker)) //we've won
bool weAreDefender = !weAreAttacker;
bool weWon = (br.winner == 0 && weAreAttacker) || (br.winner == 1 && !weAreAttacker);
bool isSiege = owner.cb->getBattle(br.battleID)->battleGetDefendedTown() != nullptr;
BattleResultResources resources;
if(weWon)
{
int text = 304;
currentVideo = BattleResultVideo::WIN;
if(isSiege && weAreDefender)
{
resources.musicName = AudioPath::builtin("Music/Defend Castle");
resources.prologueVideo = VideoPath::builtin("DEFENDALL.BIK");
resources.loopedVideo = VideoPath::builtin("defendloop.bik");
}
else
{
resources.musicName = AudioPath::builtin("Music/Win Battle");
resources.prologueVideo = VideoPath();
resources.loopedVideo = VideoPath::builtin("WIN3.BIK");
}
switch(br.result)
{
case EBattleResult::NORMAL:
if(owner.cb->getBattle(br.battleID)->battleGetDefendedTown() && !weAreAttacker)
currentVideo = BattleResultVideo::WIN_SIEGE;
resources.resultText.appendTextID("core.genrltxt.304");
break;
case EBattleResult::ESCAPE:
text = 303;
resources.resultText.appendTextID("core.genrltxt.303");
break;
case EBattleResult::SURRENDER:
text = 302;
resources.resultText.appendTextID("core.genrltxt.302");
break;
default:
logGlobal->error("Invalid battle result code %d. Assumed normal.", static_cast<int>(br.result));
break;
throw std::runtime_error("Invalid battle result!");
}
playVideo();
std::string str = CGI->generaltexth->allTexts[text];
const CGHeroInstance * ourHero = owner.cb->getBattle(br.battleID)->battleGetMyHero();
if (ourHero)
{
str += CGI->generaltexth->allTexts[305];
boost::algorithm::replace_first(str, "%s", ourHero->getNameTranslated());
boost::algorithm::replace_first(str, "%d", std::to_string(br.exp[weAreAttacker ? 0 : 1]));
resources.resultText.appendTextID("core.genrltxt.305");
resources.resultText.replaceTextID(ourHero->getNameTranslated());
resources.resultText.replaceNumber(br.exp[weAreAttacker ? 0 : 1]);
}
description = std::make_shared<CTextBox>(str, Rect(69, 203, 330, 68), 0, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE);
}
else // we lose
{
int text = 311;
currentVideo = BattleResultVideo::DEFEAT;
switch(br.result)
{
case EBattleResult::NORMAL:
if(owner.cb->getBattle(br.battleID)->battleGetDefendedTown() && !weAreAttacker)
currentVideo = BattleResultVideo::DEFEAT_SIEGE;
resources.resultText.appendTextID("core.genrltxt.311");
resources.musicName = AudioPath::builtin("Music/LoseCombat");
resources.prologueVideo = VideoPath::builtin("LBSTART.BIK");
resources.loopedVideo = VideoPath::builtin("LBLOOP.BIK");
break;
case EBattleResult::ESCAPE:
currentVideo = BattleResultVideo::RETREAT;
text = 310;
resources.resultText.appendTextID("core.genrltxt.310");
resources.musicName = AudioPath::builtin("Music/Retreat Battle");
resources.prologueVideo = VideoPath::builtin("RTSTART.BIK");
resources.loopedVideo = VideoPath::builtin("RTLOOP.BIK");
break;
case EBattleResult::SURRENDER:
currentVideo = BattleResultVideo::SURRENDER;
text = 309;
resources.resultText.appendTextID("core.genrltxt.309");
resources.musicName = AudioPath::builtin("Music/Surrender Battle");
resources.prologueVideo = VideoPath();
resources.loopedVideo = VideoPath::builtin("SURRENDER.BIK");
break;
default:
logGlobal->error("Invalid battle result code %d. Assumed normal.", static_cast<int>(br.result));
break;
throw std::runtime_error("Invalid battle result!");
}
playVideo();
labels.push_back(std::make_shared<CLabel>(235, 235, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, CGI->generaltexth->allTexts[text]));
if(isSiege && weAreDefender)
{
resources.musicName = AudioPath::builtin("Music/LoseCastle");
resources.prologueVideo = VideoPath::builtin("LOSECSTL.BIK");
resources.loopedVideo = VideoPath::builtin("LOSECSLP.BIK");
}
}
return resources;
}
void BattleResultWindow::activate()
@@ -775,81 +805,6 @@ void BattleResultWindow::activate()
CIntObject::activate();
}
void BattleResultWindow::show(Canvas & to)
{
CIntObject::show(to);
CCS->videoh->update(pos.x + 107, pos.y + 70, to.getInternalSurface(), true, false,
[&]()
{
playVideo(true);
});
}
void BattleResultWindow::playVideo(bool startLoop)
{
AudioPath musicName = AudioPath();
VideoPath videoName = VideoPath();
if(!startLoop)
{
switch(currentVideo)
{
case BattleResultVideo::WIN:
musicName = AudioPath::builtin("Music/Win Battle");
videoName = VideoPath::builtin("WIN3.BIK");
break;
case BattleResultVideo::SURRENDER:
musicName = AudioPath::builtin("Music/Surrender Battle");
videoName = VideoPath::builtin("SURRENDER.BIK");
break;
case BattleResultVideo::RETREAT:
musicName = AudioPath::builtin("Music/Retreat Battle");
videoName = VideoPath::builtin("RTSTART.BIK");
break;
case BattleResultVideo::DEFEAT:
musicName = AudioPath::builtin("Music/LoseCombat");
videoName = VideoPath::builtin("LBSTART.BIK");
break;
case BattleResultVideo::DEFEAT_SIEGE:
musicName = AudioPath::builtin("Music/LoseCastle");
videoName = VideoPath::builtin("LOSECSTL.BIK");
break;
case BattleResultVideo::WIN_SIEGE:
musicName = AudioPath::builtin("Music/Defend Castle");
videoName = VideoPath::builtin("DEFENDALL.BIK");
break;
}
}
else
{
switch(currentVideo)
{
case BattleResultVideo::RETREAT:
currentVideo = BattleResultVideo::RETREAT_LOOP;
videoName = VideoPath::builtin("RTLOOP.BIK");
break;
case BattleResultVideo::DEFEAT:
currentVideo = BattleResultVideo::DEFEAT_LOOP;
videoName = VideoPath::builtin("LBLOOP.BIK");
break;
case BattleResultVideo::DEFEAT_SIEGE:
currentVideo = BattleResultVideo::DEFEAT_SIEGE_LOOP;
videoName = VideoPath::builtin("LOSECSLP.BIK");
break;
case BattleResultVideo::WIN_SIEGE:
currentVideo = BattleResultVideo::WIN_SIEGE_LOOP;
videoName = VideoPath::builtin("DEFENDLOOP.BIK");
break;
}
}
if(musicName != AudioPath())
CCS->musich->playMusic(musicName, false, true);
if(videoName != VideoPath())
CCS->videoh->open(videoName);
}
void BattleResultWindow::buttonPressed(int button)
{
if (resultCallback)
@@ -865,7 +820,6 @@ void BattleResultWindow::buttonPressed(int button)
//Result window and battle interface are gone. We requested all dialogs to be closed before opening the battle,
//so we can be sure that there is no dialogs left on GUI stack.
intTmp.showingDialog->setn(false);
CCS->videoh->close();
}
void BattleResultWindow::bExitf()

View File

@@ -14,6 +14,7 @@
#include "../../lib/FunctionList.h"
#include "../../lib/battle/BattleHex.h"
#include "../windows/CWindowObject.h"
#include "../../lib/MetaString.h"
VCMI_LIB_NAMESPACE_BEGIN
@@ -42,6 +43,7 @@ class CAnimImage;
class TransparentFilledRectangle;
class CPlayerInterface;
class BattleRenderer;
class VideoWidget;
/// Class which shows the console at the bottom of the battle screen and manages the text of the console
class BattleConsole : public CIntObject, public IStatusBar
@@ -185,6 +187,14 @@ public:
HeroInfoWindow(const InfoAboutHero & hero, Point * position);
};
struct BattleResultResources
{
VideoPath prologueVideo;
VideoPath loopedVideo;
AudioPath musicName;
MetaString resultText;
};
/// Class which is responsible for showing the battle result window
class BattleResultWindow : public WindowBase
{
@@ -195,25 +205,10 @@ private:
std::shared_ptr<CButton> repeat;
std::vector<std::shared_ptr<CAnimImage>> icons;
std::shared_ptr<CTextBox> description;
std::shared_ptr<VideoWidget> videoPlayer;
CPlayerInterface & owner;
enum BattleResultVideo
{
NONE,
WIN,
SURRENDER,
RETREAT,
RETREAT_LOOP,
DEFEAT,
DEFEAT_LOOP,
DEFEAT_SIEGE,
DEFEAT_SIEGE_LOOP,
WIN_SIEGE,
WIN_SIEGE_LOOP,
};
BattleResultVideo currentVideo;
void playVideo(bool startLoop = false);
BattleResultResources getResources(const BattleResult & br);
void buttonPressed(int button); //internal function for button callbacks
public:
@@ -224,7 +219,6 @@ public:
std::function<void(int result)> resultCallback; //callback receiving which button was pressed
void activate() override;
void show(Canvas & to) override;
};
/// Shows the stack queue

View File

@@ -19,13 +19,13 @@
#include "../gui/CGuiHandler.h"
#include "../gui/Shortcut.h"
#include "../media/IMusicPlayer.h"
#include "../media/IVideoPlayer.h"
#include "../render/Canvas.h"
#include "../widgets/CComponent.h"
#include "../widgets/Buttons.h"
#include "../widgets/MiscWidgets.h"
#include "../widgets/ObjectLists.h"
#include "../widgets/TextControls.h"
#include "../widgets/VideoWidget.h"
#include "../windows/GUIClasses.h"
#include "../windows/InfoWindows.h"
#include "../windows/CWindowObject.h"
@@ -100,7 +100,7 @@ CCampaignScreen::CCampaignButton::CCampaignButton(const JsonNode & config, const
pos.h = 116;
campFile = config["file"].String();
video = VideoPath::fromJson(config["video"]);
videoPath = VideoPath::fromJson(config["video"]);
status = CCampaignScreen::ENABLED;
@@ -127,7 +127,6 @@ CCampaignScreen::CCampaignButton::CCampaignButton(const JsonNode & config, const
{
addUsedEvents(LCLICK | HOVER);
graphicsImage = std::make_shared<CPicture>(ImagePath::fromJson(config["image"]));
hoverLabel = std::make_shared<CLabel>(pos.w / 2, pos.h + 20, FONT_MEDIUM, ETextAlignment::CENTER, Colors::YELLOW, "");
parent->addChild(hoverLabel.get());
}
@@ -136,30 +135,19 @@ CCampaignScreen::CCampaignButton::CCampaignButton(const JsonNode & config, const
graphicsCompleted = std::make_shared<CPicture>(ImagePath::builtin("CAMPCHK"));
}
void CCampaignScreen::CCampaignButton::show(Canvas & to)
{
if(status == CCampaignScreen::DISABLED)
return;
CIntObject::show(to);
// Play the campaign button video when the mouse cursor is placed over the button
if(isHovered())
CCS->videoh->update(pos.x, pos.y, to.getInternalSurface(), true, false); // plays sequentially frame by frame, starts at the beginning when the video is over
}
void CCampaignScreen::CCampaignButton::clickReleased(const Point & cursorPosition)
{
CCS->videoh->close();
CMainMenu::openCampaignLobby(campFile, campaignSet);
}
void CCampaignScreen::CCampaignButton::hover(bool on)
{
if (on)
CCS->videoh->open(video);
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
if (on && !videoPath.empty())
videoPlayer = std::make_shared<VideoWidget>(Point(), videoPath);
else
CCS->videoh->close();
videoPlayer.reset();
if(hoverLabel)
{

View File

@@ -20,6 +20,7 @@ VCMI_LIB_NAMESPACE_END
class CLabel;
class CPicture;
class CButton;
class VideoWidget;
class CCampaignScreen : public CWindowObject
{
@@ -34,10 +35,11 @@ private:
std::shared_ptr<CLabel> hoverLabel;
std::shared_ptr<CPicture> graphicsImage;
std::shared_ptr<CPicture> graphicsCompleted;
std::shared_ptr<VideoWidget> videoPlayer;
CampaignStatus status;
VideoPath videoPath;
std::string campFile; // the filename/resourcename of the campaign
VideoPath video; // the resource name of the video
std::string hoverText;
std::string campaignSet;
@@ -47,7 +49,6 @@ private:
public:
CCampaignButton(const JsonNode & config, const JsonNode & parentConfig, std::string campaignSet);
void show(Canvas & to) override;
};
std::string campaignSet;

View File

@@ -16,11 +16,11 @@
#include "../gui/Shortcut.h"
#include "../media/IMusicPlayer.h"
#include "../media/ISoundPlayer.h"
#include "../media/IVideoPlayer.h"
#include "../widgets/Buttons.h"
#include "../widgets/CTextInput.h"
#include "../widgets/Images.h"
#include "../widgets/GraphicalPrimitiveCanvas.h"
#include "../widgets/VideoWidget.h"
#include "../windows/InfoWindows.h"
#include "../widgets/TextControls.h"
#include "../render/Canvas.h"
@@ -217,7 +217,7 @@ void CHighScoreScreen::buttonExitClick()
}
CHighScoreInputScreen::CHighScoreInputScreen(bool won, HighScoreCalculation calc)
: CWindowObject(BORDERED), won(won), calc(calc), videoSoundHandle(-1)
: CWindowObject(BORDERED), won(won), calc(calc)
{
addUsedEvents(LCLICK | KEYBOARD);
@@ -229,6 +229,8 @@ CHighScoreInputScreen::CHighScoreInputScreen(bool won, HighScoreCalculation calc
if(won)
{
videoPlayer = std::make_shared<VideoWidget>(Point(30, 120), VideoPath::builtin("HSANIM.SMK"), VideoPath::builtin("HSLOOP.SMK"));
int border = 100;
int textareaW = ((pos.w - 2 * border) / 4);
std::vector<std::string> t = { "438", "439", "440", "441", "676" }; // time, score, difficulty, final score, rank
@@ -243,9 +245,10 @@ CHighScoreInputScreen::CHighScoreInputScreen(bool won, HighScoreCalculation calc
CCS->musich->playMusic(AudioPath::builtin("music/Win Scenario"), true, true);
}
else
{
videoPlayer = std::make_shared<VideoWidget>(Point(30, 120), VideoPath::builtin("HSANIM.SMK"), VideoPath::builtin("LOSEGAME.SMK"));
CCS->musich->playMusic(AudioPath::builtin("music/UltimateLose"), false, true);
video = won ? "HSANIM.SMK" : "LOSEGAME.SMK";
}
}
int CHighScoreInputScreen::addEntry(std::string text) {
@@ -288,47 +291,6 @@ int CHighScoreInputScreen::addEntry(std::string text) {
return pos;
}
void CHighScoreInputScreen::show(Canvas & to)
{
CCS->videoh->update(pos.x, pos.y, to.getInternalSurface(), true, false,
[&]()
{
if(won)
{
CCS->videoh->close();
video = "HSLOOP.SMK";
auto audioData = CCS->videoh->getAudio(VideoPath::builtin(video));
videoSoundHandle = CCS->soundh->playSound(audioData);
CCS->videoh->open(VideoPath::builtin(video));
}
else
close();
});
redraw();
CIntObject::show(to);
}
void CHighScoreInputScreen::activate()
{
auto audioData = CCS->videoh->getAudio(VideoPath::builtin(video));
videoSoundHandle = CCS->soundh->playSound(audioData);
if(!CCS->videoh->open(VideoPath::builtin(video)))
{
if(!won)
close();
}
else
background = nullptr;
CIntObject::activate();
}
void CHighScoreInputScreen::deactivate()
{
CCS->videoh->close();
CCS->soundh->stopSound(videoSoundHandle);
}
void CHighScoreInputScreen::clickPressed(const Point & cursorPosition)
{
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;

View File

@@ -15,6 +15,7 @@ class CLabel;
class CMultiLineLabel;
class CAnimImage;
class CTextInput;
class VideoWidget;
class TransparentFilledRectangle;
@@ -93,9 +94,8 @@ class CHighScoreInputScreen : public CWindowObject
std::vector<std::shared_ptr<CMultiLineLabel>> texts;
std::shared_ptr<CHighScoreInput> input;
std::shared_ptr<TransparentFilledRectangle> background;
std::shared_ptr<VideoWidget> videoPlayer;
std::string video;
int videoSoundHandle;
bool won;
HighScoreCalculation calc;
public:
@@ -103,9 +103,6 @@ public:
int addEntry(std::string text);
void show(Canvas & to) override;
void activate() override;
void deactivate() override;
void clickPressed(const Point & cursorPosition) override;
void keyPressed(EShortcut key) override;
};
};

View File

@@ -18,7 +18,6 @@
#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"
@@ -35,6 +34,7 @@
#include "../widgets/MiscWidgets.h"
#include "../widgets/ObjectLists.h"
#include "../widgets/TextControls.h"
#include "../widgets/VideoWidget.h"
#include "../windows/InfoWindows.h"
#include "../CServerHandler.h"
@@ -92,8 +92,14 @@ CMenuScreen::CMenuScreen(const JsonNode & configNode)
menuNameToEntry.push_back("credits");
tabs = std::make_shared<CTabbedInt>(std::bind(&CMenuScreen::createTab, this, _1));
if(config["video"].isNull())
if(!config["video"].isNull())
{
Point videoPosition(config["video"]["x"].Integer(), config["video"]["y"].Integer());
videoPlayer = std::make_shared<VideoWidget>(videoPosition, VideoPath::fromJson(config["video"]["name"]));
}
else
tabs->setRedrawParent(true);
}
std::shared_ptr<CIntObject> CMenuScreen::createTab(size_t index)
@@ -104,34 +110,12 @@ std::shared_ptr<CIntObject> CMenuScreen::createTab(size_t index)
return std::make_shared<CMenuEntry>(this, config["items"].Vector()[index]);
}
void CMenuScreen::show(Canvas & to)
{
if(!config["video"].isNull())
{
// redraw order: background -> video -> buttons and pictures
background->redraw();
CCS->videoh->update((int)config["video"]["x"].Float() + pos.x, (int)config["video"]["y"].Float() + pos.y, to.getInternalSurface(), true, false);
tabs->redraw();
}
CIntObject::show(to);
}
void CMenuScreen::activate()
{
CCS->musich->playMusic(AudioPath::builtin("Music/MainMenu"), true, true);
if(!config["video"].isNull())
CCS->videoh->open(VideoPath::fromJson(config["video"]["name"]));
CIntObject::activate();
}
void CMenuScreen::deactivate()
{
if(!config["video"].isNull())
CCS->videoh->close();
CIntObject::deactivate();
}
void CMenuScreen::switchToTab(size_t index)
{
tabs->setActive(index);

View File

@@ -28,7 +28,7 @@ class CAnimation;
class CButton;
class CFilledTexture;
class CLabel;
class VideoWidget;
// TODO: Find new location for these enums
enum class ESelectionScreen : ui8 {
@@ -48,6 +48,7 @@ class CMenuScreen : public CWindowObject
std::shared_ptr<CTabbedInt> tabs;
std::shared_ptr<CPicture> background;
std::shared_ptr<VideoWidget> videoPlayer;
std::vector<std::shared_ptr<CPicture>> images;
std::shared_ptr<CIntObject> createTab(size_t index);
@@ -57,9 +58,7 @@ public:
CMenuScreen(const JsonNode & configNode);
void show(Canvas & to) override;
void activate() override;
void deactivate() override;
void switchToTab(size_t index);
void switchToTab(std::string name);

View File

@@ -14,14 +14,13 @@
#include "../CGameInfo.h"
#include "../media/IMusicPlayer.h"
#include "../media/ISoundPlayer.h"
#include "../media/IVideoPlayer.h"
#include "../gui/WindowHandler.h"
#include "../gui/CGuiHandler.h"
#include "../gui/FramerateManager.h"
#include "../widgets/TextControls.h"
#include "../widgets/VideoWidget.h"
#include "../render/Canvas.h"
CPrologEpilogVideo::CPrologEpilogVideo(CampaignScenarioPrologEpilog _spe, std::function<void()> callback)
: CWindowObject(BORDERED), spe(_spe), positionCounter(0), voiceSoundHandle(-1), videoSoundHandle(-1), exitCb(callback), elapsedTimeMilliseconds(0)
{
@@ -30,9 +29,12 @@ CPrologEpilogVideo::CPrologEpilogVideo(CampaignScenarioPrologEpilog _spe, std::f
pos = center(Rect(0, 0, 800, 600));
updateShadow();
auto audioData = CCS->videoh->getAudio(spe.prologVideo);
videoSoundHandle = CCS->soundh->playSound(audioData, -1);
CCS->videoh->open(spe.prologVideo);
videoPlayer = std::make_shared<VideoWidget>(Point(30, 120), spe.prologVideo);
//some videos are 800x600 in size while some are 800x400
if (videoPlayer->pos.h == 400)
videoPlayer->moveBy(Point(0, 100));
CCS->musich->playMusic(spe.prologMusic, true, true);
voiceDurationMilliseconds = CCS->soundh->getSoundDurationMilliseconds(spe.prologVoice);
voiceSoundHandle = CCS->soundh->playSound(spe.prologVoice);
@@ -66,9 +68,8 @@ void CPrologEpilogVideo::tick(uint32_t msPassed)
void CPrologEpilogVideo::show(Canvas & to)
{
to.drawColor(pos, Colors::BLACK);
//some videos are 800x600 in size while some are 800x400
CCS->videoh->update(pos.x, pos.y + (CCS->videoh->size().y == 400 ? 100 : 0), to.getInternalSurface(), true, false);
videoPlayer->show(to);
text->showAll(to); // blit text over video, if needed
}

View File

@@ -13,6 +13,7 @@
#include "../../lib/campaign/CampaignScenarioPrologEpilog.h"
class CMultiLineLabel;
class VideoWidget;
class CPrologEpilogVideo : public CWindowObject
{
@@ -25,6 +26,7 @@ class CPrologEpilogVideo : public CWindowObject
std::function<void()> exitCb;
std::shared_ptr<CMultiLineLabel> text;
std::shared_ptr<VideoWidget> videoPlayer;
bool voiceStopped = false;

View File

@@ -15,13 +15,10 @@
class CEmptyVideoPlayer final : public IVideoPlayer
{
public:
int curFrame() const override {return -1;};
int frameCount() const override {return -1;};
void redraw( int x, int y, SDL_Surface *dst, bool update) override {};
void show( int x, int y, SDL_Surface *dst, bool update) override {};
bool nextFrame() override {return false;};
void close() override {};
bool wait() override {return false;};
bool open(const VideoPath & name, bool scale) override {return false;};
void update(int x, int y, SDL_Surface *dst, bool forceRedraw, bool update, std::function<void()> restart) override {}
bool openAndPlayVideo(const VideoPath & name, int x, int y, EVideoType videoType) override { return false; }

View File

@@ -73,11 +73,6 @@ public:
Point size() override;
//TODO:
bool wait() override {return false;};
int curFrame() const override {return -1;};
int frameCount() const override {return -1;};
// public to allow access from ffmpeg IO functions
std::unique_ptr<CInputStream> data;
std::unique_ptr<CInputStream> dataAudio;

View File

@@ -31,9 +31,6 @@ public:
virtual bool nextFrame()=0;
virtual void show(int x, int y, SDL_Surface *dst, bool update = true)=0;
virtual void redraw(int x, int y, SDL_Surface *dst, bool update = true)=0; //reblits buffer
virtual bool wait()=0;
virtual int curFrame() const =0;
virtual int frameCount() const =0;
virtual void update(int x, int y, SDL_Surface *dst, bool forceRedraw, bool update = true, std::function<void()> restart = nullptr) = 0;
virtual bool openAndPlayVideo(const VideoPath & name, int x, int y, EVideoType videoType) = 0;
virtual std::pair<std::unique_ptr<ui8 []>, si64> getAudio(const VideoPath & videoToOpen) = 0;

View File

@@ -0,0 +1,68 @@
/*
* TextControls.cpp, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#include "StdInc.h"
#include "VideoWidget.h"
#include "../CGameInfo.h"
#include "../media/IVideoPlayer.h"
#include "../media/ISoundPlayer.h"
#include "../render/Canvas.h"
#include "../gui/CGuiHandler.h"
#include "../gui/WindowHandler.h"
VideoWidget::VideoWidget(const Point & position, const VideoPath & looped)
: VideoWidget(position, VideoPath(), looped)
{
}
VideoWidget::VideoWidget(const Point & position, const VideoPath & prologue, const VideoPath & looped)
:current(prologue)
,next(looped)
,videoSoundHandle(-1)
{
}
VideoWidget::~VideoWidget() = default;
void VideoWidget::show(Canvas & to)
{
CCS->videoh->update(pos.x + 107, pos.y + 70, to.getInternalSurface(), true, false);
}
void VideoWidget::activate()
{
CCS->videoh->open(current);
auto audioData = CCS->videoh->getAudio(current);
videoSoundHandle = CCS->soundh->playSound(audioData, -1);
if (videoSoundHandle != -1)
{
CCS->soundh->setCallback(videoSoundHandle, [this](){
if (GH.windows().isTopWindow(this))
this->videoSoundHandle = -1;
});
}
}
void VideoWidget::deactivate()
{
CCS->videoh->close();
CCS->soundh->stopSound(videoSoundHandle);
}
void VideoWidget::showAll(Canvas & to)
{
CCS->videoh->update(pos.x + 107, pos.y + 70, to.getInternalSurface(), true, false);
}
void VideoWidget::tick(uint32_t msPassed)
{
}

View File

@@ -0,0 +1,32 @@
/*
* VideoWidget.h, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#pragma once
#include "../gui/CIntObject.h"
#include "../lib/filesystem/ResourcePath.h"
class VideoWidget final : public CIntObject
{
VideoPath current;
VideoPath next;
int videoSoundHandle;
public:
VideoWidget(const Point & position, const VideoPath & prologue, const VideoPath & looped);
VideoWidget(const Point & position, const VideoPath & looped);
~VideoWidget();
void activate() override;
void deactivate() override;
void show(Canvas & to) override;
void showAll(Canvas & to) override;
void tick(uint32_t msPassed) override;
};

View File

@@ -20,10 +20,10 @@
#include "../gui/CGuiHandler.h"
#include "../gui/Shortcut.h"
#include "../gui/WindowHandler.h"
#include "../media/IVideoPlayer.h"
#include "../widgets/Images.h"
#include "../widgets/Buttons.h"
#include "../widgets/TextControls.h"
#include "../widgets/VideoWidget.h"
#include "../render/Canvas.h"
CTutorialWindow::CTutorialWindow(const TutorialMode & m)
@@ -54,7 +54,10 @@ CTutorialWindow::CTutorialWindow(const TutorialMode & m)
void CTutorialWindow::setContent()
{
video = "tutorial/" + videos[page];
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
auto video = VideoPath::builtin("tutorial/" + videos[page]);
videoPlayer = std::make_shared<VideoWidget>(Point(30, 120), video);
buttonLeft->block(page<1);
buttonRight->block(page>videos.size() - 2);
@@ -98,26 +101,3 @@ void CTutorialWindow::previous()
deactivate();
activate();
}
void CTutorialWindow::show(Canvas & to)
{
CCS->videoh->update(pos.x + 30, pos.y + 120, to.getInternalSurface(), true, false,
[&]()
{
CCS->videoh->close();
CCS->videoh->open(VideoPath::builtin(video));
});
CIntObject::show(to);
}
void CTutorialWindow::activate()
{
CCS->videoh->open(VideoPath::builtin(video));
CIntObject::activate();
}
void CTutorialWindow::deactivate()
{
CCS->videoh->close();
}

View File

@@ -15,6 +15,7 @@ class CFilledTexture;
class CButton;
class CLabel;
class CMultiLineLabel;
class VideoWidget;
enum TutorialMode
{
@@ -33,8 +34,8 @@ class CTutorialWindow : public CWindowObject
std::shared_ptr<CLabel> labelTitle;
std::shared_ptr<CMultiLineLabel> labelInformation;
std::shared_ptr<VideoWidget> videoPlayer;
std::string video;
std::vector<std::string> videos;
int page;
@@ -47,8 +48,4 @@ class CTutorialWindow : public CWindowObject
public:
CTutorialWindow(const TutorialMode & m);
static void openWindowFirstTime(const TutorialMode & m);
void show(Canvas & to) override;
void activate() override;
void deactivate() override;
};

View File

@@ -26,8 +26,6 @@
#include "../gui/Shortcut.h"
#include "../gui/WindowHandler.h"
#include "../media/IVideoPlayer.h"
#include "../widgets/CComponent.h"
#include "../widgets/CGarrisonInt.h"
#include "../widgets/CreatureCostBox.h"
@@ -36,6 +34,7 @@
#include "../widgets/Slider.h"
#include "../widgets/TextControls.h"
#include "../widgets/ObjectLists.h"
#include "../widgets/VideoWidget.h"
#include "../render/Canvas.h"
#include "../render/CAnimation.h"
@@ -516,11 +515,11 @@ CTavernWindow::CTavernWindow(const CGObjectInstance * TavernObj, const std::func
recruit->block(true);
}
if(LOCPLINT->castleInt)
CCS->videoh->open(LOCPLINT->castleInt->town->town->clientInfo.tavernVideo);
videoPlayer = std::make_shared<VideoWidget>(Point(70, 56), LOCPLINT->castleInt->town->town->clientInfo.tavernVideo);
else if(const auto * townObj = dynamic_cast<const CGTownInstance *>(TavernObj))
CCS->videoh->open(townObj->town->clientInfo.tavernVideo);
videoPlayer = std::make_shared<VideoWidget>(Point(70, 56), townObj->town->clientInfo.tavernVideo);
else
CCS->videoh->open(VideoPath::builtin("TAVERN.BIK"));
videoPlayer = std::make_shared<VideoWidget>(Point(70, 56), VideoPath::builtin("TAVERN.BIK"));
addInvite();
}
@@ -573,11 +572,6 @@ void CTavernWindow::close()
CStatusbarWindow::close();
}
CTavernWindow::~CTavernWindow()
{
CCS->videoh->close();
}
void CTavernWindow::show(Canvas & to)
{
CWindowObject::show(to);
@@ -601,8 +595,6 @@ void CTavernWindow::show(Canvas & to)
to.drawBorder(Rect::createAround(sel->pos, 2), Colors::BRIGHT_YELLOW, 2);
}
CCS->videoh->update(pos.x+70, pos.y+56, to.getInternalSurface(), true, false);
}
void CTavernWindow::HeroPortrait::clickPressed(const Point & cursorPosition)

View File

@@ -39,6 +39,7 @@ class CHeroArea;
class CAnimImage;
class CFilledTexture;
class IImage;
class VideoWidget;
enum class EUserEvent;
@@ -261,6 +262,7 @@ public:
std::shared_ptr<CLabel> cost;
std::shared_ptr<CLabel> heroesForHire;
std::shared_ptr<CTextBox> heroDescription;
std::shared_ptr<VideoWidget> videoPlayer;
std::shared_ptr<CTextBox> rumor;
@@ -272,7 +274,6 @@ public:
void addInvite();
CTavernWindow(const CGObjectInstance * TavernObj, const std::function<void()> & onWindowClosed);
~CTavernWindow();
void close() override;
void recruitb();