Browse Source

use json format

Laserlicht 1 year ago
parent
commit
8b427c3989

+ 13 - 36
client/widgets/VideoWidget.cpp

@@ -38,26 +38,19 @@ void VideoWidgetBase::playVideo(const VideoPath & fileToPlay)
 {
 	OBJECT_CONSTRUCTION;
 
-	using SubTitlePath = ResourcePathTempl<EResType::SUBTITLE>;
-	SubTitlePath subTitlePath = fileToPlay.toType<EResType::SUBTITLE>();
-	SubTitlePath subTitlePathVideoDir = subTitlePath.addPrefix("VIDEO/");
+	JsonPath subTitlePath = fileToPlay.toType<EResType::JSON>();
+	JsonPath subTitlePathVideoDir = subTitlePath.addPrefix("VIDEO/");
 	if(CResourceHandler::get()->existsResource(subTitlePath))
-	{
-		auto rawData = CResourceHandler::get()->load(subTitlePath)->readAll();
-		srtContent = std::string(reinterpret_cast<char *>(rawData.first.get()), rawData.second);
-	}
-	if(CResourceHandler::get()->existsResource(subTitlePathVideoDir))
-	{
-		auto rawData = CResourceHandler::get()->load(subTitlePathVideoDir)->readAll();
-		srtContent = std::string(reinterpret_cast<char *>(rawData.first.get()), rawData.second);
-	}
+		subTitleData = JsonNode(subTitlePath);
+	else if(CResourceHandler::get()->existsResource(subTitlePathVideoDir))
+		subTitleData = JsonNode(subTitlePathVideoDir);
 
 	videoInstance = CCS->videoh->open(fileToPlay, scaleFactor);
 	if (videoInstance)
 	{
 		pos.w = videoInstance->size().x;
 		pos.h = videoInstance->size().y;
-		subTitle = std::make_unique<CMultiLineLabel>(Rect(0, (pos.h / 5) * 4, pos.w, pos.h / 5), EFonts::FONT_HIGH_SCORE, ETextAlignment::CENTER, Colors::WHITE, "");
+		subTitle = std::make_unique<CMultiLineLabel>(Rect(0, (pos.h / 5) * 4, pos.w, pos.h / 5), EFonts::FONT_HIGH_SCORE, ETextAlignment::CENTER, Colors::WHITE);
 	}
 
 	if (playAudio)
@@ -115,30 +108,14 @@ void VideoWidgetBase::stopAudio()
 
 std::string VideoWidgetBase::getSubTitleLine(double timestamp)
 {
-	if(srtContent.empty())
-		return "";
+	if(subTitleData.isNull())
+		return {};
+
+	for(auto & segment : subTitleData.Vector())
+		if(timestamp > segment["timeStart"].Float() && timestamp < segment["timeEnd"].Float())
+			return segment["text"].String();
 	
-    std::regex exp("^\\s*(\\d+:\\d+:\\d+,\\d+)[^\\S\\n]+-->[^\\S\\n]+(\\d+:\\d+:\\d+,\\d+)((?:\\n(?!\\d+:\\d+:\\d+,\\d+\\b|\\n+\\d+$).*)*)", std::regex::multiline);
-    std::smatch res;
-
-    std::string::const_iterator searchStart(srtContent.cbegin());
-    while (std::regex_search(searchStart, srtContent.cend(), res, exp))
-    {
-		std::vector<std::string> timestamp1Str;
-		boost::split(timestamp1Str, static_cast<std::string>(res[1]), boost::is_any_of(":,"));
-		std::vector<std::string> timestamp2Str;
-		boost::split(timestamp2Str, static_cast<std::string>(res[2]), boost::is_any_of(":,"));
-		double timestamp1 = std::stoi(timestamp1Str[0]) * 3600 + std::stoi(timestamp1Str[1]) * 60 + std::stoi(timestamp1Str[2]) + (std::stoi(timestamp1Str[3]) / 1000.0);
-		double timestamp2 = std::stoi(timestamp2Str[0]) * 3600 + std::stoi(timestamp2Str[1]) * 60 + std::stoi(timestamp2Str[2]) + (std::stoi(timestamp2Str[3]) / 1000.0);
-        std::string text = res[3];
-		text.erase(0, text.find_first_not_of("\r\n\t "));
-
-		if(timestamp > timestamp1 && timestamp < timestamp2)
-			return text;
-		
-        searchStart = res.suffix().first;
-    }
-	return "";
+	return {};
 }
 
 void VideoWidgetBase::activate()

+ 2 - 1
client/widgets/VideoWidget.h

@@ -12,6 +12,7 @@
 #include "../gui/CIntObject.h"
 
 #include "../lib/filesystem/ResourcePath.h"
+#include "../lib/json/JsonNode.h"
 
 class IVideoInstance;
 class CMultiLineLabel;
@@ -25,7 +26,7 @@ class VideoWidgetBase : public CIntObject
 	int audioHandle = -1;
 	bool playAudio = false;
 	float scaleFactor = 1.0;
-	std::string srtContent = "";
+	JsonNode subTitleData;
 
 	void loadAudio(const VideoPath & file);
 	void startAudio();

+ 13 - 0
docs/translators/Translations.md

@@ -56,6 +56,19 @@ This will export all strings from game into `Documents/My Games/VCMI/extracted/t
 
 To export maps and campaigns, use '/translate maps' command instead.
 
+### Video subtitles
+It's possible to add video subtitles. Create a JSON file in `video` folder of translation mod with the name of the video (e.g. `H3Intro.json`):
+```
+[
+    {
+        "timeStart" : 5.640, // start time, seconds
+        "timeEnd" : 8.120, // end time, seconds
+        "text" : " ... " // text to show during this period
+    },
+    ...
+]
+```
+
 ## Translating VCMI data
 
 VCMI contains several new strings, to cover functionality not existing in Heroes III. It can be roughly split into following parts:

+ 0 - 1
lib/filesystem/ResourcePath.cpp

@@ -117,7 +117,6 @@ EResType EResTypeHelper::getTypeFromExtension(std::string extension)
 		{".BIK",   EResType::VIDEO},
 		{".OGV",   EResType::VIDEO},
 		{".WEBM",  EResType::VIDEO},
-		{".SRT",   EResType::SUBTITLE},
 		{".ZIP",   EResType::ARCHIVE_ZIP},
 		{".LOD",   EResType::ARCHIVE_LOD},
 		{".PAC",   EResType::ARCHIVE_LOD},

+ 0 - 2
lib/filesystem/ResourcePath.h

@@ -30,7 +30,6 @@ class JsonSerializeFormat;
  * Sound: .wav .82m
  * Video: .smk, .bik .ogv .webm
  * Music: .mp3, .ogg
- * Subtitle: .srt
  * Archive: .lod, .snd, .vid .pac .zip
  * Palette: .pal
  * Savegame: .v*gm1
@@ -49,7 +48,6 @@ enum class EResType
 	VIDEO,
 	VIDEO_LOW_QUALITY,
 	SOUND,
-	SUBTITLE,
 	ARCHIVE_VID,
 	ARCHIVE_ZIP,
 	ARCHIVE_SND,