Ver Fonte

- fixed text duplication in choice windows
- fixed compile issues
- added unused and untested for now CComponentBox

Ivan Savenko há 13 anos atrás
pai
commit
235cf458d7

+ 3 - 2
AI/VCAI/VCAI.cpp

@@ -993,7 +993,8 @@ void VCAI::makeTurnInternal()
 		std::vector<std::pair<HeroPtr, CGoal> > safeCopy;
 		boost::copy(lockedHeroes, std::back_inserter(safeCopy));
 
-		typedef decltype(*safeCopy.begin()) TItrType;
+		typedef std::pair<HeroPtr, CGoal> TItrType;
+
 		auto lockedHeroesSorter = [](TItrType h1, TItrType h2) -> bool
 		{
 			return compareMovement (h1.first, h2.first);
@@ -2308,7 +2309,7 @@ int3 whereToExplore(HeroPtr h)
 	}
 	catch(cannotFulfillGoalException &e)
 	{
-		std::vector<std::vector<int3> > tiles; //tiles[distance_to_fow], metryka taksówkowa
+		std::vector<std::vector<int3> > tiles; //tiles[distance_to_fow], metryka taksówkowa
 		try
 		{
 			return ai->explorationNewPoint(radius, h, tiles);

+ 1 - 1
client/AdventureMapClasses.cpp

@@ -791,7 +791,7 @@ void CInfoBar::CVisibleInfo::loadComponent(const Component compToDisplay, std::s
 	comp->moveTo(Point(pos.x+52, pos.y+54));
 
 	new CTextBox(message, Rect(8, 8, 164, 50), 0, FONT_SMALL, CENTER, Colors::Cornsilk);
-	new CLabel(91, 158, FONT_SMALL, CENTER, Colors::Cornsilk, comp->subtitle);
+	new CLabel(91, 158, FONT_SMALL, CENTER, Colors::Cornsilk, comp->getSubtitle());
 }
 
 void CInfoBar::CVisibleInfo::updateEnemyTurn(double progress)

+ 2 - 1
client/CMT.cpp

@@ -338,7 +338,8 @@ void printInfoAboutIntObject(const CIntObject *obj, int level)
 	}
 	else
 		tlog4 << "inactive";
-	tlog4 << " at " << obj->pos.x <<"x"<< obj->pos.y << "\n";
+	tlog4 << " at " << obj->pos.x <<"x"<< obj->pos.y;
+	tlog4 << " (" << obj->pos.w <<"x"<< obj->pos.h << ")\n";
 
 	BOOST_FOREACH(const CIntObject *child, obj->children)
 		printInfoAboutIntObject(child, level+1);

+ 2 - 27
client/CMessage.cpp

@@ -42,7 +42,6 @@ template <typename T, typename U> std::pair<T,U> max(const std::pair<T,U> &x, co
 //One image component + subtitles below it
 class ComponentResolved : public CIntObject
 {
-	std::vector<std::vector<SDL_Surface*> > * txt;
 public:
 	CComponent *comp;
 
@@ -536,17 +535,8 @@ ComponentResolved::ComponentResolved( CComponent *Comp ):
 	defActions = 255 - DISPOSE;
 	pos.x = pos.y = 0;
 
-	int textHeight = 0;
-	std::vector<std::string> textLines = CMessage::breakText(comp->subtitle, 14); //text
-	txt = CMessage::drawText(&textLines, textHeight, FONT_SMALL);
-
-	//calculate dimensions
-	std::pair<int,int> textSize = CMessage::getMaxSizes(txt, textHeight);
-	pos.w = std::max<int>(textSize.first, comp->pos.w); //bigger of: subtitle width and image width
-
-	pos.h = comp->pos.h + COMPONENT_TO_SUBTITLE + textSize.second;
-
-	comp->moveTo(Point((pos.w - comp->pos.w)/2, 0));
+	pos.w = comp->pos.w;
+	pos.h = comp->pos.h;
 }
 
 ComponentResolved::~ComponentResolved()
@@ -556,27 +546,12 @@ ComponentResolved::~ComponentResolved()
 		removeChild(comp);
 		parent->addChild(comp);
 	}
-
-	for(size_t i = 0; i < txt->size(); i++)
-		for(size_t j = 0; j < (*txt)[i].size(); j++)
-			if((*txt)[i][j])
-				SDL_FreeSurface((*txt)[i][j]);
-	delete txt;
 }
 
 void ComponentResolved::showAll(SDL_Surface *to)
 {
-	int fontHeight;
-	if (graphics->fontsTrueType[FONT_SMALL])
-		fontHeight = TTF_FontHeight(graphics->fontsTrueType[FONT_SMALL]);
-	else
-		fontHeight = graphics->fonts[FONT_SMALL]->height;
-
 	CIntObject::showAll(to);
 	comp->showAll(to);
-
-	int textY = pos.y + comp->pos.h + COMPONENT_TO_SUBTITLE;
-	CMessage::blitTextOnSur(txt, fontHeight, textY, to, pos.x + pos.w/2 );
 }
 
 ComponentsToBlit::~ComponentsToBlit()

+ 6 - 1
client/CVideoHandler.cpp

@@ -657,7 +657,7 @@ CVideoPlayer::CVideoPlayer()
 	// TODO: URL protocol marked as deprecated in favor of avioContext
 	// VCMI should to it if URL protocol will be removed from ffmpeg or
 	// when new avioContext will be available in all distros (ETA: late 2012)
-#ifdef WITH_AV_REGISTER_PROTOCOL2
+#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(52, 69, 0)
 	av_register_protocol2(&lod_protocol, sizeof(lod_protocol));
 #else
 	av_register_protocol(&lod_protocol);
@@ -846,7 +846,12 @@ bool CVideoPlayer::nextFrame()
 			if (packet.stream_index == stream)
 			{
 				// Decode video frame
+
+#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(52, 25, 0)
+				avcodec_decode_video(codecContext, frame, &frameFinished, packet.data, packet.size);
+#else
 				avcodec_decode_video2(codecContext, frame, &frameFinished, &packet);
+#endif
 
 				// Did we get a video frame?
 				if (frameFinished)

+ 171 - 36
client/GUIClasses.cpp

@@ -768,46 +768,67 @@ void CInfoPopup::init(int x, int y)
 	vstd::amin(pos.y, screen->h - bitmap->h);
 }
 
-CComponent::CComponent(Etype Type, int Subtype, int Val):
-	image(nullptr)
+CComponent::CComponent(Etype Type, int Subtype, int Val, bool showSubtitles):
+	image(nullptr),
+    perDay(false)
 {
 	addUsedEvents(RCLICK);
-	init(Type,Subtype,Val);
+	init(Type, Subtype, Val, showSubtitles);
 }
 
 CComponent::CComponent(const Component &c):
-	image(nullptr)
+	image(nullptr),
+    perDay(false)
 {
 	addUsedEvents(RCLICK);
 
+	if(c.id == Component::RESOURCE && c.when==-1)
+		perDay = true;
+
 	if(c.id == Component::EXPERIENCE)
-		init(experience,c.subtype,c.val);
+		init(experience,c.subtype,c.val, true);
 	else if(c.id == Component::SPELL)
-		init(spell,c.subtype,c.val);
+		init(spell,c.subtype,c.val, true);
 	else
-		init((Etype)c.id,c.subtype,c.val);
-
-	if(c.id == Component::RESOURCE && c.when==-1)
-		subtitle += CGI->generaltexth->allTexts[3].substr(2,CGI->generaltexth->allTexts[3].length()-2);
+		init((Etype)c.id,c.subtype,c.val, true);
 }
 
-void CComponent::init(Etype Type, int Subtype, int Val)
+void CComponent::init(Etype Type, int Subtype, int Val, bool showSubtitles)
 {
-	type = Type;
+	OBJ_CONSTRUCTION_CAPTURING_ALL;
+
+	compType = Type;
 	subtype = Subtype;
 	val = Val;
 
-	subtitle = getSubtitle();
-	description = getDescription();
 	setSurface(getFileName(), getIndex());
 
 	pos.w = image->pos.w;
 	pos.h = image->pos.h;
+
+	if (showSubtitles)
+	{
+		pos.h += 4; //distance between text and image
+
+		std::vector<std::string> textLines = CMessage::breakText(getSubtitle(), std::max<int>(64, pos.w), FONT_SMALL);
+		BOOST_FOREACH(auto & line, textLines)
+		{
+			int height = graphics->fonts[FONT_SMALL]->height;
+			CLabel * label = new CLabel(pos.w/2, pos.h + height/2, FONT_SMALL, CENTER, Colors::Cornsilk, line);
+
+			pos.h += height;
+			if (label->pos.w > pos.w)
+			{
+				pos.x -= (label->pos.w - pos.w)/2;
+				pos.w = label->pos.w;
+			}
+		}
+	}
 }
 
 std::string CComponent::getFileName()
 {
-	switch(type)
+	switch(compType)
 	{
 	case primskill:  return "PSKILL";
 	case secskill:   return "SECSK82";
@@ -824,12 +845,12 @@ std::string CComponent::getFileName()
 	case flag:       return "CREST58";
 	}
 	assert(0);
-	return 0;
+	return "";
 }
 
 size_t CComponent::getIndex()
 {
-	switch(type)
+	switch(compType)
 	{
 	case primskill:  return subtype;
 	case secskill:   return subtype*3 + 3 + val - 1;
@@ -851,7 +872,7 @@ size_t CComponent::getIndex()
 
 std::string CComponent::getDescription()
 {
-	switch (type)
+	switch (compType)
 	{
 	case primskill:  return (subtype < 4)? CGI->generaltexth->arraytxt[2+subtype] //Primary skill
 	                                     : CGI->generaltexth->allTexts[149]; //mana
@@ -869,13 +890,23 @@ std::string CComponent::getDescription()
 	case flag:       return "";
 	}
 	assert(0);
-	return 0;
+	return "";
 }
 
 std::string CComponent::getSubtitle()
+{
+	if (!perDay)
+		return getSubtitleInternal();
+
+	std::string ret = CGI->generaltexth->allTexts[3];
+	boost::replace_first(ret, "%d", getSubtitleInternal());
+	return ret;
+}
+
+std::string CComponent::getSubtitleInternal()
 {
 	//FIXME: some of these are horrible (e.g creature)
-	switch(type)
+	switch(compType)
 	{
 	case primskill:  return boost::str(boost::format("%+d %s") % val % (subtype < 4 ? CGI->generaltexth->primarySkillNames[subtype] : CGI->generaltexth->allTexts[387]));
 	case secskill:   return CGI->generaltexth->levels[val-1] + " " + CGI->generaltexth->skillName[subtype];
@@ -904,8 +935,8 @@ void CComponent::setSurface(std::string defName, int imgPos)
 
 void CComponent::clickRight(tribool down, bool previousState)
 {
-	if(description.size())
-		adventureInt->handleRightClick(description,down);
+	if(!getDescription().empty())
+		adventureInt->handleRightClick(getDescription(), down);
 }
 
 void CSelectableComponent::clickLeft(tribool down, bool previousState)
@@ -925,6 +956,7 @@ void CSelectableComponent::init()
 CSelectableComponent::CSelectableComponent(const Component &c, boost::function<void()> OnSelect):
 	CComponent(c),onSelect(OnSelect)
 {
+	type |= REDRAW_PARENT;
 	addUsedEvents(LCLICK | KEYBOARD);
 	init();
 }
@@ -932,36 +964,139 @@ CSelectableComponent::CSelectableComponent(const Component &c, boost::function<v
 CSelectableComponent::CSelectableComponent(Etype Type, int Sub, int Val, boost::function<void()> OnSelect):
 	CComponent(Type,Sub,Val),onSelect(OnSelect)
 {
+	type |= REDRAW_PARENT;
 	addUsedEvents(LCLICK | KEYBOARD);
 	init();
 }
 
-CSelectableComponent::~CSelectableComponent()
-{
-}
-
 void CSelectableComponent::select(bool on)
 {
 	if(on != selected)
 	{
 		selected = on;
-		return;
+		redraw();
 	}
-	else
+}
+
+void CSelectableComponent::showAll(SDL_Surface * to)
+{
+	CComponent::showAll(to);
+	if(selected)
 	{
-		return;
+		CSDL_Ext::drawBorder(to, Rect::around(image->pos), int3(239,215,123));
 	}
 }
 
-void CSelectableComponent::show(SDL_Surface * to)
+void CComponentBox::selectionChanged(CSelectableComponent * newSelection)
 {
-	CComponent::show(to);
-	if(selected)
+	assert(newSelection != selected);
+
+	if (selected)
+		selected->select(false);
+
+	selected = newSelection;
+	onSelect(selectedIndex());
+
+	if (selected)
+		selected->select(true);
+}
+
+int CComponentBox::selectedIndex()
+{
+	if (selected)
+		return std::find(components.begin(), components.end(), selected) - components.begin();
+	return -1;
+}
+
+void CComponentBox::placeComponents(bool selectable)
+{
+	if (components.empty())
+		return;
+
+	static const int betweenComponents = 50;
+	static const int betweenRows = 22;
+
+	//prepare components
+	BOOST_FOREACH(auto & comp, components)
+	{
+		addChild(comp);
+		comp->moveTo(Point(pos.x, pos.y));
+	}
+
+	struct RowData
+	{
+		size_t comps;
+		int width;
+		int height;
+	};
+	std::vector<RowData> rows;
+	rows.push_back({0, 0, 0});
+
+	//split components in rows
+	BOOST_FOREACH(auto & comp, components)
 	{
-		CSDL_Ext::drawBorder(to, Rect::around(Rect(pos.x, pos.y, image->pos.w, image->pos.h)), int3(239,215,123));
+		//make sure that components are smaller than our width
+		assert(pos.w == 0 || pos.w < comp->pos.w);
+
+		//start next row
+		if (pos.w != 0 && rows.back().width + comp->pos.w > pos.w)
+			rows.push_back({0, 0, 0});
+
+		rows.back().comps++;
+		rows.back().width += comp->pos.w;
+		vstd::amax(rows.back().height, comp->pos.h);
+	}
+
+	if (pos.w == 0)
+	{
+		BOOST_FOREACH(auto & row, rows)
+			vstd::amax(pos.w, row.width + (row.comps - 1) * betweenComponents);
 	}
 
-	printAtMiddleWB(subtitle,pos.x+pos.w/2,pos.y+pos.h+25,FONT_SMALL,14,Colors::Cornsilk,to);
+	int height = (rows.size() - 1) * betweenRows;
+	BOOST_FOREACH(auto & row, rows)
+		height += row.height;
+
+	assert(pos.h == 0 || pos.h < height);
+	if (pos.h == 0)
+		pos.h = height;
+
+	auto iter = components.begin();
+	int currentY = (pos.h - height) / 2;
+
+	//move components to their positions
+	for (size_t row = 0; row < rows.size(); row++)
+	{
+		int currentX = (pos.w - rows[row].width) / 2;
+		for (size_t col = 0; col < rows[row].comps; col++)
+		{
+			(*iter)->moveBy(Point(currentX, currentY));
+			currentX += (*iter)->pos.w + betweenComponents;
+			iter++;
+		}
+		currentY += rows[row].height + betweenRows;
+	}
+}
+
+CComponentBox::CComponentBox(CComponent * _components, Rect position):
+    components(1, _components),
+    selected(nullptr)
+{
+	placeComponents(false);
+}
+
+CComponentBox::CComponentBox(std::vector<CComponent *> _components, Rect position):
+    components(_components),
+    selected(nullptr)
+{
+	placeComponents(false);
+}
+
+CComponentBox::CComponentBox(std::vector<CSelectableComponent *> _components, Rect position, boost::function<void(int newID)> _onSelect):
+    components(_components.begin(), _components.end()),
+    selected(nullptr)
+{
+	placeComponents(true);
 }
 
 void CSelWindow::selectionChange(unsigned to)
@@ -1453,9 +1588,9 @@ CLevelWindow::CLevelWindow(const CGHeroInstance *hero, int pskill, std::vector<u
 		comps[i]->moveTo(Point(pos.x + curx, pos.y + 326));
 		if( i < (comps.size()-1) )
 		{
-			curx += 44+21; //skill width + margin to "or"
+			curx += comps[i]->pos.w + 10; //skill width + margin to "or"
 			new CLabel(curx, 346, FONT_MEDIUM, CENTER, Colors::Cornsilk, text);
-			curx += fontWidth+15;
+			curx += fontWidth+10;
 		}
 	}
 

+ 51 - 17
client/GUIClasses.h

@@ -173,46 +173,80 @@ public:
 /// common popup window component
 class CComponent : public virtual CIntObject
 {
+public:
+	enum Etype
+	{
+		primskill, secskill, resource, creature, artifact, experience, secskill44, spell, morale, luck, building, hero, flag
+	};
+
+private:
 	size_t getIndex();
 	std::string getFileName();
-	std::string getDescription();
-	std::string getSubtitle();
+	void setSurface(std::string defName, int imgPos);
+	std::string getSubtitleInternal();
+
+	void init(Etype Type, int Subtype, int Val, bool showSubtitles);
 
 protected:
 	CAnimImage *image; //our image
-	void setSurface(std::string defName, int imgPos);
 
 public:
-	enum Etype
-	{
-		primskill, secskill, resource, creature, artifact, experience, secskill44, spell, morale, luck, building, hero, flag
-	} type; //component type
-	int subtype; //TODO: comment me
-	int val; //TODO: comment me
+	Etype compType; //component type
+	int subtype; //type-dependant subtype. See getSomething methods for details
+	int val; // value \ strength \ amount of component. See getSomething methods for details
+	bool perDay; // add "per day" text to subtitle
 
-	std::string description; //r-click
-	std::string subtitle; //TODO: comment me
+	std::string getDescription();
+	std::string getSubtitle();
 
-	void init(Etype Type, int Subtype, int Val);
-	CComponent(Etype Type, int Subtype, int Val); //c-tor
+	CComponent(Etype Type, int Subtype, int Val, bool showSubtitles = true); //c-tor
 	CComponent(const Component &c); //c-tor
 
 	void clickRight(tribool down, bool previousState); //call-in
 };
 
+/// component that can be selected or deselected
 class CSelectableComponent : public CComponent, public CKeyShortcut
 {
+	void init();
 public:
 	bool selected; //if true, this component is selected
 	boost::function<void()> onSelect; //function called on selection change
 
+	void showAll(SDL_Surface * to);
+	void select(bool on);
+
 	void clickLeft(tribool down, bool previousState); //call-in
-	void init();
 	CSelectableComponent(Etype Type, int Sub, int Val, boost::function<void()> OnSelect = 0); //c-tor
 	CSelectableComponent(const Component &c, boost::function<void()> OnSelect = 0); //c-tor
-	~CSelectableComponent(); //d-tor
-	virtual void show(SDL_Surface * to);
-	void select(bool on);
+};
+
+/// box with multiple components (up to 8?)
+/// will take ownership on components and delete them afterwards
+class CComponentBox : public CIntObject
+{
+	std::vector<CComponent *> components;
+
+	CSelectableComponent * selected;
+	boost::function<void(int newID)> onSelect;
+
+	void selectionChanged(CSelectableComponent * newSelection);
+	void placeComponents(bool selectable);
+
+public:
+	/// return index of selected item
+	int selectedIndex();
+
+	/// constructor for quite common 1-components popups
+	/// if position width or height are 0 then it will be determined automatically
+	CComponentBox(CComponent * components, Rect position);
+	/// constructor for non-selectable components
+	CComponentBox(std::vector<CComponent *> components, Rect position);
+
+	/// constructor for selectable components
+	/// will also create "or" labels between components
+	/// onSelect - optional function that will be called every time on selection change
+	CComponentBox(std::vector<CSelectableComponent *> components, Rect position, boost::function<void(int newID)> onSelect = 0);
 };
 
 ////////////////////////////////////////////////////////////////////////////////

+ 1 - 1
config/creatures.json

@@ -1954,7 +1954,7 @@
 				"name": [ "Sorceress" ],
 				"faction": -1,
 				"defname": "ZM193Z.DEF",
-				"projectile_defname": "SMBALX.DEF",
+				"projectile_defname": "CPRZEAX.DEF",
 				"projectile_spin": false
 			},