X-Git-Url: http://git.localhorst.tv/?a=blobdiff_plain;f=src%2Fgraphics%2FMenu.h;h=19ad9071541ebbac673d8b6f97b89c0647e3a3d8;hb=ec824200aec12d6870b70304bcd2e2aeadba767b;hp=175a7114501afcd4ad1e75bfb61115c8b790f28c;hpb=795bcbebfc3a63f374f8da0790af5b7105adb68a;p=l2e.git diff --git a/src/graphics/Menu.h b/src/graphics/Menu.h index 175a711..19ad907 100644 --- a/src/graphics/Menu.h +++ b/src/graphics/Menu.h @@ -1,28 +1,31 @@ -/* - * Menu.h - * - * Created on: Aug 8, 2012 - * Author: holy - */ - #ifndef GRAPHICS_MENU_H_ #define GRAPHICS_MENU_H_ +namespace app { + class Application; + class State; +} + +#include "Animation.h" #include "Font.h" #include "Sprite.h" -#include "../geometry/Vector.h" +#include "../math/Vector.h" +#include #include #include namespace graphics { -class Sprite; - struct MenuProperties { + static const int TYPE_ID = 407; + const Font *font; const Font *disabledFont; const Sprite *cursor; + const Sprite *selectedCursor; + const Animation *cursorAnimation; + const Animation *selectedCursorAnimation; int charsPerEntry; int rows; int rowGap; @@ -32,17 +35,23 @@ struct MenuProperties { int charsPerNumber; int charsPerAdditionalText; int additionalTextGap; + int thirdColumnHack; char delimiter; + bool wrapX; + bool wrapY; MenuProperties() - : font(0), disabledFont(0), cursor(0) - , charsPerEntry(0), rows(0), rowGap(0) - , iconSpace(0), cols(0), colGap(0) + : font(0), disabledFont(0), cursor(0), selectedCursor(0) + , cursorAnimation(0), selectedCursorAnimation(0) + , charsPerEntry(0), rows(1), rowGap(0) + , iconSpace(0), cols(1), colGap(0) , charsPerNumber(0), charsPerAdditionalText(0) - , additionalTextGap(0), delimiter(':') { } + , additionalTextGap(0), thirdColumnHack(0), delimiter(':') + , wrapX(false), wrapY(false) { } + + static void CreateTypeDescription(); + static void Construct(void *); - MenuProperties(const Font *font, const Font *disabledFont, const Sprite *cursor, int charsPerEntry, int rows, int rowGap, int iconSpace, int cols, int colGap, int charsPerNumber, char delimiter, int charsPerAdditionalText, int additionalTextGap) - : font(font), disabledFont(disabledFont), cursor(cursor), charsPerEntry(charsPerEntry), rows(rows), rowGap(rowGap), iconSpace(iconSpace), cols(cols), colGap(colGap), charsPerNumber(charsPerNumber), charsPerAdditionalText(charsPerAdditionalText), additionalTextGap(additionalTextGap), delimiter(delimiter) { } }; template @@ -52,9 +61,16 @@ class Menu public: Menu(); Menu(const MenuProperties &); - Menu(const Font *font, const Font *disabledFont, const Sprite *cursor, int charsPerEntry, int rows, int rowGap = 0, int iconSpace = 0, int cols = 1, int colGap = 0, int charsPerNumber = 0, char delimiter = ':', int charsPerAdditionalText = 0, int additionalTextGap = 0); public: + void SetInactive() { state = STATE_INACTIVE; } + void SetActive() { state = STATE_ACTIVE; } + void SetSelected() { state = STATE_SELECTED; } + void SetDualSelection() { state = STATE_DUAL; secondarySelection = selected; } + bool IsActive() const { return state == STATE_ACTIVE; } + bool HasSelected() const { return state == STATE_SELECTED; } + bool InDualMode() const { return state == STATE_DUAL; } + int Width() const; int Height() const; int ColWidth() const; @@ -67,12 +83,22 @@ public: int SelectedNumber() const { return entries[selected].number; } bool SelectedIsEnabled() const { return entries[selected].enabled; } + T &SecondarySelection() { return entries[secondarySelection].value; } + const T &SecondarySelection() const { return entries[secondarySelection].value; } + const char *SecondaryTitle() const { return entries[secondarySelection].title; } + int SecondaryNumber() const { return entries[secondarySelection].number; } + bool SecondaryIsEnabled() const { return entries[secondarySelection].enabled; } + + void SwapSelected() { SwapEntriesAt(selected, secondarySelection); } + void SwapEntriesAt(int lhs, int rhs) { std::swap(entries[lhs], entries[rhs]); } + void NextItem(); void PreviousItem(); void NextRow(); void PreviousRow(); void SelectIndex(int index); int SelectedIndex() const { return selected; } + int SecondaryIndex() const { return secondarySelection; } bool IsSelected(int index) const { return index == selected; } int EntryCount() const { return entries.size(); } @@ -85,13 +111,21 @@ public: void Enable(int index) { entries[index].enabled = true; } void Reserve(int n) { entries.reserve(n); } void Clear() { entries.clear(); } + void ClearEntry(int at) { entries[at] = Entry(0, T(), false); } + + void StartAnimation(app::Application &ctrl); + void StartAnimation(app::State &ctrl); + void StopAnimation(); - void Draw(SDL_Surface *dest, const geometry::Vector &position) const; + void Draw(SDL_Surface *dest, const math::Vector &position) const; private: int GetRow(int index) const { return index / cols; } int GetCol(int index) const { return index % cols; } + void DrawCursor(SDL_Surface *, const math::Vector &) const; + void DrawSelectedCursor(SDL_Surface *, const math::Vector &) const; + private: struct Entry { Entry(const char *title, const T &value, bool enabled = true, const Sprite *icon = 0, int number = 0, const char *additionalText = 0) @@ -103,9 +137,19 @@ private: T value; bool enabled; }; + AnimationRunner animation; + AnimationRunner selectedAnimation; std::vector entries; int selected; + int secondarySelection; int topRow; + enum State { + STATE_INACTIVE, + STATE_ACTIVE, + STATE_SELECTED, + STATE_DUAL, + }; + State state; }; @@ -114,30 +158,21 @@ template Menu::Menu() : MenuProperties() , selected(0) -, topRow(0) { +, secondarySelection(0) +, topRow(0) +, state(STATE_ACTIVE) { } template Menu::Menu(const MenuProperties &p) : MenuProperties(p) +, animation(cursorAnimation) +, selectedAnimation(selectedCursorAnimation) , selected(0) -, topRow(0) { - -} - -template -Menu::Menu(const Font *font, const Font *disabledFont, const Sprite *cursor, int charsPerEntry, int rows, int rowGap, int iconSpace, int cols, int colGap, int charsPerNumber, char delimiter, int charsPerAdditionalText, int additionalTextGap) -: MenuProperties( - font, disabledFont ? disabledFont : font, - cursor, charsPerEntry, - rows, rowGap, iconSpace, - cols, colGap, charsPerNumber, - delimiter, - charsPerAdditionalText, - additionalTextGap) -, selected(0) -, topRow(0) { +, secondarySelection(0) +, topRow(0) +, state(STATE_ACTIVE) { } @@ -168,22 +203,38 @@ int Menu::Height() const { template void Menu::NextItem() { - SelectIndex(selected + 1); + int index(selected + 1); + if (wrapX && index % cols == 0) { + index -= cols; + } + SelectIndex(index); } template void Menu::PreviousItem() { - SelectIndex(selected - 1); + int index(selected - 1); + if (wrapX && selected % cols == 0) { + index += cols; + } + SelectIndex(index); } template void Menu::NextRow() { - SelectIndex(selected + cols); + int index(selected + cols); + if (wrapY && index >= int(entries.size())) { + index -= entries.size(); + } + SelectIndex(index); } template void Menu::PreviousRow() { - SelectIndex(selected - cols); + int index(selected - cols); + if (wrapY && index < 0) { + index += entries.size(); + } + SelectIndex(index); } template @@ -199,45 +250,123 @@ void Menu::SelectIndex(int index) { template -void Menu::Draw(SDL_Surface *dest, const geometry::Vector &position) const { +void Menu::StartAnimation(app::Application &ctrl) { + if (cursorAnimation) { + animation.Start(ctrl); + } + if (selectedCursorAnimation) { + selectedAnimation.Start(ctrl); + } +} + +template +void Menu::StartAnimation(app::State &ctrl) { + if (cursorAnimation) { + animation.Start(ctrl); + } + if (selectedCursorAnimation) { + selectedAnimation.Start(ctrl); + } +} + +template +void Menu::StopAnimation() { + animation.Stop(); + selectedAnimation.Stop(); +} + + +template +void Menu::Draw(SDL_Surface *dest, const math::Vector &position) const { int start(topRow * cols); int slots(rows * cols); int items(entries.size() - start); int end(start + (items < slots ? items : slots)); for (int i(0), count(end - start); i < count; ++i) { if (!entries[start + i].title) continue; - geometry::Vector iconOffset( + math::Vector iconOffset( (i % cols) * (ColWidth() + colGap), (i / cols) * RowHeight()); + + // This fixes the position of the third column of the inventory and capsule menus. + if (thirdColumnHack && i % cols == 2) { + iconOffset += math::Vector(font->CharWidth() * thirdColumnHack, 0); + } + if (entries[start + i].icon) { entries[start + i].icon->Draw(dest, position + iconOffset); } - geometry::Vector textOffset(iconOffset.X() + iconSpace, iconOffset.Y()); + math::Vector textOffset(iconOffset.X() + iconSpace, iconOffset.Y()); const Font *usedFont(entries[start + i].enabled ? font : disabledFont); usedFont->DrawString(entries[start + i].title, dest, position + textOffset, charsPerEntry); - textOffset += geometry::Vector(charsPerEntry * usedFont->CharWidth(), 0); + textOffset += math::Vector(charsPerEntry * usedFont->CharWidth(), 0); if (charsPerAdditionalText) { - textOffset += geometry::Vector(additionalTextGap, 0); + textOffset += math::Vector(additionalTextGap, 0); if (entries[start + i].additionalText) { usedFont->DrawString(entries[start + i].additionalText, dest, position + textOffset, charsPerAdditionalText); } - textOffset += geometry::Vector(charsPerAdditionalText * usedFont->CharWidth(), 0); + textOffset += math::Vector(charsPerAdditionalText * usedFont->CharWidth(), 0); } if (charsPerNumber) { usedFont->DrawChar(delimiter, dest, position + textOffset); - textOffset += geometry::Vector(usedFont->CharWidth(), 0); - usedFont->DrawNumber(entries[start + i].number, dest, position + textOffset); + textOffset += math::Vector(usedFont->CharWidth(), 0); + usedFont->DrawNumber(entries[start + i].number, dest, position + textOffset, charsPerNumber); } } - geometry::Vector cursorOffset( + math::Vector cursorOffset( (selected % cols) * (ColWidth() + colGap) - cursor->Width(), ((selected - start) / cols) * RowHeight()); - cursor->Draw(dest, position + cursorOffset); + // This fixes the position of the third column of the inventory and capsule menus. + if (thirdColumnHack && selected % cols == 2) { + cursorOffset += math::Vector(font->CharWidth() * thirdColumnHack, 0); + } + switch (state) { + case STATE_INACTIVE: + break; + case STATE_ACTIVE: + DrawCursor(dest, position + cursorOffset); + break; + case STATE_SELECTED: + DrawSelectedCursor(dest, position + cursorOffset); + break; + case STATE_DUAL: + DrawCursor(dest, position + cursorOffset + - math::Vector(selectedCursor->Width(), 0)); + if (secondarySelection >= start && secondarySelection <= end) { + math::Vector secondaryOffset( + (secondarySelection % cols) * (ColWidth() + colGap) - cursor->Width(), + ((secondarySelection - start) / cols) * RowHeight()); + DrawSelectedCursor(dest, position + secondaryOffset); + } + break; + } +} + +template +void Menu::DrawCursor( + SDL_Surface *dest, + const math::Vector &position) const { + if (animation.Running()) { + animation.Draw(dest, position); + } else { + cursor->Draw(dest, position); + } +} + +template +void Menu::DrawSelectedCursor( + SDL_Surface *dest, + const math::Vector &position) const { + if (selectedAnimation.Running()) { + selectedAnimation.Draw(dest, position); + } else { + selectedCursor->Draw(dest, position); + } } } -#endif /* GRAPHICS_MENU_H_ */ +#endif