Files
wagic/projects/mtg/src/CardSelector.cpp
T
wrenczes@gmail.com 5a1e8e6ffe More reorganization work around CardSelector and the singleton pattern. Broke the source for the singleton into its own separate source file, to keep things clean. Also broke apart a circular header dependency: CardSelector defines and uses a SelectorZone, which is a member inside of CardView. CardView in turn is used heavily by CardSelector. Instead SelectorZone is now defined within CardView (where it's set & controlled anyway).
I've also added my current work on the zone navigation system (class Navigator) - it's currently turned off for now (the override for this is inside of CardSelectorSingleton's Instance() call, simply comment out the NEW CardSelector and uncomment out the NEW Navigator line.)  It's functional, but I want to do more testing before considering wiring it into the game options or something similar.  (Also, note that it currently doesn't support the mouse functionality added by DJardin.)

Lastly, there's a bug crash fix in ActionStack that I tripped across while testing - basically, an illegal index value would have us walk off the bounds of a vector.
2010-10-31 07:50:53 +00:00

297 lines
10 KiB
C++

#include "PrecompiledHeader.h"
#include "PlayGuiObject.h"
#include "CardGui.h"
#include "CardSelector.h"
#include "GuiHand.h"
#include "Closest.cpp"
#include "GameObserver.h"
using std::cout;
// The X lib annoyingly defines True to be 1, leading to
// hard to understand syntax errors. Not using it, so it's
// safe to undefine it.
#ifdef True
#undef True
#endif
struct Left : public Exp { static inline bool test(CardSelector::Target* ref, CardSelector::Target* test)
{ return ref->x - test->x > fabs(ref->y - test->y); } };
struct Right : public Exp { static inline bool test(CardSelector::Target* ref, CardSelector::Target* test)
{ return test->x - ref->x > fabs(ref->y - test->y); } };
struct Up : public Exp { static inline bool test(CardSelector::Target* ref, CardSelector::Target* test)
{ return ref->y - test->y > fabs(ref->x - test->x); } };
struct Down : public Exp { static inline bool test(CardSelector::Target* ref, CardSelector::Target* test)
{ return test->y - ref->y > fabs(ref->x - test->x); } };
struct Diff : public Exp { static inline bool test(CardSelector::Target* ref, CardSelector::Target* test)
{ return ref != test; } };
struct True : public Exp { static inline bool test(CardSelector::Target* ref, CardSelector::Target* test)
{ return true; } };
CardSelector::SelectorMemory::SelectorMemory(PlayGuiObject* object) : object(object) { if (object) { x = object->x; y = object->y; } }
CardSelector::SelectorMemory::SelectorMemory() { object = NULL; x = y = 0; }
CardSelector::CardSelector(DuelLayers* duel) : CardSelectorBase(BIG_MODE_SHOW), active(NULL), duel(duel), limitor(NULL), bigpos(300, 150, 1.0, 0.0, 220) {}
void CardSelector::Add(CardSelector::Target* target)
{
if (NULL == active)
if (NULL == limitor || limitor->select(active))
active = target;
CardView* c = dynamic_cast<CardView*>(target);
if (c) c->zoom = 1.0f;
c = dynamic_cast<CardView*>(active);
if (c) c->zoom = 1.4f;
cards.push_back(target);
}
void CardSelector::Remove(CardSelector::Target* card)
{
for (vector<Target*>::iterator it = cards.begin(); it != cards.end(); ++it)
if (card == *it)
{
if (active == *it)
{
CardView* c = dynamic_cast<CardView*>(active); if (c) c->zoom = 1.0f;
active = closest<Diff>(cards, limitor, active);
c = dynamic_cast<CardView*>(active); if (c) c->zoom = 1.4f;
}
if (active == *it) active = NULL;
cards.erase(it);
return;
}
}
CardSelector::Target* CardSelector::fetchMemory(SelectorMemory& memory) {
if (NULL == memory.object) return NULL;
for (vector<Target*>::iterator it = cards.begin(); it != cards.end(); ++it)
if (*it == memory.object) {
if ((NULL == limitor) || (limitor->select(memory.object)))
return memory.object;
else break;
}
// We come here if the card is not in the selector any more, or if
// it is there but it is now refused by the limitor.
return closest<True>(cards, limitor, memory.x, memory.y);
}
void CardSelector::Push() {
memoryStack.push(SelectorMemory(active));
}
void CardSelector::Pop() {
Target* oldactive = active;
if (!memoryStack.empty()) {
active = fetchMemory(memoryStack.top());
memoryStack.pop();
CardView::SelectorZone oldowner;
if (CardView *q = dynamic_cast<CardView*>(oldactive)) oldowner = q->owner; else oldowner = CardView::nullZone;
if (CardView::nullZone != oldowner) lasts[oldowner] = SelectorMemory(oldactive);
}
if (active != oldactive) {
{ CardView* c = dynamic_cast<CardView*>(oldactive); if (c) c->zoom = 1.0f; } //Is this needed, I think it is one in Leaving(0) ?
{ CardView* c = dynamic_cast<CardView*>(active); if (c) c->zoom = 1.4f; } //Is this needed, I think it is one in Entering() ?
if (oldactive) oldactive->Leaving(JGE_BTN_NONE);
if (active) active->Entering();
}
}
bool CardSelector::CheckUserInput(JButton key)
{
if (!active) {
for (vector<Target*>::iterator it = cards.begin(); it != cards.end(); ++it)
if ((NULL == limitor) || (limitor->select(*it))) {
active = *it;
active->Entering();
return true;
}
return true;
}
Target* oldactive = active;
switch (key) {
case JGE_BTN_SEC:
GameObserver::GetInstance()->cancelCurrentAction();
return true;
case JGE_BTN_OK:
GameObserver::GetInstance()->ButtonPressed(active);
return true;
break;
case JGE_BTN_LEFT:
active = closest<Left>(cards, limitor, active);
break;
case JGE_BTN_RIGHT:
active = closest<Right>(cards, limitor, active);
break;
case JGE_BTN_UP:
active = closest<Up>(cards, limitor, active);
break;
case JGE_BTN_DOWN:
active = closest<Down>(cards, limitor, active);
break;
case JGE_BTN_CANCEL:
mDrawMode = (mDrawMode+1) % NB_BIG_MODES;
if(mDrawMode == BIG_MODE_TEXT)
options[Options::DISABLECARDS].number = 1;
else
options[Options::DISABLECARDS].number = 0;
return true;
default:
return false;
}
if (active != oldactive) {
CardView::SelectorZone oldowner, owner;
if (CardView *q = dynamic_cast<CardView*>(oldactive)) oldowner = q->owner; else oldowner = CardView::nullZone;
if (CardView *q = dynamic_cast<CardView*>(active)) owner = q->owner; else owner = CardView::nullZone;
if (oldowner != owner) {
if (CardView::nullZone != owner) {
if (PlayGuiObject* old = fetchMemory(lasts[owner]))
switch (key)
{
case JGE_BTN_LEFT: if (old->x < oldactive->x) active = old; break;
case JGE_BTN_RIGHT: if (old->x > oldactive->x) active = old; break;
case JGE_BTN_UP: if (old->y < oldactive->y) active = old; break;
case JGE_BTN_DOWN: if (old->y > oldactive->y) active = old; break;
default: if (old) active = old; break;
}
}
lasts[oldowner] = SelectorMemory(oldactive);
}
}
else
{
// active card hasn't changed - that means we're probably at an edge of the battlefield.
// check if we're not already a selected avatar - if not, select one depending whether we're going up/down.
GuiAvatar* avatar = dynamic_cast<GuiAvatar*>(active);
if (!avatar)
{
if (key == JGE_BTN_DOWN)
{
active = duel->GetAvatars()->GetSelf();
}
else if (key == JGE_BTN_UP)
{
active = duel->GetAvatars()->GetOpponent();
}
}
}
if (active != oldactive) {
{ CardView* c = dynamic_cast<CardView*>(oldactive); if (c) c->zoom = 1.0f; }
{ CardView* c = dynamic_cast<CardView*>(active); if (c) c->zoom = 1.4f; }
if (oldactive) oldactive->Leaving(JGE_BTN_NONE);
if (active) active->Entering();
}
return true;
}
bool CardSelector::CheckUserInput(int x, int y)
{
if (!active) {
for (vector<Target*>::iterator it = cards.begin(); it != cards.end(); ++it)
if ((NULL == limitor) || (limitor->select(*it))) {
active = *it;
active->Entering();
return true;
}
return true;
}
Target* oldactive = active;
active = closest<True>(cards, limitor, x, y);
if (active != oldactive) {
CardView::SelectorZone oldowner, owner;
if (CardView *q = dynamic_cast<CardView*>(oldactive)) oldowner = q->owner; else oldowner = CardView::nullZone;
if (CardView *q = dynamic_cast<CardView*>(active)) owner = q->owner; else owner = CardView::nullZone;
if (oldowner != owner) {
if (CardView::nullZone != owner) {
if (PlayGuiObject* old = fetchMemory(lasts[owner]))
if (old) active = old;
}
lasts[oldowner] = SelectorMemory(oldactive);
}
}
if (active != oldactive) {
{ CardView* c = dynamic_cast<CardView*>(oldactive); if (c) c->zoom = 1.0f; }
{ CardView* c = dynamic_cast<CardView*>(active); if (c) c->zoom = 1.4f; }
if (oldactive) oldactive->Leaving(JGE_BTN_NONE);
if (active) active->Entering();
}
return true;
}
void CardSelector::Update(float dt) {
float boundary = duel->RightBoundary();
float position = boundary - CardGui::BigWidth / 2;
if (CardView* c = dynamic_cast<CardView*>(active))
if ((c->x + CardGui::Width / 2 > position - CardGui::BigWidth / 2) &&
(c->x - CardGui::Width / 2 < position + CardGui::BigWidth / 2))
position = CardGui::BigWidth / 2 - 10;
if (position < CardGui::BigWidth / 2) position = CardGui::BigWidth / 2;
bigpos.x = position;
bigpos.Update(dt);
}
void CardSelector::Render() {
if (active) {
active->Render();
if (CardView* c = dynamic_cast<CardView*>(active)) {
switch(mDrawMode) {
case BIG_MODE_SHOW:
c->RenderBig(bigpos);
break;
case BIG_MODE_TEXT:
c->alternateRenderBig(bigpos);
break;
default:
break;
}
}
}
}
void CardSelector::Limit(LimitorFunctor<PlayGuiObject>* limitor, CardView::SelectorZone destzone) {
this->limitor = limitor;
if (limitor && !limitor->select(active)) {
PlayGuiObject* oldactive = active;
CardView::SelectorZone oldowner;
if (CardView *q = dynamic_cast<CardView*>(oldactive)) oldowner = q->owner; else oldowner = CardView::nullZone;
if (oldowner != destzone) {
if (CardView::nullZone != destzone)
if (PlayGuiObject* old = fetchMemory(lasts[destzone]))
active = old;
lasts[oldowner] = SelectorMemory(oldactive);
}
if (limitor && !limitor->select(active)) {
active = NULL;
for (vector<PlayGuiObject*>::iterator it = cards.begin(); it != cards.end(); ++it)
if (limitor->select(*it)) {
active = *it;
break;
}
}
if (active != oldactive) {
{ CardView* c = dynamic_cast<CardView*>(oldactive); if (c) c->zoom = 1.0f; }
{ CardView* c = dynamic_cast<CardView*>(active); if (c) c->zoom = 1.4f; }
if (oldactive) oldactive->Leaving(JGE_BTN_NONE);
if (active) active->Entering();
}
}
}
void CardSelector::PushLimitor() {
if (NULL == limitor) return;
CardView::SelectorZone owner;
if (CardView *q = dynamic_cast<CardView*>(active)) owner = q->owner; else owner = CardView::nullZone;
limitorStack.push(make_pair(limitor, owner));
}
void CardSelector::PopLimitor() {
if (limitorStack.empty()) return;
Limit(limitorStack.top().first, limitorStack.top().second);
limitorStack.pop();
}