diff options
115 files changed, 2576 insertions, 1064 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 382e281c..bca38598 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -65,8 +65,6 @@ SET(SRCS gui/widgets/textpreview.h gui/browserbox.cpp gui/browserbox.h - gui/buddywindow.cpp - gui/buddywindow.h gui/button.cpp gui/button.h gui/buy.cpp @@ -116,9 +114,11 @@ SET(SRCS gui/itempopup.cpp gui/itempopup.h gui/itemshortcutcontainer.cpp - gui/itemshortcutcontainer.h\ + gui/itemshortcutcontainer.h gui/item_amount.cpp gui/item_amount.h + gui/label.cpp + gui/label.h gui/linkhandler.h gui/listbox.cpp gui/listbox.h @@ -146,6 +146,8 @@ SET(SRCS gui/passwordfield.h gui/playerbox.cpp gui/playerbox.h + gui/popup.cpp + gui/popup.h gui/popupmenu.cpp gui/popupmenu.h gui/progressbar.cpp @@ -187,6 +189,8 @@ SET(SRCS gui/shortcutcontainer.h gui/skill.cpp gui/skill.h + gui/skin.cpp + gui/skin.h gui/slider.cpp gui/slider.h gui/speechbubble.cpp @@ -203,6 +207,7 @@ SET(SRCS gui/textbox.h gui/textfield.cpp gui/textfield.h + gui/textrenderer.h gui/trade.cpp gui/trade.h gui/truetypefont.cpp diff --git a/src/Makefile.am b/src/Makefile.am index 39fbc856..e37e007c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -33,8 +33,6 @@ tmw_SOURCES = gui/widgets/dropdown.cpp \ gui/chatinput.h \ gui/checkbox.cpp \ gui/checkbox.h \ - gui/palette.cpp \ - gui/palette.h \ gui/confirm_dialog.cpp \ gui/confirm_dialog.h \ gui/connection.cpp \ @@ -71,6 +69,8 @@ tmw_SOURCES = gui/widgets/dropdown.cpp \ gui/itemshortcutcontainer.h \ gui/item_amount.cpp \ gui/item_amount.h \ + gui/label.cpp \ + gui/label.h \ gui/linkhandler.h \ gui/listbox.cpp \ gui/listbox.h \ @@ -92,10 +92,14 @@ tmw_SOURCES = gui/widgets/dropdown.cpp \ gui/npc_text.h \ gui/ok_dialog.cpp \ gui/ok_dialog.h \ + gui/palette.cpp \ + gui/palette.h \ gui/passwordfield.cpp \ gui/passwordfield.h \ gui/playerbox.cpp \ gui/playerbox.h \ + gui/popup.cpp \ + gui/popup.h \ gui/popupmenu.cpp \ gui/popupmenu.h \ gui/progressbar.cpp \ @@ -137,6 +141,8 @@ tmw_SOURCES = gui/widgets/dropdown.cpp \ gui/shortcutcontainer.h \ gui/skill.cpp \ gui/skill.h \ + gui/skin.cpp \ + gui/skin.h \ gui/slider.cpp \ gui/slider.h \ gui/speechbubble.cpp \ diff --git a/src/being.cpp b/src/being.cpp index 66273710..f14fd64e 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -762,14 +762,15 @@ std::string Being::getHairColor(int index) void Being::load() { - // Hairstyles are encoded as negative numbers. Count how far negative + // Hairstyles are encoded as negative numbers. Count how far negative // we can go. - int hairstyles = -1; - while (ItemDB::get(hairstyles).getSprite(GENDER_MALE) != "error.xml") + int hairstyles = 1; + + while (ItemDB::get(-hairstyles).getSprite(GENDER_MALE) != "error.xml") { - hairstyles--; + hairstyles++; } - mNumberOfHairstyles = -hairstyles; + mNumberOfHairstyles = hairstyles; XML::Document doc(HAIR_FILE); xmlNodePtr root = doc.rootNode(); diff --git a/src/being.h b/src/being.h index ec6f1c44..715a7192 100644 --- a/src/being.h +++ b/src/being.h @@ -213,14 +213,12 @@ class Being : public Sprite /** * Gets the hair color for this being. */ - int getHairColor() const - { return mHairColor; } + int getHairColor() const { return mHairColor; } /** * Gets the hair style for this being. */ - int getHairStyle() const - { return mHairStyle; } + int getHairStyle() const { return mHairStyle; } /** * Get the number of hairstyles implemented diff --git a/src/game.cpp b/src/game.cpp index e04a5ee8..3ca8f5ae 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -218,14 +218,14 @@ void createGuiWindows(Network *network) chatWindow->setVisible((bool) config.getValue( chatWindow->getWindowName() + "Visible", true)); miniStatusWindow->setVisible((bool) config.getValue( - miniStatusWindow->getWindowName() + "Visible", true)); + miniStatusWindow->getPopupName() + "Visible", true)); buyDialog->setVisible(false); sellDialog->setVisible(false); minimap->setVisible((bool) config.getValue( minimap->getWindowName() + "Visible", true)); tradeWindow->setVisible(false); menuWindow->setVisible((bool) config.getValue( - menuWindow->getWindowName() + "Visible", true)); + menuWindow->getPopupName() + "Visible", true)); itemShortcutWindow->setVisible((bool) config.getValue( itemShortcutWindow->getWindowName() + "Visible", true)); emoteShortcutWindow->setVisible((bool) config.getValue( @@ -410,8 +410,11 @@ void Game::optionChanged(const std::string &name) { int fpsLimit = (int) config.getValue("fpslimit", 0); - // Calculate new minimum frame time - mMinFrameTime = fpsLimit ? 1000 / fpsLimit : 0; + // Calculate new minimum frame time. If one isn't set, use 60 FPS. + // (1000 / 60 is 16.66) Since the client can go well above the refresh + // rates for monitors now in OpenGL mode, this cutoff is done to help + // conserve on CPU time. + mMinFrameTime = fpsLimit ? 1000 / fpsLimit : 16; // Reset draw time to current time mDrawTime = tick_time * 10; diff --git a/src/graphics.cpp b/src/graphics.cpp index 4af7b723..b9bd9fa6 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -49,30 +49,25 @@ bool Graphics::setVideoMode(int w, int h, int bpp, bool fs, bool hwaccel) mFullscreen = fs; mHWAccel = hwaccel; - if (fs) { + if (fs) displayFlags |= SDL_FULLSCREEN; - } - if (hwaccel) { + if (hwaccel) displayFlags |= SDL_HWSURFACE | SDL_DOUBLEBUF; - } else { + else displayFlags |= SDL_SWSURFACE; - } mScreen = SDL_SetVideoMode(w, h, bpp, displayFlags); - if (!mScreen) { + if (!mScreen) return false; - } char videoDriverName[64]; - if (SDL_VideoDriverName(videoDriverName, 64)) { + if (SDL_VideoDriverName(videoDriverName, 64)) logger->log("Using video driver: %s", videoDriverName); - } - else { + else logger->log("Using video driver: unknown"); - } const SDL_VideoInfo *vi = SDL_GetVideoInfo(); @@ -103,9 +98,8 @@ bool Graphics::setVideoMode(int w, int h, int bpp, bool fs, bool hwaccel) bool Graphics::setFullscreen(bool fs) { - if (mFullscreen == fs) { + if (mFullscreen == fs) return true; - } return setVideoMode(mScreen->w, mScreen->h, mScreen->format->BitsPerPixel, fs, mHWAccel); @@ -127,7 +121,7 @@ bool Graphics::drawImage(Image *image, int x, int y) } bool Graphics::drawImage(Image *image, int srcX, int srcY, int dstX, int dstY, - int width, int height, bool) + int width, int height, bool) { // Check that preconditions for blitting are met. if (!mScreen || !image || !image->mImage) return false; @@ -149,7 +143,7 @@ bool Graphics::drawImage(Image *image, int srcX, int srcY, int dstX, int dstY, } void Graphics::drawImage(gcn::Image const *image, int srcX, int srcY, - int dstX, int dstY, int width, int height) + int dstX, int dstY, int width, int height) { ProxyImage const *srcImage = dynamic_cast< ProxyImage const * >(image); @@ -159,22 +153,34 @@ void Graphics::drawImage(gcn::Image const *image, int srcX, int srcY, void Graphics::drawImagePattern(Image *image, int x, int y, int w, int h) { - int iw = image->getWidth(); - int ih = image->getHeight(); - if (iw == 0 || ih == 0) return; + // Check that preconditions for blitting are met. + if (!mScreen || !image || !image->mImage) return; + + const int iw = image->getWidth(); + const int ih = image->getHeight(); + + if (iw == 0 || ih == 0) return; - int px = 0; // X position on pattern plane - int py = 0; // Y position on pattern plane + for (int py = 0; py < h; py += ih) // Y position on pattern plane + { + int dh = (py + ih >= h) ? h - py : ih; + int srcY = image->mBounds.y; + int dstY = y + py + mClipStack.top().yOffset; - while (py < h) { - while (px < w) { + for (int px = 0; px < w; px += iw) // X position on pattern plane + { int dw = (px + iw >= w) ? w - px : iw; - int dh = (py + ih >= h) ? h - py : ih; - drawImage(image, 0, 0, x + px, y + py, dw, dh); - px += iw; + int srcX = image->mBounds.x; + int dstX = x + px + mClipStack.top().xOffset; + + SDL_Rect dstRect; + SDL_Rect srcRect; + dstRect.x = dstX; dstRect.y = dstY; + srcRect.x = srcX; srcRect.y = srcY; + srcRect.w = dw; srcRect.h = dh; + + SDL_BlitSurface(image->mImage, &srcRect, mScreen, &dstRect); } - py += ih; - px = 0; } } diff --git a/src/graphics.h b/src/graphics.h index 172032dc..c4004ffc 100644 --- a/src/graphics.h +++ b/src/graphics.h @@ -48,6 +48,19 @@ struct SDL_Surface; */ struct ImageRect { + enum ImagePosition + { + UPPER_LEFT = 0, + UPPER_CENTER = 1, + UPPER_RIGHT = 2, + LEFT = 3, + CENTER = 4, + RIGHT = 5, + LOWER_LEFT = 6, + LOWER_CENTER = 7, + LOWER_RIGHT = 8, + }; + Image *grid[9]; }; diff --git a/src/gui/button.cpp b/src/gui/button.cpp index 1d3a04e4..f9e5e9dc 100644 --- a/src/gui/button.cpp +++ b/src/gui/button.cpp @@ -23,6 +23,7 @@ #include <guichan/font.hpp> #include "button.h" +#include "palette.h" #include "../configuration.h" #include "../graphics.h" @@ -72,9 +73,9 @@ Button::Button(const std::string& caption, const std::string &actionEventId, { init(); setActionEventId(actionEventId); - if (listener) { + + if (listener) addActionListener(listener); - } } void Button::init() @@ -93,8 +94,10 @@ void Button::init() { btn[mode] = resman->getImage(data[mode].file); a = 0; - for (y = 0; y < 3; y++) { - for (x = 0; x < 3; x++) { + for (y = 0; y < 3; y++) + { + for (x = 0; x < 3; x++) + { button[mode].grid[a] = btn[mode]->getSubImage( data[x].gridX, data[y].gridY, data[x + 1].gridX - data[x].gridX + 1, @@ -150,7 +153,7 @@ void Button::draw(gcn::Graphics *graphics) static_cast<Graphics*>(graphics)-> drawImageRect(0, 0, getWidth(), getHeight(), button[mode]); - graphics->setColor(getForegroundColor()); + graphics->setColor(guiPalette->getColor(Palette::TEXT)); int textX; int textY = getHeight() / 2 - getFont()->getHeight() / 2; diff --git a/src/gui/buy.cpp b/src/gui/buy.cpp index 7e03c591..c5c37601 100644 --- a/src/gui/buy.cpp +++ b/src/gui/buy.cpp @@ -19,10 +19,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <guichan/widgets/label.hpp> - #include "button.h" #include "buy.h" +#include "label.h" #include "scrollarea.h" #include "shop.h" #include "shoplistbox.h" @@ -40,34 +39,39 @@ #include "../utils/strprintf.h" BuyDialog::BuyDialog(Network *network): - Window(_("Buy")), mNetwork(network), + Window("Buy"), mNetwork(network), mMoney(0), mAmountItems(0), mMaxItems(0) { setWindowName("Buy"); setResizable(true); + setCloseButton(true); setMinWidth(260); setMinHeight(230); - setDefaultSize(0, 0, 260, 230); + setDefaultSize(260, 230, ImageRect::CENTER); mShopItems = new ShopItems; mShopItemList = new ShopListBox(mShopItems, mShopItems); mScrollArea = new ScrollArea(mShopItemList); + mScrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER); + mSlider = new Slider(1.0); - mQuantityLabel = new gcn::Label("0"); + mQuantityLabel = new Label(strprintf("%d / %d", mAmountItems, mMaxItems)); + mQuantityLabel->setAlignment(gcn::Graphics::CENTER); mMoneyLabel = new gcn::Label(strprintf(_("Price: %s / Total: %s"), "", "")); + mIncreaseButton = new Button("+", "+", this); mDecreaseButton = new Button("-", "-", this); mBuyButton = new Button(_("Buy"), "buy", this); mQuitButton = new Button(_("Quit"), "quit", this); - mItemDescLabel = new gcn::Label(strprintf(_("Description: %s"), "")); - mItemEffectLabel = new gcn::Label(strprintf(_("Effect: %s"), "")); + mAddMaxButton = new Button(_("Max"), "max", this); + mItemDescLabel = new Label(strprintf(_("Description: %s"), "")); + mItemEffectLabel = new Label(strprintf(_("Effect: %s"), "")); - mIncreaseButton->setSize(20, 20); - mDecreaseButton->setSize(20, 20); + mDecreaseButton->adjustSize(); + mDecreaseButton->setWidth(mIncreaseButton->getWidth()); - mScrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER); mIncreaseButton->setEnabled(false); mDecreaseButton->setEnabled(false); mBuyButton->setEnabled(false); @@ -77,16 +81,21 @@ BuyDialog::BuyDialog(Network *network): mSlider->addActionListener(this); mShopItemList->addSelectionListener(this); - place(0, 0, mScrollArea, 5).setPadding(3); - place(0, 1, mQuantityLabel, 2); - place(2, 1, mSlider, 3); - place(0, 2, mMoneyLabel, 5); - place(0, 3, mItemEffectLabel, 5); - place(0, 4, mItemDescLabel, 5); + ContainerPlacer place; + place = getPlacer(0, 0); + + place(0, 0, mScrollArea, 8, 5).setPadding(3); place(0, 5, mDecreaseButton); - place(1, 5, mIncreaseButton); - place(3, 5, mBuyButton); - place(4, 5, mQuitButton); + place(1, 5, mSlider, 3); + place(4, 5, mIncreaseButton); + place(5, 5, mQuantityLabel, 2); + place(7, 5, mAddMaxButton); + place(0, 6, mMoneyLabel, 8); + place(0, 7, mItemEffectLabel, 8); + place(0, 8, mItemDescLabel, 8); + place(6, 9, mBuyButton); + place(7, 9, mQuitButton); + Layout &layout = getLayout(); layout.setRowHeight(0, Layout::AUTO_SET); @@ -127,15 +136,14 @@ void BuyDialog::addItem(int id, int price) void BuyDialog::action(const gcn::ActionEvent &event) { - int selectedItem = mShopItemList->getSelected(); - if (event.getId() == "quit") { - setVisible(false); - current_npc = 0; + close(); return; } + int selectedItem = mShopItemList->getSelected(); + // The following actions require a valid selection if (selectedItem < 0 || selectedItem >= (int) mShopItems->getNumberOfElements()) @@ -160,6 +168,12 @@ void BuyDialog::action(const gcn::ActionEvent &event) mSlider->setValue(mAmountItems); updateButtonsAndLabels(); } + else if (event.getId() == "max") + { + mAmountItems = mMaxItems; + mSlider->setValue(mAmountItems); + updateButtonsAndLabels(); + } // TODO: Actually we'd have a bug elsewhere if this check for the number // of items to be bought ever fails, Bertram removed the assertions, is // there a better way to ensure this fails in an _obvious_ way in C++? @@ -253,5 +267,12 @@ void BuyDialog::setVisible(bool visible) { Window::setVisible(visible); - if (visible) requestFocus(); + if (visible) + requestFocus(); +} + +void BuyDialog::close() +{ + setVisible(false); + current_npc = 0; } diff --git a/src/gui/buy.h b/src/gui/buy.h index 5e2f0b8f..2e6b5377 100644 --- a/src/gui/buy.h +++ b/src/gui/buy.h @@ -100,12 +100,20 @@ class BuyDialog : public Window, public gcn::ActionListener, */ void logic(); + /** + * Sets the visibility of this window. + */ void setVisible(bool visible); + /** + * Closes the Buy Window, as well as resetting the current npc. + */ + void close(); private: Network *mNetwork; gcn::Button *mBuyButton; gcn::Button *mQuitButton; + gcn::Button *mAddMaxButton; gcn::Button *mIncreaseButton; gcn::Button *mDecreaseButton; ShopListBox *mShopItemList; diff --git a/src/gui/buysell.cpp b/src/gui/buysell.cpp index e6dc7c1f..04a27b8c 100644 --- a/src/gui/buysell.cpp +++ b/src/gui/buysell.cpp @@ -60,16 +60,16 @@ void BuySellDialog::logic() { Window::logic(); - if (isVisible() && !current_npc) { + if (isVisible() && !current_npc) setVisible(false); - } } void BuySellDialog::setVisible(bool visible) { Window::setVisible(visible); - if (visible) requestFocus(); + if (visible) + requestFocus(); } void BuySellDialog::action(const gcn::ActionEvent &event) diff --git a/src/gui/char_select.cpp b/src/gui/char_select.cpp index 709988a3..aaf4e8c4 100644 --- a/src/gui/char_select.cpp +++ b/src/gui/char_select.cpp @@ -23,11 +23,10 @@ #include <guichan/font.hpp> -#include <guichan/widgets/label.hpp> - #include "button.h" #include "char_select.h" #include "confirm_dialog.h" +#include "label.h" #include "ok_dialog.h" #include "playerbox.h" #include "textfield.h" @@ -94,10 +93,10 @@ CharSelectDialog::CharSelectDialog(Network *network, mPlayerBox = new PlayerBox; mPlayerBox->setWidth(74); - mNameLabel = new gcn::Label(strprintf(_("Name: %s"), "")); - mLevelLabel = new gcn::Label(strprintf(_("Level: %d"), 0)); - mJobLevelLabel = new gcn::Label(strprintf(_("Job Level: %d"), 0)); - mMoneyLabel = new gcn::Label(strprintf(_("Money: %s"), mMoney.c_str())); + mNameLabel = new Label(strprintf(_("Name: %s"), "")); + mLevelLabel = new Label(strprintf(_("Level: %d"), 0)); + mJobLevelLabel = new Label(strprintf(_("Job Level: %d"), 0)); + mMoneyLabel = new Label(strprintf(_("Money: %s"), mMoney.c_str())); const std::string tempString = getFont()->getWidth(_("New")) < getFont()->getWidth(_("Delete")) ? @@ -271,13 +270,13 @@ CharCreateDialog::CharCreateDialog(Window *parent, int slot, Network *network, mPlayer->setHairStyle(rand() % mPlayer->getNumOfHairstyles(), rand() % numberOfHairColors); mNameField = new TextField(""); - mNameLabel = new gcn::Label(_("Name:")); + mNameLabel = new Label(_("Name:")); mNextHairColorButton = new Button(">", "nextcolor", this); mPrevHairColorButton = new Button("<", "prevcolor", this); - mHairColorLabel = new gcn::Label(_("Hair Color:")); + mHairColorLabel = new Label(_("Hair Color:")); mNextHairStyleButton = new Button(">", "nextstyle", this); mPrevHairStyleButton = new Button("<", "prevstyle", this); - mHairStyleLabel = new gcn::Label(_("Hair Style:")); + mHairStyleLabel = new Label(_("Hair Style:")); mCreateButton = new Button(_("Create"), "create", this); mCancelButton = new Button(_("Cancel"), "cancel", this); mPlayerBox = new PlayerBox(mPlayer); diff --git a/src/gui/chat.cpp b/src/gui/chat.cpp index 55bc2696..94a554e8 100644 --- a/src/gui/chat.cpp +++ b/src/gui/chat.cpp @@ -54,7 +54,7 @@ Window(""), mNetwork(network), mTmpVisible(false) setWindowName("Chat"); setResizable(true); - setDefaultSize(0, windowContainer->getHeight() - 123, 600, 123); + setDefaultSize(600, 123, ImageRect::LOWER_LEFT); setMinWidth(150); setMinHeight(90); @@ -112,6 +112,12 @@ ChatWindow::~ChatWindow() delete mParty; } +void ChatWindow::resetToDefaultSize() +{ + mRecorder->resetToDefaultSize(); + Window::resetToDefaultSize(); +} + void ChatWindow::chatLog(std::string line, int own, bool ignoreRecord) { // Trim whitespace @@ -142,12 +148,12 @@ void ChatWindow::chatLog(std::string line, int own, bool ignoreRecord) // *implements actions in a backwards compatible way* if (own == BY_PLAYER && - tmp.text.at(0) == '*' && - tmp.text.at(tmp.text.length()-1) == '*') + tmp.text.at(0) == '*' && + tmp.text.at(tmp.text.length()-1) == '*') { - tmp.text[0] = ' '; - tmp.text.erase(tmp.text.length() - 1); - own = ACT_IS; + tmp.text[0] = ' '; + tmp.text.erase(tmp.text.length() - 1); + own = ACT_IS; } std::string lineColor = "##C"; @@ -629,9 +635,9 @@ void ChatWindow::chatSend(const std::string &nick, std::string msg) } else if (command == "me") { - std::stringstream actionStr; - actionStr << "*" << msg << "*"; - chatSend(player_node->getName(), actionStr.str()); + std::stringstream actionStr; + actionStr << "*" << msg << "*"; + chatSend(player_node->getName(), actionStr.str()); } else { diff --git a/src/gui/chat.h b/src/gui/chat.h index 6002fed3..09f3260b 100644 --- a/src/gui/chat.h +++ b/src/gui/chat.h @@ -119,6 +119,12 @@ class ChatWindow : public Window, public gcn::ActionListener, ~ChatWindow(); /** + * Reset the chat window and recorder window attached to it to their + * default positions. + */ + void resetToDefaultSize(); + + /** * Adds a line of text to our message list. Parameters: * * @param line Text message. @@ -238,12 +244,12 @@ class ChatWindow : public Window, public gcn::ActionListener, typedef std::list<std::string> History; typedef History::iterator HistoryIterator; History mHistory; /**< Command history */ - HistoryIterator mCurHist; /**< History iterator */ - Recorder *mRecorder; /**< Recording class */ - char mPartyPrefix; /**< Messages beginning with the prefix are sent to - the party */ - bool mReturnToggles; /**< Marks whether <Return> toggles the chat log - or not */ + HistoryIterator mCurHist; /**< History iterator */ + Recorder *mRecorder; /**< Recording class */ + char mPartyPrefix; /**< Messages beginning with the prefix are + sent to the party */ + bool mReturnToggles; /**< Marks whether <Return> toggles the chat + log or not */ Party *mParty; }; extern ChatWindow *chatWindow; diff --git a/src/gui/checkbox.cpp b/src/gui/checkbox.cpp index 7fa4fa81..5695a23f 100644 --- a/src/gui/checkbox.cpp +++ b/src/gui/checkbox.cpp @@ -20,6 +20,7 @@ */ #include "checkbox.h" +#include "palette.h" #include "../configuration.h" #include "../graphics.h" @@ -68,6 +69,18 @@ CheckBox::~CheckBox() } } +void CheckBox::draw(gcn::Graphics* graphics) +{ + drawBox(graphics); + + graphics->setFont(getFont()); + graphics->setColor(guiPalette->getColor(Palette::TEXT)); + + const int h = getHeight() + getHeight() / 2; + + graphics->drawText(getCaption(), h - 2, 0); +} + void CheckBox::drawBox(gcn::Graphics* graphics) { Image *box; diff --git a/src/gui/checkbox.h b/src/gui/checkbox.h index 20adb43c..dd59493c 100644 --- a/src/gui/checkbox.h +++ b/src/gui/checkbox.h @@ -45,6 +45,11 @@ class CheckBox : public gcn::CheckBox ~CheckBox(); /** + * Draws the caption, then calls drawBox to draw the check box. + */ + void draw(gcn::Graphics* graphics); + + /** * Draws the check box, not the caption. */ void drawBox(gcn::Graphics* graphics); diff --git a/src/gui/connection.cpp b/src/gui/connection.cpp index 981100f9..658eade7 100644 --- a/src/gui/connection.cpp +++ b/src/gui/connection.cpp @@ -21,10 +21,9 @@ #include <guichan/actionlistener.hpp> -#include <guichan/widgets/label.hpp> - #include "button.h" #include "connection.h" +#include "label.h" #include "progressbar.h" #include "../main.h" @@ -46,7 +45,7 @@ ConnectionDialog::ConnectionDialog(): Button *cancelButton = new Button(_("Cancel"), "cancelButton", &listener); mProgressBar = new ProgressBar(0.0, 200 - 10, 20, 128, 128, 128); - gcn::Label *label = new gcn::Label(_("Connecting...")); + gcn::Label *label = new Label(_("Connecting...")); cancelButton->setPosition(5, 100 - 5 - cancelButton->getHeight()); mProgressBar->setPosition(5, cancelButton->getY() - 25); diff --git a/src/gui/debugwindow.cpp b/src/gui/debugwindow.cpp index cf2f9613..a98c9af4 100644 --- a/src/gui/debugwindow.cpp +++ b/src/gui/debugwindow.cpp @@ -19,9 +19,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <guichan/widgets/label.hpp> - #include "debugwindow.h" +#include "label.h" #include "viewport.h" #include "widgets/layout.h" @@ -40,14 +39,14 @@ DebugWindow::DebugWindow(): setResizable(true); setCloseButton(true); - setDefaultSize(0, 0, 400, 60); - - mFPSLabel = new gcn::Label("0 FPS"); - mMusicFileLabel = new gcn::Label("Music: "); - mMapLabel = new gcn::Label("Map: "); - mMiniMapLabel = new gcn::Label("Mini-Map: "); - mTileMouseLabel = new gcn::Label("Mouse: 0, 0"); - mParticleCountLabel = new gcn::Label("Particle count: 0"); + setDefaultSize(400, 100, ImageRect::CENTER); + + mFPSLabel = new Label("0 FPS"); + mMusicFileLabel = new Label("Music: "); + mMapLabel = new Label("Map: "); + mMiniMapLabel = new Label("Mini-Map: "); + mTileMouseLabel = new Label("Mouse: 0, 0"); + mParticleCountLabel = new Label("Particle count: 0"); place(0, 0, mFPSLabel, 3); place(3, 0, mTileMouseLabel); diff --git a/src/gui/debugwindow.h b/src/gui/debugwindow.h index e089de27..8097132c 100644 --- a/src/gui/debugwindow.h +++ b/src/gui/debugwindow.h @@ -50,4 +50,6 @@ class DebugWindow : public Window gcn::Label *mParticleCountLabel; }; +extern DebugWindow *debugWindow; + #endif diff --git a/src/gui/emoteshortcutcontainer.cpp b/src/gui/emoteshortcutcontainer.cpp index c96ea855..661f42a7 100644 --- a/src/gui/emoteshortcutcontainer.cpp +++ b/src/gui/emoteshortcutcontainer.cpp @@ -20,6 +20,7 @@ */ #include "emoteshortcutcontainer.h" +#include "palette.h" #include "../animatedsprite.h" #include "../configuration.h" @@ -98,7 +99,7 @@ void EmoteShortcutContainer::draw(gcn::Graphics *graphics) // Draw emote keyboard shortcut. const char *key = SDL_GetKeyName( (SDLKey) keyboard.getKeyValue(keyboard.KEY_EMOTE_1 + i)); - graphics->setColor(0x000000); + graphics->setColor(guiPalette->getColor(Palette::TEXT)); g->drawText(key, emoteX + 2, emoteY + 2, gcn::Graphics::LEFT); if (emoteShortcut->getEmote(i)) diff --git a/src/gui/emotewindow.cpp b/src/gui/emotewindow.cpp index 48635720..d4b3cf2e 100644 --- a/src/gui/emotewindow.cpp +++ b/src/gui/emotewindow.cpp @@ -40,7 +40,7 @@ EmoteWindow::EmoteWindow(): setCloseButton(true); setMinWidth(80); setMinHeight(130); - setDefaultSize(115, 25, 322, 200); + setDefaultSize(322, 200, ImageRect::CENTER); mUseButton = new Button(_("Use"), "use", this); diff --git a/src/gui/equipmentwindow.cpp b/src/gui/equipmentwindow.cpp index 9a00f7a7..856d7d03 100644 --- a/src/gui/equipmentwindow.cpp +++ b/src/gui/equipmentwindow.cpp @@ -27,6 +27,7 @@ #include "button.h" #include "equipmentwindow.h" #include "itempopup.h" +#include "palette.h" #include "playerbox.h" #include "viewport.h" @@ -62,6 +63,7 @@ EquipmentWindow::EquipmentWindow(): mSelected(-1) { mItemPopup = new ItemPopup; + mItemPopup->setOpaque(false); // Control that shows the Player mPlayerBox = new PlayerBox; @@ -70,7 +72,7 @@ EquipmentWindow::EquipmentWindow(): setWindowName("Equipment"); setCloseButton(true); - setDefaultSize(5, 195, 180, 300); + setDefaultSize(180, 300, ImageRect::CENTER); loadWindowState(); mUnequip = new Button(_("Unequip"), "unequip", this); @@ -112,6 +114,22 @@ void EquipmentWindow::draw(gcn::Graphics *graphics) for (int i = EQUIP_LEGS_SLOT; i < EQUIP_VECTOREND; i++) { + if (i == mSelected) + { + const gcn::Color color = guiPalette->getColor(Palette::HIGHLIGHT); + + // Set color to the highligh color + g->setColor(gcn::Color(color.r, color.g, color.b, getGuiAlpha())); + g->fillRectangle(gcn::Rectangle(mEquipBox[i].posX, mEquipBox[i].posY, + BOX_WIDTH, BOX_HEIGHT)); + } + + // Set color black. + g->setColor(gcn::Color(0, 0, 0)); + // Draw box border. + g->drawRectangle(gcn::Rectangle(mEquipBox[i].posX, mEquipBox[i].posY, + BOX_WIDTH, BOX_HEIGHT)); + item = (i != EQUIP_AMMO_SLOT) ? mInventory->getItem(mEquipment->getEquipment(i)) : mInventory->getItem(mEquipment->getArrows()); @@ -122,28 +140,13 @@ void EquipmentWindow::draw(gcn::Graphics *graphics) g->drawImage(image, mEquipBox[i].posX, mEquipBox[i].posY); if (i == EQUIP_AMMO_SLOT) { - g->setColor(gcn::Color(0, 0, 0)); + g->setColor(guiPalette->getColor(Palette::TEXT)); graphics->drawText(toString(item->getQuantity()), mEquipBox[i].posX + (BOX_WIDTH / 2), mEquipBox[i].posY - getFont()->getHeight(), gcn::Graphics::CENTER); } } - - if (i == mSelected) - { - // Set color red. - g->setColor(gcn::Color(255, 0, 0)); - } - else - { - // Set color black. - g->setColor(gcn::Color(0, 0, 0)); - } - - // Draw box border. - g->drawRectangle(gcn::Rectangle(mEquipBox[i].posX, mEquipBox[i].posY, - BOX_WIDTH, BOX_HEIGHT)); } } @@ -234,8 +237,9 @@ void EquipmentWindow::mouseMoved(gcn::MouseEvent &event) int mouseX, mouseY; SDL_GetMouseState(&mouseX, &mouseY); - mItemPopup->setItem(item->getInfo()); - mItemPopup->setOpaque(false); + if (item->getInfo().getName() != mItemPopup->getItemName()) + mItemPopup->setItem(item->getInfo()); + mItemPopup->updateColors(); mItemPopup->view(x + getX(), y + getY()); } else diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 4081eeac..83441e1b 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -27,6 +27,7 @@ #include "gui.h" #include "palette.h" #include "sdlinput.h" +#include "skin.h" #include "truetypefont.h" #include "viewport.h" #include "window.h" @@ -239,3 +240,8 @@ void Gui::handleMouseMoved(const gcn::MouseInput &mouseInput) gcn::Gui::handleMouseMoved(mouseInput); mMouseInactivityTimer = 0; } + +const int Gui::getFontHeight() const +{ + return mGuiFont->getHeight(); +} diff --git a/src/gui/gui.h b/src/gui/gui.h index 340eec09..2ce153db 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -77,6 +77,11 @@ class Gui : public gcn::Gui { return mGuiFont; } /** + * Return game font height. + */ + const int getFontHeight() const; + + /** * Return the Font used for "Info Particles", i.e. ones showing, what * you picked up, etc. */ diff --git a/src/gui/help.cpp b/src/gui/help.cpp index 78b3c93a..03dfd08d 100644 --- a/src/gui/help.cpp +++ b/src/gui/help.cpp @@ -39,16 +39,17 @@ HelpWindow::HelpWindow(): setWindowName("Help"); setResizable(true); + setDefaultSize(500, 400, ImageRect::CENTER); + mBrowserBox = new BrowserBox; mBrowserBox->setOpaque(false); mScrollArea = new ScrollArea(mBrowserBox); Button *okButton = new Button(_("Close"), "close", this); - mScrollArea->setDimension(gcn::Rectangle( - 5, 5, 445, 335 - okButton->getHeight())); - okButton->setPosition( - 450 - okButton->getWidth(), - 345 - okButton->getHeight()); + mScrollArea->setDimension(gcn::Rectangle(5, 5, 445, + 335 - okButton->getHeight())); + okButton->setPosition(450 - okButton->getWidth(), + 345 - okButton->getHeight()); mBrowserBox->setLinkHandler(this); @@ -58,7 +59,7 @@ HelpWindow::HelpWindow(): Layout &layout = getLayout(); layout.setRowHeight(0, Layout::AUTO_SET); - center(); + loadWindowState(); } void HelpWindow::action(const gcn::ActionEvent &event) diff --git a/src/gui/inventorywindow.cpp b/src/gui/inventorywindow.cpp index 80017d28..50fae483 100644 --- a/src/gui/inventorywindow.cpp +++ b/src/gui/inventorywindow.cpp @@ -24,12 +24,11 @@ #include <guichan/font.hpp> #include <guichan/mouseinput.hpp> -#include <guichan/widgets/label.hpp> - #include "button.h" #include "inventorywindow.h" #include "item_amount.h" #include "itemcontainer.h" +#include "label.h" #include "progressbar.h" #include "scrollarea.h" #include "viewport.h" @@ -57,7 +56,7 @@ InventoryWindow::InventoryWindow(int invSize): setCloseButton(true); // If you adjust these defaults, don't forget to adjust the trade window's. - setDefaultSize(115, 25, 375, 300); + setDefaultSize(375, 300, ImageRect::CENTER); std::string longestUseString = getFont()->getWidth(_("Equip")) > getFont()->getWidth(_("Use")) ? @@ -82,8 +81,8 @@ InventoryWindow::InventoryWindow(int invSize): mMaxWeight = -1; mUsedSlots = toString(player_node->getInventory()->getNumberOfSlotsUsed()); - mSlotsLabel = new gcn::Label(_("Slots: ")); - mWeightLabel = new gcn::Label(_("Weight: ")); + mSlotsLabel = new Label(_("Slots: ")); + mWeightLabel = new Label(_("Weight: ")); mSlotsBar = new ProgressBar(1.0f, 100, 20, 225, 200, 25); mWeightBar = new ProgressBar(1.0f, 100, 20, 0, 0, 255); diff --git a/src/gui/item_amount.cpp b/src/gui/item_amount.cpp index 9398dc47..a8242aae 100644 --- a/src/gui/item_amount.cpp +++ b/src/gui/item_amount.cpp @@ -20,8 +20,8 @@ */ #include "button.h" -#include "inttextfield.h" #include "item_amount.h" +#include "label.h" #include "slider.h" #include "storagewindow.h" #include "trade.h" @@ -32,19 +32,20 @@ #include "../localplayer.h" #include "../utils/gettext.h" +#include "../utils/strprintf.h" ItemAmountWindow::ItemAmountWindow(int usage, Window *parent, Item *item): Window("", true, parent), mItem(item), - mMax(mItem->getQuantity()), + mMax(item->getQuantity()), mUsage(usage) { + setCloseButton(true); + // Integer field - mItemAmountTextField = new IntTextField(1); - mItemAmountTextField->setRange(1, mMax); - mItemAmountTextField->setWidth(30); - mItemAmountTextField->setActionEventId("Dummy"); - mItemAmountTextField->addActionListener(this); + + mItemAmountLabel = new Label(strprintf("%d / %d", 1, mMax)); + mItemAmountLabel->setAlignment(gcn::Graphics::CENTER); // Slider mItemAmountSlide = new Slider(1.0, mMax); @@ -54,22 +55,27 @@ ItemAmountWindow::ItemAmountWindow(int usage, Window *parent, Item *item): // Buttons Button *minusButton = new Button("-", "Minus", this); - minusButton->setSize(20, 20); Button *plusButton = new Button("+", "Plus", this); - plusButton->setSize(20, 20); Button *okButton = new Button(_("Ok"), "Ok", this); Button *cancelButton = new Button(_("Cancel"), "Cancel", this); Button *addAllButton = new Button(_("All"), "All", this); + minusButton->adjustSize(); + minusButton->setWidth(plusButton->getWidth()); + // Set positions + ContainerPlacer place; + place = getPlacer(0, 0); + place(0, 0, minusButton); - place(1, 0, mItemAmountTextField).setPadding(2); - place(2, 0, plusButton); - place(4, 0, addAllButton, 2); - place(0, 1, mItemAmountSlide, 6); - place(4, 2, okButton); - place(5, 2, cancelButton); - reflowLayout(250, 0); + place(1, 0, mItemAmountSlide, 3); + place(4, 0, plusButton); + place(5, 0, mItemAmountLabel, 2); + place(7, 0, addAllButton); + place = getPlacer(0, 1); + place(4, 0, cancelButton); + place(5, 0, okButton); + reflowLayout(225, 0); resetAmount(); @@ -97,22 +103,22 @@ ItemAmountWindow::ItemAmountWindow(int usage, Window *parent, Item *item): void ItemAmountWindow::resetAmount() { - mItemAmountTextField->setValue(1); + mItemAmountLabel->setCaption(strprintf("%d / %d", 1, mMax)); } void ItemAmountWindow::action(const gcn::ActionEvent &event) { - int amount = mItemAmountTextField->getValue(); + int amount = mItemAmountSlide->getValue(); if (event.getId() == "Cancel") { - scheduleDelete(); + close(); } - else if (event.getId() == "Plus") + else if (event.getId() == "Plus" && amount < mMax) { amount++; } - else if (event.getId() == "Minus") + else if (event.getId() == "Minus" && amount > 1) { amount--; } @@ -122,9 +128,8 @@ void ItemAmountWindow::action(const gcn::ActionEvent &event) } else if (event.getId() == "Ok" || event.getId() == "All") { - if (event.getId() == "All") { + if (event.getId() == "All") amount = mMax; - } switch (mUsage) { @@ -149,9 +154,11 @@ void ItemAmountWindow::action(const gcn::ActionEvent &event) return; } - if (amount < 0) amount = 0; - else if (amount > mMax) amount = mMax; - - mItemAmountTextField->setValue(amount); + mItemAmountLabel->setCaption(strprintf("%d / %d", amount, mMax)); mItemAmountSlide->setValue(amount); } + +void ItemAmountWindow::close() +{ + scheduleDelete(); +} diff --git a/src/gui/item_amount.h b/src/gui/item_amount.h index f0534ec8..d8253e3c 100644 --- a/src/gui/item_amount.h +++ b/src/gui/item_amount.h @@ -57,8 +57,13 @@ class ItemAmountWindow : public Window, public gcn::ActionListener */ void resetAmount(); + /** + * Schedules the Item Amount window for deletion. + */ + void close(); + private: - IntTextField *mItemAmountTextField; /**< Item amount caption. */ + gcn::Label *mItemAmountLabel; /**< Item amount caption. */ Item *mItem; int mMax, mUsage; diff --git a/src/gui/itemcontainer.cpp b/src/gui/itemcontainer.cpp index 8285a491..8a780eb4 100644 --- a/src/gui/itemcontainer.cpp +++ b/src/gui/itemcontainer.cpp @@ -24,6 +24,7 @@ #include "itemcontainer.h" #include "itempopup.h" +#include "palette.h" #include "viewport.h" #include "../graphics.h" @@ -50,13 +51,14 @@ ItemContainer::ItemContainer(Inventory *inventory, int offset): mOffset(offset) { mItemPopup = new ItemPopup; + mItemPopup->setOpaque(false); ResourceManager *resman = ResourceManager::getInstance(); mSelImg = resman->getImage("graphics/gui/selection.png"); if (!mSelImg) logger->error("Unable to load selection.png"); - mMaxItems = mInventory->getLastUsedSlot() - 1; // Count from 0, usage from 2 + mMaxItems = mInventory->getLastUsedSlot() - (mOffset - 1); // Count from 0, usage from 2 addMouseListener(this); addWidgetListener(this); @@ -75,7 +77,7 @@ void ItemContainer::logic() gcn::Widget::logic(); - int i = mInventory->getLastUsedSlot() - 1; // Count from 0, usage from 2 + int i = mInventory->getLastUsedSlot() - (mOffset - 1); // Count from 0, usage from 2 if (i != mMaxItems) { @@ -122,7 +124,7 @@ void ItemContainer::draw(gcn::Graphics *graphics) // Draw item caption graphics->setFont(getFont()); - graphics->setColor(gcn::Color(0, 0, 0)); + graphics->setColor(guiPalette->getColor(Palette::TEXT)); graphics->drawText( (item->isEquipped() ? "Eq." : toString(item->getQuantity())), itemX + gridWidth / 2, itemY + gridHeight - 11, @@ -254,8 +256,9 @@ void ItemContainer::mouseMoved(gcn::MouseEvent &event) if (item) { - mItemPopup->setItem(item->getInfo()); - mItemPopup->setOpaque(false); + if (item->getInfo().getName() != mItemPopup->getItemName()) + mItemPopup->setItem(item->getInfo()); + mItemPopup->updateColors(); mItemPopup->view(viewport->getMouseX(), viewport->getMouseY()); } else diff --git a/src/gui/itemlinkhandler.cpp b/src/gui/itemlinkhandler.cpp index bd8985dc..29fa310d 100644 --- a/src/gui/itemlinkhandler.cpp +++ b/src/gui/itemlinkhandler.cpp @@ -32,6 +32,7 @@ ItemLinkHandler::ItemLinkHandler() { mItemPopup = new ItemPopup; + mItemPopup->setOpaque(false); } ItemLinkHandler::~ItemLinkHandler() @@ -49,11 +50,17 @@ void ItemLinkHandler::handleLink(const std::string &link) { const ItemInfo &iteminfo = ItemDB::get(id); - mItemPopup->setItem(iteminfo); + if (iteminfo.getName() != mItemPopup->getItemName()) + mItemPopup->setItem(iteminfo); if (mItemPopup->isVisible()) + { mItemPopup->setVisible(false); + } else + { + mItemPopup->updateColors(); mItemPopup->view(viewport->getMouseX(), viewport->getMouseY()); + } } } diff --git a/src/gui/itempopup.cpp b/src/gui/itempopup.cpp index efbee6b0..61cb18fb 100644 --- a/src/gui/itempopup.cpp +++ b/src/gui/itempopup.cpp @@ -26,11 +26,11 @@ #include "gui.h" #include "itempopup.h" +#include "palette.h" #include "scrollarea.h" #include "textbox.h" -#include "windowcontainer.h" -#include "widgets/layout.h" +#include "../graphics.h" #include "../units.h" @@ -40,14 +40,12 @@ #include "../utils/stringutils.h" ItemPopup::ItemPopup(): - Window() + Popup() { - setResizable(false); - setShowTitle(false); - setTitleBarHeight(0); + mItemType = ""; // Item Name - mItemName = new gcn::Label("Label"); + mItemName = new gcn::Label(""); mItemName->setFont(boldFont); mItemName->setPosition(2, 2); @@ -88,8 +86,6 @@ ItemPopup::ItemPopup(): add(mItemDescScroll); add(mItemEffectScroll); add(mItemWeightScroll); - - center(); } ItemPopup::~ItemPopup() @@ -109,12 +105,12 @@ void ItemPopup::setItem(const ItemInfo &item) return; mItemName->setCaption(item.getName()); - mItemName->setForegroundColor(getColor(item.getType())); mItemName->setWidth(boldFont->getWidth(item.getName())); mItemDesc->setTextWrapped(item.getDescription(), 196); mItemEffect->setTextWrapped(item.getEffect(), 196); mItemWeight->setTextWrapped(_("Weight: ") + Units::formatWeight(item.getWeight()), 196); + mItemType = item.getType(); int minWidth = mItemName->getWidth(); @@ -167,40 +163,51 @@ void ItemPopup::setItem(const ItemInfo &item) (2 * getFont()->getHeight())); } +void ItemPopup::updateColors() +{ + mItemName->setForegroundColor(getColor(mItemType)); + graphics->setColor(guiPalette->getColor(Palette::TEXT)); +} + gcn::Color ItemPopup::getColor(const std::string& type) { gcn::Color color; if (type.compare("generic") == 0) - color = 0x21a5b1; + color = guiPalette->getColor(Palette::GENERIC); else if (type.compare("equip-head") == 0) - color = 0x527fa4; + color = guiPalette->getColor(Palette::HEAD); else if (type.compare("usable") == 0) - color = 0x268d24; + color = guiPalette->getColor(Palette::USABLE); else if (type.compare("equip-torso") == 0) - color = 0xd12aa4; + color = guiPalette->getColor(Palette::TORSO); else if (type.compare("equip-1hand") == 0) - color = 0xf42a2a; + color = guiPalette->getColor(Palette::ONEHAND); else if (type.compare("equip-legs") == 0) - color = 0x699900; + color = guiPalette->getColor(Palette::LEGS); else if (type.compare("equip-feet") == 0) - color = 0xaa1d48; + color = guiPalette->getColor(Palette::FEET); else if (type.compare("equip-2hand") == 0) - color = 0xf46d0e; + color = guiPalette->getColor(Palette::TWOHAND); else if (type.compare("equip-shield") == 0) - color = 0x9c2424; + color = guiPalette->getColor(Palette::SHIELD); else if (type.compare("equip-ring") == 0) - color = 0x0000ff; + color = guiPalette->getColor(Palette::RING); else if (type.compare("equip-arms") == 0) - color = 0x9c24e8; + color = guiPalette->getColor(Palette::ARMS); else if (type.compare("equip-ammo") == 0) - color = 0x8b6311; + color = guiPalette->getColor(Palette::AMMO); else - color = 0x000000; + color = guiPalette->getColor(Palette::UNKNOWN_ITEM); return color; } +std::string ItemPopup::getItemName() +{ + return mItemName->getCaption(); +} + unsigned int ItemPopup::getNumRows() { return mItemDesc->getNumberOfRows() + mItemEffect->getNumberOfRows() + @@ -209,8 +216,8 @@ unsigned int ItemPopup::getNumRows() void ItemPopup::view(int x, int y) { - if (windowContainer->getWidth() < (x + getWidth() + 5)) - x = windowContainer->getWidth() - getWidth(); + if (graphics->getWidth() < (x + getWidth() + 5)) + x = graphics->getWidth() - getWidth(); if ((y - getHeight() - 10) < 0) y = 0; else diff --git a/src/gui/itempopup.h b/src/gui/itempopup.h index c820e3a0..03e79886 100644 --- a/src/gui/itempopup.h +++ b/src/gui/itempopup.h @@ -23,20 +23,48 @@ #ifndef ITEMPOPUP_H #define ITEMPOPUP_H -#include "window.h" +#include "popup.h" class ItemInfo; class ScrollArea; class TextBox; -class ItemPopup : public Window +class ItemPopup : public Popup { public: + /** + * Constructor. Initializes the item popup. + */ ItemPopup(); + + /** + * Destructor. Cleans up the item popup on deletion. + */ ~ItemPopup(); + /** + * Sets the info to be displayed given a particular item. + */ void setItem(const ItemInfo &item); + + /** + * Gets the number of rows that the item popup currently has. + */ unsigned int getNumRows(); + + /** + * Gets the name of the currently stored item in this popup. + */ + std::string getItemName(); + + /** + * Updates the colors used within the item popup. + */ + void updateColors(); + + /** + * Sets the location to display the item popup. + */ void view(int x, int y); private: @@ -44,6 +72,7 @@ class ItemPopup : public Window TextBox *mItemDesc; TextBox *mItemEffect; TextBox *mItemWeight; + std::string mItemType; ScrollArea *mItemDescScroll; ScrollArea *mItemEffectScroll; ScrollArea *mItemWeightScroll; diff --git a/src/gui/itemshortcutcontainer.cpp b/src/gui/itemshortcutcontainer.cpp index 67525140..9f77fd65 100644 --- a/src/gui/itemshortcutcontainer.cpp +++ b/src/gui/itemshortcutcontainer.cpp @@ -22,6 +22,7 @@ #include "inventorywindow.h" #include "itemshortcutcontainer.h" #include "itempopup.h" +#include "palette.h" #include "viewport.h" #include "../configuration.h" @@ -46,6 +47,7 @@ ItemShortcutContainer::ItemShortcutContainer(): addWidgetListener(this); mItemPopup = new ItemPopup; + mItemPopup->setOpaque(false); ResourceManager *resman = ResourceManager::getInstance(); @@ -64,22 +66,6 @@ ItemShortcutContainer::~ItemShortcutContainer() delete mItemPopup; } -void ItemShortcutContainer::logic() -{ - if (!isVisible()) - return; - - gcn::Widget::logic(); - - int i = itemShortcut->getItemCount(); - - if (i != mMaxItems) - { - mMaxItems = i; - setWidth(getWidth()); - } -} - void ItemShortcutContainer::draw(gcn::Graphics *graphics) { if (!isVisible()) @@ -93,7 +79,6 @@ void ItemShortcutContainer::draw(gcn::Graphics *graphics) Graphics *g = static_cast<Graphics*>(graphics); - graphics->setColor(gcn::Color(0, 0, 0)); graphics->setFont(getFont()); for (int i = 0; i < mMaxItems; i++) @@ -106,7 +91,7 @@ void ItemShortcutContainer::draw(gcn::Graphics *graphics) // Draw item keyboard shortcut. const char *key = SDL_GetKeyName( (SDLKey) keyboard.getKeyValue(keyboard.KEY_SHORTCUT_1 + i)); - graphics->setColor(0x000000); + graphics->setColor(guiPalette->getColor(Palette::TEXT)); g->drawText(key, itemX + 2, itemY + 2, gcn::Graphics::LEFT); if (itemShortcut->getItem(i) < 0) @@ -249,8 +234,9 @@ void ItemShortcutContainer::mouseMoved(gcn::MouseEvent &event) if (item && inventoryWindow->isVisible()) { - mItemPopup->setItem(item->getInfo()); - mItemPopup->setOpaque(false); + if (item->getInfo().getName() != mItemPopup->getItemName()) + mItemPopup->setItem(item->getInfo()); + mItemPopup->updateColors(); mItemPopup->view(viewport->getMouseX(), viewport->getMouseY()); } else diff --git a/src/gui/itemshortcutcontainer.h b/src/gui/itemshortcutcontainer.h index 22d94ec2..9d188bf0 100644 --- a/src/gui/itemshortcutcontainer.h +++ b/src/gui/itemshortcutcontainer.h @@ -49,11 +49,6 @@ class ItemShortcutContainer : public ShortcutContainer virtual ~ItemShortcutContainer(); /** - * Handles the logic of the ItemContainer - */ - void logic(); - - /** * Draws the items. */ void draw(gcn::Graphics *graphics); diff --git a/src/gui/label.cpp b/src/gui/label.cpp new file mode 100644 index 00000000..e8d72ace --- /dev/null +++ b/src/gui/label.cpp @@ -0,0 +1,40 @@ +/* + * Aethyra + * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson + * Copyright (c) 2009 Aethyra Development Team + * + * This file is part of Aethyra based on original code + * from GUIChan. + * + * 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 "label.h" +#include "palette.h" + +Label::Label() : + gcn::Label() +{ +} + +Label::Label(const std::string& caption) : + gcn::Label(caption) +{ +} + +void Label::draw(gcn::Graphics* graphics) +{ + setForegroundColor(guiPalette->getColor(Palette::TEXT)); + gcn::Label::draw(static_cast<gcn::Graphics*>(graphics)); +} diff --git a/src/gui/label.h b/src/gui/label.h new file mode 100644 index 00000000..961286e0 --- /dev/null +++ b/src/gui/label.h @@ -0,0 +1,55 @@ +/* + * Aethyra + * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson + * Copyright (c) 2009 Aethyra Development Team + * + * This file is part of Aethyra based on original code + * from GUIChan. + * + * 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 LABEL_H +#define LABEL_H + +#include <guichan/widgets/label.hpp> + +/** + * Label widget. Same as the Guichan label but modified to use the palette + * system. + * + * \ingroup GUI + */ +class Label : public gcn::Label +{ + public: + /** + * Constructor. + */ + Label(); + + /** + * Constructor. This version of the constructor sets the label with an + * inintialization string. + */ + Label(const std::string& caption); + + /** + * Draws the label. + */ + void draw(gcn::Graphics* graphics); +}; + +#endif diff --git a/src/gui/login.cpp b/src/gui/login.cpp index 414de40e..5eaf6626 100644 --- a/src/gui/login.cpp +++ b/src/gui/login.cpp @@ -19,10 +19,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <guichan/widgets/label.hpp> - #include "button.h" #include "checkbox.h" +#include "label.h" #include "listbox.h" #include "login.h" #include "ok_dialog.h" @@ -48,11 +47,11 @@ static const int FIELD_WIDTH = LOGIN_DIALOG_WIDTH - 70; LoginDialog::LoginDialog(LoginData *loginData): Window(_("Login")), mLoginData(loginData) { - gcn::Label *userLabel = new gcn::Label(_("Name:")); - gcn::Label *passLabel = new gcn::Label(_("Password:")); - gcn::Label *serverLabel = new gcn::Label(_("Server:")); - gcn::Label *portLabel = new gcn::Label(_("Port:")); - gcn::Label *dropdownLabel = new gcn::Label(_("Recent:")); + gcn::Label *userLabel = new Label(_("Name:")); + gcn::Label *passLabel = new Label(_("Password:")); + gcn::Label *serverLabel = new Label(_("Server:")); + gcn::Label *portLabel = new Label(_("Port:")); + gcn::Label *dropdownLabel = new Label(_("Recent:")); std::vector<std::string> dfltServer; dfltServer.push_back("server.themanaworld.org"); std::vector<std::string> dfltPort; @@ -113,11 +112,10 @@ LoginDialog::LoginDialog(LoginData *loginData): center(); setVisible(true); - if (mUserField->getText().empty()) { + if (mUserField->getText().empty()) mUserField->requestFocus(); - } else { + else mPassField->requestFocus(); - } mOkButton->setEnabled(canSubmit()); } @@ -152,14 +150,12 @@ void LoginDialog::action(const gcn::ActionEvent &event) { // Transfer these fields on to the register dialog mLoginData->hostname = mServerField->getText(); + if (isUShort(mPortField->getText())) - { mLoginData->port = getUShort(mPortField->getText()); - } else - { mLoginData->port = 6901; - } + mLoginData->username = mUserField->getText(); mLoginData->password = mPassField->getText(); @@ -192,14 +188,12 @@ bool LoginDialog::isUShort(const std::string &str) strPtr != strEnd; ++strPtr) { if (*strPtr < '0' || *strPtr > '9') - { return false; - } + l = l * 10 + (*strPtr - '0'); // *strPtr - '0' will never be negative + if (l > 65535) - { return false; - } } return true; } @@ -275,9 +269,7 @@ void LoginDialog::DropDownList::save(const std::string &server, ++sPtr, ++pPtr) { if (*sPtr != server || *pPtr != port) - { saveEntry(*sPtr, *pPtr, position); - } } } @@ -289,26 +281,23 @@ int LoginDialog::DropDownList::getNumberOfElements() std::string LoginDialog::DropDownList::getElementAt(int i) { if (i < 0 || i >= getNumberOfElements()) - { - return ""; - } + return ""; + return getServerAt(i) + ":" + getPortAt(i); } std::string LoginDialog::DropDownList::getServerAt(int i) { if (i < 0 || i >= getNumberOfElements()) - { return ""; - } + return mServers.at(i); } std::string LoginDialog::DropDownList::getPortAt(int i) { if (i < 0 || i >= getNumberOfElements()) - { return ""; - } + return mPorts.at(i); } diff --git a/src/gui/menuwindow.cpp b/src/gui/menuwindow.cpp index 97553586..62f3766f 100644 --- a/src/gui/menuwindow.cpp +++ b/src/gui/menuwindow.cpp @@ -25,7 +25,9 @@ #include "button.h" #include "menuwindow.h" -#include "windowcontainer.h" +#include "window.h" + +#include "../graphics.h" #include "../utils/gettext.h" @@ -49,13 +51,8 @@ namespace { } MenuWindow::MenuWindow(): - Window("") + Popup("Menu") { - setResizable(false); - setWindowName("Menu"); - setMovable(false); - setTitleBarHeight(0); - // Buttons static const char *buttonNames[] = { @@ -80,7 +77,7 @@ MenuWindow::MenuWindow(): h = btn->getHeight(); } - setPosition(windowContainer->getWidth() - x - 3, 3); + setPosition(graphics->getWidth() - x - 3, 3); setContentSize(x - 3, h); } diff --git a/src/gui/menuwindow.h b/src/gui/menuwindow.h index 9bb54e29..c3d5673e 100644 --- a/src/gui/menuwindow.h +++ b/src/gui/menuwindow.h @@ -22,14 +22,14 @@ #ifndef MENU_H #define MENU_H -#include "window.h" +#include "popup.h" /** * The Button Menu. * * \ingroup Interface */ -class MenuWindow : public Window +class MenuWindow : public Popup { public: /** diff --git a/src/gui/minimap.cpp b/src/gui/minimap.cpp index 57fd7457..d8c5d742 100644 --- a/src/gui/minimap.cpp +++ b/src/gui/minimap.cpp @@ -79,19 +79,6 @@ void Minimap::setMapImage(Image *img) mMapImage->getWidth() + offsetX : titleWidth); setMaxHeight(mMapImage->getHeight() + offsetY); - // Make sure the window is within the minimum and maximum boundaries - // TODO: Shouldn't this be happening automatically within the Window - // class? - if (getMinWidth() > getWidth()) - setWidth(getMinWidth()); - else if (getMaxWidth() < getWidth()) - setWidth(getMaxWidth()); - if (getMinHeight() > getHeight()) - setHeight(getMinHeight()); - else if (getMaxHeight() < getHeight()) - setHeight(getMaxHeight()); - - setContentSize(getWidth() - offsetX, getHeight() - offsetY); setDefaultSize(getX(), getY(), getWidth(), getHeight()); resetToDefaultSize(); diff --git a/src/gui/ministatus.cpp b/src/gui/ministatus.cpp index 9a3d27cc..9f789a9d 100644 --- a/src/gui/ministatus.cpp +++ b/src/gui/ministatus.cpp @@ -32,13 +32,8 @@ #include "../utils/stringutils.h" MiniStatusWindow::MiniStatusWindow(): - Window("") + Popup("MiniStatus") { - setWindowName("MiniStatus"); - setResizable(false); - setMovable(false); - setTitleBarHeight(0); - mHpBar = new ProgressBar(1.0f, 100, 20, 0, 171, 34); mMpBar = new ProgressBar(1.0f, 100, 20, 26, 102, 230); mXpBar = new ProgressBar(1.0f, 100, 20, 143, 192, 211); @@ -53,8 +48,6 @@ MiniStatusWindow::MiniStatusWindow(): setContentSize(mXpBar->getX() + mXpBar->getWidth(), mXpBar->getY() + mXpBar->getHeight()); - setDefaultSize(0, 0, getWidth(), getHeight()); - loadWindowState(); } void MiniStatusWindow::setIcon(int index, AnimatedSprite *sprite) diff --git a/src/gui/ministatus.h b/src/gui/ministatus.h index f262a2a0..6e47f490 100644 --- a/src/gui/ministatus.h +++ b/src/gui/ministatus.h @@ -22,7 +22,7 @@ #ifndef MINISTATUS_H #define MINISTATUS_H -#include "window.h" +#include "popup.h" #include <vector> @@ -34,7 +34,7 @@ class ProgressBar; * * \ingroup Interface */ -class MiniStatusWindow : public Window +class MiniStatusWindow : public Popup { public: /** diff --git a/src/gui/npc_text.cpp b/src/gui/npc_text.cpp index 5bc654b8..5bde7f36 100644 --- a/src/gui/npc_text.cpp +++ b/src/gui/npc_text.cpp @@ -43,7 +43,7 @@ NpcTextDialog::NpcTextDialog(Network *network): setMinWidth(200); setMinHeight(150); - setDefaultSize(0, 0, 260, 200); + setDefaultSize(260, 200, ImageRect::CENTER); mTextBox = new TextBox; mTextBox->setEditable(false); @@ -140,3 +140,9 @@ void NpcTextDialog::widgetResized(const gcn::Event &event) setText(mText); } + +void NpcTextDialog::requestFocus() +{ + loadWindowState(); + setVisible(true); +} diff --git a/src/gui/npc_text.h b/src/gui/npc_text.h index f030115b..011c7bcf 100644 --- a/src/gui/npc_text.h +++ b/src/gui/npc_text.h @@ -77,11 +77,24 @@ class NpcTextDialog : public Window, public gcn::ActionListener void showCloseButton(); + /** + * Notifies the server that the client has performed a next action. + */ void nextDialog(int npcID = current_npc); + /** + * Notifies the server that the client has performed a close action. + */ void closeDialog(int npcID = current_npc); /** + * Initializes window width to the last known setting. Since the dialog + * doesn't need any extra focus outside of what it's given in the Game + * class, this is all it does for now. + */ + void requestFocus(); + + /** * Called when resizing the window. * * @param event The calling event diff --git a/src/gui/npcintegerdialog.cpp b/src/gui/npcintegerdialog.cpp index 643a7ef8..896f3380 100644 --- a/src/gui/npcintegerdialog.cpp +++ b/src/gui/npcintegerdialog.cpp @@ -40,14 +40,16 @@ NpcIntegerDialog::NpcIntegerDialog(Network *network): setWindowName("NPCInteger"); mValueField = new IntTextField; + setDefaultSize(175, 75, ImageRect::CENTER); + mDecButton = new Button("-", "decvalue", this); mIncButton = new Button("+", "incvalue", this); gcn::Button *okButton = new Button(_("OK"), "ok", this); gcn::Button *cancelButton = new Button(_("Cancel"), "cancel", this); gcn::Button *resetButton = new Button(_("Reset"), "reset", this); - mDecButton->setSize(20, 20); - mIncButton->setSize(20, 20); + mDecButton->adjustSize(); + mDecButton->setWidth(mIncButton->getWidth()); ContainerPlacer place; place = getPlacer(0, 0); diff --git a/src/gui/npclistdialog.cpp b/src/gui/npclistdialog.cpp index d280a982..ef8b0627 100644 --- a/src/gui/npclistdialog.cpp +++ b/src/gui/npclistdialog.cpp @@ -38,7 +38,7 @@ #include "../utils/strprintf.h" NpcListDialog::NpcListDialog(Network *network): - Window(_("NPC")), mNetwork(network) + Window("NPC"), mNetwork(network) { setWindowName("NPCList"); setResizable(true); @@ -46,7 +46,7 @@ NpcListDialog::NpcListDialog(Network *network): setMinWidth(200); setMinHeight(150); - setDefaultSize(0, 0, 260, 200); + setDefaultSize(260, 200, ImageRect::CENTER); mItemList = new ListBox(this); mItemList->setWrappingEnabled(true); @@ -60,8 +60,8 @@ NpcListDialog::NpcListDialog(Network *network): scrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER); place(0, 0, scrollArea, 5).setPadding(3); - place(3, 1, okButton); - place(4, 1, cancelButton); + place(3, 1, cancelButton); + place(4, 1, okButton); Layout &layout = getLayout(); layout.setRowHeight(0, Layout::AUTO_SET); @@ -121,6 +121,7 @@ void NpcListDialog::action(const gcn::ActionEvent &event) if (choice) { setVisible(false); + saveWindowState(); reset(); MessageOut outMsg(mNetwork); @@ -144,4 +145,6 @@ void NpcListDialog::requestFocus() { mItemList->requestFocus(); mItemList->setSelected(0); + loadWindowState(); + setVisible(true); } diff --git a/src/gui/npclistdialog.h b/src/gui/npclistdialog.h index b5a62515..f5f2147b 100644 --- a/src/gui/npclistdialog.h +++ b/src/gui/npclistdialog.h @@ -77,7 +77,8 @@ class NpcListDialog : public Window, public gcn::ActionListener, void setVisible(bool visible); /** - * Requests the listbox to take focus for input. + * Requests the listbox to take focus for input and sets window width + * to the last known setting. */ void requestFocus(); diff --git a/src/gui/npcstringdialog.cpp b/src/gui/npcstringdialog.cpp index 7ae2d5ed..c2379e7a 100644 --- a/src/gui/npcstringdialog.cpp +++ b/src/gui/npcstringdialog.cpp @@ -40,6 +40,8 @@ NpcStringDialog::NpcStringDialog(Network *network): setWindowName("NPCString"); mValueField = new TextField(""); + setDefaultSize(175, 75, ImageRect::CENTER); + gcn::Button *okButton = new Button(_("OK"), "ok", this); gcn::Button *cancelButton = new Button(_("Cancel"), "cancel", this); diff --git a/src/gui/palette.cpp b/src/gui/palette.cpp index fec04145..b1e165aa 100644 --- a/src/gui/palette.cpp +++ b/src/gui/palette.cpp @@ -1,6 +1,7 @@ /* * Configurable text colors * Copyright (C) 2008 Douglas Boffey <dougaboffey@netscape.net> + * Copyright (C) 2009 The Mana World Development Team * * This file is part of The Mana World. * @@ -32,7 +33,7 @@ const gcn::Color Palette::BLACK = gcn::Color(0, 0, 0); -const gcn::Color Palette::RAINBOW_COLORS[8] = { +const gcn::Color Palette::RAINBOW_COLORS[7] = { gcn::Color(255, 0, 0), gcn::Color(255, 153, 0), gcn::Color(255, 255, 0), @@ -54,9 +55,8 @@ std::string Palette::getConfigName(const std::string &typeName) if (i == 0 || typeName[i] == '_') { if (i > 0) - { i++; - } + res[pos] = typeName[i]; } else @@ -72,9 +72,9 @@ std::string Palette::getConfigName(const std::string &typeName) DEFENUMNAMES(ColorType, COLOR_TYPE) -const int Palette::GRADIENT_DELAY = 20; +const int Palette::GRADIENT_DELAY = 40; -Palette::Palette() : +Palette::Palette() : mRainbowTime(tick_time), mColVector(ColVector(TYPE_COUNT)) { @@ -82,10 +82,12 @@ Palette::Palette() : addColor(TEXT, 0x000000, STATIC, _("Text")); addColor(SHADOW, 0x000000, STATIC, indent + _("Text Shadow")); addColor(OUTLINE, 0x000000, STATIC, indent + _("Text Outline")); + addColor(PROGRESS_BAR, 0xffffff, STATIC, indent + _("Progress Bar Labels")); addColor(BACKGROUND, 0xffffff, STATIC, _("Background")); addColor(HIGHLIGHT, 0xebc873, STATIC, _("Highlight"), 'H'); + addColor(TAB_HIGHLIGHT, 0xff0000, PULSE, indent + _("Tab Highlight")); addColor(SHOP_WARNING, 0x910000, STATIC, indent + _("Item too expensive")); @@ -106,6 +108,20 @@ Palette::Palette() : addColor(NPC, 0xc8c8ff, STATIC, indent + _("NPCs")); addColor(MONSTER, 0xff4040, STATIC, indent + _("Monsters")); + addColor(UNKNOWN_ITEM, 0x000000, STATIC, _("Unknown Item Type")); + addColor(GENERIC, 0x21a5b1, STATIC, indent + _("Generic")); + addColor(HEAD, 0x527fa4, STATIC, indent + _("Hat")); + addColor(USABLE, 0x268d24, STATIC, indent + _("Usable")); + addColor(TORSO, 0xd12aa4, STATIC, indent + _("Shirt")); + addColor(ONEHAND, 0xf42a2a, STATIC, indent + _("1 Handed Weapons")); + addColor(LEGS, 0x699900, STATIC, indent + _("Pants")); + addColor(FEET, 0xaa1d48, STATIC, indent + _("Shoes")); + addColor(TWOHAND, 0xf46d0e, STATIC, indent + _("2 Handed Weapons")); + addColor(SHIELD, 0x9c2424, STATIC, indent + _("Shield")); + addColor(RING, 0x0000ff, STATIC, indent + _("Ring")); + addColor(ARMS, 0x9c24e8, STATIC, indent + _("Arms")); + addColor(AMMO, 0x8b6311, STATIC, indent + _("Ammo")); + addColor(PARTICLE, 0xffffff, STATIC, _("Particle Effects")); addColor(PICKUP_INFO, 0x28dc28, STATIC, indent + _("Pickup Notification")); addColor(EXP_INFO, 0xffff00, STATIC, indent + _("Exp Notification")); @@ -122,12 +138,11 @@ Palette::~Palette() { const std::string *configName; for (ColVector::iterator col = mColVector.begin(), - colEnd = mColVector.end(); - col != colEnd; ++col) + colEnd = mColVector.end(); col != colEnd; ++col) { configName = &ColorTypeNames[col->type]; config.setValue(*configName + "Gradient", col->committedGrad); - if (col->grad == STATIC) + if (col->grad == STATIC || col->grad == PULSE) { config.setValue(*configName, toString(col->getRGB())); } @@ -137,7 +152,7 @@ Palette::~Palette() const gcn::Color& Palette::getColor(char c, bool &valid) { for (ColVector::const_iterator col = mColVector.begin(), - colEnd = mColVector.end(); col != colEnd; ++col) + colEnd = mColVector.end(); col != colEnd; ++col) { if (col->ch == c) { @@ -209,6 +224,10 @@ void Palette::commit(bool commitNonStatic) { i->committedColor = i->color; } + else if (i->grad == PULSE) + { + i->committedColor = i->testColor; + } } } @@ -223,13 +242,19 @@ void Palette::rollback() setGradient(i->type, i->committedGrad); } setColor(i->type, i->committedColor.r, i->committedColor.g, - i->committedColor.b); + i->committedColor.b); + if (i->grad == PULSE) + { + i->testColor.r = i->committedColor.r; + i->testColor.g = i->committedColor.g; + i->testColor.b = i->committedColor.b; + } } } void Palette::addColor(Palette::ColorType type, int rgb, - Palette::GradientType grad, - const std::string &text, char c) + Palette::GradientType grad, + const std::string &text, char c) { const std::string *configName = &ColorTypeNames[type]; gcn::Color trueCol = (int)config.getValue(*configName, rgb); @@ -246,7 +271,7 @@ void Palette::advanceGradient () if (get_elapsed_time(mRainbowTime) > 5) { int pos, colIndex, colVal; - // For slower systems, advance can be greater than one (adcanve > 1 + // For slower systems, advance can be greater than one (advance > 1 // skips advance-1 steps). Should make gradient look the same // independent of the framerate. int advance = get_elapsed_time(mRainbowTime) / 5; @@ -256,25 +281,35 @@ void Palette::advanceGradient () { mGradVector[i]->gradientIndex = (mGradVector[i]->gradientIndex + advance) % - (GRADIENT_DELAY * - ((mGradVector[i]->grad == SPECTRUM) ? 6 : - RAINBOW_COLOR_COUNT)); + (GRADIENT_DELAY * ((mGradVector[i]->grad == SPECTRUM) ? + (mGradVector[i]->grad == PULSE) ? 255 : 6 : + RAINBOW_COLOR_COUNT)); pos = mGradVector[i]->gradientIndex % GRADIENT_DELAY; colIndex = mGradVector[i]->gradientIndex / GRADIENT_DELAY; + if (mGradVector[i]->grad == PULSE) + { + colVal = (int) (255.0 * (sin(M_PI * + (mGradVector[i]->gradientIndex) / 255) + 1) / 2); + + const gcn::Color* col = &mGradVector[i]->testColor; + + mGradVector[i]->color.r = ((colVal * col->r) / 255) % (col->r + 1); + mGradVector[i]->color.g = ((colVal * col->g) / 255) % (col->g + 1); + mGradVector[i]->color.b = ((colVal * col->b) / 255) % (col->b + 1); + } if (mGradVector[i]->grad == SPECTRUM) { if (colIndex % 2) { // falling curve - colVal = (int)(255.0 * - (cos(M_PI * pos / GRADIENT_DELAY) + 1) / 2); + colVal = (int)(255.0 * (cos(M_PI * pos / GRADIENT_DELAY) + + 1) / 2); } else { // ascending curve - colVal = (int)(255.0 * - (cos(M_PI * (GRADIENT_DELAY-pos) / GRADIENT_DELAY) + - 1) / 2); + colVal = (int)(255.0 * (cos(M_PI * (GRADIENT_DELAY-pos) / + GRADIENT_DELAY) + 1) / 2); } mGradVector[i]->color.r = @@ -287,7 +322,7 @@ void Palette::advanceGradient () (colIndex == 3 || colIndex == 4) ? 255 : (colIndex == 2 || colIndex == 5) ? colVal : 0; } - else + else if (mGradVector[i]->grad == RAINBOW) { const gcn::Color* startCol = &RAINBOW_COLORS[colIndex]; const gcn::Color* destCol = @@ -296,17 +331,14 @@ void Palette::advanceGradient () startColVal = (cos(M_PI * pos / GRADIENT_DELAY) + 1) / 2; destColVal = 1 - startColVal; - mGradVector[i]->color.r =(int)( - startColVal * startCol->r + - destColVal * destCol->r); + mGradVector[i]->color.r =(int)(startColVal * startCol->r + + destColVal * destCol->r); - mGradVector[i]->color.g =(int)( - startColVal * startCol->g + - destColVal * destCol->g); + mGradVector[i]->color.g =(int)(startColVal * startCol->g + + destColVal * destCol->g); - mGradVector[i]->color.b =(int)( - startColVal * startCol->b + - destColVal * destCol->b); + mGradVector[i]->color.b =(int)(startColVal * startCol->b + + destColVal * destCol->b); } } diff --git a/src/gui/palette.h b/src/gui/palette.h index e56bf9c5..1a466ed4 100644 --- a/src/gui/palette.h +++ b/src/gui/palette.h @@ -1,6 +1,7 @@ /* * Configurable text colors * Copyright (C) 2008 Douglas Boffey <dougaboffey@netscape.net> + * Copyright (C) 2009 The Mana World Development Team * * This file is part of The Mana World. * @@ -50,8 +51,10 @@ class Palette : public gcn::ListModel ENTRY(TEXT)\ ENTRY(SHADOW)\ ENTRY(OUTLINE)\ + ENTRY(PROGRESS_BAR)\ ENTRY(BACKGROUND)\ ENTRY(HIGHLIGHT)\ + ENTRY(TAB_HIGHLIGHT)\ ENTRY(SHOP_WARNING)\ ENTRY(CHAT)\ ENTRY(GM)\ @@ -68,6 +71,19 @@ class Palette : public gcn::ListModel ENTRY(GM_NAME)\ ENTRY(NPC)\ ENTRY(MONSTER)\ + ENTRY(UNKNOWN_ITEM)\ + ENTRY(GENERIC)\ + ENTRY(HEAD)\ + ENTRY(USABLE)\ + ENTRY(TORSO)\ + ENTRY(ONEHAND)\ + ENTRY(LEGS)\ + ENTRY(FEET)\ + ENTRY(TWOHAND)\ + ENTRY(SHIELD)\ + ENTRY(RING)\ + ENTRY(ARMS)\ + ENTRY(AMMO)\ ENTRY(PARTICLE)\ ENTRY(EXP_INFO)\ ENTRY(PICKUP_INFO)\ @@ -82,6 +98,7 @@ class Palette : public gcn::ListModel /** Colors can be static or can alter over time. */ enum GradientType { STATIC, + PULSE, SPECTRUM, RAINBOW }; @@ -136,6 +153,29 @@ class Palette : public gcn::ListModel } /** + * Gets the test color associated with the specified type. + * + * @param type the color type requested + * + * @return the requested test color + */ + inline const gcn::Color& getTestColor(ColorType type) + { + return mColVector[type].testColor; + } + + /** + * Sets the test color associated with the specified type. + * + * @param type the color type requested + * @param color the color that should be tested + */ + inline void setTestColor(ColorType type, gcn::Color color) + { + mColVector[type].testColor = color; + } + + /** * Gets the GradientType associated with the specified type. * * @param type the color type of the color @@ -252,6 +292,7 @@ class Palette : public gcn::ListModel { ColorType type; gcn::Color color; + gcn::Color testColor; gcn::Color committedColor; std::string text; char ch; @@ -270,7 +311,8 @@ class Palette : public gcn::ListModel ColorElem::gradientIndex = rand(); } - inline int getRGB() { + inline int getRGB() + { return (committedColor.r << 16) | (committedColor.g << 8) | committedColor.b; } diff --git a/src/gui/popup.cpp b/src/gui/popup.cpp new file mode 100644 index 00000000..17d299a5 --- /dev/null +++ b/src/gui/popup.cpp @@ -0,0 +1,209 @@ +/* + * Aethyra + * Copyright (C) 2009 Aethyra Development Team + * + * This file is part of Aethyra based on original code + * from 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 <algorithm> +#include <cassert> +#include <climits> + +#include <guichan/exception.hpp> + +#include "gui.h" +#include "skin.h" +#include "popup.h" +#include "window.h" +#include "windowcontainer.h" + +#include "../configlistener.h" +#include "../configuration.h" +#include "../log.h" + +#include "../resources/image.h" + +ConfigListener *Popup::popupConfigListener = 0; +int Popup::instances = 0; +bool Popup::mAlphaChanged = false; + +class PopupConfigListener : public ConfigListener +{ + void optionChanged(const std::string &) + { + Popup::mAlphaChanged = true; + } +}; + +Popup::Popup(const std::string& name, Window *parent, + const std::string& skin): + mParent(parent), + mPopupName(name), + mMinWidth(100), + mMinHeight(40), + mMaxWidth(INT_MAX), + mMaxHeight(INT_MAX) +{ + logger->log("Popup::Popup(\"%s\")", name.c_str()); + + if (!windowContainer) + throw GCN_EXCEPTION("Popup::Popup(): no windowContainer set"); + + if (instances == 0) + { + popupConfigListener = new PopupConfigListener(); + // Send GUI alpha changed for initialization + popupConfigListener->optionChanged("guialpha"); + config.addListener("guialpha", popupConfigListener); + } + + setPadding(3); + + instances++; + + // Loads the skin + mSkin = skinLoader->load(skin); + + setGuiAlpha(); + + // Add this window to the window container + windowContainer->add(this); + + // Popups are invisible by default + setVisible(false); +} + +Popup::~Popup() +{ + logger->log("Popup::~Popup(\"%s\")", mPopupName.c_str()); + + while (!mWidgets.empty()) + { + gcn::Widget *w = mWidgets.front(); + remove(w); + delete(w); + } + + instances--; + + mSkin->instances--; + + if (instances == 0) + { + config.removeListener("guialpha", popupConfigListener); + delete popupConfigListener; + popupConfigListener = NULL; + } +} + +void Popup::setWindowContainer(WindowContainer *wc) +{ + windowContainer = wc; +} + +void Popup::draw(gcn::Graphics *graphics) +{ + if (!isVisible()) + return; + + Graphics *g = static_cast<Graphics*>(graphics); + + g->drawImageRect(0, 0, getWidth(), getHeight(), mSkin->getBorder()); + + // Update Popup alpha values + if (mAlphaChanged) + { + for_each(mSkin->getBorder().grid, mSkin->getBorder().grid + 9, + std::bind2nd(std::mem_fun(&Image::setAlpha), + config.getValue("guialpha", 0.8))); + } + drawChildren(graphics); +} + +gcn::Rectangle Popup::getChildrenArea() +{ + return gcn::Rectangle(getPadding(), 0, getWidth() - getPadding() * 2, + getHeight() - getPadding() * 2); +} + +void Popup::setContentSize(int width, int height) +{ + width += 2 * getPadding(); + height += 2 * getPadding(); + + if (getMinWidth() > width) + width = getMinWidth(); + else if (getMaxWidth() < width) + width = getMaxWidth(); + if (getMinHeight() > height) + height = getMinHeight(); + else if (getMaxHeight() < height) + height = getMaxHeight(); + + setSize(width, height); +} + +void Popup::setLocationRelativeTo(gcn::Widget *widget) +{ + int wx, wy; + int x, y; + + widget->getAbsolutePosition(wx, wy); + getAbsolutePosition(x, y); + + setPosition(getX() + (wx + (widget->getWidth() - getWidth()) / 2 - x), + getY() + (wy + (widget->getHeight() - getHeight()) / 2 - y)); +} + +void Popup::setMinWidth(unsigned int width) +{ + mMinWidth = width > mSkin->getMinWidth() ? width : mSkin->getMinWidth(); +} + +void Popup::setMinHeight(unsigned int height) +{ + mMinHeight = height > mSkin->getMinHeight() ? height : mSkin->getMinHeight(); +} + +void Popup::setMaxWidth(unsigned int width) +{ + mMaxWidth = width; +} + +void Popup::setMaxHeight(unsigned int height) +{ + mMaxHeight = height; +} + +void Popup::scheduleDelete() +{ + windowContainer->scheduleDelete(this); +} + +void Popup::setGuiAlpha() +{ + //logger->log("Popup::setGuiAlpha: Alpha Value %f", config.getValue("guialpha", 0.8)); + for (int i = 0; i < 9; i++) + { + //logger->log("Popup::setGuiAlpha: Border Image (%i)", i); + mSkin->getBorder().grid[i]->setAlpha(config.getValue("guialpha", 0.8)); + } + + mAlphaChanged = false; +} + diff --git a/src/gui/popup.h b/src/gui/popup.h new file mode 100644 index 00000000..bfe8d7e9 --- /dev/null +++ b/src/gui/popup.h @@ -0,0 +1,194 @@ +/* + * Aethyra + * Copyright (C) 2009 Aethyra Development Team + * + * This file is part of Aethyra based on original code + * from 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 POPUP_H +#define POPUP_H + +#include <guichan/widgets/container.hpp> + +#include "../graphics.h" +#include "../guichanfwd.h" + +class ConfigListener; +class Skin; +class SkinLoader; +class Window; +class WindowContainer; + +/** + * A rather reduced down version of the Window class that is particularly suited + * for + * + * \ingroup GUI + */ +class Popup : public gcn::Container +{ + public: + friend class PopupConfigListener; + + /** + * Constructor. Initializes the title to the given text and hooks + * itself into the popup container. + * + * @param name A human readable name for the popup. Only useful for + * debugging purposes. + * @param parent The parent Window. This is the Window standing above + * this one in the Window hiearchy. When reordering, + * a Popup will never go below its parent Window. + * @param skin The location where the Popup's skin XML can be found. + */ + Popup(const std::string& name = "", Window *parent = NULL, + const std::string &skin = "graphics/gui/gui.xml"); + + /** + * Destructor. Deletes all the added widgets. + */ + ~Popup(); + + /** + * Sets the window container to be used by new popups. + */ + static void setWindowContainer(WindowContainer *windowContainer); + + /** + * Draws the popup. + */ + void draw(gcn::Graphics *graphics); + + /** + * Sets the size of this popup. + */ + void setContentSize(int width, int height); + + /** + * Sets the location relative to the given widget. + */ + void setLocationRelativeTo(gcn::Widget *widget); + + /** + * Sets the minimum width of the popup. + */ + void setMinWidth(unsigned int width); + + /** + * Sets the minimum height of the popup. + */ + void setMinHeight(unsigned int height); + + /** + * Sets the maximum width of the popup. + */ + void setMaxWidth(unsigned int width); + + /** + * Sets the minimum height of the popup. + */ + void setMaxHeight(unsigned int height); + + /** + * Gets the minimum width of the popup. + */ + int getMinWidth() { return mMinWidth; } + + /** + * Gets the minimum height of the popup. + */ + int getMinHeight() { return mMinHeight; } + + /** + * Gets the maximum width of the popup. + */ + int getMaxWidth() { return mMaxWidth; } + + /** + * Gets the minimum height of the popup. + */ + int getMaxHeight() { return mMaxHeight; } + + /** + * Gets the padding of the popup. The padding is the distance between + * the popup border and the content. + * + * @return The padding of the popup. + * @see setPadding + */ + unsigned int getPadding() const { return mPadding; } + + /** + * Sets the padding of the popup. The padding is the distance between the + * popup border and the content. + * + * @param padding The padding of the popup. + * @see getPadding + */ + void setPadding(unsigned int padding) { mPadding = padding; } + + /** + * Returns the parent Window. + * + * @return The parent Window or <code>NULL</code> if there is none. + */ + Window* getParentWindow() { return mParent; } + + /** + * Sets the name of the popup. This is only useful for debug purposes. + */ + void setPopupName(const std::string &name) { mPopupName = name; } + + /** + * Returns the name of the popup. This is only useful for debug purposes. + */ + const std::string& getPopupName() { return mPopupName; } + + /** + * Schedule this popup for deletion. It will be deleted at the start + * of the next logic update. + */ + void scheduleDelete(); + + // Inherited from BasicContainer + + virtual gcn::Rectangle getChildrenArea(); + + private: + void setGuiAlpha(); + + Window *mParent; /**< The parent Window (if there is one) */ + std::string mPopupName; /**< Name of the Popup */ + static bool mAlphaChanged; /**< Whether the alpha percent was changed */ + int mMinWidth; /**< Minimum Popup width */ + int mMinHeight; /**< Minimum Popup height */ + int mMaxWidth; /**< Maximum Popup width */ + int mMaxHeight; /**< Maximum Popup height */ + unsigned int mPadding; /**< Holds the padding of the window. */ + + /** + * The config listener that listens to changes relevant to all Popups. + */ + static ConfigListener *popupConfigListener; + + static int instances; /**< Number of Popup instances */ + + Skin* mSkin; /**< Skin in use by this Popup */ +}; + +#endif diff --git a/src/gui/popupmenu.cpp b/src/gui/popupmenu.cpp index 4577baee..7627c1ad 100644 --- a/src/gui/popupmenu.cpp +++ b/src/gui/popupmenu.cpp @@ -26,11 +26,11 @@ #include "inventorywindow.h" #include "item_amount.h" #include "popupmenu.h" -#include "windowcontainer.h" #include "../being.h" #include "../beingmanager.h" #include "../floor_item.h" +#include "../graphics.h" #include "../item.h" #include "../localplayer.h" #include "../npc.h" @@ -305,10 +305,10 @@ void PopupMenu::showPopup(int x, int y, Item *item) void PopupMenu::showPopup(int x, int y) { setContentSize(mBrowserBox->getWidth() + 8, mBrowserBox->getHeight() + 8); - if (windowContainer->getWidth() < (x + getWidth() + 5)) - x = windowContainer->getWidth() - getWidth(); - if (windowContainer->getHeight() < (y + getHeight() + 5)) - y = windowContainer->getHeight() - getHeight(); + if (graphics->getWidth() < (x + getWidth() + 5)) + x = graphics->getWidth() - getWidth(); + if (graphics->getHeight() < (y + getHeight() + 5)) + y = graphics->getHeight() - getHeight(); setPosition(x, y); setVisible(true); requestMoveToTop(); diff --git a/src/gui/progressbar.cpp b/src/gui/progressbar.cpp index f0acfecf..58d7d815 100644 --- a/src/gui/progressbar.cpp +++ b/src/gui/progressbar.cpp @@ -22,6 +22,7 @@ #include <guichan/font.hpp> #include "gui.h" +#include "palette.h" #include "progressbar.h" #include "textrenderer.h" @@ -35,8 +36,6 @@ ImageRect ProgressBar::mBorder; int ProgressBar::mInstances = 0; float ProgressBar::mAlpha = config.getValue("guialpha", 0.8); -const gcn::Color ProgressBar::TEXT_COLOR = gcn::Color(255, 255, 255); - ProgressBar::ProgressBar(float progress, unsigned int width, unsigned int height, Uint8 red, Uint8 green, Uint8 blue): @@ -121,23 +120,22 @@ void ProgressBar::draw(gcn::Graphics *graphics) // The bar if (mProgress > 0) { - graphics->setColor(gcn::Color(mRed, mGreen, mBlue, alpha)); graphics->fillRectangle(gcn::Rectangle(4, 4, - (int) (mProgress * (getWidth() - 8)), - getHeight() - 8)); + (int) (mProgress * (getWidth() - 8)), + getHeight() - 8)); } // The label if (!mText.empty()) { - gcn::Font *f = boldFont; - int textX = getWidth() / 2; - int textY = (getHeight() - f->getHeight()) / 2; + const int textX = getWidth() / 2; + const int textY = (getHeight() - boldFont->getHeight()) / 2; TextRenderer::renderText(graphics, mText, textX, textY, - gcn::Graphics::CENTER, &TEXT_COLOR, f, true, - false); + gcn::Graphics::CENTER, + guiPalette->getColor(Palette::PROGRESS_BAR, + alpha), boldFont, true, false); } } diff --git a/src/gui/recorder.cpp b/src/gui/recorder.cpp index ce097db2..479ab76b 100644 --- a/src/gui/recorder.cpp +++ b/src/gui/recorder.cpp @@ -40,9 +40,11 @@ Recorder::Recorder(ChatWindow *chat, const std::string &title, mChat = chat; Button *button = new Button(buttonTxt, "activate", this); - setDefaultSize(0, windowContainer->getHeight() - 123 - button->getHeight() - - offsetY, button->getWidth() + offsetX, button->getHeight() + - offsetY); + + // 123 is the default chat window height. If you change this in Chat, please + // change it here as well + setDefaultSize(button->getWidth() + offsetX, button->getHeight() + + offsetY, ImageRect::LOWER_LEFT, 0, 123); place(0, 0, button); diff --git a/src/gui/register.cpp b/src/gui/register.cpp index 25c97713..0e8a99ca 100644 --- a/src/gui/register.cpp +++ b/src/gui/register.cpp @@ -19,8 +19,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <guichan/widgets/label.hpp> - #include "../configuration.h" #include "../log.h" #include "../logindata.h" @@ -28,6 +26,7 @@ #include "button.h" #include "checkbox.h" +#include "label.h" #include "login.h" #include "ok_dialog.h" #include "passwordfield.h" @@ -46,7 +45,8 @@ * to the field which contained wrong data when the Ok button was pressed on * the error notice. */ -class WrongDataNoticeListener : public gcn::ActionListener { +class WrongDataNoticeListener : public gcn::ActionListener +{ public: void setTarget(gcn::TextField *textField); void action(const gcn::ActionEvent &event); @@ -62,22 +62,19 @@ void WrongDataNoticeListener::setTarget(gcn::TextField *textField) void WrongDataNoticeListener::action(const gcn::ActionEvent &event) { if (event.getId() == "ok") - { mTarget->requestFocus(); - } } - RegisterDialog::RegisterDialog(LoginData *loginData): Window(_("Register")), mWrongDataNoticeListener(new WrongDataNoticeListener), mLoginData(loginData) { - gcn::Label *userLabel = new gcn::Label(_("Name:")); - gcn::Label *passwordLabel = new gcn::Label(_("Password:")); - gcn::Label *confirmLabel = new gcn::Label(_("Confirm:")); - gcn::Label *serverLabel = new gcn::Label(_("Server:")); - gcn::Label *portLabel = new gcn::Label(_("Port:")); + gcn::Label *userLabel = new Label(_("Name:")); + gcn::Label *passwordLabel = new Label(_("Password:")); + gcn::Label *confirmLabel = new Label(_("Confirm:")); + gcn::Label *serverLabel = new Label(_("Server:")); + gcn::Label *portLabel = new Label(_("Port:")); mUserField = new TextField(loginData->username); mPasswordField = new PasswordField(loginData->password); mConfirmField = new PasswordField; diff --git a/src/gui/sell.cpp b/src/gui/sell.cpp index e1b15bac..fe391636 100644 --- a/src/gui/sell.cpp +++ b/src/gui/sell.cpp @@ -19,9 +19,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <guichan/widgets/label.hpp> - #include "button.h" +#include "label.h" #include "scrollarea.h" #include "sell.h" #include "shop.h" @@ -46,30 +45,36 @@ SellDialog::SellDialog(Network *network): { setWindowName("Sell"); setResizable(true); + setCloseButton(true); setMinWidth(260); setMinHeight(230); - setDefaultSize(0, 0, 260, 230); + setDefaultSize(260, 230, ImageRect::CENTER); // Create a ShopItems instance, that is aware of duplicate entries. mShopItems = new ShopItems(true); mShopItemList = new ShopListBox(mShopItems, mShopItems); mScrollArea = new ScrollArea(mShopItemList); + mScrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER); + mSlider = new Slider(1.0); - mQuantityLabel = new gcn::Label("0"); - mMoneyLabel = new gcn::Label(strprintf(_("Price: %s / Total: %s"), - "", "")); + + mQuantityLabel = new Label(strprintf("%d / %d", mAmountItems, mMaxItems)); + mQuantityLabel->setAlignment(gcn::Graphics::CENTER); + mMoneyLabel = new Label(strprintf(_("Price: %s / Total: %s"), + "", "")); + mIncreaseButton = new Button("+", "+", this); mDecreaseButton = new Button("-", "-", this); mSellButton = new Button(_("Sell"), "sell", this); mQuitButton = new Button(_("Quit"), "quit", this); - mItemDescLabel = new gcn::Label(strprintf(_("Description: %s"), "")); - mItemEffectLabel = new gcn::Label(strprintf(_("Effect: %s"), "")); + mAddMaxButton = new Button(_("Max"), "max", this); + mItemDescLabel = new Label(strprintf(_("Description: %s"), "")); + mItemEffectLabel = new Label(strprintf(_("Effect: %s"), "")); - mIncreaseButton->setSize(20, 20); - mDecreaseButton->setSize(20, 20); + mDecreaseButton->adjustSize(); + mDecreaseButton->setWidth(mIncreaseButton->getWidth()); - mScrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER); mIncreaseButton->setEnabled(false); mDecreaseButton->setEnabled(false); mSellButton->setEnabled(false); @@ -80,16 +85,21 @@ SellDialog::SellDialog(Network *network): mSlider->setActionEventId("slider"); mSlider->addActionListener(this); - place(0, 0, mScrollArea, 5).setPadding(3); - place(0, 1, mQuantityLabel, 2); - place(2, 1, mSlider, 3); - place(0, 2, mMoneyLabel, 5); - place(0, 3, mItemEffectLabel, 5); - place(0, 4, mItemDescLabel, 5); + ContainerPlacer place; + place = getPlacer(0, 0); + + place(0, 0, mScrollArea, 8, 5).setPadding(3); place(0, 5, mDecreaseButton); - place(1, 5, mIncreaseButton); - place(3, 5, mSellButton); - place(4, 5, mQuitButton); + place(1, 5, mSlider, 3); + place(4, 5, mIncreaseButton); + place(5, 5, mQuantityLabel, 2); + place(7, 5, mAddMaxButton); + place(0, 6, mMoneyLabel, 8); + place(0, 7, mItemEffectLabel, 8); + place(0, 8, mItemDescLabel, 8); + place(6, 9, mSellButton); + place(7, 9, mQuitButton); + Layout &layout = getLayout(); layout.setRowHeight(0, Layout::AUTO_SET); @@ -116,9 +126,7 @@ void SellDialog::reset() void SellDialog::addItem(const Item *item, int price) { if (!item) - { return; - } mShopItems->addItem(item->getInvIndex(), item->getId(), item->getQuantity(), price); @@ -128,15 +136,14 @@ void SellDialog::addItem(const Item *item, int price) void SellDialog::action(const gcn::ActionEvent &event) { - int selectedItem = mShopItemList->getSelected(); - if (event.getId() == "quit") { - setVisible(false); - current_npc = 0; + close(); return; } + int selectedItem = mShopItemList->getSelected(); + // The following actions require a valid item selection if (selectedItem == -1 || selectedItem >= (int) mShopItems->getNumberOfElements()) @@ -161,6 +168,12 @@ void SellDialog::action(const gcn::ActionEvent &event) mSlider->setValue(mAmountItems); updateButtonsAndLabels(); } + else if (event.getId() == "max") + { + mAmountItems = mMaxItems; + mSlider->setValue(mAmountItems); + updateButtonsAndLabels(); + } else if (event.getId() == "sell" && mAmountItems > 0 && mAmountItems <= mMaxItems) { @@ -279,5 +292,12 @@ void SellDialog::setVisible(bool visible) { Window::setVisible(visible); - if (visible) requestFocus(); + if (visible) + requestFocus(); +} + +void SellDialog::close() +{ + setVisible(false); + current_npc = 0; } diff --git a/src/gui/sell.h b/src/gui/sell.h index 3ae5e320..45b6a704 100644 --- a/src/gui/sell.h +++ b/src/gui/sell.h @@ -86,8 +86,15 @@ class SellDialog : public Window, gcn::ActionListener, gcn::SelectionListener */ void logic(); + /** + * Sets the visibility of this window. + */ void setVisible(bool visible); + /** + * Closes the Buy Window, as well as resetting the current npc. + */ + void close(); private: /** * Updates the state of buttons and labels. @@ -97,6 +104,7 @@ class SellDialog : public Window, gcn::ActionListener, gcn::SelectionListener Network *mNetwork; gcn::Button *mSellButton; gcn::Button *mQuitButton; + gcn::Button *mAddMaxButton; gcn::Button *mIncreaseButton; gcn::Button *mDecreaseButton; ShopListBox *mShopItemList; diff --git a/src/gui/setup.cpp b/src/gui/setup.cpp index 872596b0..849a30c2 100644 --- a/src/gui/setup.cpp +++ b/src/gui/setup.cpp @@ -34,16 +34,23 @@ #include "../utils/gettext.h" extern Window *chatWindow; -extern Window *equipmentWindow; -extern Window *helpWindow; +extern Window *statusWindow; +extern Window *buyDialog; +extern Window *sellDialog; +extern Window *buySellDialog; extern Window *inventoryWindow; -extern Window *minimap; +extern Window *emoteWindow; +extern Window *npcTextDialog; +extern Window *npcStringDialog; extern Window *skillDialog; -extern Window *statusWindow; +extern Window *minimap; +extern Window *equipmentWindow; +extern Window *tradeWindow; +extern Window *helpWindow; +extern Window *debugWindow; extern Window *itemShortcutWindow; extern Window *emoteShortcutWindow; -extern Window *emoteWindow; -extern Window *tradeWindow; +extern Window *storageWindow; Setup::Setup(): Window(_("Setup")) @@ -65,9 +72,8 @@ Setup::Setup(): add(btn); // Store this button, as it needs to be enabled/disabled - if (!strcmp(*curBtn, "Reset Windows")) { + if (!strcmp(*curBtn, "Reset Windows")) mResetWindows = btn; - } } TabbedArea *panel = new TabbedArea; @@ -130,17 +136,24 @@ void Setup::action(const gcn::ActionEvent &event) if (!statusWindow) return; - statusWindow->resetToDefaultSize(); - minimap->resetToDefaultSize(); chatWindow->resetToDefaultSize(); + statusWindow->resetToDefaultSize(); + buyDialog->resetToDefaultSize(); + sellDialog->resetToDefaultSize(); + buySellDialog->resetToDefaultSize(); inventoryWindow->resetToDefaultSize(); + emoteWindow->resetToDefaultSize(); + npcTextDialog->resetToDefaultSize(); + npcStringDialog->resetToDefaultSize(); + skillDialog->resetToDefaultSize(); + minimap->resetToDefaultSize(); equipmentWindow->resetToDefaultSize(); + tradeWindow->resetToDefaultSize(); helpWindow->resetToDefaultSize(); - skillDialog->resetToDefaultSize(); + debugWindow->resetToDefaultSize(); itemShortcutWindow->resetToDefaultSize(); emoteShortcutWindow->resetToDefaultSize(); - emoteWindow->resetToDefaultSize(); - tradeWindow->resetToDefaultSize(); + storageWindow->resetToDefaultSize(); } } diff --git a/src/gui/setup.h b/src/gui/setup.h index 919445b7..4c387d34 100644 --- a/src/gui/setup.h +++ b/src/gui/setup.h @@ -31,7 +31,6 @@ #include "../guichanfwd.h" class SetupTab; -class Button; /** * The setup dialog. @@ -51,13 +50,16 @@ class Setup : public Window, public gcn::ActionListener */ ~Setup(); - void setInGame(bool inGame); - /** * Event handling method. */ void action(const gcn::ActionEvent &event); + /** + * Enables the reset button when in game. + */ + void setInGame(bool inGame); + private: std::list<SetupTab*> mTabs; gcn::Button *mResetWindows; diff --git a/src/gui/setup_audio.cpp b/src/gui/setup_audio.cpp index a4bc05ae..2ca39282 100644 --- a/src/gui/setup_audio.cpp +++ b/src/gui/setup_audio.cpp @@ -19,9 +19,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <guichan/widgets/label.hpp> - #include "checkbox.h" +#include "label.h" #include "ok_dialog.h" #include "setup_audio.h" #include "slider.h" @@ -44,8 +43,8 @@ Setup_Audio::Setup_Audio(): { setOpaque(false); - gcn::Label *sfxLabel = new gcn::Label(_("Sfx volume")); - gcn::Label *musicLabel = new gcn::Label(_("Music volume")); + gcn::Label *sfxLabel = new Label(_("Sfx volume")); + gcn::Label *musicLabel = new Label(_("Music volume")); mSfxSlider->setActionEventId("sfx"); mMusicSlider->setActionEventId("music"); @@ -79,7 +78,8 @@ void Setup_Audio::apply() if (mSoundCheckBox->isSelected()) { config.setValue("sound", 1); - try { + try + { sound.init(); } catch (const char *err) diff --git a/src/gui/setup_colors.cpp b/src/gui/setup_colors.cpp index dcad8670..033ba372 100644 --- a/src/gui/setup_colors.cpp +++ b/src/gui/setup_colors.cpp @@ -23,12 +23,12 @@ #include <cmath> #include <guichan/listmodel.hpp> -#include <guichan/widgets/label.hpp> #include <guichan/widgets/slider.hpp> #include "browserbox.h" #include "gui.h" #include "itemlinkhandler.h" +#include "label.h" #include "listbox.h" #include "palette.h" #include "scrollarea.h" @@ -60,7 +60,7 @@ Setup_Colors::Setup_Colors() : mTextPreview = new TextPreview(&rawmsg); mPreview = new BrowserBox(BrowserBox::AUTO_WRAP); - mPreview->setOpaque(true); + mPreview->setOpaque(false); // don't do anything with links mPreview->setLinkHandler(NULL); @@ -70,18 +70,18 @@ Setup_Colors::Setup_Colors() : mPreviewBox->setScrollPolicy(gcn::ScrollArea::SHOW_NEVER, gcn::ScrollArea::SHOW_NEVER); - mGradTypeLabel = new gcn::Label(_("Type: ")); + mGradTypeLabel = new Label(_("Type: ")); - mGradTypeSlider = new Slider(0, 2); + mGradTypeSlider = new Slider(0, 3); mGradTypeSlider->setWidth(160); mGradTypeSlider->setActionEventId("slider_grad"); mGradTypeSlider->setValue(0); mGradTypeSlider->addActionListener(this); mGradTypeSlider->setEnabled(false); - mGradTypeText = new gcn::Label(); + mGradTypeText = new Label(); - mRedLabel = new gcn::Label(_("Red: ")); + mRedLabel = new Label(_("Red: ")); mRedText = new TextField; mRedText->setWidth(40); @@ -97,7 +97,7 @@ Setup_Colors::Setup_Colors() : mRedSlider->addActionListener(this); mRedSlider->setEnabled(false); - mGreenLabel = new gcn::Label(_("Green: ")); + mGreenLabel = new Label(_("Green: ")); mGreenText = new TextField; mGreenText->setWidth(40); @@ -113,7 +113,7 @@ Setup_Colors::Setup_Colors() : mGreenSlider->addActionListener(this); mGreenSlider->setEnabled(false); - mBlueLabel = new gcn::Label(_("Blue: ")); + mBlueLabel = new Label(_("Blue: ")); mBlueText = new TextField; mBlueText->setWidth(40); @@ -156,13 +156,9 @@ Setup_Colors::Setup_Colors() : Setup_Colors::~Setup_Colors() { if (mPreviewBox->getContent() == mPreview) - { delete mTextPreview; - } else - { delete mPreview; - } } void Setup_Colors::action(const gcn::ActionEvent &event) @@ -180,11 +176,12 @@ void Setup_Colors::action(const gcn::ActionEvent &event) mPreview->clearRows(); mPreviewBox->setContent(mTextPreview); mTextPreview->setFont(gui->getFont()); - mTextPreview->setTextColor( - &guiPalette->getColor(Palette::TEXT)); + mTextPreview->setTextColor(&guiPalette->getColor(Palette::TEXT)); mTextPreview->setTextBGColor(NULL); + mTextPreview->setOpaque(false); mTextPreview->setShadow(true); mTextPreview->setOutline(true); + mTextPreview->useTextAlpha(false); switch (type) { @@ -192,13 +189,30 @@ void Setup_Colors::action(const gcn::ActionEvent &event) case Palette::SHADOW: case Palette::OUTLINE: mTextPreview->setFont(gui->getFont()); - mTextPreview->setOutline(true); mTextPreview->setShadow(type == Palette::SHADOW); mTextPreview->setOutline(type == Palette::OUTLINE); break; + case Palette::PROGRESS_BAR: + mTextPreview->useTextAlpha(true); + mTextPreview->setFont(boldFont); + mTextPreview->setTextColor(col); + mTextPreview->setOutline(true); + mTextPreview->setShadow(false); + break; + case Palette::TAB_HIGHLIGHT: + mTextPreview->setFont(gui->getFont()); + mTextPreview->setTextColor(col); + mTextPreview->setOutline(false); + mTextPreview->setShadow(false); + break; case Palette::BACKGROUND: - case Palette::HIGHLIGHT: case Palette::SHOP_WARNING: + mTextPreview->setBGColor(col); + mTextPreview->setOpaque(true); + mTextPreview->setOutline(false); + mTextPreview->setShadow(false); + break; + case Palette::HIGHLIGHT: mTextPreview->setTextBGColor(col); mTextPreview->setOutline(false); mTextPreview->setShadow(false); @@ -217,15 +231,30 @@ void Setup_Colors::action(const gcn::ActionEvent &event) mPreview->clearRows(); if (ch == '<') - { msg = toString("@@|") + rawmsg + "@@"; - } else - { msg = "##" + toString(ch) + rawmsg; - } + mPreview->addRow(msg); break; + case Palette::UNKNOWN_ITEM: + case Palette::GENERIC: + case Palette::HEAD: + case Palette::USABLE: + case Palette::TORSO: + case Palette::ONEHAND: + case Palette::LEGS: + case Palette::FEET: + case Palette::TWOHAND: + case Palette::SHIELD: + case Palette::RING: + case Palette::ARMS: + case Palette::AMMO: + mTextPreview->setFont(boldFont); + mTextPreview->setTextColor(col); + mTextPreview->setOutline(false); + mTextPreview->setShadow(false); + break; case Palette::PARTICLE: case Palette::EXP_INFO: case Palette::PICKUP_INFO: @@ -242,14 +271,19 @@ void Setup_Colors::action(const gcn::ActionEvent &event) case Palette::MONSTER: mTextPreview->setFont(boldFont); mTextPreview->setTextColor(col); + case Palette::TYPE_COUNT: break; } - if (grad != Palette::STATIC) + if (grad != Palette::STATIC && grad != Palette::PULSE) { // If nonstatic color, don't display the current, but the committed // color at the sliders col = &guiPalette->getCommittedColor(type); } + else if (grad == Palette::PULSE) + { + col = &guiPalette->getTestColor(type); + } setEntry(mRedSlider, mRedText, col->r); setEntry(mGreenSlider, mGreenText, col->g); @@ -337,11 +371,10 @@ void Setup_Colors::listen(const TextField *tf) } } -void Setup_Colors::updateGradType() { +void Setup_Colors::updateGradType() +{ if (mSelected == -1) - { return; - } mSelected = mColorBox->getSelected(); Palette::ColorType type = guiPalette->getColorTypeAt(mSelected); @@ -349,9 +382,10 @@ void Setup_Colors::updateGradType() { mGradTypeText->setCaption( (grad == Palette::STATIC) ? _("Static") : + (grad == Palette::PULSE) ? _("Pulse") : (grad == Palette::RAINBOW) ? _("Rainbow") : _("Spectrum")); - bool enable = (grad == Palette::STATIC); + bool enable = (grad == Palette::STATIC || grad == Palette::PULSE); mRedText->setEnabled(enable); mRedSlider->setEnabled(enable); mGreenText->setEnabled(enable); @@ -363,13 +397,11 @@ void Setup_Colors::updateGradType() { void Setup_Colors::updateColor() { if (mSelected == -1) - { return; - } Palette::ColorType type = guiPalette->getColorTypeAt(mSelected); Palette::GradientType grad = - static_cast<Palette::GradientType>((int)mGradTypeSlider->getValue()); + static_cast<Palette::GradientType>(mGradTypeSlider->getValue()); guiPalette->setGradient(type, grad); if (grad == Palette::STATIC) @@ -379,4 +411,11 @@ void Setup_Colors::updateColor() static_cast<int>(mGreenSlider->getValue()), static_cast<int>(mBlueSlider->getValue())); } + else if (grad == Palette::PULSE) + { + guiPalette->setTestColor(type, gcn::Color( + static_cast<int>(mRedSlider->getValue()), + static_cast<int>(mGreenSlider->getValue()), + static_cast<int>(mBlueSlider->getValue()))); + } } diff --git a/src/gui/setup_joystick.cpp b/src/gui/setup_joystick.cpp index c0c04949..59a882c7 100644 --- a/src/gui/setup_joystick.cpp +++ b/src/gui/setup_joystick.cpp @@ -19,10 +19,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <guichan/widgets/label.hpp> - #include "button.h" #include "checkbox.h" +#include "label.h" #include "setup_joystick.h" #include "widgets/layouthelper.h" @@ -35,7 +34,7 @@ extern Joystick *joystick; Setup_Joystick::Setup_Joystick(): - mCalibrateLabel(new gcn::Label(_("Press the button to start calibration"))), + mCalibrateLabel(new Label(_("Press the button to start calibration"))), mCalibrateButton(new Button(_("Calibrate"), "calibrate", this)), mJoystickEnabled(new CheckBox(_("Enable joystick"))) { diff --git a/src/gui/setup_players.cpp b/src/gui/setup_players.cpp index 84dbed55..1451e71e 100644 --- a/src/gui/setup_players.cpp +++ b/src/gui/setup_players.cpp @@ -22,10 +22,9 @@ #include <string> #include <vector> -#include <guichan/widgets/label.hpp> - #include "button.h" #include "checkbox.h" +#include "label.h" #include "listbox.h" #include "ok_dialog.h" #include "scrollarea.h" @@ -137,7 +136,7 @@ public: for (unsigned int r = 0; r < player_names->size(); ++r) { std::string name = (*player_names)[r]; - gcn::Widget *widget = new gcn::Label(name); + gcn::Widget *widget = new Label(name); mWidgets.push_back(widget); gcn::ListModel *playerRelation = new PlayerRelationListModel; @@ -247,7 +246,7 @@ Setup_Players::Setup_Players(): for (int i = 0; i < COLUMNS_NR; i++) { mPlayerTableTitleModel->set(0, i, - new gcn::Label(gettext(table_titles[i]))); + new Label(gettext(table_titles[i]))); } mPlayerTitleTable->setLinewiseSelection(true); @@ -257,7 +256,7 @@ Setup_Players::Setup_Players(): mPlayerTable->setLinewiseSelection(true); mPlayerTable->addActionListener(this); - gcn::Label *ignore_action_label = new gcn::Label(_("When ignoring:")); + gcn::Label *ignore_action_label = new Label(_("When ignoring:")); mIgnoreActionChoicesBox->setActionEventId(ACTION_STRATEGY); mIgnoreActionChoicesBox->addActionListener(this); diff --git a/src/gui/setup_video.cpp b/src/gui/setup_video.cpp index ad133e7e..74574ec7 100644 --- a/src/gui/setup_video.cpp +++ b/src/gui/setup_video.cpp @@ -26,9 +26,8 @@ #include <guichan/key.hpp> #include <guichan/listmodel.hpp> -#include <guichan/widgets/label.hpp> - #include "checkbox.h" +#include "label.h" #include "listbox.h" #include "ok_dialog.h" #include "scrollarea.h" @@ -88,13 +87,15 @@ ModeListModel::ModeListModel() SDL_Rect **modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_HWSURFACE); /* Check which modes are available */ - if (modes == (SDL_Rect **)0) { + if (modes == (SDL_Rect **)0) logger->log("No modes available"); - } else if (modes == (SDL_Rect **)-1) { + else if (modes == (SDL_Rect **)-1) logger->log("All resolutions available"); - } else { + else + { //logger->log("Available Modes"); - for (int i = 0; modes[i]; ++i) { + for (int i = 0; modes[i]; ++i) + { const std::string modeString = toString((int)modes[i]->w) + "x" + toString((int)modes[i]->h); //logger->log(modeString.c_str()); @@ -121,15 +122,15 @@ Setup_Video::Setup_Video(): mCustomCursorCheckBox(new CheckBox(_("Custom cursor"), mCustomCursorEnabled)), mParticleEffectsCheckBox(new CheckBox(_("Particle effects"), mParticleEffectsEnabled)), mNameCheckBox(new CheckBox(_("Show name"), mNameEnabled)), - mPickupNotifyLabel(new gcn::Label(_("Show pickup notification"))), + mPickupNotifyLabel(new Label(_("Show pickup notification"))), mPickupChatCheckBox(new CheckBox(_("in chat"), mPickupChatEnabled)), mPickupParticleCheckBox(new CheckBox(_("as particle"), mPickupParticleEnabled)), mSpeechSlider(new Slider(0, 3)), - mSpeechLabel(new gcn::Label("")), + mSpeechLabel(new Label("")), mAlphaSlider(new Slider(0.2, 1.0)), mFpsCheckBox(new CheckBox(_("FPS Limit:"))), - mFpsSlider(new Slider(10, 200)), + mFpsSlider(new Slider(10, 120)), mFpsField(new TextField), mOriginalScrollLaziness((int) config.getValue("ScrollLaziness", 16)), mScrollLazinessSlider(new Slider(1, 64)), @@ -139,22 +140,22 @@ Setup_Video::Setup_Video(): mScrollRadiusField(new TextField), mOverlayDetail((int) config.getValue("OverlayDetail", 2)), mOverlayDetailSlider(new Slider(0, 2)), - mOverlayDetailField(new gcn::Label("")), + mOverlayDetailField(new Label("")), mParticleDetail(3 - (int) config.getValue("particleEmitterSkip", 1)), mParticleDetailSlider(new Slider(0, 3)), - mParticleDetailField(new gcn::Label("")) + mParticleDetailField(new Label("")) { setOpaque(false); ScrollArea *scrollArea = new ScrollArea(mModeList); scrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER); - speechLabel = new gcn::Label(_("Overhead text")); - alphaLabel = new gcn::Label(_("Gui opacity")); - scrollRadiusLabel = new gcn::Label(_("Scroll radius")); - scrollLazinessLabel = new gcn::Label(_("Scroll laziness")); - overlayDetailLabel = new gcn::Label(_("Ambient FX")); - particleDetailLabel = new gcn::Label(_("Particle Detail")); + speechLabel = new Label(_("Overhead text")); + alphaLabel = new Label(_("Gui opacity")); + scrollRadiusLabel = new Label(_("Scroll radius")); + scrollLazinessLabel = new Label(_("Scroll laziness")); + overlayDetailLabel = new Label(_("Ambient FX")); + particleDetailLabel = new Label(_("Particle Detail")); mModeList->setEnabled(true); #ifndef USE_OPENGL @@ -337,9 +338,11 @@ void Setup_Video::apply() } } #if defined(WIN32) || defined(__APPLE__) - } else { + } + else + { new OkDialog(_("Switching to full screen"), - _("Restart needed for changes to take effect.")); + _("Restart needed for changes to take effect.")); } #endif config.setValue("screen", fullscreen ? true : false); @@ -352,7 +355,7 @@ void Setup_Video::apply() // OpenGL can currently only be changed by restarting, notify user. new OkDialog(_("Changing OpenGL"), - _("Applying change to OpenGL requires restart.")); + _("Applying change to OpenGL requires restart.")); } // FPS change @@ -450,8 +453,9 @@ void Setup_Video::action(const gcn::ActionEvent &event) { config.setValue("particleeffects", mParticleEffectsCheckBox->isSelected() ? true : false); - new OkDialog(_("Particle effect settings changed"), - _("Restart your client or change maps for the change to take effect.")); + new OkDialog(_("Particle effect settings changed."), + _("Restart your client or change maps " + "for the change to take effect.")); } else if (event.getId() == "pickupchat") { @@ -461,8 +465,7 @@ void Setup_Video::action(const gcn::ActionEvent &event) else if (event.getId() == "pickupparticle") { config.setValue("showpickupparticle", - mPickupParticleCheckBox->isSelected() - ? true : false); + mPickupParticleCheckBox->isSelected() ? true : false); } else if (event.getId() == "speech") { @@ -576,9 +579,9 @@ void Setup_Video::keyPressed(gcn::KeyEvent &event) { mFps = 10; } - else if (mFps > 200) + else if (mFps > 120) { - mFps = 200; + mFps = 120; } mFpsField->setText(toString(mFps)); mFpsSlider->setValue(mFps); diff --git a/src/gui/shortcutcontainer.cpp b/src/gui/shortcutcontainer.cpp index f149266b..901095e5 100644 --- a/src/gui/shortcutcontainer.cpp +++ b/src/gui/shortcutcontainer.cpp @@ -42,13 +42,12 @@ void ShortcutContainer::widgetResized(const gcn::Event &event) if (mGridWidth < 1) mGridWidth = 1; + setHeight((mMaxItems / mGridWidth) * mBoxHeight); + mGridHeight = getHeight() / mBoxHeight; if (mGridHeight < 1) mGridHeight = 1; - - setHeight((mMaxItems / mGridWidth + - (mMaxItems % mGridWidth > 0 ? 1 : 0)) * mBoxHeight); } int ShortcutContainer::getIndexFromGrid(int pointX, int pointY) const diff --git a/src/gui/shortcutwindow.cpp b/src/gui/shortcutwindow.cpp index c704fc44..dcc7f72e 100644 --- a/src/gui/shortcutwindow.cpp +++ b/src/gui/shortcutwindow.cpp @@ -23,6 +23,8 @@ #include "shortcutcontainer.h" #include "shortcutwindow.h" +#include "widgets/layout.h" + #include "../configuration.h" static const int SCROLL_PADDING = 0; @@ -39,29 +41,28 @@ ShortcutWindow::ShortcutWindow(const char *title, ShortcutContainer *content) mItems = content; - mInstances++; - const int border = SCROLL_PADDING * 2 + getPadding() * 2; setMinWidth(mItems->getBoxWidth() + border); setMinHeight(mItems->getBoxHeight() + border); setMaxWidth(mItems->getBoxWidth() * mItems->getMaxItems() + border); setMaxHeight(mItems->getBoxHeight() * mItems->getMaxItems() + border); - const int width = (int) config.getValue("screenwidth", 800); - const int height = (int) config.getValue("screenheight", 600); + setDefaultSize(mItems->getBoxWidth() + border, (mItems->getBoxHeight() * + mItems->getMaxItems()) + border, ImageRect::LOWER_RIGHT, + mInstances * mItems->getBoxWidth(), 0); - setDefaultSize(width - (mInstances * mItems->getBoxWidth()) - - (mInstances * border), height - (mItems->getBoxHeight() * - mItems->getMaxItems()) - border, mItems->getBoxWidth() + - border, (mItems->getBoxHeight() * mItems->getMaxItems()) + - border); + mInstances++; mScrollArea = new ScrollArea(mItems); mScrollArea->setPosition(SCROLL_PADDING, SCROLL_PADDING); mScrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER); mScrollArea->setOpaque(false); - add(mScrollArea); + place(0, 0, mScrollArea, 5, 5).setPadding(0); + + Layout &layout = getLayout(); + layout.setRowHeight(0, Layout::AUTO_SET); + layout.setMargin(0); loadWindowState(); } @@ -71,13 +72,3 @@ ShortcutWindow::~ShortcutWindow() delete mItems; } -void ShortcutWindow::widgetResized(const gcn::Event &event) -{ - Window::widgetResized(event); - - const gcn::Rectangle &area = getChildrenArea(); - - mScrollArea->setSize( - area.width - SCROLL_PADDING, - area.height - SCROLL_PADDING); -} diff --git a/src/gui/shortcutwindow.h b/src/gui/shortcutwindow.h index 64592328..eae881ba 100644 --- a/src/gui/shortcutwindow.h +++ b/src/gui/shortcutwindow.h @@ -45,11 +45,6 @@ class ShortcutWindow : public Window */ ~ShortcutWindow(); - /** - * Called whenever the widget changes size. - */ - void widgetResized(const gcn::Event &event); - private: ShortcutWindow(); ShortcutContainer *mItems; diff --git a/src/gui/skill.cpp b/src/gui/skill.cpp index ed374a31..39ccbb06 100644 --- a/src/gui/skill.cpp +++ b/src/gui/skill.cpp @@ -19,9 +19,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <guichan/widgets/label.hpp> - #include "button.h" +#include "label.h" #include "listbox.h" #include "scrollarea.h" #include "skill.h" @@ -102,13 +101,13 @@ public: info = &fakeSkillInfo; sprintf(tmp, "%c%s", info->modifiable? ' ' : '*', info->name.c_str()); - gcn::Label *name_label = new gcn::Label(tmp); + gcn::Label *name_label = new Label(tmp); sprintf(tmp, "Lv:%i", skill->lv); - gcn::Label *lv_label = new gcn::Label(tmp); + gcn::Label *lv_label = new Label(tmp); sprintf(tmp, "Sp:%i", skill->sp); - gcn::Label *sp_label = new gcn::Label(tmp); + gcn::Label *sp_label = new Label(tmp); set(i, 0, name_label); set(i, 1, lv_label); @@ -136,13 +135,13 @@ SkillDialog::SkillDialog(): setWindowName("Skills"); setCloseButton(true); - setDefaultSize(windowContainer->getWidth() - 260, 25, 255, 260); + setDefaultSize(255, 260, ImageRect::CENTER); setMinHeight(50 + mTableModel->getHeight()); setMinWidth(200); ScrollArea *skillScrollArea = new ScrollArea(mTable); - mPointsLabel = new gcn::Label(strprintf(_("Skill points: %d"), 0)); + mPointsLabel = new Label(strprintf(_("Skill points: %d"), 0)); mIncButton = new Button(_("Up"), _("inc"), this); mUseButton = new Button(_("Use"), _("use"), this); mUseButton->setEnabled(false); diff --git a/src/gui/skin.cpp b/src/gui/skin.cpp new file mode 100644 index 00000000..d44c54a8 --- /dev/null +++ b/src/gui/skin.cpp @@ -0,0 +1,191 @@ +/* + * Aethyra + * Copyright (C) 2009 Aethyra Development Team + * + * This file is part of Aethyra. + * + * 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 "skin.h" + +#include "../log.h" + +#include "../resources/image.h" +#include "../resources/resourcemanager.h" + +#include "../utils/dtor.h" +#include "../utils/xml.h" + +SkinLoader* skinLoader = NULL; + +Skin::Skin(ImageRect skin, Image* close, std::string name): + instances(0), + mName(name), + border(skin), + closeImage(close) +{ +} + +Skin::~Skin() +{ + // Clean up static resources + for (int i = 0; i < 9; i++) + { + delete border.grid[i]; + border.grid[i] = NULL; + } + + closeImage->decRef(); +} + +unsigned int Skin::getMinWidth() +{ + return (border.grid[0]->getWidth() + border.grid[1]->getWidth()) + + border.grid[2]->getWidth(); +} + +unsigned int Skin::getMinHeight() +{ + return (border.grid[0]->getHeight() + border.grid[3]->getHeight()) + + border.grid[6]->getHeight(); +} + +Skin* SkinLoader::load(const std::string &filename) +{ + SkinIterator skinIterator = mSkins.find(filename); + + if (mSkins.end() != skinIterator) + { + skinIterator->second->instances++; + return skinIterator->second; + } + + ResourceManager *resman = ResourceManager::getInstance(); + + logger->log("Loading Skin '%s'.", filename.c_str()); + + if (filename.empty()) + logger->error("SkinLoader::load(): Invalid File Name."); + + // TODO: + // If there is an error loading the specified file, we should try to revert + // to a 'default' skin file. Only if the 'default' skin file can't be loaded + // should we have a terminating error. + XML::Document doc(filename); + xmlNodePtr rootNode = doc.rootNode(); + + if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "skinset")) + logger->error("Widget Skinning error"); + + std::string skinSetImage; + skinSetImage = XML::getProperty(rootNode, "image", ""); + Image *dBorders = NULL; + ImageRect border; + + if (!skinSetImage.empty()) + { + logger->log("SkinLoader::load(): <skinset> defines " + "'%s' as a skin image.", skinSetImage.c_str()); + dBorders = resman->getImage("graphics/gui/" + skinSetImage); + } + else + { + logger->error("SkinLoader::load(): Skinset does not define an image!"); + } + + //iterate <widget>'s + for_each_xml_child_node(widgetNode, rootNode) + { + if (!xmlStrEqual(widgetNode->name, BAD_CAST "widget")) + continue; + + std::string widgetType; + widgetType = XML::getProperty(widgetNode, "type", "unknown"); + if (widgetType == "Window") + { + // Iterate through <part>'s + // LEEOR / TODO: + // We need to make provisions to load in a CloseButton image. For + // now it can just be hard-coded. + for_each_xml_child_node(partNode, widgetNode) + { + if (!xmlStrEqual(partNode->name, BAD_CAST "part")) + continue; + + std::string partType; + partType = XML::getProperty(partNode, "type", "unknown"); + // TOP ROW + const int xPos = XML::getProperty(partNode, "xpos", 0); + const int yPos = XML::getProperty(partNode, "ypos", 0); + const int width = XML::getProperty(partNode, "width", 1); + const int height = XML::getProperty(partNode, "height", 1); + + if (partType == "top-left-corner") + border.grid[0] = dBorders->getSubImage(xPos, yPos, width, height); + else if (partType == "top-edge") + border.grid[1] = dBorders->getSubImage(xPos, yPos, width, height); + else if (partType == "top-right-corner") + border.grid[2] = dBorders->getSubImage(xPos, yPos, width, height); + + // MIDDLE ROW + else if (partType == "left-edge") + border.grid[3] = dBorders->getSubImage(xPos, yPos, width, height); + else if (partType == "bg-quad") + border.grid[4] = dBorders->getSubImage(xPos, yPos, width, height); + else if (partType == "right-edge") + border.grid[5] = dBorders->getSubImage(xPos, yPos, width, height); + + // BOTTOM ROW + else if (partType == "bottom-left-corner") + border.grid[6] = dBorders->getSubImage(xPos, yPos, width, height); + else if (partType == "bottom-edge") + border.grid[7] = dBorders->getSubImage(xPos, yPos, width, height); + else if (partType == "bottom-right-corner") + border.grid[8] = dBorders->getSubImage(xPos, yPos, width, height); + + // Part is of an uknown type. + else + logger->log("SkinLoader::load(): Unknown Part Type '%s'", partType.c_str()); + } + } + // Widget is of an uknown type. + else + { + logger->log("SkinLoader::load(): Unknown Widget Type '%s'", widgetType.c_str()); + } + } + dBorders->decRef(); + + logger->log("Finished loading Skin."); + + // Hard-coded for now until we update the above code to look for window buttons. + Image* closeImage = resman->getImage("graphics/gui/close_button.png"); + + Skin* skin = new Skin(border, closeImage); + + mSkins[filename] = skin; + return skin; +} + +SkinLoader::SkinLoader() +{ +} + +SkinLoader::~SkinLoader() +{ + delete_all(mSkins); +} + diff --git a/src/gui/skin.h b/src/gui/skin.h new file mode 100644 index 00000000..b8a1242e --- /dev/null +++ b/src/gui/skin.h @@ -0,0 +1,101 @@ +/* + * Aethyra + * Copyright (C) 2009 Aethyra Development Team + * + * This file is part of Aethyra. + * + * 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 SKIN_H +#define SKIN_H + +#include <map> +#include <string> + +#include "../graphics.h" + +class Image; + +class Skin +{ + public: + Skin(ImageRect skin, Image* close, std::string name = ""); + ~Skin(); + + /** + * Returns the skin's name. Useful for giving a human friendly skin + * name if a dialog for skin selection for a specific window type is + * done. + */ + std::string getName() { return mName; } + + /** + * Returns the background skin. + */ + ImageRect getBorder() { return border; } + + /** + * Returns the image used by a close button for this skin. + */ + Image* getCloseImage() { return closeImage; } + + /** + * Returns the number of instances which use this skin. + */ + int getNumberOfInstances() { return instances; } + + /** + * Returns the minimum width which can be used with this skin. + */ + unsigned int getMinWidth(); + + /** + * Returns the minimum height which can be used with this skin. + */ + unsigned int getMinHeight(); + + int instances; + + private: + std::string mName; /**< Name of the skin to use */ + ImageRect border; /**< The window border and background */ + Image *closeImage; /**< Close Button Image */ +}; + +// Map containing all window skins +typedef std::map<std::string, Skin*> Skins; + +// Iterator for window skins +typedef Skins::iterator SkinIterator; + +class SkinLoader +{ + public: + SkinLoader(); + ~SkinLoader(); + + /** + * Loads a skin + */ + Skin* load(const std::string &filename); + + private: + Skins mSkins; +}; + +extern SkinLoader* skinLoader; + +#endif diff --git a/src/gui/slider.cpp b/src/gui/slider.cpp index 9bfa840f..cc381c32 100644 --- a/src/gui/slider.cpp +++ b/src/gui/slider.cpp @@ -95,6 +95,16 @@ void Slider::init() vGrip = slider->getSubImage(x, y, w, h); slider->decRef(); + + hStart->setAlpha(mAlpha); + hMid->setAlpha(mAlpha); + hEnd->setAlpha(mAlpha); + hGrip->setAlpha(mAlpha); + + vStart->setAlpha(mAlpha); + vMid->setAlpha(mAlpha); + vEnd->setAlpha(mAlpha); + vGrip->setAlpha(mAlpha); } mInstances++; diff --git a/src/gui/speechbubble.cpp b/src/gui/speechbubble.cpp index fb0d7684..de0c8406 100644 --- a/src/gui/speechbubble.cpp +++ b/src/gui/speechbubble.cpp @@ -28,15 +28,17 @@ #include "speechbubble.h" #include "textbox.h" +#include "../graphics.h" + #include "../utils/gettext.h" SpeechBubble::SpeechBubble(): - Window(_("Speech"), false, NULL, "graphics/gui/speechbubble.xml"), + Popup("Speech", NULL, "graphics/gui/speechbubble.xml"), mText("") { setContentSize(140, 46); - setShowTitle(false); - setTitleBarHeight(0); + setMinWidth(29); + setMinHeight(29); mCaption = new gcn::Label(""); mCaption->setFont(boldFont); @@ -57,8 +59,6 @@ SpeechBubble::SpeechBubble(): add(mCaption); add(mSpeechArea); - - center(); } void SpeechBubble::setCaption(const std::string &name, const gcn::Color *color) @@ -73,13 +73,15 @@ void SpeechBubble::setText(std::string text, bool showName) if ((text == mText) && (mCaption->getWidth() <= mSpeechBox->getMinWidth())) return; + graphics->setColor(guiPalette->getColor(Palette::TEXT)); + int width = mCaption->getWidth(); mSpeechBox->setTextWrapped(text, 130 > width ? 130 : width); const int fontHeight = getFont()->getHeight(); const int numRows = showName ? mSpeechBox->getNumberOfRows() + 1 : mSpeechBox->getNumberOfRows(); - int yPos = showName ? fontHeight + 3 : 3; + int yPos = showName ? fontHeight + getPadding() : getPadding(); int height = (numRows * fontHeight); if (width < mSpeechBox->getMinWidth()) @@ -87,11 +89,11 @@ void SpeechBubble::setText(std::string text, bool showName) if (numRows == 1) { - yPos = (fontHeight / 4) + 3; + yPos = (fontHeight / 4) + getPadding(); height = ((3 * fontHeight) / 2) + 1; } - setContentSize(width + fontHeight, height + 6); + setContentSize(width + fontHeight, height + getPadding()); mSpeechArea->setDimension(gcn::Rectangle(4, yPos, width + 5, height)); } diff --git a/src/gui/speechbubble.h b/src/gui/speechbubble.h index 34e00722..8bb0e5ea 100644 --- a/src/gui/speechbubble.h +++ b/src/gui/speechbubble.h @@ -23,21 +23,39 @@ #define SPEECHBUBBLE_H #include "palette.h" -#include "window.h" +#include "popup.h" class ScrollArea; class TextBox; -class SpeechBubble : public Window +class SpeechBubble : public Popup { public: + /** + * Constructor. Initializes the speech bubble. + */ SpeechBubble(); + /** + * Sets the name displayed for the speech bubble, and in what color. + */ void setCaption(const std::string &name, const gcn::Color *color = &guiPalette->getColor(Palette::TEXT)); + + /** + * Sets the text to be displayed. + */ void setText(std::string text, bool showName = true); + + /** + * Sets the location in which the speech bubble will be displayed. + */ void setLocation(int x, int y); + + /** + * Gets the number of rows the speech bubble has. + */ unsigned int getNumRows(); private: diff --git a/src/gui/status.cpp b/src/gui/status.cpp index ff0c8563..a9af2ab4 100644 --- a/src/gui/status.cpp +++ b/src/gui/status.cpp @@ -19,9 +19,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <guichan/widgets/label.hpp> - #include "button.h" +#include "label.h" #include "progressbar.h" #include "status.h" #include "windowcontainer.h" @@ -42,28 +41,27 @@ StatusWindow::StatusWindow(LocalPlayer *player): { setWindowName("Status"); setCloseButton(true); - setDefaultSize((windowContainer->getWidth() - 365) / 2, - (windowContainer->getHeight() - 255) / 2, 400, 345); + setDefaultSize(400, 345, ImageRect::CENTER); // ---------------------- // Status Part // ---------------------- - mLvlLabel = new gcn::Label(strprintf(_("Level: %d"), 0)); - mJobLvlLabel = new gcn::Label(strprintf(_("Job: %d"), 0)); - mGpLabel = new gcn::Label(strprintf(_("Money: %s"), + mLvlLabel = new Label(strprintf(_("Level: %d"), 0)); + mJobLvlLabel = new Label(strprintf(_("Job: %d"), 0)); + mGpLabel = new Label(strprintf(_("Money: %s"), Units::formatCurrency(mCurrency).c_str())); - mHpLabel = new gcn::Label(_("HP:")); + mHpLabel = new Label(_("HP:")); mHpBar = new ProgressBar(1.0f, 80, 15, 0, 171, 34); - mXpLabel = new gcn::Label(_("Exp:")); + mXpLabel = new Label(_("Exp:")); mXpBar = new ProgressBar(1.0f, 80, 15, 143, 192, 211); - mMpLabel = new gcn::Label(_("MP:")); + mMpLabel = new Label(_("MP:")); mMpBar = new ProgressBar(1.0f, 80, 15, 26, 102, 230); - mJobLabel = new gcn::Label(_("Job:")); + mJobLabel = new Label(_("Job:")); mJobBar = new ProgressBar(1.0f, 80, 15, 220, 135, 203); // ---------------------- @@ -71,41 +69,41 @@ StatusWindow::StatusWindow(LocalPlayer *player): // ---------------------- // Static Labels - gcn::Label *mStatsTitleLabel = new gcn::Label(_("Stats")); - gcn::Label *mStatsTotalLabel = new gcn::Label(_("Total")); - gcn::Label *mStatsCostLabel = new gcn::Label(_("Cost")); + gcn::Label *mStatsTitleLabel = new Label(_("Stats")); + gcn::Label *mStatsTotalLabel = new Label(_("Total")); + gcn::Label *mStatsCostLabel = new Label(_("Cost")); mStatsTotalLabel->setAlignment(gcn::Graphics::CENTER); // Derived Stats - mStatsAttackLabel = new gcn::Label(_("Attack:")); - mStatsDefenseLabel= new gcn::Label(_("Defense:")); - mStatsMagicAttackLabel = new gcn::Label(_("M.Attack:")); - mStatsMagicDefenseLabel = new gcn::Label(_("M.Defense:")); + mStatsAttackLabel = new Label(_("Attack:")); + mStatsDefenseLabel= new Label(_("Defense:")); + mStatsMagicAttackLabel = new Label(_("M.Attack:")); + mStatsMagicDefenseLabel = new Label(_("M.Defense:")); // Gettext flag for next line: xgettext:no-c-format - mStatsAccuracyLabel = new gcn::Label(_("% Accuracy:")); + mStatsAccuracyLabel = new Label(_("% Accuracy:")); // Gettext flag for next line: xgettext:no-c-format - mStatsEvadeLabel = new gcn::Label(_("% Evade:")); + mStatsEvadeLabel = new Label(_("% Evade:")); // Gettext flag for next line: xgettext:no-c-format - mStatsReflexLabel = new gcn::Label(_("% Reflex:")); + mStatsReflexLabel = new Label(_("% Reflex:")); - mStatsAttackPoints = new gcn::Label; - mStatsDefensePoints = new gcn::Label; - mStatsMagicAttackPoints = new gcn::Label; - mStatsMagicDefensePoints = new gcn::Label; - mStatsAccuracyPoints = new gcn::Label; - mStatsEvadePoints = new gcn::Label; - mStatsReflexPoints = new gcn::Label; + mStatsAttackPoints = new Label; + mStatsDefensePoints = new Label; + mStatsMagicAttackPoints = new Label; + mStatsMagicDefensePoints = new Label; + mStatsAccuracyPoints = new Label; + mStatsEvadePoints = new Label; + mStatsReflexPoints = new Label; // New labels for (int i = 0; i < 6; i++) { - mStatsLabel[i] = new gcn::Label("0"); + mStatsLabel[i] = new Label("0"); mStatsLabel[i]->setAlignment(gcn::Graphics::CENTER); - mStatsDisplayLabel[i] = new gcn::Label; - mPointsLabel[i] = new gcn::Label("0"); + mStatsDisplayLabel[i] = new Label; + mPointsLabel[i] = new Label("0"); mPointsLabel[i]->setAlignment(gcn::Graphics::CENTER); } - mRemainingStatsPointsLabel = new gcn::Label; + mRemainingStatsPointsLabel = new Label; // Set button events Id mStatsButton[0] = new Button("+", "STR", this); @@ -269,29 +267,17 @@ void StatusWindow::action(const gcn::ActionEvent &event) if (event.getId().length() == 3) { if (event.getId() == "STR") - { player_node->raiseAttribute(LocalPlayer::STR); - } if (event.getId() == "AGI") - { player_node->raiseAttribute(LocalPlayer::AGI); - } if (event.getId() == "VIT") - { player_node->raiseAttribute(LocalPlayer::VIT); - } if (event.getId() == "INT") - { player_node->raiseAttribute(LocalPlayer::INT); - } if (event.getId() == "DEX") - { player_node->raiseAttribute(LocalPlayer::DEX); - } if (event.getId() == "LUK") - { player_node->raiseAttribute(LocalPlayer::LUK); - } } } diff --git a/src/gui/storagewindow.cpp b/src/gui/storagewindow.cpp index 663ad784..8484093a 100644 --- a/src/gui/storagewindow.cpp +++ b/src/gui/storagewindow.cpp @@ -24,12 +24,11 @@ #include <guichan/font.hpp> #include <guichan/mouseinput.hpp> -#include <guichan/widgets/label.hpp> - #include "button.h" #include "inventorywindow.h" #include "item_amount.h" #include "itemcontainer.h" +#include "label.h" #include "progressbar.h" #include "scrollarea.h" #include "storagewindow.h" @@ -59,11 +58,11 @@ StorageWindow::StorageWindow(Network *network, int invSize): { setWindowName("Storage"); setResizable(true); + setCloseButton(true); // If you adjust these defaults, don't forget to adjust the trade window's. - setDefaultSize(115, 25, 375, 300); + setDefaultSize(375, 300, ImageRect::CENTER); - mCancelButton = new Button(_("Close"), "close", this); mStoreButton = new Button(_("Store"), "store", this); mRetrieveButton = new Button(_("Retrieve"), "retrieve", this); @@ -75,7 +74,7 @@ StorageWindow::StorageWindow(Network *network, int invSize): mUsedSlots = toString(player_node->getStorage()->getNumberOfSlotsUsed()); - mSlotsLabel = new gcn::Label(_("Slots: ")); + mSlotsLabel = new Label(_("Slots: ")); mSlotsBar = new ProgressBar(1.0f, 100, 20, 225, 200, 25); @@ -85,14 +84,12 @@ StorageWindow::StorageWindow(Network *network, int invSize): place(0, 0, mSlotsLabel).setPadding(3); place(1, 0, mSlotsBar, 3); place(0, 1, mInvenScroll, 4, 4); - place(0, 5, mCancelButton); place(2, 5, mStoreButton); place(3, 5, mRetrieveButton); Layout &layout = getLayout(); layout.setRowHeight(0, mStoreButton->getHeight()); - center(); loadWindowState(); } @@ -121,11 +118,7 @@ void StorageWindow::logic() void StorageWindow::action(const gcn::ActionEvent &event) { - if (event.getId() == "close") - { - close(); - } - else if (event.getId() == "store") + if (event.getId() == "store") { if (!inventoryWindow->isVisible()) return; @@ -212,4 +205,4 @@ void StorageWindow::close() { MessageOut outMsg(mNetwork); outMsg.writeInt16(CMSG_CLOSE_STORAGE); -}
\ No newline at end of file +} diff --git a/src/gui/storagewindow.h b/src/gui/storagewindow.h index 35d76ffb..c78d33a7 100644 --- a/src/gui/storagewindow.h +++ b/src/gui/storagewindow.h @@ -26,13 +26,12 @@ #include "../inventory.h" -#include "../net/network.h" - #include <guichan/actionlistener.hpp> #include <guichan/selectionlistener.hpp> class Item; class ItemContainer; +class Network; class ProgressBar; class TextBox; @@ -82,6 +81,10 @@ class StorageWindow : public Window, gcn::ActionListener, */ void removeStore(Item* item, int ammount); + /** + * Closes the Storage Window, as well as telling the server that the + * window has been closed. + */ void close(); private: @@ -90,7 +93,7 @@ class StorageWindow : public Window, gcn::ActionListener, std::string mSlots; std::string mUsedSlots; - gcn::Button *mCancelButton, *mStoreButton, *mRetrieveButton; + gcn::Button *mStoreButton, *mRetrieveButton; gcn::ScrollArea *mInvenScroll; gcn::Label *mSlotsLabel; diff --git a/src/gui/table.cpp b/src/gui/table.cpp index 5fc96dbd..ec5b0480 100644 --- a/src/gui/table.cpp +++ b/src/gui/table.cpp @@ -319,11 +319,19 @@ void GuiTable::draw(gcn::Graphics* graphics) widget->setDimension(bounds); - if (!mLinewiseMode && c == mSelectedColumn && r == mSelectedRow) + graphics->setColor(guiPalette->getColor(Palette::HIGHLIGHT, + (int)(mAlpha * 255.0f))); + + if (mLinewiseMode && r == mSelectedRow && c == 0) + { + graphics->fillRectangle(gcn::Rectangle(0, y_offset, + getWidth(), height)); + } + else if (!mLinewiseMode && + c == mSelectedColumn && r == mSelectedRow) { - graphics->setColor(guiPalette->getColor(Palette::HIGHLIGHT, - (int)(mAlpha * 127.0f))); - graphics->fillRectangle(bounds); + graphics->fillRectangle(gcn::Rectangle(x_offset, y_offset, + width, height)); } graphics->pushClipArea(bounds); @@ -334,14 +342,6 @@ void GuiTable::draw(gcn::Graphics* graphics) x_offset += width; } - if (mLinewiseMode && r == mSelectedRow) - { - graphics->setColor(guiPalette->getColor(Palette::HIGHLIGHT, - (int)(mAlpha * 127.0f))); - graphics->fillRectangle(gcn::Rectangle(0, y_offset, - x_offset, height)); - } - y_offset += height; } diff --git a/src/gui/textfield.cpp b/src/gui/textfield.cpp index 0e839b1f..5c6e4f49 100644 --- a/src/gui/textfield.cpp +++ b/src/gui/textfield.cpp @@ -21,6 +21,7 @@ #include <guichan/font.hpp> +#include "palette.h" #include "sdlinput.h" #include "textfield.h" @@ -54,8 +55,10 @@ TextField::TextField(const std::string& text): int gridy[4] = {0, 3, 28, 31}; int a = 0, x, y; - for (y = 0; y < 3; y++) { - for (x = 0; x < 3; x++) { + for (y = 0; y < 3; y++) + { + for (x = 0; x < 3; x++) + { skin.grid[a] = textbox->getSubImage( gridx[x], gridy[y], gridx[x + 1] - gridx[x] + 1, @@ -76,9 +79,7 @@ TextField::~TextField() instances--; if (instances == 0) - { for_each(skin.grid, skin.grid + 9, dtor<Image*>()); - } } void TextField::draw(gcn::Graphics *graphics) @@ -89,11 +90,11 @@ void TextField::draw(gcn::Graphics *graphics) if (isFocused()) { drawCaret(graphics, - getFont()->getWidth(mText.substr(0, mCaretPosition)) - - mXScroll); + getFont()->getWidth(mText.substr(0, mCaretPosition)) - + mXScroll); } - graphics->setColor(getForegroundColor()); + graphics->setColor(guiPalette->getColor(Palette::TEXT)); graphics->setFont(getFont()); graphics->drawText(mText, 1 - mXScroll, 1); @@ -101,9 +102,7 @@ void TextField::draw(gcn::Graphics *graphics) { mAlpha = config.getValue("guialpha", 0.8); for (int a = 0; a < 9; a++) - { skin.grid[a]->setAlpha(mAlpha); - } } } @@ -121,9 +120,8 @@ void TextField::setNumeric(bool numeric) { mNumeric = numeric; if (!numeric) - { return; - } + const char *text = mText.c_str(); for (const char *textPtr = text; *textPtr; ++textPtr) { @@ -138,18 +136,15 @@ void TextField::setNumeric(bool numeric) int TextField::getValue() const { if (!mNumeric) - { return 0; - } + int value = atoi(mText.c_str()); if (value < mMinimum) - { return mMinimum; - } + if (value > mMaximum) - { return mMaximum; - } + return value; } diff --git a/src/gui/textrenderer.h b/src/gui/textrenderer.h index 0381f766..b69e72a7 100644 --- a/src/gui/textrenderer.h +++ b/src/gui/textrenderer.h @@ -37,7 +37,7 @@ class TextRenderer */ static inline void renderText(gcn::Graphics *graphics, const std::string& text, int x, int y, gcn::Graphics::Alignment align, - const gcn::Color* color, gcn::Font *font, bool outline = false, + const gcn::Color color, gcn::Font *font, bool outline = false, bool shadow = false, int alpha = 255) { graphics->setFont(font); @@ -73,7 +73,7 @@ class TextRenderer graphics->drawText(text, x, y - 1, align); } - graphics->setColor(*color); + graphics->setColor(color); graphics->drawText(text, x, y, align); } }; diff --git a/src/gui/trade.cpp b/src/gui/trade.cpp index 30604d6b..d7554de8 100644 --- a/src/gui/trade.cpp +++ b/src/gui/trade.cpp @@ -21,13 +21,14 @@ #include <sstream> -#include <guichan/widgets/label.hpp> +#include <guichan/font.hpp> #include "button.h" #include "chat.h" #include "inventorywindow.h" #include "item_amount.h" #include "itemcontainer.h" +#include "label.h" #include "scrollarea.h" #include "textfield.h" #include "trade.h" @@ -47,24 +48,25 @@ #include "../utils/stringutils.h" TradeWindow::TradeWindow(Network *network): - Window(_("Trade: You")), + Window("Trade"), mNetwork(network), - mMyInventory(new Inventory(INVENTORY_SIZE)), - mPartnerInventory(new Inventory(INVENTORY_SIZE)) + mMyInventory(new Inventory(INVENTORY_SIZE, 2)), + mPartnerInventory(new Inventory(INVENTORY_SIZE, 2)) { - setWindowName("Trade"); - setDefaultSize(115, 227, 342, 209); + setWindowName(_("Trade")); + setDefaultSize(342, 209, ImageRect::CENTER); setResizable(true); + setCloseButton(true); setMinWidth(342); setMinHeight(209); - mAddButton = new Button(_("Add"), "add", this); - mOkButton = new Button(_("Ok"), "ok", this); - mCancelButton = new Button(_("Cancel"), "cancel", this); - mTradeButton = new Button(_("Trade"), "trade", this); + std::string longestName = getFont()->getWidth(_("OK")) > + getFont()->getWidth(_("Trade")) ? + _("OK") : _("Trade"); - mTradeButton->setEnabled(false); + mAddButton = new Button(_("Add"), "add", this); + mOkButton = new Button(longestName, "ok", this); mMyItemContainer = new ItemContainer(mMyInventory.get(), 2); mMyItemContainer->setWidth(160); @@ -78,8 +80,8 @@ TradeWindow::TradeWindow(Network *network): mPartnerScroll = new ScrollArea(mPartnerItemContainer); - mMoneyLabel = new gcn::Label(strprintf(_("You get %s."), "")); - mMoneyLabel2 = new gcn::Label(_("You give:")); + mMoneyLabel = new Label(strprintf(_("You get %s."), "")); + mMoneyLabel2 = new Label(_("You give:")); mMoneyField = new TextField; mMoneyField->setWidth(50); @@ -91,10 +93,8 @@ TradeWindow::TradeWindow(Network *network): place(0, 0, mMoneyLabel2); place(1, 0, mMoneyField); place = getPlacer(0, 2); - place(0, 0, mAddButton); - place(1, 0, mOkButton); - place(2, 0, mTradeButton); - place(3, 0, mCancelButton); + place(6, 0, mAddButton); + place(7, 0, mOkButton); Layout &layout = getLayout(); layout.extend(0, 2, 2, 1); layout.setRowHeight(1, Layout::AUTO_SET); @@ -102,6 +102,8 @@ TradeWindow::TradeWindow(Network *network): layout.setColWidth(0, Layout::AUTO_SET); layout.setColWidth(1, Layout::AUTO_SET); + mOkButton->setCaption(_("OK")); + loadWindowState(); } @@ -109,14 +111,6 @@ TradeWindow::~TradeWindow() { } -void TradeWindow::widgetResized(const gcn::Event &event) -{ - mMyItemContainer->setWidth(mMyScroll->getWidth()); - mPartnerItemContainer->setWidth(mPartnerScroll->getWidth()); - - Window::widgetResized(event); -} - void TradeWindow::addMoney(int amount) { mMoneyLabel->setCaption(strprintf(_("You get %s."), @@ -166,7 +160,8 @@ void TradeWindow::reset() { mMyInventory->clear(); mPartnerInventory->clear(); - mTradeButton->setEnabled(false); + mOkButton->setCaption(_("OK")); + mOkButton->setActionEventId("ok"); mOkButton->setEnabled(true); mOkOther = false; mOkMe = false; @@ -175,11 +170,6 @@ void TradeWindow::reset() mMoneyField->setText(""); } -void TradeWindow::setTradeButton(bool enabled) -{ - mTradeButton->setEnabled(enabled); -} - void TradeWindow::receivedOk(bool own) { if (own) @@ -187,13 +177,8 @@ void TradeWindow::receivedOk(bool own) mOkMe = true; if (mOkOther) { - mTradeButton->setEnabled(true); - mOkButton->setEnabled(false); - } - else - { - mTradeButton->setEnabled(false); - mOkButton->setEnabled(false); + mOkButton->setCaption(_("Trade")); + mOkButton->setActionEventId("trade"); } } else @@ -201,19 +186,18 @@ void TradeWindow::receivedOk(bool own) mOkOther = true; if (mOkMe) { - mTradeButton->setEnabled(true); - mOkButton->setEnabled(false); - } - else - { - mTradeButton->setEnabled(false); - mOkButton->setEnabled(true); + mOkButton->setCaption(_("Trade")); + mOkButton->setActionEventId("trade"); } } } void TradeWindow::tradeItem(Item *item, int quantity) { + // TODO: Our newer version of eAthena doesn't register this following + // function. Detect the actual server version, and re-enable this + // for that version only. + //addItem(item->getId(), true, quantity, item->isEquipment()); MessageOut outMsg(mNetwork); outMsg.writeInt16(CMSG_TRADE_ITEM_ADD_REQUEST); outMsg.writeInt16(item->getInvIndex()); @@ -251,7 +235,8 @@ void TradeWindow::action(const gcn::ActionEvent &event) if (mMyInventory->contains(item)) { chatWindow->chatLog(_("Failed adding item. You can not " - "overlap one kind of item on the window."), BY_SERVER); + "overlap one kind of item on the window."), + BY_SERVER); return; } @@ -297,3 +282,9 @@ void TradeWindow::action(const gcn::ActionEvent &event) outMsg.writeInt16(CMSG_TRADE_OK); } } + +void TradeWindow::close() +{ + MessageOut outMsg(mNetwork); + outMsg.writeInt16(CMSG_TRADE_CANCEL_REQUEST); +} diff --git a/src/gui/trade.h b/src/gui/trade.h index df724038..67138c24 100644 --- a/src/gui/trade.h +++ b/src/gui/trade.h @@ -56,13 +56,6 @@ class TradeWindow : public Window, gcn::ActionListener, gcn::SelectionListener ~TradeWindow(); /** - * Called when resizing the window. - * - * @param event The calling event - */ - void widgetResized(const gcn::Event &event); - - /** * Add money to the trade window. */ void addMoney(int quantity); @@ -93,11 +86,6 @@ class TradeWindow : public Window, gcn::ActionListener, gcn::SelectionListener void increaseQuantity(int index, bool own, int quantity); /** - * Set trade Button disabled - */ - void setTradeButton(bool enabled); - - /** * Player received ok message from server */ void receivedOk(bool own); @@ -118,6 +106,12 @@ class TradeWindow : public Window, gcn::ActionListener, gcn::SelectionListener */ void action(const gcn::ActionEvent &event); + /** + * Closes the Trade Window, as well as telling the server that the + * window has been closed. + */ + void close(); + private: Network *mNetwork; @@ -130,7 +124,7 @@ class TradeWindow : public Window, gcn::ActionListener, gcn::SelectionListener gcn::Label *mMoneyLabel; gcn::Label *mMoneyLabel2; - gcn::Button *mAddButton, *mOkButton, *mCancelButton, *mTradeButton; + gcn::Button *mAddButton, *mOkButton; ScrollArea *mMyScroll, *mPartnerScroll; gcn::TextField *mMoneyField; bool mOkOther, mOkMe; diff --git a/src/gui/updatewindow.cpp b/src/gui/updatewindow.cpp index df0a1f80..295b752e 100644 --- a/src/gui/updatewindow.cpp +++ b/src/gui/updatewindow.cpp @@ -24,13 +24,11 @@ #include <SDL_thread.h> #include <zlib.h> -#include <guichan/widgets/label.hpp> - -// Curl should be included after Guichan to avoid Windows redefinitions #include <curl/curl.h> #include "browserbox.h" #include "button.h" +#include "label.h" #include "progressbar.h" #include "scrollarea.h" #include "updatewindow.h" @@ -109,7 +107,7 @@ UpdaterWindow::UpdaterWindow(const std::string &updateHost, mBrowserBox = new BrowserBox; mScrollArea = new ScrollArea(mBrowserBox); - mLabel = new gcn::Label(_("Connecting...")); + mLabel = new Label(_("Connecting...")); mProgressBar = new ProgressBar(0.0, 310, 20, 168, 116, 31); mCancelButton = new Button(_("Cancel"), "cancel", this); mPlayButton = new Button(_("Play"), "play", this); diff --git a/src/gui/widgets/tab.cpp b/src/gui/widgets/tab.cpp index 3a79dd91..7a2d9ee8 100644 --- a/src/gui/widgets/tab.cpp +++ b/src/gui/widgets/tab.cpp @@ -24,6 +24,8 @@ #include "tab.h" #include "tabbedarea.h" +#include "../palette.h" + #include "../../configuration.h" #include "../../graphics.h" @@ -123,13 +125,17 @@ void Tab::draw(gcn::Graphics *graphics) { mode = TAB_SELECTED; // if tab is selected, it doesnt need to highlight activity - mLabel->setForegroundColor(gcn::Color(0, 0, 0)); + mLabel->setForegroundColor(guiPalette->getColor(Palette::TEXT)); mHighlighted = false; } else if (mHighlighted) { mode = TAB_HIGHLIGHTED; - mLabel->setForegroundColor(gcn::Color(255, 0, 0)); + mLabel->setForegroundColor(guiPalette->getColor(Palette::TAB_HIGHLIGHT)); + } + else + { + mLabel->setForegroundColor(guiPalette->getColor(Palette::TEXT)); } } diff --git a/src/gui/widgets/textpreview.cpp b/src/gui/widgets/textpreview.cpp index 4fcaa4a7..01790a67 100644 --- a/src/gui/widgets/textpreview.cpp +++ b/src/gui/widgets/textpreview.cpp @@ -28,28 +28,54 @@ #include "../textrenderer.h" #include "../truetypefont.h" +#include "../../configuration.h" + +float TextPreview::mAlpha = config.getValue("guialpha", 0.8); + TextPreview::TextPreview(const std::string* text) { mText = text; + mTextAlpha = false; mFont = gui->getFont(); mTextColor = &guiPalette->getColor(Palette::TEXT); mTextBGColor = NULL; mBGColor = &guiPalette->getColor(Palette::BACKGROUND); + mOpaque = false; } void TextPreview::draw(gcn::Graphics* graphics) { - graphics->setColor(*mBGColor); - graphics->fillRectangle(gcn::Rectangle(0, 0, getWidth(), getHeight())); + if (config.getValue("guialpha", 0.8) != mAlpha) + mAlpha = config.getValue("guialpha", 0.8); + + int alpha = (int) (mAlpha * 255.0f); + + if (!mTextAlpha) + alpha = 255; + + if (mOpaque) + { + graphics->setColor(gcn::Color((int) mBGColor->r, + (int) mBGColor->g, + (int) mBGColor->b, + (int)(mAlpha * 255.0f))); + graphics->fillRectangle(gcn::Rectangle(0, 0, getWidth(), getHeight())); + } - if (mTextBGColor && typeid(*mFont) == typeid(TrueTypeFont)) { + if (mTextBGColor && typeid(*mFont) == typeid(TrueTypeFont)) + { TrueTypeFont *font = static_cast<TrueTypeFont*>(mFont); - graphics->setColor(*mTextBGColor); int x = font->getWidth(*mText) + 1 + 2 * ((mOutline || mShadow) ? 1 :0); int y = font->getHeight() + 1 + 2 * ((mOutline || mShadow) ? 1 : 0); + graphics->setColor(gcn::Color((int) mTextBGColor->r, + (int) mTextBGColor->g, + (int) mTextBGColor->b, + (int)(mAlpha * 255.0f))); graphics->fillRectangle(gcn::Rectangle(1, 1, x, y)); } TextRenderer::renderText(graphics, *mText, 2, 2, gcn::Graphics::LEFT, - mTextColor, mFont, mOutline, mShadow); + gcn::Color(mTextColor->r, mTextColor->g, + mTextColor->b, alpha), + mFont, mOutline, mShadow, alpha); } diff --git a/src/gui/widgets/textpreview.h b/src/gui/widgets/textpreview.h index 1c1fa1e4..e7b7db80 100644 --- a/src/gui/widgets/textpreview.h +++ b/src/gui/widgets/textpreview.h @@ -29,7 +29,8 @@ /** * Preview widget for particle colors, etc. */ -class TextPreview : public gcn::Widget { +class TextPreview : public gcn::Widget +{ public: TextPreview(const std::string* text); @@ -44,6 +45,16 @@ class TextPreview : public gcn::Widget { } /** + * Sets the text to use the set alpha value. + * + * @param alpha whether to use alpha values for the text or not + */ + inline void useTextAlpha(bool alpha) + { + mTextAlpha = alpha; + } + + /** * Sets the color the text background is drawn in. This is only the * rectangle directly behind the text, not to full widget. * @@ -101,12 +112,29 @@ class TextPreview : public gcn::Widget { */ void draw(gcn::Graphics *graphics); + /** + * Set opacity for this widget (whether or not to show the background + * color) + * + * @param opaque Whether the widget should be opaque or not + */ + void setOpaque(bool opaque) { mOpaque = opaque; } + + /** + * Gets opacity for this widget (whether or not the background color + * is shown below the widget) + */ + bool isOpaque() { return mOpaque; } + private: gcn::Font *mFont; const std::string* mText; const gcn::Color* mTextColor; const gcn::Color* mBGColor; const gcn::Color* mTextBGColor; + static float mAlpha; + bool mTextAlpha; + bool mOpaque; bool mShadow; bool mOutline; }; diff --git a/src/gui/window.cpp b/src/gui/window.cpp index d4665427..4689c86a 100644 --- a/src/gui/window.cpp +++ b/src/gui/window.cpp @@ -26,6 +26,8 @@ #include <guichan/exception.hpp> #include "gui.h" +#include "palette.h" +#include "skin.h" #include "window.h" #include "windowcontainer.h" @@ -37,16 +39,10 @@ #include "../log.h" #include "../resources/image.h" -#include "../resources/resourcemanager.h" - -#include "../utils/xml.h" ConfigListener *Window::windowConfigListener = 0; -WindowContainer *Window::windowContainer = 0; int Window::instances = 0; int Window::mouseResize = 0; -//ImageRect Window::border; -Image *Window::closeImage = NULL; bool Window::mAlphaChanged = false; class WindowConfigListener : public ConfigListener @@ -67,25 +63,19 @@ Window::Window(const std::string& caption, bool modal, Window *parent, const std mModal(modal), mCloseButton(false), mSticky(false), - mMinWinWidth(100), mDefaultWidth(100), mMaxWinWidth(INT_MAX), - mMinWinHeight(40), mDefaultHeight(40), mMaxWinHeight(INT_MAX), - mDefaultX(100), mDefaultY(100), - mSkin(skin) + mMinWinWidth(100), + mMinWinHeight(40), + mMaxWinWidth(INT_MAX), + mMaxWinHeight(INT_MAX) { logger->log("Window::Window(\"%s\")", caption.c_str()); if (!windowContainer) - { throw GCN_EXCEPTION("Window::Window(): no windowContainer set"); - } - - // Loads the skin - loadSkin(mSkin); - - setGuiAlpha(); if (instances == 0) { + skinLoader = new SkinLoader(); windowConfigListener = new WindowConfigListener; // Send GUI alpha changed for initialization windowConfigListener->optionChanged("guialpha"); @@ -98,6 +88,11 @@ Window::Window(const std::string& caption, bool modal, Window *parent, const std setPadding(3); setTitleBarHeight(20); + // Loads the skin + mSkin = skinLoader->load(skin); + + setGuiAlpha(); + // Add this window to the window container windowContainer->add(this); @@ -116,21 +111,8 @@ Window::Window(const std::string& caption, bool modal, Window *parent, const std Window::~Window() { logger->log("Window::~Window(\"%s\")", getCaption().c_str()); - const std::string &name = mWindowName; - // Saving X, Y and Width and Height for resizables in the config - if (!name.empty() && name != "window") - { - config.setValue(name + "WinX", getX()); - config.setValue(name + "WinY", getY()); - config.setValue(name + "Visible", isVisible()); - - if (mGrip) - { - config.setValue(name + "WinWidth", getWidth()); - config.setValue(name + "WinHeight", getHeight()); - } - } + saveWindowState(); delete mLayout; @@ -145,20 +127,14 @@ Window::~Window() instances--; - // Clean up static resources - for (int i = 0; i < 9; i++) - { - delete border.grid[i]; - border.grid[i] = NULL; - } + mSkin->instances--; if (instances == 0) { + delete skinLoader; config.removeListener("guialpha", windowConfigListener); delete windowConfigListener; windowConfigListener = NULL; - - closeImage->decRef(); } } @@ -174,12 +150,12 @@ void Window::draw(gcn::Graphics *graphics) Graphics *g = static_cast<Graphics*>(graphics); - g->drawImageRect(0, 0, getWidth(), getHeight(), border); + g->drawImageRect(0, 0, getWidth(), getHeight(), mSkin->getBorder()); // Draw title if (mShowTitle) { - g->setColor(gcn::Color(0, 0, 0)); + g->setColor(guiPalette->getColor(Palette::TEXT)); g->setFont(getFont()); g->drawText(getCaption(), 7, 5, gcn::Graphics::LEFT); } @@ -187,8 +163,8 @@ void Window::draw(gcn::Graphics *graphics) // Draw Close Button if (mCloseButton) { - g->drawImage(closeImage, - getWidth() - closeImage->getWidth() - getPadding(), + g->drawImage(mSkin->getCloseImage(), + getWidth() - mSkin->getCloseImage()->getWidth() - getPadding(), getPadding() ); } @@ -196,18 +172,29 @@ void Window::draw(gcn::Graphics *graphics) // Update window alpha values if (mAlphaChanged) { - for_each(border.grid, border.grid + 9, + for_each(mSkin->getBorder().grid, mSkin->getBorder().grid + 9, std::bind2nd(std::mem_fun(&Image::setAlpha), config.getValue("guialpha", 0.8))); - closeImage->setAlpha(config.getValue("guialpha", 0.8)); + mSkin->getCloseImage()->setAlpha(config.getValue("guialpha", 0.8)); } drawChildren(graphics); } void Window::setContentSize(int width, int height) { - setSize(width + 2 * getPadding(), - height + getPadding() + getTitleBarHeight()); + width = width + 2 * getPadding(); + height = height + getPadding() + getTitleBarHeight(); + + if (getMinWidth() > width) + width = getMinWidth(); + else if (getMaxWidth() < width) + width = getMaxWidth(); + if (getMinHeight() > height) + height = getMinHeight(); + else if (getMaxHeight() < height) + height = getMaxHeight(); + + setSize(width, height); } void Window::setLocationRelativeTo(gcn::Widget *widget) @@ -222,14 +209,61 @@ void Window::setLocationRelativeTo(gcn::Widget *widget) getY() + (wy + (widget->getHeight() - getHeight()) / 2 - y)); } +void Window::setLocationRelativeTo(ImageRect::ImagePosition position, + int offsetX, int offsetY) +{ + if (position == ImageRect::UPPER_LEFT) + { + } + else if (position == ImageRect::UPPER_CENTER) + { + offsetX += (graphics->getWidth() - getWidth()) / 2; + } + else if (position == ImageRect::UPPER_RIGHT) + { + offsetX += graphics->getWidth() - getWidth(); + } + else if (position == ImageRect::LEFT) + { + offsetY += (graphics->getHeight() - getHeight()) / 2; + } + else if (position == ImageRect::CENTER) + { + offsetX += (graphics->getWidth() - getWidth()) / 2; + offsetY += (graphics->getHeight() - getHeight()) / 2; + } + else if (position == ImageRect::RIGHT) + { + offsetX += graphics->getWidth() - getWidth(); + offsetY += (graphics->getHeight() - getHeight()) / 2; + } + else if (position == ImageRect::LOWER_LEFT) + { + offsetY += graphics->getHeight() - getHeight(); + } + else if (position == ImageRect::LOWER_CENTER) + { + offsetX += (graphics->getWidth() - getWidth()) / 2; + offsetY += graphics->getHeight() - getHeight(); + } + else if (position == ImageRect::LOWER_RIGHT) + { + offsetX += graphics->getWidth() - getWidth(); + offsetY += graphics->getHeight() - getHeight(); + } + + setPosition(offsetX, offsetY); +} + void Window::setMinWidth(unsigned int width) { - mMinWinWidth = width; + mMinWinWidth = width > mSkin->getMinWidth() ? width : mSkin->getMinWidth(); } void Window::setMinHeight(unsigned int height) { - mMinWinHeight = height; + mMinWinHeight = height > mSkin->getMinHeight() ? + height : mSkin->getMinHeight(); } void Window::setMaxWidth(unsigned int width) @@ -321,14 +355,14 @@ void Window::mousePressed(gcn::MouseEvent &event) if (mCloseButton) { gcn::Rectangle closeButtonRect( - getWidth() - closeImage->getWidth() - getPadding(), + getWidth() - mSkin->getCloseImage()->getWidth() - getPadding(), getPadding(), - closeImage->getWidth(), - closeImage->getHeight()); + mSkin->getCloseImage()->getWidth(), + mSkin->getCloseImage()->getHeight()); if (closeButtonRect.isPointInRect(x, y)) { - setVisible(false); + close(); } } @@ -337,6 +371,11 @@ void Window::mousePressed(gcn::MouseEvent &event) } } +void Window::close() +{ + setVisible(false); +} + void Window::mouseReleased(gcn::MouseEvent &event) { if (mGrip && mouseResize) @@ -392,8 +431,8 @@ void Window::mouseDragged(gcn::MouseEvent &event) { int newX = std::max(0, getX()); int newY = std::max(0, getY()); - newX = std::min(windowContainer->getWidth() - getWidth(), newX); - newY = std::min(windowContainer->getHeight() - getHeight(), newY); + newX = std::min(graphics->getWidth() - getWidth(), newX); + newY = std::min(graphics->getHeight() - getHeight(), newY); setPosition(newX, newY); } @@ -438,13 +477,13 @@ void Window::mouseDragged(gcn::MouseEvent &event) newDim.height += newDim.y; newDim.y = 0; } - if (newDim.x + newDim.width > windowContainer->getWidth()) + if (newDim.x + newDim.width > graphics->getWidth()) { - newDim.width = windowContainer->getWidth() - newDim.x; + newDim.width = graphics->getWidth() - newDim.x; } - if (newDim.y + newDim.height > windowContainer->getHeight()) + if (newDim.y + newDim.height > graphics->getHeight()) { - newDim.height = windowContainer->getHeight() - newDim.y; + newDim.height = graphics->getHeight() - newDim.y; } // Update mouse offset when dragging bottom or right border @@ -473,8 +512,19 @@ void Window::loadWindowState() if (mGrip) { - setSize((int) config.getValue(name + "WinWidth", mDefaultWidth), - (int) config.getValue(name + "WinHeight", mDefaultHeight)); + int width = (int) config.getValue(name + "WinWidth", mDefaultWidth); + int height = (int) config.getValue(name + "WinHeight", mDefaultHeight); + + if (getMinWidth() > width) + width = getMinWidth(); + else if (getMaxWidth() < width) + width = getMaxWidth(); + if (getMinHeight() > height) + height = getMinHeight(); + else if (getMaxHeight() < height) + height = getMaxHeight(); + + setSize(width, height); } else { @@ -482,9 +532,44 @@ void Window::loadWindowState() } } +void Window::saveWindowState() +{ + // Saving X, Y and Width and Height for resizables in the config + if (!mWindowName.empty() && mWindowName != "window") + { + config.setValue(mWindowName + "WinX", getX()); + config.setValue(mWindowName + "WinY", getY()); + config.setValue(mWindowName + "Visible", isVisible()); + + if (mGrip) + { + if (getMinWidth() > getWidth()) + setWidth(getMinWidth()); + else if (getMaxWidth() < getWidth()) + setWidth(getMaxWidth()); + if (getMinHeight() > getHeight()) + setHeight(getMinHeight()); + else if (getMaxHeight() < getHeight()) + setHeight(getMaxHeight()); + + config.setValue(mWindowName + "WinWidth", getWidth()); + config.setValue(mWindowName + "WinHeight", getHeight()); + } + } +} + void Window::setDefaultSize(int defaultX, int defaultY, int defaultWidth, int defaultHeight) { + if (getMinWidth() > defaultWidth) + defaultWidth = getMinWidth(); + else if (getMaxWidth() < defaultWidth) + defaultWidth = getMaxWidth(); + if (getMinHeight() > defaultHeight) + defaultHeight = getMinHeight(); + else if (getMaxHeight() < defaultHeight) + defaultHeight = getMaxHeight(); + mDefaultX = defaultX; mDefaultY = defaultY; mDefaultWidth = defaultWidth; @@ -499,10 +584,63 @@ void Window::setDefaultSize() mDefaultHeight = getHeight(); } -void Window::resetToDefaultSize(bool changePosition) +void Window::setDefaultSize(int defaultWidth, int defaultHeight, + ImageRect::ImagePosition position, + int offsetX, int offsetY) +{ + int x = 0, y = 0; + + if (position == ImageRect::UPPER_LEFT) + { + } + else if (position == ImageRect::UPPER_CENTER) + { + x = (graphics->getWidth() - defaultWidth) / 2; + } + else if (position == ImageRect::UPPER_RIGHT) + { + x = graphics->getWidth() - defaultWidth; + } + else if (position == ImageRect::LEFT) + { + y = (graphics->getHeight() - defaultHeight) / 2; + } + else if (position == ImageRect::CENTER) + { + x = (graphics->getWidth() - defaultWidth) / 2; + y = (graphics->getHeight() - defaultHeight) / 2; + } + else if (position == ImageRect::RIGHT) + { + x = graphics->getWidth() - defaultWidth; + y = (graphics->getHeight() - defaultHeight) / 2; + } + else if (position == ImageRect::LOWER_LEFT) + { + y = graphics->getHeight() - defaultHeight; + } + else if (position == ImageRect::LOWER_CENTER) + { + x = (graphics->getWidth() - defaultWidth) / 2; + y = graphics->getHeight() - defaultHeight; + } + else if (position == ImageRect::LOWER_RIGHT) + { + x = graphics->getWidth() - defaultWidth; + y = graphics->getHeight() - defaultHeight; + } + + mDefaultX = x - offsetX; + mDefaultY = y - offsetY; + mDefaultWidth = defaultWidth; + mDefaultHeight = defaultHeight; +} + +void Window::resetToDefaultSize() { - if (changePosition) setPosition(mDefaultX, mDefaultY); + setPosition(mDefaultX, mDefaultY); setSize(mDefaultWidth, mDefaultHeight); + saveWindowState(); } int Window::getResizeHandles(gcn::MouseEvent &event) @@ -540,179 +678,16 @@ void Window::setGuiAlpha() for (int i = 0; i < 9; i++) { //logger->log("Window::setGuiAlpha: Border Image (%i)", i); - border.grid[i]->setAlpha(config.getValue("guialpha", 0.8)); + mSkin->getBorder().grid[i]->setAlpha(config.getValue("guialpha", 0.8)); } mAlphaChanged = false; } -void Window::loadSkin(const std::string &filename) +int Window::getGuiAlpha() { - const std::string windowId = Window::getId(); - - ResourceManager *resman = ResourceManager::getInstance(); - - logger->log("Loading Window Skin '%s'.", filename.c_str()); - logger->log("Loading Window ID '%s'.", windowId.c_str()); - - - if (filename.empty()) - logger->error("Window::loadSkin(): Invalid File Name."); - - // TODO: - // If there is an error loading the specified file, we should try to revert - // to a 'default' skin file. Only if the 'default' skin file can't be loaded - // should we have a terminating error. - XML::Document doc(filename); - xmlNodePtr rootNode = doc.rootNode(); - - if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "skinset")) - { - logger->error("Widget Skinning error"); - } - - std::string skinSetImage; - skinSetImage = XML::getProperty(rootNode, "image", ""); - Image *dBorders = NULL; - if (!skinSetImage.empty()) - { - logger->log("Window::loadSkin(): <skinset> defines '%s' as a skin image.", skinSetImage.c_str()); - dBorders = resman->getImage("graphics/gui/" + skinSetImage);//"graphics/gui/speech_bubble.png"); - } - else - { - logger->error("Window::loadSkin(): Skinset does not define an image!"); - } - - //iterate <widget>'s - for_each_xml_child_node(widgetNode, rootNode) - { - if (!xmlStrEqual(widgetNode->name, BAD_CAST "widget")) - continue; - - std::string widgetType; - widgetType = XML::getProperty(widgetNode, "type", "unknown"); - if (widgetType == "Window") - { - // Iterate through <part>'s - // LEEOR / TODO: - // We need to make provisions to load in a CloseButton image. For now it - // can just be hard-coded. - for_each_xml_child_node(partNode, widgetNode) - { - if (!xmlStrEqual(partNode->name, BAD_CAST "part")) - { - continue; - } - - std::string partType; - partType = XML::getProperty(partNode, "type", "unknown"); - // TOP ROW - if (partType == "top-left-corner") - { - const int xPos = XML::getProperty(partNode, "xpos", 0); - const int yPos = XML::getProperty(partNode, "ypos", 0); - const int width = XML::getProperty(partNode, "width", 1); - const int height = XML::getProperty(partNode, "height", 1); - - border.grid[0] = dBorders->getSubImage(xPos, yPos, width, height); - } - else if (partType == "top-edge") - { - const int xPos = XML::getProperty(partNode, "xpos", 0); - const int yPos = XML::getProperty(partNode, "ypos", 0); - const int width = XML::getProperty(partNode, "width", 1); - const int height = XML::getProperty(partNode, "height", 1); - - border.grid[1] = dBorders->getSubImage(xPos, yPos, width, height); - } - else if (partType == "top-right-corner") - { - const int xPos = XML::getProperty(partNode, "xpos", 0); - const int yPos = XML::getProperty(partNode, "ypos", 0); - const int width = XML::getProperty(partNode, "width", 1); - const int height = XML::getProperty(partNode, "height", 1); - - border.grid[2] = dBorders->getSubImage(xPos, yPos, width, height); - } - - // MIDDLE ROW - else if (partType == "left-edge") - { - const int xPos = XML::getProperty(partNode, "xpos", 0); - const int yPos = XML::getProperty(partNode, "ypos", 0); - const int width = XML::getProperty(partNode, "width", 1); - const int height = XML::getProperty(partNode, "height", 1); - - border.grid[3] = dBorders->getSubImage(xPos, yPos, width, height); - } - else if (partType == "bg-quad") - { - const int xPos = XML::getProperty(partNode, "xpos", 0); - const int yPos = XML::getProperty(partNode, "ypos", 0); - const int width = XML::getProperty(partNode, "width", 1); - const int height = XML::getProperty(partNode, "height", 1); - - border.grid[4] = dBorders->getSubImage(xPos, yPos, width, height); - } - else if (partType == "right-edge") - { - const int xPos = XML::getProperty(partNode, "xpos", 0); - const int yPos = XML::getProperty(partNode, "ypos", 0); - const int width = XML::getProperty(partNode, "width", 1); - const int height = XML::getProperty(partNode, "height", 1); - - border.grid[5] = dBorders->getSubImage(xPos, yPos, width, height); - } - - // BOTTOM ROW - else if (partType == "bottom-left-corner") - { - const int xPos = XML::getProperty(partNode, "xpos", 0); - const int yPos = XML::getProperty(partNode, "ypos", 0); - const int width = XML::getProperty(partNode, "width", 1); - const int height = XML::getProperty(partNode, "height", 1); - - border.grid[6] = dBorders->getSubImage(xPos, yPos, width, height); - } - else if (partType == "bottom-edge") - { - const int xPos = XML::getProperty(partNode, "xpos", 0); - const int yPos = XML::getProperty(partNode, "ypos", 0); - const int width = XML::getProperty(partNode, "width", 1); - const int height = XML::getProperty(partNode, "height", 1); - - border.grid[7] = dBorders->getSubImage(xPos, yPos, width, height); - } - else if (partType == "bottom-right-corner") - { - const int xPos = XML::getProperty(partNode, "xpos", 0); - const int yPos = XML::getProperty(partNode, "ypos", 0); - const int width = XML::getProperty(partNode, "width", 1); - const int height = XML::getProperty(partNode, "height", 1); - - border.grid[8] = dBorders->getSubImage(xPos, yPos, width, height); - } - - // Part is of an uknown type. - else - { - logger->log("Window::loadSkin(): Unknown Part Type '%s'", partType.c_str()); - } - } - } - // Widget is of an uknown type. - else - { - logger->log("Window::loadSkin(): Unknown Widget Type '%s'", widgetType.c_str()); - } - } - dBorders->decRef(); - - logger->log("Finished loading Window Skin."); - - // Hard-coded for now until we update the above code to look for window buttons. - closeImage = resman->getImage("graphics/gui/close_button.png"); + float alpha = config.getValue("guialpha", 0.8); + return (int) (alpha * 255.0f); } Layout &Window::getLayout() diff --git a/src/gui/window.h b/src/gui/window.h index 95fe2174..7f15e262 100644 --- a/src/gui/window.h +++ b/src/gui/window.h @@ -31,11 +31,11 @@ class ConfigListener; class ContainerPlacer; -class Image; -class ImageRect; class Layout; class LayoutCell; class ResizeGrip; +class Skin; +class SkinLoader; class WindowContainer; /** @@ -61,7 +61,7 @@ class Window : public gcn::Window, gcn::WidgetListener * @param skin The location where the window's skin XML can be found. */ Window(const std::string &caption = "Window", bool modal = false, - Window *parent = NULL, const std::string &skin = "graphics/gui/gui.xml"); + Window *parent = NULL, const std::string &skin = "graphics/gui/gui.xml"); /** * Destructor. Deletes all the added widgets. @@ -89,6 +89,12 @@ class Window : public gcn::Window, gcn::WidgetListener void setLocationRelativeTo(gcn::Widget *widget); /** + * Sets the location relative to the given enumerated position. + */ + void setLocationRelativeTo(ImageRect::ImagePosition position, + int offsetX = 0, int offsetY = 0); + + /** * Sets whether or not the window can be resized. */ void setResizable(bool resize); @@ -151,8 +157,7 @@ class Window : public gcn::Window, gcn::WidgetListener /** * Sets flag to show a title or not. */ - void setShowTitle(bool flag) - { mShowTitle = flag; } + void setShowTitle(bool flag) { mShowTitle = flag; } /** * Sets whether the window is sticky. A sticky window will not have @@ -233,6 +238,12 @@ class Window : public gcn::Window, gcn::WidgetListener void loadWindowState(); /** + * Saves the window state so that when the window is reloaded, it'll + * maintain its previous state and location. + */ + void saveWindowState(); + + /** * Set the default win pos and size. * (which can be different of the actual ones.) */ @@ -245,10 +256,20 @@ class Window : public gcn::Window, gcn::WidgetListener void setDefaultSize(); /** + * Set the default win pos and size. + * (which can be different of the actual ones.) + * This version of setDefaultSize sets the window's position based + * on a relative enumerated position, rather than a coordinate position. + */ + void setDefaultSize(int defaultWidth, int defaultHeight, + ImageRect::ImagePosition position, + int offsetx = 0, int offsetY = 0); + + /** * Reset the win pos and size to default. Don't forget to set defaults * first. */ - void resetToDefaultSize(bool changePosition = true); + virtual void resetToDefaultSize(); /** * Gets the layout handler for this window. @@ -266,11 +287,6 @@ class Window : public gcn::Window, gcn::WidgetListener void reflowLayout(int w = 0, int h = 0); /** - * Loads a window skin - */ - void loadSkin(const std::string &filename); - - /** * Adds a widget to the window and sets it at given cell. */ LayoutCell &place(int x, int y, gcn::Widget *, int w = 1, int h = 1); @@ -285,9 +301,17 @@ class Window : public gcn::Window, gcn::WidgetListener */ void center(); - protected: - /** The window container windows add themselves to. */ - static WindowContainer *windowContainer; + /** + * Overrideable functionality for when the window is to close. This + * allows for class implementations to clean up or do certain actions + * on window close they couldn't do otherwise. + */ + virtual void close(); + + /** + * Gets the alpha value used by the window, in a GUIChan usable format. + */ + int getGuiAlpha(); private: enum ResizeHandles @@ -326,7 +350,6 @@ class Window : public gcn::Window, gcn::WidgetListener int mDefaultY; /**< Default window Y position */ int mDefaultWidth; /**< Default window width */ int mDefaultHeight; /**< Default window height */ - std::string mSkin; /**< Name of the skin to use */ /** * The config listener that listens to changes relevant to all windows. @@ -335,8 +358,8 @@ class Window : public gcn::Window, gcn::WidgetListener static int mouseResize; /**< Active resize handles */ static int instances; /**< Number of Window instances */ - ImageRect border; /**< The window border and background */ - static Image *closeImage; /**< Close Button Image */ + + Skin* mSkin; /**< Skin in use by this window */ /** * The width of the resize border. Is independent of the actual window diff --git a/src/gui/windowcontainer.cpp b/src/gui/windowcontainer.cpp index 2846b1c1..eda739b9 100644 --- a/src/gui/windowcontainer.cpp +++ b/src/gui/windowcontainer.cpp @@ -23,6 +23,8 @@ #include "../utils/dtor.h" +WindowContainer *windowContainer = NULL; + void WindowContainer::logic() { delete_all(mDeathList); diff --git a/src/gui/windowcontainer.h b/src/gui/windowcontainer.h index 62704d1b..bc918184 100644 --- a/src/gui/windowcontainer.h +++ b/src/gui/windowcontainer.h @@ -45,6 +45,11 @@ class WindowContainer : public gcn::Container */ void scheduleDelete(gcn::Widget *widget); + /** + * Get the number of widget instances + */ + int getNumberOfInstances() { return mDeathList.size(); } + private: /** * List of widgets that are scheduled to be deleted. @@ -54,4 +59,6 @@ class WindowContainer : public gcn::Container Widgets mDeathList; }; +extern WindowContainer* windowContainer; + #endif diff --git a/src/inventory.cpp b/src/inventory.cpp index 3ca26e1e..5092fe3c 100644 --- a/src/inventory.cpp +++ b/src/inventory.cpp @@ -33,8 +33,9 @@ struct SlotUsed : public std::unary_function<Item*, bool> } }; -Inventory::Inventory(int size): - mSize(size) +Inventory::Inventory(int size, int offset): + mSize(size), + mOffset(offset) { mItems = new Item*[mSize]; std::fill_n(mItems, mSize, (Item*) 0); @@ -50,7 +51,7 @@ Inventory::~Inventory() Item* Inventory::getItem(int index) const { - if (index < 0 || index >= INVENTORY_SIZE || !mItems[index] || mItems[index]->getQuantity() <= 0) + if (index < 0 || index >= mSize || !mItems[index] || mItems[index]->getQuantity() <= 0) return 0; return mItems[index]; @@ -126,7 +127,7 @@ bool Inventory::contains(Item *item) const int Inventory::getFreeSlot() const { - Item **i = std::find_if(mItems + 2, mItems + mSize, + Item **i = std::find_if(mItems + mOffset, mItems + mSize, std::not1(SlotUsed())); return (i == mItems + mSize) ? -1 : (i - mItems); } @@ -147,5 +148,5 @@ int Inventory::getLastUsedSlot() const int Inventory::getInventorySize() const { - return INVENTORY_SIZE - 2; + return mSize - mOffset; } diff --git a/src/inventory.h b/src/inventory.h index df2aac38..ee8d072a 100644 --- a/src/inventory.h +++ b/src/inventory.h @@ -33,7 +33,7 @@ class Inventory /** * Constructor. */ - Inventory(int size); + Inventory(int size, int offset); /** * Destructor. @@ -111,6 +111,7 @@ class Inventory protected: Item **mItems; /**< The holder of items */ int mSize; /**< The max number of inventory items */ + int mOffset; /**< Offset used by the inventory */ }; #endif diff --git a/src/localplayer.cpp b/src/localplayer.cpp index 30ff9c35..245bd891 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -77,8 +77,8 @@ LocalPlayer::LocalPlayer(Uint32 id, Uint16 job, Map *map): mTargetTime(-1), mLastAction(-1), mLastTarget(-1), mWalkingDir(0), mDestX(0), mDestY(0), - mInventory(new Inventory(INVENTORY_SIZE)), - mStorage(new Inventory(STORAGE_SIZE)) + mInventory(new Inventory(INVENTORY_SIZE, 2)), + mStorage(new Inventory(STORAGE_SIZE, 1)) { // Variable to keep the local player from doing certain actions before a map // is initialized. e.g. drawing a player's name using the TextManager, since diff --git a/src/main.cpp b/src/main.cpp index 82f0ad20..1c05dbb7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -28,8 +28,6 @@ #include <guichan/actionlistener.hpp> -#include <guichan/widgets/label.hpp> - #include <libxml/parser.h> #include <SDL/SDL_ttf.h> @@ -58,6 +56,7 @@ #include "gui/char_server.h" #include "gui/char_select.h" #include "gui/gui.h" +#include "gui/label.h" #include "gui/login.h" #include "gui/ok_dialog.h" #include "gui/palette.h" @@ -445,16 +444,18 @@ void init_engine(const Options &options) state = LOGIN_STATE; /**< Initial game state */ // Initialize sound engine - try { - if (config.getValue("sound", 0) == 1) { + try + { + if (config.getValue("sound", 0) == 1) sound.init(); - } + sound.setSfxVolume((int) config.getValue("sfxVolume", defaultSfxVolume)); sound.setMusicVolume((int) config.getValue("musicVolume", defaultMusicVolume)); } - catch (const char *err) { + catch (const char *err) + { state = ERROR_STATE; errorMessage = err; logger->log("Warning: %s", err); @@ -787,11 +788,11 @@ int main(int argc, char *argv[]) gcn::Container *top = static_cast<gcn::Container*>(gui->getTop()); #ifdef PACKAGE_VERSION - gcn::Label *versionLabel = new gcn::Label(PACKAGE_VERSION); + gcn::Label *versionLabel = new Label(PACKAGE_VERSION); top->add(versionLabel, 2, 2); #endif ProgressBar *progressBar = new ProgressBar(0.0f, 100, 20, 168, 116, 31); - gcn::Label *progressLabel = new gcn::Label(); + gcn::Label *progressLabel = new Label(); top->add(progressBar, 5, top->getHeight() - 5 - progressBar->getHeight()); top->add(progressLabel, 15 + progressBar->getWidth(), progressBar->getY() + 4); @@ -846,17 +847,18 @@ int main(int argc, char *argv[]) while (state != EXIT_STATE) { // Handle SDL events - while (SDL_PollEvent(&event)) { - switch (event.type) { + while (SDL_PollEvent(&event)) + { + switch (event.type) + { case SDL_QUIT: state = EXIT_STATE; break; case SDL_KEYDOWN: if (event.key.keysym.sym == SDLK_ESCAPE) - { state = EXIT_STATE; - } + break; } @@ -871,11 +873,10 @@ int main(int argc, char *argv[]) { state = ERROR_STATE; - if (!network->getError().empty()) { + if (!network->getError().empty()) errorMessage = network->getError(); - } else { + else errorMessage = _("Got disconnected from server!"); - } } if (progressBar->isVisible()) @@ -898,7 +899,8 @@ int main(int argc, char *argv[]) gui->draw(); graphics->updateScreen(); - if (state != oldstate) { + if (state != oldstate) + { switch (oldstate) { case UPDATE_STATE: @@ -931,12 +933,14 @@ int main(int argc, char *argv[]) oldstate = state; if (currentDialog && state != ACCOUNT_STATE && - state != CHAR_CONNECT_STATE) { + state != CHAR_CONNECT_STATE) + { delete currentDialog; currentDialog = NULL; } - switch (state) { + switch (state) + { case LOADDATA_STATE: logger->log("State: LOADDATA"); @@ -961,10 +965,13 @@ int main(int argc, char *argv[]) case LOGIN_STATE: logger->log("State: LOGIN"); - if (!loginData.password.empty()) { + if (!loginData.password.empty()) + { loginData.registerLogin = false; state = ACCOUNT_STATE; - } else { + } + else + { currentDialog = new LoginDialog(&loginData); positionDialog(currentDialog, screenWidth, screenHeight); @@ -1048,9 +1055,12 @@ int main(int argc, char *argv[]) break; case UPDATE_STATE: - if (options.skipUpdate) { + if (options.skipUpdate) + { state = LOADDATA_STATE; - } else { + } + else + { // Determine which source to use for the update host if (!options.updateHost.empty()) updateHost = options.updateHost; @@ -1110,9 +1120,9 @@ int main(int argc, char *argv[]) /* * This loop can really stress the CPU, for no reason since it's * just constantly redrawing the wallpaper. Added the following - * usleep to limit it to 20 FPS during the login sequence + * usleep to limit it to 40 FPS during the login sequence */ - usleep(50000); + usleep(25000); } delete guiPalette; @@ -1128,9 +1138,8 @@ int main(int argc, char *argv[]) SDLNet_Quit(); if (nullFile) - { fclose(nullFile); - } + logger->log("State: EXIT"); exit_engine(); PHYSFS_deinit(); @@ -1142,16 +1151,12 @@ void SetupListener::action(const gcn::ActionEvent &event) Window *window = NULL; if (event.getId() == "Setup") - { window = setupWindow; - } if (window) { window->setVisible(!window->isVisible()); if (window->isVisible()) - { window->requestMoveToTop(); - } } } diff --git a/src/map.cpp b/src/map.cpp index 39e6d0a5..962ea499 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -119,10 +119,8 @@ Image* MapLayer::getTile(int x, int y) const return mTiles[x + y * mWidth]; } -void MapLayer::draw(Graphics *graphics, - int startX, int startY, - int endX, int endY, - int scrollX, int scrollY, +void MapLayer::draw(Graphics *graphics, int startX, int startY, + int endX, int endY, int scrollX, int scrollY, const Sprites &sprites) const { startX -= mX; @@ -163,8 +161,10 @@ void MapLayer::draw(Graphics *graphics, } // Draw any remaining sprites - if (mIsFringeLayer) { - while (si != sprites.end()) { + if (mIsFringeLayer) + { + while (si != sprites.end()) + { (*si)->draw(graphics, -scrollX, -scrollY); si++; } diff --git a/src/net/inventoryhandler.cpp b/src/net/inventoryhandler.cpp index 7d33b419..fa66821d 100644 --- a/src/net/inventoryhandler.cpp +++ b/src/net/inventoryhandler.cpp @@ -216,7 +216,7 @@ void InventoryHandler::handleMessage(MessageIn *msg) case SMSG_PLAYER_STORAGE_STATUS: /* * This is the closest we get to an "Open Storage" packet from the - * server. It always comes after the two SMSG_PLAYER_STORAGE_... + * server. It always comes after the two SMSG_PLAYER_STORAGE_... * packets that update storage contents. */ player_node->setInStorage(true); diff --git a/src/net/npchandler.cpp b/src/net/npchandler.cpp index 08ea8506..69346b65 100644 --- a/src/net/npchandler.cpp +++ b/src/net/npchandler.cpp @@ -59,7 +59,6 @@ void NPCHandler::handleMessage(MessageIn *msg) current_npc = msg->readInt32(); player_node->setAction(LocalPlayer::STAND); npcListDialog->parseItems(msg->readString(msg->getLength() - 8)); - npcListDialog->setVisible(true); npcListDialog->requestFocus(); break; @@ -68,7 +67,7 @@ void NPCHandler::handleMessage(MessageIn *msg) current_npc = msg->readInt32(); player_node->setAction(LocalPlayer::STAND); npcTextDialog->addText(msg->readString(msg->getLength() - 8)); - npcTextDialog->setVisible(true); + npcTextDialog->requestFocus(); break; case SMSG_NPC_CLOSE: diff --git a/src/openglgraphics.cpp b/src/openglgraphics.cpp index 0ee2bc50..7a1d259e 100644 --- a/src/openglgraphics.cpp +++ b/src/openglgraphics.cpp @@ -62,18 +62,17 @@ bool OpenGLGraphics::setVideoMode(int w, int h, int bpp, bool fs, bool hwaccel) mFullscreen = fs; mHWAccel = hwaccel; - if (fs) { + if (fs) displayFlags |= SDL_FULLSCREEN; - } SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); - if (!(mScreen = SDL_SetVideoMode(w, h, bpp, displayFlags))) { + if (!(mScreen = SDL_SetVideoMode(w, h, bpp, displayFlags))) return false; - } #ifdef __APPLE__ - if (mSync) { + if (mSync) + { const GLint VBL = 1; CGLSetParameter(CGLGetCurrentContext(), kCGLCPSwapInterval, &VBL); } @@ -110,6 +109,8 @@ bool OpenGLGraphics::setVideoMode(int w, int h, int bpp, bool fs, bool hwaccel) bool OpenGLGraphics::drawImage(Image *image, int srcX, int srcY, int dstX, int dstY, int width, int height, bool useColor) { + if (!image) return false; + srcX += image->mBounds.x; srcY += image->mBounds.y; @@ -157,13 +158,80 @@ bool OpenGLGraphics::drawImage(Image *image, int srcX, int srcY, glEnd(); if (!useColor) - { glColor4ub(mColor.r, mColor.g, mColor.b, mColor.a); - } return true; } +/* Optimising the functions that Graphics::drawImagePattern would call, + * so that glBegin...glEnd are outside the main loop. */ +void OpenGLGraphics::drawImagePattern(Image *image, int x, int y, int w, int h) +{ + if (!image) return; + + const int srcX = image->mBounds.x; + const int srcY = image->mBounds.y; + + const float texX1 = srcX / (float)image->mTexWidth; + const float texY1 = srcY / (float)image->mTexHeight; + + int iw = image->getWidth(); + int ih = image->getHeight(); + if (iw == 0 || ih == 0) + return; + + glColor4f(1.0f, 1.0f, 1.0f, image->mAlpha); + + glBindTexture(Image::mTextureType, image->mGLImage); + + setTexturingAndBlending(true); + + // Draw a set of textured rectangles + glBegin(GL_QUADS); + + for (int py = 0; py < h; py += ih) + { + int height = (py + ih >= h) ? h - py : ih; + int dstY = y + py; + for (int px = 0; px < w; px += iw) + { + int width = (px + iw >= w) ? w - px : iw; + int dstX = x + px; + + if (Image::mTextureType == GL_TEXTURE_2D) + { + // Find OpenGL normalized texture coordinates. + float texX2 = (srcX + width) / (float) image->mTexWidth; + float texY2 = (srcY + height) / (float) image->mTexHeight; + + glTexCoord2f(texX1, texY1); + glVertex2i(dstX, dstY); + glTexCoord2f(texX2, texY1); + glVertex2i(dstX + width, dstY); + glTexCoord2f(texX2, texY2); + glVertex2i(dstX + width, dstY + height); + glTexCoord2f(texX1, texY2); + glVertex2i(dstX, dstY + height); + } + else + { + glTexCoord2i(srcX, srcY); + glVertex2i(dstX, dstY); + glTexCoord2i(srcX + width, srcY); + glVertex2i(dstX + width, dstY); + glTexCoord2i(srcX + width, srcY + height); + glVertex2i(dstX + width, dstY + height); + glTexCoord2i(srcX, srcY + height); + glVertex2i(dstX, dstY + height); + } + } + } + + glEnd(); + + glColor4ub(mColor.r, mColor.g, mColor.b, mColor.a); +} + void OpenGLGraphics::updateScreen() { glFlush(); @@ -205,9 +273,8 @@ SDL_Surface* OpenGLGraphics::getScreenshot() w, h, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000); - if (SDL_MUSTLOCK(screenshot)) { + if (SDL_MUSTLOCK(screenshot)) SDL_LockSurface(screenshot); - } // Grap the pixel buffer and write it to the SDL surface glPixelStorei(GL_PACK_ALIGNMENT, 1); @@ -229,9 +296,8 @@ SDL_Surface* OpenGLGraphics::getScreenshot() free(buf); - if (SDL_MUSTLOCK(screenshot)) { + if (SDL_MUSTLOCK(screenshot)) SDL_UnlockSurface(screenshot); - } return screenshot; } @@ -241,7 +307,8 @@ bool OpenGLGraphics::pushClipArea(gcn::Rectangle area) int transX = 0; int transY = 0; - if (!mClipStack.empty()) { + if (!mClipStack.empty()) + { transX = -mClipStack.top().xOffset; transY = -mClipStack.top().yOffset; } @@ -266,9 +333,7 @@ void OpenGLGraphics::popClipArea() gcn::Graphics::popClipArea(); if (mClipStack.empty()) - { return; - } glPopMatrix(); glScissor(mClipStack.top().x, @@ -324,8 +389,10 @@ void OpenGLGraphics::setTargetPlane(int width, int height) void OpenGLGraphics::setTexturingAndBlending(bool enable) { - if (enable) { - if (!mTexture) { + if (enable) + { + if (!mTexture) + { glEnable(Image::mTextureType); mTexture = true; } @@ -335,16 +402,22 @@ void OpenGLGraphics::setTexturingAndBlending(bool enable) glEnable(GL_BLEND); mAlpha = true; } - } else { - if (mAlpha && !mColorAlpha) { + } + else + { + if (mAlpha && !mColorAlpha) + { glDisable(GL_BLEND); mAlpha = false; - } else if (!mAlpha && mColorAlpha) { + } + else if (!mAlpha && mColorAlpha) + { glEnable(GL_BLEND); mAlpha = true; } - if (mTexture) { + if (mTexture) + { glDisable(Image::mTextureType); mTexture = false; } diff --git a/src/openglgraphics.h b/src/openglgraphics.h index 566d6252..469e1f53 100644 --- a/src/openglgraphics.h +++ b/src/openglgraphics.h @@ -46,6 +46,10 @@ class OpenGLGraphics : public Graphics int width, int height, bool useColor); + void drawImagePattern(Image *image, + int x, int y, + int w, int h); + void updateScreen(); void _beginDraw(); diff --git a/src/particle.cpp b/src/particle.cpp index 82c163c6..21844f01 100644 --- a/src/particle.cpp +++ b/src/particle.cpp @@ -176,7 +176,8 @@ bool Particle::update() mVelocity *= mBounce; mVelocity.z = -mVelocity.z; } - else { + else + { mAlive = false; } } @@ -184,16 +185,12 @@ bool Particle::update() // Update child emitters if ((mLifetimePast-1)%Particle::emitterSkip == 0) { - for ( EmitterIterator e = mChildEmitters.begin(); - e != mChildEmitters.end(); - e++ - ) + for (EmitterIterator e = mChildEmitters.begin(); + e != mChildEmitters.end(); e++) { Particles newParticles = (*e)->createParticles(mLifetimePast); - for ( ParticleIterator p = newParticles.begin(); - p != newParticles.end(); - p++ - ) + for (ParticleIterator p = newParticles.begin(); + p != newParticles.end(); p++) { (*p)->moveBy(mPos); mChildParticles.push_back (*p); @@ -218,7 +215,9 @@ bool Particle::update() if ((*p)->update()) { p++; - } else { + } + else + { delete (*p); p = mChildParticles.erase(p); } @@ -236,8 +235,7 @@ void Particle::moveBy(const Vector &change) { mPos += change; for (ParticleIterator p = mChildParticles.begin(); - p != mChildParticles.end(); - p++) + p != mChildParticles.end(); p++) { if ((*p)->doesFollow()) { @@ -278,20 +276,21 @@ Particle *Particle::addEffect(const std::string &particleEffectFile, xmlNodePtr node; // Animation - if ((node = XML::findFirstChildByName( - effectChildNode, "animation"))) { + if ((node = XML::findFirstChildByName(effectChildNode, "animation"))) + { newParticle = new AnimationParticle(mMap, node); } // Image - else if ((node = XML::findFirstChildByName( - effectChildNode, "image"))) { + else if ((node = XML::findFirstChildByName(effectChildNode, "image"))) + { Image *img= resman->getImage((const char*) node->xmlChildrenNode->content); newParticle = new ImageParticle(mMap, img); } // Other - else { + else + { newParticle = new Particle(mMap); } @@ -314,7 +313,8 @@ Particle *Particle::addEffect(const std::string &particleEffectFile, continue; ParticleEmitter *newEmitter; - newEmitter = new ParticleEmitter(emitterNode, newParticle, mMap, rotation); + newEmitter = new ParticleEmitter(emitterNode, newParticle, mMap, + rotation); newParticle->addEmitter(newEmitter); } @@ -325,7 +325,8 @@ Particle *Particle::addEffect(const std::string &particleEffectFile, } Particle *Particle::addTextSplashEffect(const std::string &text, int x, int y, - const gcn::Color *color, gcn::Font *font, bool outline) + const gcn::Color *color, + gcn::Font *font, bool outline) { Particle *newParticle = new TextParticle(mMap, text, color, font, outline); newParticle->moveTo(x, y); @@ -343,7 +344,10 @@ Particle *Particle::addTextSplashEffect(const std::string &text, int x, int y, } Particle *Particle::addTextRiseFadeOutEffect(const std::string &text, - int x, int y, const gcn::Color *color, gcn::Font *font, bool outline){ + int x, int y, + const gcn::Color *color, + gcn::Font *font, bool outline) +{ Particle *newParticle = new TextParticle(mMap, text, color, font, outline); newParticle->moveTo(x, y); newParticle->setVelocity(0.0f, 0.0f, 0.5f); diff --git a/src/player.cpp b/src/player.cpp index 8668ac58..90d1aa8e 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -56,7 +56,7 @@ void Player::setName(const std::string &name) mNameColor = &guiPalette->getColor(Palette::GM); mName = new FlashText("(GM) " + name, mPx + NAME_X_OFFSET, mPy + NAME_Y_OFFSET, gcn::Graphics::CENTER, - &guiPalette->getColor(Palette::GM)); + &guiPalette->getColor(Palette::GM_NAME)); } else { diff --git a/src/player_relations.cpp b/src/player_relations.cpp index 14df3f01..ef2ef1bc 100644 --- a/src/player_relations.cpp +++ b/src/player_relations.cpp @@ -354,14 +354,15 @@ private: std::vector<PlayerIgnoreStrategy *> * PlayerRelationsManager::getPlayerIgnoreStrategies() { - if (mIgnoreStrategies.size() == 0) { + if (mIgnoreStrategies.size() == 0) + { // not initialised yet? mIgnoreStrategies.push_back(new PIS_emote(FIRST_IGNORE_EMOTE, - "floating '...' bubble", - PLAYER_IGNORE_STRATEGY_EMOTE0)); + "floating '...' bubble", + PLAYER_IGNORE_STRATEGY_EMOTE0)); mIgnoreStrategies.push_back(new PIS_emote(FIRST_IGNORE_EMOTE + 1, - "floating bubble", - "emote1")); + "floating bubble", + "emote1")); mIgnoreStrategies.push_back(new PIS_nothing()); mIgnoreStrategies.push_back(new PIS_dotdotdot()); mIgnoreStrategies.push_back(new PIS_blinkname()); diff --git a/src/player_relations.h b/src/player_relations.h index dd363d41..a6c6a115 100644 --- a/src/player_relations.h +++ b/src/player_relations.h @@ -143,7 +143,6 @@ public: */ void removePlayer(const std::string &name); - /** * Retrieves the default permissions. */ @@ -154,8 +153,6 @@ public: */ void setDefault(unsigned int permissions); - - /** * Retrieves all known player ignore strategies. * diff --git a/src/resources/dye.cpp b/src/resources/dye.cpp index 22bd2411..1e4fd2fd 100644 --- a/src/resources/dye.cpp +++ b/src/resources/dye.cpp @@ -25,7 +25,7 @@ #include "../log.h" -Palette::Palette(const std::string &description) +DyePalette::DyePalette(const std::string &description) { int size = description.length(); if (size == 0) return; @@ -62,7 +62,7 @@ Palette::Palette(const std::string &description) logger->log("Error, invalid embedded palette: %s", description.c_str()); } -void Palette::getColor(int intensity, int color[3]) const +void DyePalette::getColor(int intensity, int color[3]) const { if (intensity == 0) { @@ -111,7 +111,7 @@ void Palette::getColor(int intensity, int color[3]) const Dye::Dye(const std::string &description) { for (int i = 0; i < 7; ++i) - mPalettes[i] = 0; + mDyePalettes[i] = 0; if (description.empty()) return; @@ -141,7 +141,7 @@ Dye::Dye(const std::string &description) logger->log("Error, invalid dye: %s", description.c_str()); return; } - mPalettes[i] = new Palette(description.substr(pos + 2, next_pos - pos - 2)); + mDyePalettes[i] = new DyePalette(description.substr(pos + 2, next_pos - pos - 2)); ++next_pos; } while (next_pos < length); @@ -150,7 +150,7 @@ Dye::Dye(const std::string &description) Dye::~Dye() { for (int i = 0; i < 7; ++i) - delete mPalettes[i]; + delete mDyePalettes[i]; } void Dye::update(int color[3]) const @@ -170,8 +170,8 @@ void Dye::update(int color[3]) const int i = (color[0] != 0) | ((color[1] != 0) << 1) | ((color[2] != 0) << 2); - if (mPalettes[i - 1]) - mPalettes[i - 1]->getColor(cmax, color); + if (mDyePalettes[i - 1]) + mDyePalettes[i - 1]->getColor(cmax, color); } void Dye::instantiate(std::string &target, const std::string &palettes) diff --git a/src/resources/dye.h b/src/resources/dye.h index 3cef334a..d0d010bc 100644 --- a/src/resources/dye.h +++ b/src/resources/dye.h @@ -28,7 +28,7 @@ /** * Class for performing a linear interpolation between colors. */ -class Palette +class DyePalette { public: @@ -37,7 +37,7 @@ class Palette * The string is either a file name or a sequence of hexadecimal RGB * values separated by ',' and starting with '#'. */ - Palette(const std::string &pallete); + DyePalette(const std::string &pallete); /** * Gets a pixel color depending on its intensity. @@ -89,7 +89,7 @@ class Dye * * Red, Green, Yellow, Blue, Magenta, White (or rather gray). */ - Palette *mPalettes[7]; + DyePalette *mDyePalettes[7]; }; #endif diff --git a/src/resources/image.cpp b/src/resources/image.cpp index 7a7e6ac8..b696389f 100644 --- a/src/resources/image.cpp +++ b/src/resources/image.cpp @@ -25,6 +25,7 @@ #include "image.h" #include "../log.h" +#include "../position.h" #ifdef USE_OPENGL bool Image::mUseOpenGL = false; @@ -46,8 +47,7 @@ Image::Image(SDL_Surface *image): } #ifdef USE_OPENGL -Image::Image(GLuint glimage, int width, int height, - int texWidth, int texHeight): +Image::Image(GLuint glimage, int width, int height, int texWidth, int texHeight): mGLImage(glimage), mTexWidth(texWidth), mTexHeight(texHeight), @@ -315,6 +315,81 @@ void Image::setAlpha(float a) } } +Image* Image::merge(Image* image, const Position& pos) +{ + SDL_Surface* surface = new SDL_Surface(*(image->mImage)); + + Uint32 surface_pix, cur_pix; + Uint8 r, g, b, a, p_r, p_g, p_b, p_a; + double f_a, f_ca, f_pa; + SDL_PixelFormat *current_fmt = mImage->format; + SDL_PixelFormat *surface_fmt = surface->format; + int current_offset, surface_offset; + Position offset(0, 0); + + SDL_LockSurface(surface); + SDL_LockSurface(mImage); + // for each pixel lines of a source image + for (offset.x = (pos.x > 0 ? 0 : -pos.x); offset.x < image->getWidth() && + pos.x + offset.x < getWidth(); offset.x++) + { + for (offset.y = (pos.y > 0 ? 0 : -pos.y); offset.y < image->getHeight() + && pos.y + offset.y < getHeight(); offset.y++) + { + // Computing offset on both images + current_offset = (pos.y + offset.y) * getWidth() + pos.x + offset.x; + surface_offset = offset.y * surface->w + offset.x; + + // Retrieving a pixel to merge + surface_pix = ((Uint32*) surface->pixels)[surface_offset]; + cur_pix = ((Uint32*) mImage->pixels)[current_offset]; + + // Retreiving each channel of the pixel using pixel format + r = (Uint8)(((surface_pix & surface_fmt->Rmask) >> + surface_fmt->Rshift) << surface_fmt->Rloss); + g = (Uint8)(((surface_pix & surface_fmt->Gmask) >> + surface_fmt->Gshift) << surface_fmt->Gloss); + b = (Uint8)(((surface_pix & surface_fmt->Bmask) >> + surface_fmt->Bshift) << surface_fmt->Bloss); + a = (Uint8)(((surface_pix & surface_fmt->Amask) >> + surface_fmt->Ashift) << surface_fmt->Aloss); + + // Retreiving previous alpha value + p_a = (Uint8)(((cur_pix & current_fmt->Amask) >> + current_fmt->Ashift) << current_fmt->Aloss); + + // new pixel with no alpha or nothing on previous pixel + if (a == SDL_ALPHA_OPAQUE || (p_a == 0 && a > 0)) + ((Uint32 *)(surface->pixels))[current_offset] = + SDL_MapRGBA(current_fmt, r, g, b, a); + else if (a > 0) + { // alpha is lower => merge color with previous value + f_a = (double) a / 255.0; + f_ca = 1.0 - f_a; + f_pa = (double) p_a / 255.0; + p_r = (Uint8)(((cur_pix & current_fmt->Rmask) >> + current_fmt->Rshift) << current_fmt->Rloss); + p_g = (Uint8)(((cur_pix & current_fmt->Gmask) >> + current_fmt->Gshift) << current_fmt->Gloss); + p_b = (Uint8)(((cur_pix & current_fmt->Bmask) >> + current_fmt->Bshift) << current_fmt->Bloss); + r = (Uint8)((double) p_r * f_ca * f_pa + (double)r * f_a); + g = (Uint8)((double) p_g * f_ca * f_pa + (double)g * f_a); + b = (Uint8)((double) p_b * f_ca * f_pa + (double)b * f_a); + a = (a > p_a ? a : p_a); + ((Uint32 *)(surface->pixels))[current_offset] = + SDL_MapRGBA(current_fmt, r, g, b, a); + } + } + } + SDL_UnlockSurface(surface); + SDL_UnlockSurface(mImage); + + Image* newImage = new Image(surface); + + return newImage; +} + float Image::getAlpha() { return mAlpha; diff --git a/src/resources/image.h b/src/resources/image.h index fe3081ac..eeaa574e 100644 --- a/src/resources/image.h +++ b/src/resources/image.h @@ -40,6 +40,7 @@ #include "resource.h" class Dye; +class Position; class SDL_Rect; class SDL_Surface; @@ -131,6 +132,15 @@ class Image : public Resource static void setLoadAsOpenGL(bool useOpenGL); #endif + /** + * Merges two image SDL_Surfaces together. This is for SDL use only, as + * reducing the number of surfaces that SDL has to render can cut down + * on the number of blit operations necessary, which in turn can help + * improve overall framerates. Don't use unless you are using it to + * reduce the number of overall layers that need to be drawn through SDL. + */ + Image* merge(Image* image, const Position& pos); + protected: /** * Constructor. diff --git a/src/resources/itemdb.cpp b/src/resources/itemdb.cpp index 1ff34d98..dbd12eee 100644 --- a/src/resources/itemdb.cpp +++ b/src/resources/itemdb.cpp @@ -144,9 +144,12 @@ void ItemDB::load() if (param == error_value) \ logger->log("ItemDB: Missing " #param " attribute for item %i!",id) - CHECK_PARAM(name, ""); + if (id >= 0) + { + CHECK_PARAM(name, ""); + CHECK_PARAM(description, ""); + } CHECK_PARAM(image, ""); - CHECK_PARAM(description, ""); // CHECK_PARAM(effect, ""); // CHECK_PARAM(type, 0); // CHECK_PARAM(weight, 0); diff --git a/src/text.cpp b/src/text.cpp index b0be25bf..83bd6c24 100644 --- a/src/text.cpp +++ b/src/text.cpp @@ -133,7 +133,7 @@ void Text::draw(gcn::Graphics *graphics, int xOff, int yOff) TextRenderer::renderText(graphics, mText, mX - xOff, mY - yOff, gcn::Graphics::LEFT, - mColor, boldFont, !mIsSpeech, true); + *mColor, boldFont, !mIsSpeech, true); } FlashText::FlashText(const std::string &text, int x, int y, @@ -149,9 +149,7 @@ void FlashText::draw(gcn::Graphics *graphics, int xOff, int yOff) if (mTime) { if ((--mTime & 4) == 0) - { return; - } } Text::draw(graphics, xOff, yOff); } diff --git a/src/textparticle.cpp b/src/textparticle.cpp index 792b6bea..04b7abe1 100644 --- a/src/textparticle.cpp +++ b/src/textparticle.cpp @@ -60,5 +60,5 @@ void TextParticle::draw(Graphics *graphics, int offsetX, int offsetY) const TextRenderer::renderText(graphics, mText, screenX, screenY, gcn::Graphics::CENTER, - mColor, mTextFont, mOutline, false, (int)alpha); + *mColor, mTextFont, mOutline, false, (int) alpha); } @@ -162,6 +162,8 @@ <Unit filename="src\gui\itempopup.h" /> <Unit filename="src\gui\itemshortcutcontainer.cpp" /> <Unit filename="src\gui\itemshortcutcontainer.h" /> + <Unit filename="src\gui\label.cpp" /> + <Unit filename="src\gui\label.h" /> <Unit filename="src\gui\linkhandler.h" /> <Unit filename="src\gui\listbox.cpp" /> <Unit filename="src\gui\listbox.h" /> @@ -189,6 +191,8 @@ <Unit filename="src\gui\passwordfield.h" /> <Unit filename="src\gui\playerbox.cpp" /> <Unit filename="src\gui\playerbox.h" /> + <Unit filename="src\gui\popup.cpp" /> + <Unit filename="src\gui\popup.h" /> <Unit filename="src\gui\popupmenu.cpp" /> <Unit filename="src\gui\popupmenu.h" /> <Unit filename="src\gui\progressbar.cpp" /> @@ -230,6 +234,8 @@ <Unit filename="src\gui\shortcutwindow.h" /> <Unit filename="src\gui\skill.cpp" /> <Unit filename="src\gui\skill.h" /> + <Unit filename="src\gui\skin.cpp" /> + <Unit filename="src\gui\skin.h" /> <Unit filename="src\gui\slider.cpp" /> <Unit filename="src\gui\slider.h" /> <Unit filename="src\gui\speechbubble.cpp" /> @@ -246,6 +252,7 @@ <Unit filename="src\gui\textbox.h" /> <Unit filename="src\gui\textfield.cpp" /> <Unit filename="src\gui\textfield.h" /> + <Unit filename="src\gui\textrenderer.h" /> <Unit filename="src\gui\trade.cpp" /> <Unit filename="src\gui\trade.h" /> <Unit filename="src\gui\truetypefont.cpp" /> diff --git a/tools/tmxcopy/main.cpp b/tools/tmxcopy/main.cpp index ac18ce04..4926d69f 100644 --- a/tools/tmxcopy/main.cpp +++ b/tools/tmxcopy/main.cpp @@ -1,6 +1,7 @@ /* * TMXCopy * Copyright (C) 2007 Philipp Sehmisch + * Copyright (C) 2009 Steve Cotton * * 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 @@ -19,34 +20,70 @@ #include <iostream> #include <string> +#include <unistd.h> #include "map.hpp" +void printUsage() +{ + std::cerr<<"Usage: tmxcopy [-c] [-n] srcFile x y width height tgtFile x y [outfile]"<<std::endl + <<" -c create layers, if they don't already exist in the target"<<std::endl + <<" -n copy layers by number, not name"<<std::endl; +} + int main(int argc, char * argv[] ) { - // parsing command line options - if (argc < 9 || argc > 10) + ConfigurationOptions config = {0}; + int opt; + while ((opt = getopt(argc, argv, "cn")) != -1) + { + switch (opt) + { + case 'c': + config.createMissingLayers = true; + break; + case 'n': + config.copyLayersByOrdinal = true; + break; + case '?': + std::cerr<<"Unrecognized option"<<std::endl; + printUsage(); + return -1; + } + } + + if ((argc-optind) < 8) + { + std::cerr<<"Too few args"<<std::endl; + printUsage(); + return -1; + } + if ((argc-optind) > 9) { - std::cerr<<"Usage: srcFile x y width height tgtFile x y [outfile]\n"; + std::cerr<<"Too many args"<<std::endl; + printUsage(); return -1; } - std::string srcFile = argv[1]; - int srcX= atoi(argv[2]); - int srcY= atoi(argv[3]); - int width= atoi(argv[4]); - int height=atoi(argv[5]); - std::string tgtFile = argv[6]; - int destX=atoi(argv[7]); - int destY=atoi(argv[8]); + std::string srcFile = argv[optind+0]; + int srcX= atoi(argv[optind+1]); + int srcY= atoi(argv[optind+2]); + int width= atoi(argv[optind+3]); + int height=atoi(argv[optind+4]); + std::string tgtFile = argv[optind+5]; + int destX=atoi(argv[optind+6]); + int destY=atoi(argv[optind+7]); std::string outFile = tgtFile; - if (argc == 10) outFile = argv[9]; + if (argc == optind+9) + { + outFile = argv[optind+8]; + } // plausibility check of command line options if (height < 1 || width < 1 || srcX < 0 || srcY < 0 || destX < 0 || destY < 0) { std::cerr<<"Illegal coordinates!"<<std::endl; - std::cerr<<"Usage: sourceFile x y height width targetFile x y [outputFile]"<<std::endl; + printUsage(); return -1; } @@ -54,16 +91,17 @@ int main(int argc, char * argv[] ) { Map* srcMap = new Map(srcFile); Map* tgtMap = new Map(tgtFile); - if (tgtMap->overwrite(srcMap, srcX, srcY, width, height, destX, destY)) + if (tgtMap->overwrite(srcMap, srcX, srcY, width, height, destX, destY, config)) { tgtMap->save(outFile); } else { return -1; } + delete srcMap; + delete tgtMap; } catch (int) { return -1; } - } diff --git a/tools/tmxcopy/map.cpp b/tools/tmxcopy/map.cpp index d9fc8ada..75cbecbb 100644 --- a/tools/tmxcopy/map.cpp +++ b/tools/tmxcopy/map.cpp @@ -1,6 +1,7 @@ /* * TMXCopy * Copyright (C) 2007 Philipp Sehmisch + * Copyright (C) 2009 Steve Cotton * * 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 @@ -24,6 +25,7 @@ #include <string.h> #include <zlib.h> +#include <cassert> #include "xmlutils.h" #include "zlibutils.h" @@ -80,9 +82,19 @@ Map::Map(std::string filename): { if (xmlStrEqual(node->name, BAD_CAST "layer")) { - Layer* layer = new Layer; - layer->resize(mWidth * mHeight); //build layer information + std::string name = XML::getProperty(node, "name", ""); + Layer* layer = new Layer(name, mWidth * mHeight); + if ( + (mWidth != XML::getProperty(node, "width" , 0)) || + (mHeight != XML::getProperty(node, "height", 0)) || + (0 != XML::getProperty(node, "x" , 0)) || + (0 != XML::getProperty(node, "y" , 0))) + { + std::cerr<<"Error: layer size does not match map size for layer \""<<name<<"\" in "<<filename<<std::endl; + throw 1; + } + for_each_xml_child_node(dataNode, node) { if (!xmlStrEqual(dataNode->name, BAD_CAST "data")) continue; @@ -155,7 +167,7 @@ Map::Map(std::string filename): { for (int s = mTilesets.size()-1; s >= 0; s--) { - if (mTilesets.at(s)->firstgid < gid) + if (mTilesets.at(s)->firstgid <= gid) { layer->at(c).tileset = s; layer->at(c).index = gid - mTilesets.at(s)->firstgid; @@ -184,7 +196,8 @@ Map::Map(std::string filename): bool Map::overwrite( Map* srcMap, int srcX, int srcY, int srcWidth, int srcHeight, - int destX, int destY) + int destX, int destY, + const ConfigurationOptions& config) { //plausibility check of coordinates bool checkPassed = true; @@ -204,6 +217,32 @@ bool Map::overwrite( Map* srcMap, std::cerr<<"Error: Area exceeds lower map border of target map!"<<std::endl; checkPassed = false; } + if (!config.createMissingLayers) + { + if (config.copyLayersByOrdinal) + { + if (srcMap->getNumberOfLayers() > mLayers.size()) { + std::cerr<<"Error: Source has more layers than target map"<<std::endl + <<"(and the command-line \"create layers\" option was not used)"<<std::endl; + checkPassed = false; + } + } + else + { + for (int i = 0; i < srcMap->getNumberOfLayers(); i++) + { + Layer* srcLayer = srcMap->getLayer(i); + Layer* destLayer = getLayer(srcLayer->getName()); + if (!destLayer) + { + std::cerr<<"Error: target map has no layer named \""<<srcLayer->getName()<<"\""<<std::endl + <<"(and the command-line \"create layers\" option was not used)"<<std::endl; + checkPassed = false; + } + } + } + } + if (!checkPassed) return false; std::map<int, int> translation; @@ -234,7 +273,43 @@ bool Map::overwrite( Map* srcMap, for (int i = 0; i < srcMap->getNumberOfLayers(); i++) { Layer* srcLayer = srcMap->getLayer(i); - Layer* destLayer = mLayers.at(i); + Layer* destLayer = NULL; + if (config.copyLayersByOrdinal) + { + if (i < mLayers.size()) + { + destLayer = mLayers.at(i); + } + } + else + { + destLayer = getLayer(srcLayer->getName()); + } + + if (!destLayer) + { + assert(config.createMissingLayers); /* Tested earlier, in the checkPassed section */ + /* Generate a name for the new layer, which must be + * unique in the target map, and should be unique in + * the source map (to avoid collisions later in the + * copying process). + * Start by trying the name of the source layer. + */ + std::string name = srcLayer->getName(); + if (getLayer(name)) + { + int k=0; + do + { + name = "Layer" + toString(k); + k++; + } while (getLayer(name) || srcMap->getLayer(name)); + } + + destLayer = new Layer(name, mWidth * mHeight); + mLayers.push_back(destLayer); + std::cout<<"Created new layer "<<name<<std::endl; + } for (int y=0; y<srcHeight; y++) { @@ -340,7 +415,7 @@ int Map::save(std::string filename) xmlNodePtr newNode; xmlAddChild(rootNode, xmlNewDocText(mXmlDoc, BAD_CAST " ")); newNode = xmlNewNode(NULL, BAD_CAST "layer"); - xmlNewProp(newNode, BAD_CAST "name", BAD_CAST ("Layer" + toString(i)).c_str()); + xmlNewProp(newNode, BAD_CAST "name", BAD_CAST (mLayers.at(i)->getName()).c_str()); xmlNewProp(newNode, BAD_CAST "width", BAD_CAST toString(mWidth).c_str()); xmlNewProp(newNode, BAD_CAST "height", BAD_CAST toString(mHeight).c_str()); xmlAddChild(newNode, xmlNewDocText(mXmlDoc, BAD_CAST "\n ")); @@ -354,6 +429,9 @@ int Map::save(std::string filename) xmlAddChild(newNode, xmlNewDocText(mXmlDoc, BAD_CAST "\n ")); xmlAddChild(rootNode, newNode); xmlAddChild(rootNode, xmlNewDocText(mXmlDoc, BAD_CAST "\n")); + + free(base64Data); + free(binData); } //save XML tree @@ -370,3 +448,34 @@ int Map::save(std::string filename) return true; } } + +Layer* Map::getLayer(std::string name) +{ + for (std::vector<Layer*>::iterator layer = mLayers.begin(); + layer != mLayers.end(); + layer++) + { + if ((*layer)->getName() == name) + return *layer; + } + return NULL; +} + +Map::~Map() +{ + for (std::vector<Layer*>::iterator layer = mLayers.begin(); + layer != mLayers.end(); + layer++) + { + delete *layer; + } + + for (std::vector<Tileset*>::iterator tileset = mTilesets.begin(); + tileset != mTilesets.end(); + tileset++) + { + delete *tileset; + } + + xmlFreeDoc(mXmlDoc); +} diff --git a/tools/tmxcopy/map.hpp b/tools/tmxcopy/map.hpp index 2ca9061a..af2f5385 100644 --- a/tools/tmxcopy/map.hpp +++ b/tools/tmxcopy/map.hpp @@ -1,6 +1,7 @@ /* * TMXCopy * Copyright (C) 2007 Philipp Sehmisch + * Copyright (C) 2009 Steve Cotton * * 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 @@ -22,6 +23,22 @@ #include <set> #include <libxml/parser.h> +struct ConfigurationOptions +{ + /* When copying map layers, how to match source layer to + * destination layer. + * + * True: Pair the first layer to the first layer, the second + * to the second, etc. + * + * False: Pair up layers with matching names. + */ + bool copyLayersByOrdinal; + + /* Create extra layers in the target as necessary. */ + bool createMissingLayers; +}; + struct Tileset { std::string imagefile; @@ -45,22 +62,50 @@ struct Tile size_t index; // index in said tileset }; -typedef std::vector<Tile> Layer; +typedef std::vector<Tile> LayerTiles; + +/* This represents an empty tile in the layer. + * Note that {0,0} would be the first tile in the first tileset. + */ +const Tile defaultTile = {-1, 0}; + +class Layer +{ + public: + /* name - the name of the layer, as shown in Tiled + * tileCount - total number of tiles (width*height) + */ + Layer(std::string name, LayerTiles::size_type tileCount) + : mTiles(tileCount, defaultTile), + mName (name) + { + } + + std::string getName() { return mName; } + Tile& at(LayerTiles::size_type c) { return mTiles.at(c); } + + private: + LayerTiles mTiles; + std::string mName; +}; class Map { public: Map(std::string filename); + ~Map(); - bool overwrite( Map* srcMap, + bool overwrite(Map* srcMap, int srcX, int srcY, int srcWidth, int srcHeight, - int destX, int destY); + int destX, int destY, + const ConfigurationOptions& config); int save(std::string filename); int getNumberOfLayers() { return mLayers.size(); } Layer* getLayer(size_t num) { return mLayers.at(num); } + Layer* getLayer(std::string name); std::vector<Tileset*>* getTilesets() { return &mTilesets; } diff --git a/tools/tmxcopy/readme.txt b/tools/tmxcopy/readme.txt index e4235b94..e8ec830a 100644 --- a/tools/tmxcopy/readme.txt +++ b/tools/tmxcopy/readme.txt @@ -23,6 +23,22 @@ But when you enter this command the mapB will be overwritten. This could be a pr Now we can check temp.tmx to see if the copying worked correctly. +Which layer gets copied to which: +By default layers are copied to layers of the same name. The -n option will make it copy by layer number instead. + + mapA: Ground, Fringe, Over, Collision, Object + mapB: Ground, Fencing, Fringe, Over, Collision, Object + The default copies Ground->Ground, Fringe->Fringe, Over->Over, Collision->Collision (the object layer is not affected) + -n copies Ground->Ground, Fringe->Fencing, Over->Fringe, Collision->Over (mapB's collision and object layers are not affected) + + mapA: Ground, Fringe, Over, Collision, Object + mapC: Ground, Fringe, Overhead, Collision, Object + The default quits with an error + -n copies Over->Overhead + +The -c option creates layers as needed. Using it to copy mapB to mapA will add a Fencing layer to mapA. + + The program works so far but there are still some minor problems: -Only tested for TMW-compilant maps. I don't guarantee that it works with Tiled maps that are made for other games and thus use different features. It is assumed that the target map and the source maps have the same number of layers, for example. @@ -31,4 +47,4 @@ The program works so far but there are still some minor problems: -Layer data of output file isn't gzip-compressed yet -Created TMX file is a bit malformated (but working properly) -The last 2 problems can be solved easily by opening and saving the map in Tiled.
\ No newline at end of file +The last 2 problems can be solved easily by opening and saving the map in Tiled. |