diff options
author | Bjørn Lindeijer <bjorn@lindeijer.nl> | 2009-05-04 23:26:22 +0200 |
---|---|---|
committer | Bjørn Lindeijer <bjorn@lindeijer.nl> | 2009-05-04 23:41:45 +0200 |
commit | 6cacaa3d7f55d91d8b7ca178f8595cc6c6b4383d (patch) | |
tree | a4ae355fe26eda518a5fd82c15347b6cfcf6b7f6 /src/gui | |
parent | 1b06ec9f12e3fbfe6fbf6579fb64bb895464badb (diff) | |
download | mana-6cacaa3d7f55d91d8b7ca178f8595cc6c6b4383d.tar.gz mana-6cacaa3d7f55d91d8b7ca178f8595cc6c6b4383d.tar.bz2 mana-6cacaa3d7f55d91d8b7ca178f8595cc6c6b4383d.tar.xz mana-6cacaa3d7f55d91d8b7ca178f8595cc6c6b4383d.zip |
Replaced emote window with a new emote popup
The popup is meant to be temporary, showing the emote instantly when you
click on it. It adapts nicely to show any number of emotes.
I still need to add a better way of assigning emote shortcuts, since
currently you can only change which emote is assigned to which shortcut
by actually using it.
Diffstat (limited to 'src/gui')
-rw-r--r-- | src/gui/emotecontainer.cpp | 6 | ||||
-rw-r--r-- | src/gui/emotepopup.cpp | 191 | ||||
-rw-r--r-- | src/gui/emotepopup.h | 125 | ||||
-rw-r--r-- | src/gui/emotewindow.cpp | 79 | ||||
-rw-r--r-- | src/gui/emotewindow.h | 66 | ||||
-rw-r--r-- | src/gui/setup.cpp | 4 | ||||
-rw-r--r-- | src/gui/windowmenu.cpp (renamed from src/gui/menuwindow.cpp) | 82 | ||||
-rw-r--r-- | src/gui/windowmenu.h (renamed from src/gui/menuwindow.h) | 37 |
8 files changed, 392 insertions, 198 deletions
diff --git a/src/gui/emotecontainer.cpp b/src/gui/emotecontainer.cpp index 3003b949..0eee5434 100644 --- a/src/gui/emotecontainer.cpp +++ b/src/gui/emotecontainer.cpp @@ -70,11 +70,7 @@ EmoteContainer::EmoteContainer(): EmoteContainer::~EmoteContainer() { - if (mSelImg) - { - mSelImg->decRef(); - mSelImg = NULL; - } + mSelImg->decRef(); } void EmoteContainer::draw(gcn::Graphics *graphics) diff --git a/src/gui/emotepopup.cpp b/src/gui/emotepopup.cpp new file mode 100644 index 00000000..036a25ec --- /dev/null +++ b/src/gui/emotepopup.cpp @@ -0,0 +1,191 @@ +/* + * Extended support for activating emotes + * Copyright (C) 2009 Aethyra Development Team + * Copyright (C) 2009 The Mana World Development Team + * + * This file is part of The Mana World. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "gui/emotepopup.h" + +#include "animatedsprite.h" +#include "configuration.h" +#include "emoteshortcut.h" +#include "graphics.h" +#include "localplayer.h" +#include "log.h" + +#include "resources/emotedb.h" +#include "resources/image.h" +#include "resources/iteminfo.h" +#include "resources/resourcemanager.h" + +#include "utils/dtor.h" +#include "utils/gettext.h" +#include "utils/stringutils.h" + +#include <guichan/mouseinput.hpp> +#include <guichan/selectionlistener.hpp> + +const int EmotePopup::gridWidth = 34; // emote icon width + 4 +const int EmotePopup::gridHeight = 36; // emote icon height + 4 + +static const int MAX_COLUMNS = 6; + +EmotePopup::EmotePopup(): + mSelectedEmoteIndex(-1), + mHoveredEmoteIndex(-1), + mRowCount(1), + mColumnCount(1) +{ + // Setup emote sprites + for (int i = 0; i <= EmoteDB::getLast(); ++i) + { + mEmotes.push_back(EmoteDB::getAnimation(i)); + } + + ResourceManager *resman = ResourceManager::getInstance(); + mSelectionImage = resman->getImage("graphics/gui/selection.png"); + if (!mSelectionImage) + logger->error(_("Unable to load selection.png")); + + mSelectionImage->setAlpha(config.getValue("guialpha", 0.8)); + + addMouseListener(this); + recalculateSize(); + setVisible(true); +} + +EmotePopup::~EmotePopup() +{ + mSelectionImage->decRef(); +} + +void EmotePopup::draw(gcn::Graphics *graphics) +{ + Popup::draw(graphics); + + const int emoteCount = mEmotes.size(); + const int emotesLeft = mEmotes.size() % mColumnCount; + + for (int i = 0; i < emoteCount ; i++) + { + int row = i / mColumnCount; + int column = i % mColumnCount; + + int emoteX = 4 + column * gridWidth; + int emoteY = 4 + row * gridHeight; + + // Center the last row when there are less emotes than columns + if (emotesLeft > 0 && row == mRowCount - 1) + emoteX += (mColumnCount - emotesLeft) * gridWidth / 2; + + // Draw selection image below hovered item + if (i == mHoveredEmoteIndex) + { + static_cast<Graphics*>(graphics)->drawImage( + mSelectionImage, emoteX, emoteY + 4); + } + + // Draw emote icon + mEmotes[i]->draw(static_cast<Graphics*>(graphics), emoteX, emoteY); + } +} + +void EmotePopup::mousePressed(gcn::MouseEvent &event) +{ + if (event.getButton() != gcn::MouseEvent::LEFT) + return; + + const int index = getIndexAt(event.getX(), event.getY()); + if (index != -1) { + setSelectedEmoteIndex(index); + emoteShortcut->setEmoteSelected(index + 1); + } +} + +void EmotePopup::mouseMoved(gcn::MouseEvent &event) +{ + mHoveredEmoteIndex = getIndexAt(event.getX(), event.getY()); +} + +int EmotePopup::getSelectedEmote() const +{ + return 1 + mSelectedEmoteIndex; +} + +void EmotePopup::setSelectedEmoteIndex(int index) +{ + if (index == mSelectedEmoteIndex) + return; + + mSelectedEmoteIndex = index; + distributeValueChangedEvent(); +} + +int EmotePopup::getIndexAt(int x, int y) const +{ + const int emotesLeft = mEmotes.size() % mColumnCount; + const int row = y / gridHeight; + int column; + + // Take into account that the last row is centered + if (emotesLeft > 0 && row == mRowCount - 1) + { + int emotesMissing = mColumnCount - emotesLeft; + column = std::min((x - emotesMissing * gridWidth / 2) / gridWidth, + emotesLeft - 1); + } + else + { + column = std::min(x / gridWidth, mColumnCount - 1); + } + + int index = column + (row * mColumnCount); + + if ((unsigned) index < mEmotes.size()) + return index; + + return -1; +} + +void EmotePopup::recalculateSize() +{ + const unsigned emoteCount = mEmotes.size(); + + mRowCount = emoteCount / MAX_COLUMNS; + if (emoteCount % MAX_COLUMNS > 0) + ++mRowCount; + + mColumnCount = emoteCount / mRowCount; + if (emoteCount % mRowCount > 0) + ++mColumnCount; + + setContentSize(mColumnCount * gridWidth, mRowCount * gridHeight); +} + +void EmotePopup::distributeValueChangedEvent() +{ + gcn::SelectionEvent event(this); + Listeners::const_iterator i_end = mListeners.end(); + Listeners::const_iterator i; + + for (i = mListeners.begin(); i != i_end; ++i) + { + (*i)->valueChanged(event); + } +} diff --git a/src/gui/emotepopup.h b/src/gui/emotepopup.h new file mode 100644 index 00000000..f6ed6cab --- /dev/null +++ b/src/gui/emotepopup.h @@ -0,0 +1,125 @@ +/* + * Extended support for activating emotes + * Copyright (C) 2009 Aethyra Development Team + * Copyright (C) 2009 The Mana World Development Team + * + * This file is part of The Mana World. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef EMOTEPOPUP_H +#define EMOTEPOPUP_H + +#include "gui/widgets/popup.h" + +#include <guichan/mouselistener.hpp> + +#include <list> +#include <vector> + +class AnimatedSprite; +class Image; + +namespace gcn { + class SelectionListener; +} + +/** + * An emote popup. Used to activate emotes and assign them to shortcuts. + * + * \ingroup GUI + */ +class EmotePopup : public Popup, + public gcn::MouseListener +{ + public: + /** + * Constructor. Initializes the graphic. + */ + EmotePopup(); + + virtual ~EmotePopup(); + + /** + * Draws the emotes. + */ + void draw(gcn::Graphics *graphics); + + void mousePressed(gcn::MouseEvent &event); + void mouseMoved(gcn::MouseEvent &event); + + /** + * Returns the selected emote. + */ + int getSelectedEmote() const; + + /** + * Adds a listener to the list that's notified each time a change to + * the selection occurs. + */ + void addSelectionListener(gcn::SelectionListener *listener) + { + mListeners.push_back(listener); + } + + /** + * Removes a listener from the list that's notified each time a change + * to the selection occurs. + */ + void removeSelectionListener(gcn::SelectionListener *listener) + { + mListeners.remove(listener); + } + + private: + /** + * Sets the index of the currently selected emote. + */ + void setSelectedEmoteIndex(int index); + + /** + * Returns the index at the specified coordinates. Returns -1 when + * there is no valid index. + */ + int getIndexAt(int x, int y) const; + + /** + * Determine and set the size of the container. + */ + void recalculateSize(); + + /** + * Sends out selection events to the list of selection listeners. + */ + void distributeValueChangedEvent(); + + std::vector<const AnimatedSprite*> mEmotes; + Image *mSelectionImage; + int mSelectedEmoteIndex; + int mHoveredEmoteIndex; + + int mRowCount; + int mColumnCount; + + typedef std::list<gcn::SelectionListener*> Listeners; + + Listeners mListeners; + + static const int gridWidth; + static const int gridHeight; +}; + +#endif diff --git a/src/gui/emotewindow.cpp b/src/gui/emotewindow.cpp deleted file mode 100644 index 69282f8f..00000000 --- a/src/gui/emotewindow.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Extended support for activating emotes - * Copyright (C) 2009 Aethyra Development Team - * - * This file is part of The Mana World. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "gui/emotewindow.h" - -#include "gui/gui.h" -#include "gui/emotecontainer.h" - -#include "gui/widgets/button.h" -#include "gui/widgets/layout.h" -#include "gui/widgets/scrollarea.h" - -#include "localplayer.h" - -#include "utils/gettext.h" -#include "utils/stringutils.h" - -EmoteWindow::EmoteWindow(): - Window(_("Emote")) -{ - setWindowName("Emote"); - setResizable(true); - setCloseButton(true); - setSaveVisible(true); - setMinWidth(80); - setMinHeight(130); - setDefaultSize(322, 200, ImageRect::CENTER); - - mUseButton = new Button(_("Use"), "use", this); - - mEmotes = new EmoteContainer; - mEmotes->addSelectionListener(this); - - mEmoteScroll = new ScrollArea(mEmotes); - mEmoteScroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER); - - place(0, 0, mEmoteScroll, 5, 4); - place(4, 4, mUseButton); - - Layout &layout = getLayout(); - layout.setRowHeight(0, Layout::AUTO_SET); - - mUseButton->setSize(60, mUseButton->getHeight()); - - loadWindowState(); -} - -void EmoteWindow::action(const gcn::ActionEvent &event) -{ - int emote = mEmotes->getSelectedEmote(); - - if (!emote) - return; - - player_node->emote(emote); -} - -int EmoteWindow::getSelectedEmote() const -{ - return mEmotes->getSelectedEmote(); -} diff --git a/src/gui/emotewindow.h b/src/gui/emotewindow.h deleted file mode 100644 index 15d4b427..00000000 --- a/src/gui/emotewindow.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Extended support for activating emotes - * Copyright (C) 2009 Aethyra Development Team - * - * This file is part of The Mana World. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef EMOTEWINDOW_H -#define EMOTEWINDOW_H - -#include "gui/widgets/window.h" - -#include <guichan/actionlistener.hpp> -#include <guichan/selectionlistener.hpp> - -class EmoteContainer; -class TextBox; - -/** - * Emote dialog. - * - * \ingroup Interface - */ -class EmoteWindow : public Window, gcn::ActionListener, - gcn::SelectionListener -{ - public: - /** - * Constructor. - */ - EmoteWindow(); - - /** - * Called when receiving actions from the widgets. - */ - void action(const gcn::ActionEvent &event); - - /** - * Returns the selected item. - */ - int getSelectedEmote() const; - - private: - EmoteContainer *mEmotes; - - gcn::Button *mUseButton; - gcn::ScrollArea *mEmoteScroll; -}; - -extern EmoteWindow *emoteWindow; - -#endif diff --git a/src/gui/setup.cpp b/src/gui/setup.cpp index 5dbce81b..ee69eaaf 100644 --- a/src/gui/setup.cpp +++ b/src/gui/setup.cpp @@ -43,7 +43,6 @@ extern Window *buyDialog; extern Window *sellDialog; extern Window *buySellDialog; extern Window *inventoryWindow; -extern Window *emoteWindow; extern Window *npcTextDialog; extern Window *npcStringDialog; extern Window *skillDialog; @@ -145,7 +144,6 @@ void Setup::action(const gcn::ActionEvent &event) buySellDialog->resetToDefaultSize(); #endif inventoryWindow->resetToDefaultSize(); - emoteWindow->resetToDefaultSize(); skillDialog->resetToDefaultSize(); minimap->resetToDefaultSize(); equipmentWindow->resetToDefaultSize(); @@ -168,4 +166,4 @@ void Setup::setInGame(bool inGame) mResetWindows->setEnabled(inGame); } -Setup* setupWindow; +Setup *setupWindow; diff --git a/src/gui/menuwindow.cpp b/src/gui/windowmenu.cpp index 06ebb39c..5e33a4ed 100644 --- a/src/gui/menuwindow.cpp +++ b/src/gui/windowmenu.cpp @@ -19,23 +19,26 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "gui/menuwindow.h" +#include "gui/windowmenu.h" + +#include "gui/emotepopup.h" #include "gui/widgets/button.h" #include "gui/widgets/window.h" +#include "gui/widgets/windowcontainer.h" #include "graphics.h" -#include "utils/gettext.h" +#include "net/net.h" +#include "net/playerhandler.h" -#include <guichan/actionlistener.hpp> +#include "utils/gettext.h" #include <string> extern Window *equipmentWindow; extern Window *inventoryWindow; extern Window *itemShortcutWindow; -extern Window *emoteWindow; extern Window *setupWindow; extern Window *skillDialog; extern Window *statusWindow; @@ -45,22 +48,14 @@ extern Window *guildWindow; extern Window *magicDialog; #endif -namespace { - struct MenuWindowListener : public gcn::ActionListener - { - /** - * Called when receiving actions from widget. - */ - void action(const gcn::ActionEvent &event); - } listener; -} -MenuWindow::MenuWindow(): - Popup("Menu") +WindowMenu::WindowMenu(): + mEmotePopup(0) { // Buttons static const char *buttonNames[] = { + ":-)", N_("Status"), N_("Equipment"), N_("Inventory"), @@ -71,7 +66,6 @@ MenuWindow::MenuWindow(): N_("Buddys"), #endif N_("Shortcut"), - N_("Emote"), N_("Setup"), 0 }; @@ -79,29 +73,48 @@ MenuWindow::MenuWindow(): for (const char **curBtn = buttonNames; *curBtn; curBtn++) { - gcn::Button *btn = new Button(gettext(*curBtn), *curBtn, &listener); + gcn::Button *btn = new Button(gettext(*curBtn), *curBtn, this); btn->setPosition(x, 0); add(btn); x += btn->getWidth() + 3; h = btn->getHeight(); } - setPosition(graphics->getWidth() - x - 3, 3); - setContentSize(x - 3, h); - - setVisible((bool) config.getValue(getPopupName() + "Visible", true)); + setDimension(gcn::Rectangle(graphics->getWidth() - x - 3, 3, + x - 3, h)); + setVisible(true); } -void MenuWindow::draw(gcn::Graphics *graphics) +WindowMenu::~WindowMenu() { - drawChildren(graphics); } -void MenuWindowListener::action(const gcn::ActionEvent &event) +void WindowMenu::action(const gcn::ActionEvent &event) { - Window *window = NULL; + Window *window = 0; - if (event.getId() == "Status") + if (event.getId() == ":-)") + { + if (!mEmotePopup) + { + const gcn::Widget *s = event.getSource(); + const gcn::Rectangle &r = s->getDimension(); + const int parentX = s->getParent()->getX(); + + mEmotePopup = new EmotePopup; + const int offset = (r.width - mEmotePopup->getWidth()) / 2; + mEmotePopup->setPosition(parentX + r.x + offset, + r.y + r.height + 5); + + mEmotePopup->addSelectionListener(this); + } + else + { + windowContainer->scheduleDelete(mEmotePopup); + mEmotePopup = 0; + } + } + else if (event.getId() == "Status") { window = statusWindow; } @@ -135,10 +148,6 @@ void MenuWindowListener::action(const gcn::ActionEvent &event) { window = itemShortcutWindow; } - else if (event.getId() == "Emote") - { - window = emoteWindow; - } else if (event.getId() == "Setup") { window = setupWindow; @@ -153,3 +162,16 @@ void MenuWindowListener::action(const gcn::ActionEvent &event) } } } + +void WindowMenu::valueChanged(const gcn::SelectionEvent &event) +{ + if (event.getSource() == mEmotePopup) + { + int emote = mEmotePopup->getSelectedEmote(); + if (emote) + Net::getPlayerHandler()->emote(emote); + + windowContainer->scheduleDelete(mEmotePopup); + mEmotePopup = 0; + } +} diff --git a/src/gui/menuwindow.h b/src/gui/windowmenu.h index c3190680..b060a3e5 100644 --- a/src/gui/menuwindow.h +++ b/src/gui/windowmenu.h @@ -19,29 +19,36 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef MENU_H -#define MENU_H +#ifndef WINDOWMENU_H +#define WINDOWMENU_H -#include "gui/widgets/popup.h" +#include "gui/widgets/container.h" + +#include <guichan/actionlistener.hpp> +#include <guichan/selectionlistener.hpp> + +class EmotePopup; /** - * The Button Menu. + * The window menu. Allows showing and hiding many of the different windows + * used in the game. * * \ingroup Interface */ -class MenuWindow : public Popup +class WindowMenu : public Container, + public gcn::ActionListener, + public gcn::SelectionListener { public: - /** - * Constructor. - */ - MenuWindow(); - - /** - * Draw this window - */ - void draw(gcn::Graphics *graphics); + WindowMenu(); + ~WindowMenu(); + + void action(const gcn::ActionEvent &event); + + void valueChanged(const gcn::SelectionEvent &event); + + private: + EmotePopup *mEmotePopup; }; #endif - |