浏览代码

* @previous revision: not an AI bug, it was a vector traversing bug. Fixed :-)
* Scrolling through scenario list with mouse wheel, HOME, END, PAGE UP and PAGE DOWN buttons
* Starting selected scenario with double-click

Michał W. Urbańczyk 16 年之前
父节点
当前提交
1f79af440f
共有 5 个文件被更改,包括 185 次插入37 次删除
  1. 53 7
      client/CPreGame.cpp
  2. 3 0
      client/CPreGame.h
  3. 96 22
      client/GUIBase.cpp
  4. 28 3
      client/GUIBase.h
  5. 5 5
      hch/CObjectHandler.cpp

+ 53 - 7
client/CPreGame.cpp

@@ -436,7 +436,7 @@ SelectionTab::SelectionTab(EState Type, const boost::function<void(CMapInfo *)>
 	OBJ_CONSTRUCTION;
 	selectionPos = 0;
 
-	used = LCLICK;
+	used = LCLICK | WHEEL | KEYBOARD | DOUBLECLICK;
 	slider = NULL;
 	type = Type;
 	std::vector<FileInfo> toParse;
@@ -528,13 +528,18 @@ void SelectionTab::select( int position )
 {
 	// New selection. py is the index in curItems.
 	int py = position + slider->value;
-	if (py < curItems.size()) 
-	{
-		CGI->soundh->playSound(soundBase::button);
-		selectionPos = py;
+	amax(py, 0);
+	amin(py, curItems.size()-1);
 
-		onSelect(curItems[py]);
-	}
+	CGI->soundh->playSound(soundBase::button);
+	selectionPos = py;
+
+	if(position < 0)
+		slider->moveTo(slider->value + position);
+	else if(position >= positions)
+		slider->moveTo(slider->value + position - positions + 1);
+
+	onSelect(curItems[py]);
 }
 
 int SelectionTab::getPosition( int x, int y )
@@ -667,6 +672,47 @@ void SelectionTab::clickLeft( tribool down, bool previousState )
 	}
 }
 
+void SelectionTab::wheelScrolled( bool down, bool in )
+{
+	slider->moveTo(slider->value + 3 * (down ? +1 : -1));
+	//select(selectionPos - slider->value + (down ? +1 : -1));
+}
+
+void SelectionTab::keyPressed( const SDL_KeyboardEvent & key )
+{
+	if(key.state != SDL_PRESSED) return;
+
+	int moveBy = 0;
+	switch(key.keysym.sym)
+	{
+	case SDLK_UP:
+		moveBy = -1;
+		break;
+	case SDLK_DOWN:
+		moveBy = +1;
+		break;
+	case SDLK_PAGEUP:
+		moveBy = -positions+1;
+		break;
+	case SDLK_PAGEDOWN:
+		moveBy = +positions-1; 
+		break;
+	case SDLK_HOME:
+		select(-slider->value);
+		return;
+	case SDLK_END:
+		select(curItems.size() - slider->value);
+		return;
+	}
+	select(selectionPos - slider->value + moveBy); 
+}
+
+void SelectionTab::onDoubleClick()
+{
+	//act as start button was pressed
+	(static_cast<CSelectionScreen*>(parent))->start->callback();
+}
+
 InfoCard::InfoCard( EState Type )
 {
 	OBJ_CONSTRUCTION;

+ 3 - 0
client/CPreGame.h

@@ -96,6 +96,9 @@ public:
 
 	void showAll(SDL_Surface * to);
 	void clickLeft(tribool down, bool previousState);
+	void wheelScrolled(bool down, bool in);
+	void keyPressed(const SDL_KeyboardEvent & key);
+	void onDoubleClick();
 	SelectionTab(EState Type, const boost::function<void(CMapInfo *)> &OnSelect);
 	~SelectionTab();
 };

+ 96 - 22
client/GUIBase.cpp

@@ -178,17 +178,61 @@ void CGuiHandler::handleEvent(SDL_Event *sEvent)
 		CGI->curh->cursorMove(sEvent->motion.x, sEvent->motion.y);
 		handleMouseMotion(sEvent);
 	}
-	else if ((sEvent->type==SDL_MOUSEBUTTONDOWN) && (sEvent->button.button == SDL_BUTTON_LEFT))
+	else if (sEvent->type==SDL_MOUSEBUTTONDOWN)
 	{
-		std::list<CIntObject*> hlp = lclickable;
-		for(std::list<CIntObject*>::iterator i=hlp.begin(); i != hlp.end();i++)
+		if(sEvent->button.button == SDL_BUTTON_LEFT)
 		{
-			if(!vstd::contains(lclickable,*i)) continue;
-			if (isItIn(&(*i)->pos,sEvent->motion.x,sEvent->motion.y))
+			
+			if(lastClick == sEvent->motion  &&  (SDL_GetTicks() - lastClickTime) < 300)
+			{
+				std::list<CIntObject*> hlp = doubleClickInterested;
+				for(std::list<CIntObject*>::iterator i=hlp.begin(); i != hlp.end();i++)
+				{
+					if(!vstd::contains(doubleClickInterested,*i)) continue;
+					if (isItIn(&(*i)->pos,sEvent->motion.x,sEvent->motion.y))
+					{
+						(*i)->onDoubleClick();
+					}
+				}
+
+			}
+
+			lastClick = sEvent->motion;
+			lastClickTime = SDL_GetTicks();
+
+			std::list<CIntObject*> hlp = lclickable;
+			for(std::list<CIntObject*>::iterator i=hlp.begin(); i != hlp.end();i++)
 			{
-				prev = (*i)->pressedL;
-				(*i)->pressedL = true;
-				(*i)->clickLeft(true, prev);
+				if(!vstd::contains(lclickable,*i)) continue;
+				if (isItIn(&(*i)->pos,sEvent->motion.x,sEvent->motion.y))
+				{
+					prev = (*i)->pressedL;
+					(*i)->pressedL = true;
+					(*i)->clickLeft(true, prev);
+				}
+			}
+		}
+		else if (sEvent->button.button == SDL_BUTTON_RIGHT)
+		{
+			std::list<CIntObject*> hlp = rclickable;
+			for(std::list<CIntObject*>::iterator i=hlp.begin(); i != hlp.end();i++)
+			{
+				if(!vstd::contains(rclickable,*i)) continue;
+				if (isItIn(&(*i)->pos,sEvent->motion.x,sEvent->motion.y))
+				{
+					prev = (*i)->pressedR;
+					(*i)->pressedR = true;
+					(*i)->clickRight(true, prev);
+				}
+			}
+		}
+		else if(sEvent->button.button == SDL_BUTTON_WHEELDOWN || sEvent->button.button == SDL_BUTTON_WHEELUP)
+		{
+			std::list<CIntObject*> hlp = wheelInterested;
+			for(std::list<CIntObject*>::iterator i=hlp.begin(); i != hlp.end();i++)
+			{
+				if(!vstd::contains(wheelInterested,*i)) continue;
+				(*i)->wheelScrolled(sEvent->button.button == SDL_BUTTON_WHEELDOWN, isItIn(&(*i)->pos,sEvent->motion.x,sEvent->motion.y));
 			}
 		}
 	}
@@ -208,20 +252,6 @@ void CGuiHandler::handleEvent(SDL_Event *sEvent)
 				(*i)->clickLeft(boost::logic::indeterminate, prev);
 		}
 	}
-	else if ((sEvent->type==SDL_MOUSEBUTTONDOWN) && (sEvent->button.button == SDL_BUTTON_RIGHT))
-	{
-		std::list<CIntObject*> hlp = rclickable;
-		for(std::list<CIntObject*>::iterator i=hlp.begin(); i != hlp.end();i++)
-		{
-			if(!vstd::contains(rclickable,*i)) continue;
-			if (isItIn(&(*i)->pos,sEvent->motion.x,sEvent->motion.y))
-			{
-				prev = (*i)->pressedR;
-				(*i)->pressedR = true;
-				(*i)->clickRight(true, prev);
-			}
-		}
-	}
 	else if ((sEvent->type==SDL_MOUSEBUTTONUP) && (sEvent->button.button == SDL_BUTTON_RIGHT))
 	{
 		std::list<CIntObject*> hlp = rclickable;
@@ -455,6 +485,10 @@ void CIntObject::activate()
 		activateKeys();
 	if(used & TIME)
 		activateTimer();
+	if(used & WHEEL)
+		activateWheel();
+	if(used & DOUBLECLICK)
+		activateDClick();
 
 	if(defActions & ACTIVATE)
 		for(size_t i = 0; i < children.size(); i++)
@@ -478,6 +512,10 @@ void CIntObject::deactivate()
 		deactivateKeys();
 	if(used & TIME)
 		deactivateTimer();
+	if(used & WHEEL)
+		deactivateWheel();
+	if(used & DOUBLECLICK)
+		deactivateDClick();
 
 	if(defActions & DEACTIVATE)
 		for(size_t i = 0; i < children.size(); i++)
@@ -546,6 +584,42 @@ bool CIntObject::isItInLoc( const SDL_Rect &rect, const Point &p )
 	return isItIn(&rect, p.x - pos.x, p.y - pos.y);
 }
 
+void CIntObject::activateWheel()
+{
+	GH.wheelInterested.push_front(this);
+	active |= WHEEL;
+}
+
+void CIntObject::deactivateWheel()
+{
+	std::list<CIntObject*>::iterator hlp = std::find(GH.wheelInterested.begin(),GH.wheelInterested.end(),this);
+	assert(hlp != GH.wheelInterested.end());
+	GH.wheelInterested.erase(hlp);
+	active &= ~WHEEL;
+}
+
+void CIntObject::wheelScrolled(bool down, bool in)
+{
+}
+
+void CIntObject::activateDClick()
+{
+	GH.doubleClickInterested.push_front(this);
+	active |= DOUBLECLICK;
+}
+
+void CIntObject::deactivateDClick()
+{
+	std::list<CIntObject*>::iterator hlp = std::find(GH.doubleClickInterested.begin(),GH.doubleClickInterested.end(),this);
+	assert(hlp != GH.doubleClickInterested.end());
+	GH.doubleClickInterested.erase(hlp);
+	active &= ~DOUBLECLICK;
+}
+
+void CIntObject::onDoubleClick()
+{
+}
+
 CPicture::CPicture( SDL_Surface *BG, int x, int y, bool Free )
 {
 	bg = BG; 

+ 28 - 3
client/GUIBase.h

@@ -93,6 +93,16 @@ struct Point
 	{
 		return x < b.x   &&   y < b.y;
 	}
+	template<typename T> Point& operator=(const T &t)
+	{
+		x = t.x;
+		y = t.y;
+		return *this;
+	}
+	template<typename T> bool operator==(const T &t)
+	{
+		return x == t.x  &&  y == t.y;
+	}
 };
 
 struct Rect : public SDL_Rect
@@ -309,9 +319,19 @@ public:
 	void deactivateTimer();
 	virtual void tick();
 
-	enum {LCLICK=1, RCLICK=2, HOVER=4, MOVE=8, KEYBOARD=16, TIME=32, GENERAL=64};
-	ui8 active;
-	ui8 used;
+	//mouse wheel
+	void activateWheel();
+	void deactivateWheel();
+	virtual void wheelScrolled(bool down, bool in);
+
+	//double click
+	void activateDClick();
+	void deactivateDClick();
+	virtual void onDoubleClick();
+
+	enum {LCLICK=1, RCLICK=2, HOVER=4, MOVE=8, KEYBOARD=16, TIME=32, GENERAL=64, WHEEL=128, DOUBLECLICK=256, ALL=0xffff};
+	ui16 active;
+	ui16 used;
 
 	enum {ACTIVATE=1, DEACTIVATE=2, UPDATE=4, SHOWALL=8, DISPOSE=16, SHARE_POS=32};
 	ui8 defActions; //which calls will be tried to be redirected to children
@@ -390,12 +410,17 @@ public:
 	std::list<CIntObject*> keyinterested;
 	std::list<CIntObject*> motioninterested;
 	std::list<CIntObject*> timeinterested;
+	std::list<CIntObject*> wheelInterested;
+	std::list<CIntObject*> doubleClickInterested;
 
 	//objs to blit
 	std::vector<IShowable*> objsToBlit;
 
 	SDL_Event * current; //current event
 
+	Point lastClick;
+	unsigned lastClickTime;
+
 	void totalRedraw(); //forces total redraw (using showAll)
 	void simpleRedraw(); //update only top interface and draw background from buffer
 	void popInt(IShowActivable *top); //removes given interface from the top and activates next

+ 5 - 5
hch/CObjectHandler.cpp

@@ -3708,16 +3708,16 @@ void CBank::reset()
 
 	int val1 = ran()%100;
 	int chance = 0;
-	for (ui8 i = 1; i <= VLC->objh->banksInfo[index].size(); i++)
+	for (ui8 i = 0; i < VLC->objh->banksInfo[index].size(); i++)
 	{
-		if (val1 < (chance += VLC->objh->banksInfo[index][i].chance))
-			cb->setObjProperty (id, 13, i);
+// 		if (val1 < (chance += VLC->objh->banksInfo[index][i].chance))
+// 			cb->setObjProperty (id, 13, i);
 	}
 	artifacts.clear();
 	for (ui8 i = 1; i <= 4; i++)
 	{
-		for (ui8 j = 1; j <= bc->artifacts[i]; j++)
-			cb->setObjProperty (id, 18, i);
+// 		for (ui8 j = 1; j <= bc->artifacts[i]; j++)
+// 			cb->setObjProperty (id, 18, i);
 	}
 
 }