Browse Source

Impemented scrollbar for Creature Window. Call it finished.

DjWarmonger 14 years ago
parent
commit
0f60ceb414
2 changed files with 209 additions and 133 deletions
  1. 181 124
      client/CCreatureWindow.cpp
  2. 28 9
      client/CCreatureWindow.h

+ 181 - 124
client/CCreatureWindow.cpp

@@ -21,10 +21,11 @@
 #include <boost/format.hpp>
 #include <boost/bind.hpp>
 #include <boost/foreach.hpp>
-#include <boost/tuple/tuple.hpp>
 
 using namespace CSDL_Ext;
 
+class CBonusItem;
+
 /*
  * CCreatureWindow.cpp, part of VCMI engine
  *
@@ -61,10 +62,65 @@ CCreatureWindow::CCreatureWindow(int Cid, int Type, int creatureCount)
 	delete stack;
 }
 
-void CCreatureWindow::init(const CStackInstance *stack, const CBonusSystemNode *stackNode, const CGHeroInstance *heroOwner)
+CCreatureWindow::CCreatureWindow(const CStackInstance &st, int Type, boost::function<void()> Upg, boost::function<void()> Dsm, UpgradeInfo *ui)
+	: type(Type), dsm(Dsm), dismiss(0), upgrade(0), ok(0)
 {
+	OBJ_CONSTRUCTION_CAPTURING_ALL;
+	init(&st, &st,dynamic_cast<const CGHeroInstance*>(st.armyObj));
+
+	//print abilities text - if r-click popup
+	if(type)
+	{
+		if(Upg && ui)
+		{
+			bool enough = true;
+			for(std::set<std::pair<int,int> >::iterator i=ui->cost[0].begin(); i!=ui->cost[0].end(); i++) //calculate upgrade cost
+			{
+				BLOCK_CAPTURING;
+				if(LOCPLINT->cb->getResourceAmount(i->first) < i->second*st.count)
+					enough = false;
+				upgResCost.push_back(new SComponent(SComponent::resource,i->first,i->second*st.count)); 
+			}
+
+			if(enough)
+			{
+				CFunctionList<void()> fs;
+				fs += Upg;
+				fs += boost::bind(&CCreatureWindow::close,this);
+				CFunctionList<void()> cfl;
+				cfl = boost::bind(&CPlayerInterface::showYesNoDialog, LOCPLINT, CGI->generaltexth->allTexts[207], boost::ref(upgResCost), fs, 0, false);
+				upgrade = new AdventureMapButton("",CGI->generaltexth->zelp[446].second,cfl,385, 148,"IVIEWCR.DEF",SDLK_u);
+			}
+			else
+			{
+				upgrade = new AdventureMapButton("",CGI->generaltexth->zelp[446].second,boost::function<void()>(),385, 148,"IVIEWCR.DEF");
+				upgrade->callback.funcs.clear();
+				upgrade->setOffset(2);
+			}
+
+		}
+		if(Dsm)
+		{
+			CFunctionList<void()> fs[2];
+			//on dismiss confirmed
+			fs[0] += Dsm; //dismiss
+			fs[0] += boost::bind(&CCreatureWindow::close,this);//close this window
+			CFunctionList<void()> cfl;
+			cfl = boost::bind(&CPlayerInterface::showYesNoDialog,LOCPLINT,CGI->generaltexth->allTexts[12],std::vector<SComponent*>(),fs[0],fs[1],false);
+			dismiss = new AdventureMapButton("",CGI->generaltexth->zelp[445].second,cfl,333, 148,"IVIEWCR2.DEF",SDLK_d);
+		}
+	}
+}
+
+void CCreatureWindow::init(const CStackInstance *Stack, const CBonusSystemNode *StackNode, const CGHeroInstance *HeroOwner)
+{
+	stack = Stack;
 	c = stack->type;
-	if(!stackNode) stackNode = c;
+	if(!StackNode)
+		stackNode = c;
+	else
+		stackNode = StackNode;
+	heroOwner = HeroOwner;
 
 	//Basic graphics - need to calculate size
 
@@ -81,24 +137,19 @@ void CCreatureWindow::init(const CStackInstance *stack, const CBonusSystemNode *
 		node.bonuses.remove_if (Selector::typeSybtype(b->type, b->subtype)); //remove used bonuses
 	}
 
-	typedef boost::tuple<std::string,std::string, std::string> skillLine; //jeez
-	std::vector<skillLine> descriptions; //quick, yet slow solution
-	std::string text, text2, bonusGfx;
+	std::string text;
 	BOOST_FOREACH(Bonus* b, bl)
 	{
 		text = stack->bonusToString(b, false);
-		if (text.size())
+		if (text.size()) //if it's possible to give any description for this kind of bonus
 		{
-			text2 = stack->bonusToString(b, true);
-			bonusGfx = stack->bonusToGraphics(b); // may be empty
-			descriptions.push_back(boost::tuple<std::string,std::string, std::string>(text, text2, bonusGfx));
+			bonusItems.push_back (new CBonusItem(genRect(0, 0, 251, 57), text, stack->bonusToString(b, true), stack->bonusToGraphics(b)));
 		}
 	}
 
-	int bonusRows = std::min ((int)((descriptions.size() + 1) / 2), (conf.cc.resy - 230) / 60);
+	bonusRows = std::min ((int)((bonusItems.size() + 1) / 2), (conf.cc.resy - 230) / 60);
 	amin(bonusRows, 4);
 	amax(bonusRows, 1);
-	//TODO: Scroll them
 
 	bitmap = new CPicture("CreWin" + boost::lexical_cast<std::string>(bonusRows) + ".pcx"); //1 to 4 rows for now
 	bitmap->colorizeAndConvert(LOCPLINT->playerID);
@@ -113,10 +164,6 @@ void CCreatureWindow::init(const CStackInstance *stack, const CBonusSystemNode *
 		dismiss = NULL;
 	}
 	anim = new CCreaturePic(22, 48, c);
-	count = boost::lexical_cast<std::string>(stack->count);
-	if (count.size()) //TODO
-		printTo(count, 117, 174, FONT_SMALL, tytulowy,*bitmap);
-	printAtMiddle(c->namePl, 180, 30, FONT_SMALL, tytulowy,*bitmap); //creature name
 
 	//Stats
 	morale = new MoraleLuckBox(true, genRect(42, 42, 335, 100));
@@ -124,20 +171,6 @@ void CCreatureWindow::init(const CStackInstance *stack, const CBonusSystemNode *
 	luck = new MoraleLuckBox(false, genRect(42, 42, 387, 100));
 	luck->set(stack);
 
-	printLine(0, CGI->generaltexth->primarySkillNames[0], c->valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK), stackNode->valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK));
-	printLine(1, CGI->generaltexth->primarySkillNames[1], c->valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE), stackNode->valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE));
-	if(c->shots)
-		printLine(2, CGI->generaltexth->allTexts[198], c->shots);
-
-	//TODO
-	int dmgMultiply = 1;
-	if(heroOwner && stackNode->hasBonusOfType(Bonus::SIEGE_WEAPON))
-		dmgMultiply += heroOwner->Attack(); 
-
-	printLine(3, CGI->generaltexth->allTexts[199], stackNode->getMinDamage() * dmgMultiply, stackNode->getMaxDamage() * dmgMultiply, true);
-	printLine(4, CGI->generaltexth->allTexts[388], c->valOfBonuses(Bonus::STACK_HEALTH), stackNode->valOfBonuses(Bonus::STACK_HEALTH));
-	printLine(6, CGI->generaltexth->zelp[441].first, c->valOfBonuses(Bonus::STACKS_SPEED), stackNode->valOfBonuses(Bonus::STACKS_SPEED));
-
 	new CPicture(graphics->pskillsm->ourImages[4].bitmap, 335, 50, false); //exp icon - Print it always?
 	if (type) //not in fort window
 	{
@@ -178,25 +211,10 @@ void CCreatureWindow::init(const CStackInstance *stack, const CBonusSystemNode *
 				expmin = CGI->creh->expRanks[tier][9];
 				int expmax = CGI->creh->expRanks[tier][10];
 				number = expmax - expmin;
-				boost::replace_first (expText, "%i", boost::lexical_cast<std::string>(number));
+				boost::replace_first (expText, "%i", boost::lexical_cast<std::string>(number)); //Experience after Rank 10 
 				number = (stack->count * (expmax - expmin)) / expmin; 
-				boost::replace_first (expText, "%i", boost::lexical_cast<std::string>(number));
+				boost::replace_first (expText, "%i", boost::lexical_cast<std::string>(number)); //Maximum New Recruits to remain at Rank 10 if at Maximum Experience 
 			
-				//» S t a c k   E x p e r i e n c e   D e t a i l s «
-				//
-				//Creature Type ................... : %s
-				//Experience Rank ................. : %s (%i)
-				//Experience Points ............... : %i
-				//Experience Points to Next Rank .. : %i
-				//Maximum Experience per Battle ... : %i%% (%i)
-				//Number of Creatures in stack .... : %i
-				//Maximum New Recruits
-				// without losing current Rank .... : %i
-				//Experience Multiplier ........... : %.2f
-				//Upgrade Multiplier .............. : %.2f
-				//Experience after Rank 10 ........ : %i
-				//Maximum New Recruits to remain at
-				// Rank 10 if at Maximum Experience : %i
 				expArea = new LRClickableAreaWText(Rect(334, 49, 160, 44), "" , expText );
 			}
 		}
@@ -229,82 +247,16 @@ void CCreatureWindow::init(const CStackInstance *stack, const CBonusSystemNode *
 		printLine (5, CGI->generaltexth->allTexts[200], battleStack->firstHPleft);
 	}
 
-	//All bonuses - abilities
-
-	int i = 0, j = 0;
-	std::string gfxName;
-	BOOST_FOREACH(skillLine p, descriptions)
+	if (bonusItems.size() > (bonusRows << 1)) //only after graphics are created
 	{
-		int offsetx = 257*j;
-		int offsety = 60*i + (bonusRows > 1 ? 1 : 0); //lack of precision :<
-
-		printAt(p.get<0>(), 84 + offsetx, 238 + offsety, FONT_SMALL, tytulowy, *bitmap);
-		printAt(p.get<1>(), 84 + offsetx, 258 + offsety, FONT_SMALL, zwykly, *bitmap);
-		gfxName = p.get<2>();
-		if (gfxName.size())
-		{
-			CPicture * bonusGfx = new CPicture(gfxName, 22 + offsetx, 232 + offsety);
-			bonusGraphics.push_back(bonusGfx);
-		}
-
-		if (++j > 1) //next line
-		{
-			++i;
-			j = 0;
-		}
+		slider = new CSlider(528, 231, bonusRows*60, boost::bind (&CCreatureWindow::sliderMoved, this, _1),
+		bonusRows, (bonusItems.size() + 1) >> 1, 0, false, 0);
 	}
+	else //slider automatically places bonus Items
+		recreateSkillList (0);
 
 	//AUIDAT.DEF
 }
-CCreatureWindow::CCreatureWindow(const CStackInstance &st, int Type, boost::function<void()> Upg, boost::function<void()> Dsm, UpgradeInfo *ui)
-	: type(Type), dsm(Dsm), dismiss(0), upgrade(0), ok(0)
-{
-	OBJ_CONSTRUCTION_CAPTURING_ALL;
-	init(&st, &st,dynamic_cast<const CGHeroInstance*>(st.armyObj));
-
-	//print abilities text - if r-click popup
-	if(type)
-	{
-		if(Upg && ui)
-		{
-			bool enough = true;
-			for(std::set<std::pair<int,int> >::iterator i=ui->cost[0].begin(); i!=ui->cost[0].end(); i++) //calculate upgrade cost
-			{
-				BLOCK_CAPTURING;
-				if(LOCPLINT->cb->getResourceAmount(i->first) < i->second*st.count)
-					enough = false;
-				upgResCost.push_back(new SComponent(SComponent::resource,i->first,i->second*st.count)); 
-			}
-
-			if(enough)
-			{
-				CFunctionList<void()> fs;
-				fs += Upg;
-				fs += boost::bind(&CCreatureWindow::close,this);
-				CFunctionList<void()> cfl;
-				cfl = boost::bind(&CPlayerInterface::showYesNoDialog, LOCPLINT, CGI->generaltexth->allTexts[207], boost::ref(upgResCost), fs, 0, false);
-				upgrade = new AdventureMapButton("",CGI->generaltexth->zelp[446].second,cfl,385, 148,"IVIEWCR.DEF",SDLK_u);
-			}
-			else
-			{
-				upgrade = new AdventureMapButton("",CGI->generaltexth->zelp[446].second,boost::function<void()>(),385, 148,"IVIEWCR.DEF");
-				upgrade->callback.funcs.clear();
-				upgrade->setOffset(2);
-			}
-
-		}
-		if(Dsm)
-		{
-			CFunctionList<void()> fs[2];
-			//on dismiss confirmed
-			fs[0] += Dsm; //dismiss
-			fs[0] += boost::bind(&CCreatureWindow::close,this);//close this window
-			CFunctionList<void()> cfl;
-			cfl = boost::bind(&CPlayerInterface::showYesNoDialog,LOCPLINT,CGI->generaltexth->allTexts[12],std::vector<SComponent*>(),fs[0],fs[1],false);
-			dismiss = new AdventureMapButton("",CGI->generaltexth->zelp[445].second,cfl,333, 148,"IVIEWCR2.DEF",SDLK_d);
-		}
-	}
-}
 
 void CCreatureWindow::printLine(int nr, const std::string &text, int baseVal, int val/*=-1*/, bool range/*=false*/)
 {
@@ -321,12 +273,67 @@ void CCreatureWindow::printLine(int nr, const std::string &text, int baseVal, in
 	printTo(hlp, 325, 64 + nr*19, FONT_SMALL, zwykly, *bitmap);
 }
 
-//void CCreatureWindow::activate()
-//{
-//	CIntObject::activate();
-//	if(type < 3)
-//		activateRClick();
-//}
+void CCreatureWindow::recreateSkillList(int Pos)
+{
+	int n = 0, i = 0, j = 0;
+	int numSkills = std::min ((bonusRows + Pos) << 1, (int)bonusItems.size());
+	std::string gfxName;
+	for (n = 0; n < Pos << 1; ++n)
+	{
+		bonusItems[n]->visible = false;
+	}
+	for (n = Pos << 1; n < numSkills; ++n)
+	{
+		int offsetx = 257*j;
+		int offsety = 60*i + (bonusRows > 1 ? 1 : 0); //lack of precision :/
+
+		bonusItems[n]->moveTo (Point(pos.x + offsetx + 10, pos.y + offsety + 230), true);
+		bonusItems[n]->visible = true;
+
+		if (++j > 1) //next line
+		{
+			++i;
+			j = 0;
+		}
+	}
+	for (n = numSkills; n < bonusItems.size(); ++n)
+	{
+		bonusItems[n]->visible = false;
+	}
+}
+
+void CCreatureWindow::showAll(SDL_Surface * to)
+{
+	CIntObject::showAll(to);
+
+	count = boost::lexical_cast<std::string>(stack->count);
+	if (count.size()) //TODO
+		printTo(count, 117, 174, FONT_SMALL, tytulowy,*bitmap);
+	printAtMiddle(c->namePl, 180, 30, FONT_SMALL, tytulowy,*bitmap); //creature name
+
+	printLine(0, CGI->generaltexth->primarySkillNames[0], c->valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK), stackNode->valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK));
+	printLine(1, CGI->generaltexth->primarySkillNames[1], c->valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE), stackNode->valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE));
+	if(c->shots)
+		printLine(2, CGI->generaltexth->allTexts[198], c->shots);
+
+	//TODO
+	int dmgMultiply = 1;
+	if(heroOwner && stackNode->hasBonusOfType(Bonus::SIEGE_WEAPON))
+		dmgMultiply += heroOwner->Attack(); 
+
+	printLine(3, CGI->generaltexth->allTexts[199], stackNode->getMinDamage() * dmgMultiply, stackNode->getMaxDamage() * dmgMultiply, true);
+	printLine(4, CGI->generaltexth->allTexts[388], c->valOfBonuses(Bonus::STACK_HEALTH), stackNode->valOfBonuses(Bonus::STACK_HEALTH));
+	printLine(6, CGI->generaltexth->zelp[441].first, c->valOfBonuses(Bonus::STACKS_SPEED), stackNode->valOfBonuses(Bonus::STACKS_SPEED));
+
+	BOOST_FOREACH(CBonusItem* b, bonusItems)
+		b->showAll (to);
+}
+
+void CCreatureWindow::sliderMoved(int newpos)
+{
+	recreateSkillList(newpos); //move components
+	redraw();
+}
 
 void CCreatureWindow::scrollArt(int dir)
 {
@@ -340,6 +347,18 @@ void CCreatureWindow::clickRight(tribool down, bool previousState)
 		close();
 }
 
+//void CCreatureWindow::activate()
+//{
+//	CIntObject::activate();
+//	if(type < 3)
+//		activateRClick();
+//}
+
+//void CCreatureWindow::deactivate()
+//{
+//
+//}
+
 void CCreatureWindow::close()
 {
 	GH.popIntTotally(this);
@@ -349,4 +368,42 @@ CCreatureWindow::~CCreatureWindow()
 {
  	for (int i=0; i<upgResCost.size(); ++i)
  		delete upgResCost[i];
+	bonusItems.clear();
+}
+
+CBonusItem::CBonusItem()
+{
+
+}
+
+CBonusItem::CBonusItem(const Rect &Pos, const std::string &Name, const std::string &Description, const std::string &graphicsName)
+{
+	OBJ_CONSTRUCTION;
+	SHARE_POS;
+	visible = false;
+
+	name = Name;
+	description = Description;
+	if (graphicsName.size())
+		bonusGraphics = new CPicture(graphicsName, 26, 232);
+	else
+		bonusGraphics = NULL;
+
+	used = 0; //no actions atm
+}
+
+void CBonusItem::showAll (SDL_Surface * to)
+{
+	if (visible)
+	{
+		printAt(name, pos.x + 72, pos.y + 6, FONT_SMALL, tytulowy, to);
+		printAt(description, pos.x + 72, pos.y + 30, FONT_SMALL, zwykly, to);
+		if (bonusGraphics && bonusGraphics->bg)
+			blitAtLoc(bonusGraphics->bg, 12, 2, to);
+	}
+}
+
+CBonusItem::~CBonusItem()
+{
+	//delete bonusGraphics; //automatic destruction
 }

+ 28 - 9
client/CCreatureWindow.h

@@ -18,6 +18,7 @@ class CCreature;
 class CStackInstance;
 class CStack;
 class AdventureMapButton;
+class CBonusItem;
 
 class CCreatureWindow : public CIntObject
 {
@@ -25,40 +26,58 @@ public:
 	enum CreWinType {OTHER = 0, BATTLE = 1, ARMY = 2, HERO = 3}; //only last one should open permanently
 	//bool active; //TODO: comment me
 	int type;//0 - rclick popup; 1 - normal window
-	CPicture *bitmap; //background
-	std::string count; //creature count in text format
+	int bonusRows; //height of skill window
 
-	boost::function<void()> dsm; //dismiss button callback
-	boost::function<void()> Upg; //upgrade button callback
-	CCreaturePic *anim; //related creature's animation
+	std::string count; //creature count in text format
 	const CCreature *c; //related creature
+	const CStackInstance *stack;
+	const CBonusSystemNode *stackNode;
+	const CGHeroInstance *heroOwner;
 	std::vector<SComponent*> upgResCost; //cost of upgrade (if not possible then empty)
-	std::vector<CPicture*> bonusGraphics;
+	std::vector<CBonusItem*> bonusItems;
 
+	CPicture *bitmap; //background
+	CCreaturePic *anim; //related creature's animation
 	MoraleLuckBox *luck, *morale;
 	LRClickableAreaWText * expArea; //displays exp details
 	CArtPlace *creatureArtifact;
-
 	CSlider * slider; //Abilities
 	AdventureMapButton *dismiss, *upgrade, *ok;
 	AdventureMapButton * leftArtRoll, * rightArtRoll; //artifact selection
 	//TODO: Arifact drop
 
+	boost::function<void()> dsm; //dismiss button callback
+	boost::function<void()> Upg; //upgrade button callback
+
 	CCreatureWindow(const CStack & stack, int type); //battle c-tor
 	CCreatureWindow (const CStackInstance &stack, int Type); //pop-up c-tor
 	CCreatureWindow(const CStackInstance &st, int Type, boost::function<void()> Upg, boost::function<void()> Dsm, UpgradeInfo *ui); //full garrison window
 	CCreatureWindow(int Cid, int Type, int creatureCount); //c-tor
 	void init(const CStackInstance *stack, const CBonusSystemNode *stackNode, const CGHeroInstance *heroOwner);
+	void showAll(SDL_Surface * to);
 	void printLine(int nr, const std::string &text, int baseVal, int val=-1, bool range=false);
+	void recreateSkillList(int pos);
 	~CCreatureWindow(); //d-tor
 	//void activate();
+	//void deactivate();
 	void close();
 	void clickRight(tribool down, bool previousState); //call-in
+	void sliderMoved(int newpos);
 	//void keyPressed (const SDL_KeyboardEvent & key); //call-in
 	void scrollArt(int dir);
 };
 
-class CBonusItem : LRClickableAreaWTextComp //responsible for displaying creature skill, active or not
+class CBonusItem : public LRClickableAreaWTextComp //responsible for displaying creature skill, active or not
 {
-	const Bonus * bonus;
+public:
+	std::string name, description;
+	CPicture * bonusGraphics;
+	bool visible;
+
+	CBonusItem();
+	CBonusItem(const Rect &Pos, const std::string &Name, const std::string &Description, const std::string &graphicsName);
+	~CBonusItem();
+
+	void setBonus (const Bonus &bonus);
+	void showAll (SDL_Surface * to);
 };