Browse Source

A bit more text-related work:
- credits screen will use multi-line label instead of hackish usage of text box
- campaign intro movie player now plays voiced intro
- minor fixes to last commit

Ivan Savenko 12 years ago
parent
commit
83440f1149

+ 35 - 43
client/CPreGame.cpp

@@ -396,7 +396,8 @@ CMenuEntry::CMenuEntry(CMenuScreen* parent, const JsonNode &config)
 	}
 }
 
-CreditsScreen::CreditsScreen()
+CreditsScreen::CreditsScreen():
+    positionCounter(0)
 {
 	addUsedEvents(LCLICK | RCLICK);
 	type |= REDRAW_PARENT;
@@ -407,34 +408,19 @@ CreditsScreen::CreditsScreen()
 	std::string text((char*)textFile.first.get(), textFile.second);
 	size_t firstQuote = text.find('\"')+1;
 	text = text.substr(firstQuote, text.find('\"', firstQuote) - firstQuote );
-	credits = new CTextBox(text, Rect(pos.w - 350, 600, 350, 32000), 0, FONT_CREDITS, CENTER, Colors::WHITE);
-	credits->pos.h = credits->label->textSize.y;
-}
-
-void CreditsScreen::showAll(SDL_Surface * to)
-{
-	//Do not draw anything
+	credits = new CMultiLineLabel(Rect(pos.w - 350, 0, 350, 600), FONT_CREDITS, CENTER, Colors::WHITE, text);
+	credits->scrollTextTo(-600); // move all text below the screen
 }
 
 void CreditsScreen::show(SDL_Surface * to)
 {
-	static int count = 0;
-	count++;
-	if (count == 2)
-	{
-		credits->pos.y--;
-		count = 0;
-	}
-	Rect creditsArea = credits->pos & pos;
-	SDL_SetClipRect(screenBuf, &creditsArea);
-	SDL_SetClipRect(screen, &creditsArea);
-	redraw();
-	CIntObject::showAll(to);
-	SDL_SetClipRect(screen, nullptr);
-	SDL_SetClipRect(screenBuf, nullptr);
+	CIntObject::show(to);
+	positionCounter++;
+	if (positionCounter % 2 == 0)
+		credits->scrollTextBy(1);
 
 	//end of credits, close this screen
-	if (credits->pos.y + credits->pos.h < 0)
+	if (credits->textSize.y + 600 < positionCounter / 2)
 		clickRight(false, false);
 }
 
@@ -4091,45 +4077,51 @@ void CLoadingScreen::showAll(SDL_Surface *to)
 	CWindowObject::showAll(to);
 }
 
-CPrologEpilogVideo::CPrologEpilogVideo( CCampaignScenario::SScenarioPrologEpilog _spe, std::function<void()> callback )
-	: spe(_spe), decrementDelayCounter(0), exitCb(callback)
+CPrologEpilogVideo::CPrologEpilogVideo( CCampaignScenario::SScenarioPrologEpilog _spe, std::function<void()> callback ):
+    CWindowObject(BORDERED),
+    spe(_spe),
+    positionCounter(0),
+    voiceSoundHandle(-1),
+    exitCb(callback)
 {
 	OBJ_CONSTRUCTION_CAPTURING_ALL;
 	addUsedEvents(LCLICK);
-	pos = Rect(screen);
+	pos = center(Rect(0,0, 800, 600));
+	updateShadow();
 
 	CCS->videoh->open(CCampaignHandler::prologVideoName(spe.prologVideo));
+	CCS->musich->playMusic("Music/" + CCampaignHandler::prologMusicName(spe.prologMusic), true);
+	voiceSoundHandle = CCS->soundh->playSound(CCampaignHandler::prologVoiceName(spe.prologVideo));
 
-	auto lines = CMessage::breakText(spe.prologText, 500, EFonts::FONT_BIG);
-
-	txt = CSDL_Ext::newSurface(500, 20 * lines.size() + 10);
-	curTxtH = screen->h;
-	graphics->fonts[FONT_BIG]->renderTextLinesCenter(txt, lines, Colors::METALLIC_GOLD, Point(txt->w/2, txt->h/2 + 5));
+	text = new CMultiLineLabel(Rect(100, 500, 600, 100), EFonts::FONT_BIG, CENTER, Colors::METALLIC_GOLD, spe.prologText );
+	text->scrollTextTo(-100);
 }
 
 void CPrologEpilogVideo::show( SDL_Surface * to )
 {
-	memset(to->pixels, 0, to->h*to->pitch); //make bg black
-	CCS->videoh->update(pos.x, pos.y, to, true, false);
-	SDL_Rect tmp, our;
-	our = Rect(0, to->h-100, to->w, 100);
-	SDL_GetClipRect(to, &tmp);
-	SDL_SetClipRect(to, &our);
-	blitAt(txt, (to->w-txt->w)/2, curTxtH, to);
-	SDL_SetClipRect(to, &tmp);
+	CSDL_Ext::fillRect(to, &pos, 0); // fill screen with black
+	//BUG: some videos are 800x600 in size while some are 800x400
+	//VCMI should center them in the middle of the screen. Possible but needs modification
+	//of video player API which I'd like to avoid untill we'll get rid of Windows-specific player
+	CCS->videoh->update(pos.x, pos.y, to, false, false);
 
 	//move text every 5 calls/frames; seems to be good enough
-	++decrementDelayCounter;
-	if(decrementDelayCounter == 5)
+	++positionCounter;
+	if(positionCounter % 5 == 0)
 	{
-		curTxtH = std::max(curTxtH - 1, to->h - txt->h);
-		decrementDelayCounter = 0;
+		text->scrollTextBy(1);
 	}
+	else
+		text->showAll(to);// blit text over video, if needed
+
+	if (text->textSize.y + 100 < positionCounter / 5)
+		clickLeft(false, false);
 }
 
 void CPrologEpilogVideo::clickLeft( tribool down, bool previousState )
 {
 	GH.popInt(this);
+	CCS->soundh->stopSound(voiceSoundHandle);
 	exitCb();
 }
 

+ 7 - 5
client/CPreGame.h

@@ -89,12 +89,12 @@ public:
 
 class CreditsScreen : public CIntObject
 {
-	CTextBox* credits;
+	int positionCounter;
+	CMultiLineLabel* credits;
 public:
 	CreditsScreen();
 
 	void show(SDL_Surface * to);
-	void showAll(SDL_Surface * to);
 
 	void clickLeft(tribool down, bool previousState);
 	void clickRight(tribool down, bool previousState);
@@ -434,12 +434,14 @@ public:
 };
 
 
-class CPrologEpilogVideo : public CIntObject
+class CPrologEpilogVideo : public CWindowObject
 {
 	CCampaignScenario::SScenarioPrologEpilog spe;
-	SDL_Surface * txt;
-	int curTxtH, decrementDelayCounter;
+	int positionCounter;
+	int voiceSoundHandle;
 	std::function<void()> exitCb;
+
+	CMultiLineLabel * text;
 public:
 	CPrologEpilogVideo(CCampaignScenario::SScenarioPrologEpilog _spe, std::function<void()> callback);
 

+ 1 - 2
client/CQuestLog.cpp

@@ -142,9 +142,8 @@ void CQuestLog::init()
 		quests[i].quest->getRolloverText (text, false);
 		if (quests[i].obj)
 			text.addReplacement (quests[i].obj->getHoverText()); //get name of the object
-		CQuestLabel * label = new CQuestLabel (28, 199 + i * 24, FONT_SMALL, TOPLEFT, Colors::WHITE, text.toString());
+		CQuestLabel * label = new CQuestLabel (Rect(28, 199 + i * 24, 172,30), FONT_SMALL, TOPLEFT, Colors::WHITE, text.toString());
 		label->callback = boost::bind(&CQuestLog::selectQuest, this, i);
-		label->setVisibleSize (Rect(0, 0, 172, 30));
 		labels.push_back(label);
 	}
 

+ 2 - 2
client/CQuestLog.h

@@ -38,8 +38,8 @@ class CQuestLabel : public LRClickableAreaWText, public CMultiLineLabel
 public:
 	std::function<void()> callback;
 
-	CQuestLabel (int x=0, int y=0, EFonts Font = FONT_SMALL, EAlignment Align = TOPLEFT, const SDL_Color &Color = Colors::WHITE, const std::string &Text =  "")
-		: CMultiLineLabel (x, y, FONT_SMALL, TOPLEFT, Colors::WHITE, Text){};
+	CQuestLabel (Rect position, EFonts Font = FONT_SMALL, EAlignment Align = TOPLEFT, const SDL_Color &Color = Colors::WHITE, const std::string &Text =  "")
+		: CMultiLineLabel (position, FONT_SMALL, TOPLEFT, Colors::WHITE, Text){};
 	void clickLeft(tribool down, bool previousState);
 	void showAll(SDL_Surface * to);
 };

+ 23 - 10
client/gui/CIntObjectClasses.cpp

@@ -1204,10 +1204,12 @@ void CLabel::setText(const std::string &Txt)
 	}
 }
 
-CMultiLineLabel::CMultiLineLabel(int x, int y, EFonts Font, EAlignment Align, const SDL_Color &Color, const std::string &Text):
-    CLabel(x, y, Font, Align, Color, Text),
-    visibleSize(0, 0, 0, 0)
+CMultiLineLabel::CMultiLineLabel(Rect position, EFonts Font, EAlignment Align, const SDL_Color &Color, const std::string &Text):
+    CLabel(position.x, position.y, Font, Align, Color, Text),
+    visibleSize(0, 0, position.w, position.h)
 {
+	pos.w = position.w;
+	pos.h = position.h;
 	splitText(Text);
 }
 
@@ -1298,9 +1300,20 @@ void CMultiLineLabel::showAll(SDL_Surface * to)
 	const IFont * f = graphics->fonts[font];
 
 	// calculate which lines should be visible
-	size_t totalLines = lines.size();
-	size_t beginLine  = visibleSize.y / f->getLineHeight();
-	size_t endLine    = (getTextLocation().h + visibleSize.y) / f->getLineHeight() + 1;
+	int totalLines = lines.size();
+	int beginLine  = visibleSize.y;
+	int endLine    = getTextLocation().h + visibleSize.y;
+
+	if (beginLine < 0)
+		beginLine = 0;
+	else
+		beginLine /= f->getLineHeight();
+
+	if (endLine < 0)
+		endLine = 0;
+	else
+		endLine /= f->getLineHeight();
+	endLine++;
 
 	// and where they should be displayed
 	Point lineStart = getTextLocation().topLeft() - visibleSize + Point(0, beginLine * f->getLineHeight());
@@ -1308,7 +1321,7 @@ void CMultiLineLabel::showAll(SDL_Surface * to)
 
 	CSDL_Ext::CClipRectGuard guard(to, getTextLocation()); // to properly trim text that is too big to fit
 
-	for (size_t i = beginLine; i < std::min(totalLines, endLine); i++)
+	for (int i = beginLine; i < std::min(totalLines, endLine); i++)
 	{
 		if (!lines[i].empty()) //non-empty line
 			blitLine(to, Rect(lineStart, lineSize), lines[i]);
@@ -1369,11 +1382,11 @@ CTextBox::CTextBox(std::string Text, const Rect &rect, int SliderStyle, EFonts F
     slider(nullptr)
 {
 	OBJ_CONSTRUCTION_CAPTURING_ALL;
-	label = new CMultiLineLabel(rect.x, rect.y, Font, Align, Color);
+	label = new CMultiLineLabel(rect, Font, Align, Color);
 
 	type |= REDRAW_PARENT;
-	label->pos.h = pos.h = rect.h;
-	label->pos.w = pos.w = rect.w;
+	pos.h = rect.h;
+	pos.w = rect.w;
 
 	assert(pos.w >= 40); //we need some space
 	setText(Text);

+ 1 - 1
client/gui/CIntObjectClasses.h

@@ -379,7 +379,7 @@ public:
 	// total size of text, x = longest line of text, y = total height of lines
 	Point textSize;
 
-	CMultiLineLabel(int x=0, int y=0, EFonts Font = FONT_SMALL, EAlignment Align = TOPLEFT, const SDL_Color &Color = Colors::WHITE, const std::string &Text =  "");
+	CMultiLineLabel(Rect position, EFonts Font = FONT_SMALL, EAlignment Align = TOPLEFT, const SDL_Color &Color = Colors::WHITE, const std::string &Text =  "");
 
 	void setText(const std::string &Txt);
 	void showAll(SDL_Surface * to);

+ 3 - 1
config/campaignMedia.json

@@ -125,9 +125,11 @@
 		"H3x2_UAl.smk", //UnholyAlliance_l
  		"H3x2_UAm.smk", //UnholyAlliance_end //H3x2_UAm.bik?
 	],
+
 	"music" : [
-		
+		// Use CmpMusic.txt from H3 instead
 	],
+
 	"voice" : [
 	//Restoration of Erathia
 		"G1A", //Long live the Queen 1 

+ 14 - 0
lib/mapping/CCampaignHandler.cpp

@@ -482,6 +482,20 @@ std::string CCampaignHandler::prologVideoName(ui8 index)
 
 std::string CCampaignHandler::prologMusicName(ui8 index)
 {
+	std::vector<std::string> music;
+
+	VLC->generaltexth->readToVector("Data/CmpMusic.txt", music);
+	if(index < music.size())
+		return music[index];
+	return "";
+}
+
+std::string CCampaignHandler::prologVoiceName(ui8 index)
+{
+	JsonNode config(ResourceID(std::string("CONFIG/campaignMedia"), EResType::TEXT));
+	auto audio = config["voice"].Vector();
+	if(index < audio.size())
+		return audio[index].String();
 	return "";
 }
 

+ 1 - 0
lib/mapping/CCampaignHandler.h

@@ -181,6 +181,7 @@ class DLL_LINKAGE CCampaignHandler
 public:
 	static std::string prologVideoName(ui8 index);
 	static std::string prologMusicName(ui8 index);
+	static std::string prologVoiceName(ui8 index);
 
 	static CCampaignHeader getHeader( const std::string & name); //name - name of appropriate file