Przeglądaj źródła

Merge pull request #5005 from Laserlicht/video

Video rework
Ivan Savenko 10 miesięcy temu
rodzic
commit
150f4904ab

+ 0 - 4
client/media/CEmptyVideoPlayer.h

@@ -14,10 +14,6 @@
 class CEmptyVideoPlayer final : public IVideoPlayer
 {
 public:
-	void playSpellbookAnimation(const VideoPath & name, const Point & position) override
-	{
-	}
-
 	/// Load video from specified path
 	std::unique_ptr<IVideoInstance> open(const VideoPath & name, float scaleFactor) override
 	{

+ 0 - 62
client/media/CVideoHandler.cpp

@@ -637,68 +637,6 @@ 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 stopOnKey)
-{
-	CVideoInstance instance;
-
-	auto extractedAudio = getAudio(name);
-	int audioHandle = CCS->soundh->playSound(extractedAudio);
-
-	if (!instance.openInput(name))
-		return true;
-
-	instance.openVideo();
-	instance.prepareOutput(1, true);
-
-	auto lastTimePoint = boost::chrono::steady_clock::now();
-
-	while(instance.loadNextFrame())
-	{
-		if(stopOnKey)
-		{
-			GH.input().fetchEvents();
-			if(GH.input().ignoreEventsUntilInput())
-			{
-				CCS->soundh->stopSound(audioHandle);
-				return false;
-			}
-		}
-
-		SDL_Rect rect;
-		rect.x = position.x;
-		rect.y = position.y;
-		rect.w = instance.dimensions.x;
-		rect.h = instance.dimensions.y;
-
-		SDL_RenderFillRect(mainRenderer, &rect);
-
-		if(instance.textureYUV)
-			SDL_RenderCopy(mainRenderer, instance.textureYUV, nullptr, &rect);
-		else
-			SDL_RenderCopy(mainRenderer, instance.textureRGB, nullptr, &rect);
-
-		SDL_RenderPresent(mainRenderer);
-
-		// Framerate delay
-		double targetFrameTimeSeconds = instance.getCurrentFrameDuration();
-		auto targetFrameTime = boost::chrono::milliseconds(static_cast<int>(1000 * targetFrameTimeSeconds));
-
-		auto timePointAfterPresent = boost::chrono::steady_clock::now();
-		auto timeSpentBusy = boost::chrono::duration_cast<boost::chrono::milliseconds>(timePointAfterPresent - lastTimePoint);
-
-		if(targetFrameTime > timeSpentBusy)
-			boost::this_thread::sleep_for(targetFrameTime - timeSpentBusy);
-
-		lastTimePoint = boost::chrono::steady_clock::now();
-	}
-	return true;
-}
-
-void CVideoPlayer::playSpellbookAnimation(const VideoPath & name, const Point & position)
-{
-	openAndPlayVideoImpl(name, position * GH.screenHandler().getScalingFactor(), false, false);
-}
-
 std::unique_ptr<IVideoInstance> CVideoPlayer::open(const VideoPath & name, float scaleFactor)
 {
 	auto result = std::make_unique<CVideoInstance>();

+ 0 - 2
client/media/CVideoHandler.h

@@ -103,11 +103,9 @@ public:
 
 class CVideoPlayer final : public IVideoPlayer
 {
-	bool openAndPlayVideoImpl(const VideoPath & name, const Point & position, bool useOverlay, bool stopOnKey);
 	void openVideoFile(CVideoInstance & state, const VideoPath & fname);
 
 public:
-	void playSpellbookAnimation(const VideoPath & name, const Point & position) final;
 	std::unique_ptr<IVideoInstance> open(const VideoPath & name, float scaleFactor) final;
 	std::pair<std::unique_ptr<ui8[]>, si64> getAudio(const VideoPath & videoToOpen) final;
 };

+ 0 - 3
client/media/IVideoPlayer.h

@@ -45,9 +45,6 @@ public:
 class IVideoPlayer : boost::noncopyable
 {
 public:
-	/// 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, float scaleFactor) = 0;
 

+ 21 - 1
client/widgets/VideoWidget.cpp

@@ -16,6 +16,7 @@
 #include "../media/ISoundPlayer.h"
 #include "../media/IVideoPlayer.h"
 #include "../render/Canvas.h"
+#include "../render/IScreenHandler.h"
 
 #include "../../lib/filesystem/Filesystem.h"
 
@@ -45,7 +46,26 @@ void VideoWidgetBase::playVideo(const VideoPath & fileToPlay)
 	else if(CResourceHandler::get()->existsResource(subTitlePathVideoDir))
 		subTitleData = JsonNode(subTitlePathVideoDir);
 
-	videoInstance = CCS->videoh->open(fileToPlay, scaleFactor);
+	float preScaleFactor = 1;
+	VideoPath videoFile = fileToPlay;
+	if(GH.screenHandler().getScalingFactor() > 1)
+	{
+		std::vector<int> factorsToCheck = {GH.screenHandler().getScalingFactor(), 4, 3, 2};
+		for(auto factorToCheck : factorsToCheck)
+		{
+			std::string name = boost::algorithm::to_upper_copy(videoFile.getName());
+			boost::replace_all(name, "VIDEO/", std::string("VIDEO") + std::to_string(factorToCheck) + std::string("X/"));
+			auto p = VideoPath::builtin(name).addPrefix("VIDEO" + std::to_string(factorToCheck) + "X/");
+			if(CResourceHandler::get()->existsResource(p))
+			{
+				preScaleFactor = 1.0 / static_cast<float>(factorToCheck);
+				videoFile = p;
+				break;
+			}
+		}
+	}
+
+	videoInstance = CCS->videoh->open(videoFile, scaleFactor * preScaleFactor);
 	if (videoInstance)
 	{
 		pos.w = videoInstance->size().x;

+ 13 - 2
client/windows/CSpellWindow.cpp

@@ -30,6 +30,7 @@
 #include "../widgets/CTextInput.h"
 #include "../widgets/TextControls.h"
 #include "../widgets/Buttons.h"
+#include "../widgets/VideoWidget.h"
 #include "../adventureMap/AdventureMapInterface.h"
 #include "../render/AssetGenerator.h"
 
@@ -395,6 +396,8 @@ void CSpellWindow::fRcornerb()
 
 void CSpellWindow::show(Canvas & to)
 {
+	if(video)
+		video->show(to);
 	statusBar->show(to);
 }
 
@@ -493,14 +496,22 @@ void CSpellWindow::setCurrentPage(int value)
 
 void CSpellWindow::turnPageLeft()
 {
+	OBJECT_CONSTRUCTION;
 	if(settings["video"]["spellbookAnimation"].Bool() && !isBigSpellbook)
-		CCS->videoh->playSpellbookAnimation(VideoPath::builtin("PGTRNLFT.SMK"), pos.topLeft() + Point(13, 14));
+		video = std::make_shared<VideoWidgetOnce>(Point(13, 14), VideoPath::builtin("PGTRNLFT.SMK"), false, [this](){
+			video.reset();
+			redraw();
+		});
 }
 
 void CSpellWindow::turnPageRight()
 {
+	OBJECT_CONSTRUCTION;
 	if(settings["video"]["spellbookAnimation"].Bool() && !isBigSpellbook)
-		CCS->videoh->playSpellbookAnimation(VideoPath::builtin("PGTRNRGH.SMK"), pos.topLeft() + Point(13, 14));
+		video = std::make_shared<VideoWidgetOnce>(Point(13, 14), VideoPath::builtin("PGTRNRGH.SMK"), false, [this](){
+			video.reset();
+			redraw();
+		});
 }
 
 void CSpellWindow::keyPressed(EShortcut key)

+ 3 - 0
client/windows/CSpellWindow.h

@@ -28,6 +28,7 @@ class CSpellWindow;
 class CTextInput;
 class TransparentFilledRectangle;
 class CToggleButton;
+class VideoWidgetOnce;
 
 /// The spell window
 class CSpellWindow : public CWindowObject
@@ -86,6 +87,8 @@ class CSpellWindow : public CWindowObject
 	std::shared_ptr<CToggleButton> showAllSpells;
 	std::shared_ptr<CLabel> showAllSpellsDescription;
 
+	std::shared_ptr<VideoWidgetOnce> video;
+
 	bool isBigSpellbook;
 	int spellsPerPage;
 	int offL;

+ 4 - 3
docs/modders/HD_Graphics.md

@@ -12,12 +12,13 @@ If user for example selects 3x resolution and only 2x exists in mod then the 2x
 
 ## Mod
 
-For upscaled images you have to use following folders (next to `sprites` and `data` folders):
+For upscaled images you have to use following folders (next to `sprites`, `data` and `video` folders):
 
 - `sprites2x`, `sprites3x`, `sprites4x` for sprites
 - `data2x`, `data3x`, `data4x` for images
+- `video2x`, `video3x`, `video4x` for videos
 
-The sprites should have the same name and folder structure as in `sprites` and `data` folder. All images that are missing in the upscaled folders are scaled with the selected upscaling filter instead of using prescaled images.
+The sprites should have the same name and folder structure as in `sprites`, `data` and `video` folder. All images that are missing in the upscaled folders are scaled with the selected upscaling filter instead of using prescaled images.
 
 ### Shadows / Overlays
 
@@ -34,4 +35,4 @@ Same for overlays with `-overlay`. But overlays are **necessary** for some anima
 Currently needed for:
 
 - Flaggable adventure map objects. Overlay must contain a transparent image with white flags on it and will be used to colorize flags to owning player
-- Creature battle animations, idle and mouse hover group. Overlay must contain a transparent image with white outline of creature for highlighting on mouse hover)
+- Creature battle animations, idle and mouse hover group. Overlay must contain a transparent image with white outline of creature for highlighting on mouse hover