]> git.localhorst.tv Git - l2e.git/blobdiff - src/graphics/Menu.h
added menu cursor animations
[l2e.git] / src / graphics / Menu.h
index 886e2fd07af5a7bacb4d0c04566bc9824719231f..19ad9071541ebbac673d8b6f97b89c0647e3a3d8 100644 (file)
@@ -1,10 +1,15 @@
 #ifndef GRAPHICS_MENU_H_
 #define GRAPHICS_MENU_H_
 
+namespace app {
+       class Application;
+       class State;
+}
+
+#include "Animation.h"
 #include "Font.h"
-#include "fwd.h"
 #include "Sprite.h"
-#include "../geometry/Vector.h"
+#include "../math/Vector.h"
 
 #include <algorithm>
 #include <vector>
@@ -19,6 +24,8 @@ struct MenuProperties {
        const Font *disabledFont;
        const Sprite *cursor;
        const Sprite *selectedCursor;
+       const Animation *cursorAnimation;
+       const Animation *selectedCursorAnimation;
        int charsPerEntry;
        int rows;
        int rowGap;
@@ -28,16 +35,18 @@ struct MenuProperties {
        int charsPerNumber;
        int charsPerAdditionalText;
        int additionalTextGap;
+       int thirdColumnHack;
        char delimiter;
        bool wrapX;
        bool wrapY;
 
        MenuProperties()
        : 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();
@@ -104,12 +113,19 @@ public:
        void Clear() { entries.clear(); }
        void ClearEntry(int at) { entries[at] = Entry(0, T(), false); }
 
-       void Draw(SDL_Surface *dest, const geometry::Vector<int> &position) const;
+       void StartAnimation(app::Application &ctrl);
+       void StartAnimation(app::State &ctrl);
+       void StopAnimation();
+
+       void Draw(SDL_Surface *dest, const math::Vector<int> &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<int> &) const;
+       void DrawSelectedCursor(SDL_Surface *, const math::Vector<int> &) 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)
@@ -121,6 +137,8 @@ private:
                T value;
                bool enabled;
        };
+       AnimationRunner animation;
+       AnimationRunner selectedAnimation;
        std::vector<Entry> entries;
        int selected;
        int secondarySelection;
@@ -149,6 +167,8 @@ Menu<T>::Menu()
 template<class T>
 Menu<T>::Menu(const MenuProperties &p)
 : MenuProperties(p)
+, animation(cursorAnimation)
+, selectedAnimation(selectedCursorAnimation)
 , selected(0)
 , secondarySelection(0)
 , topRow(0)
@@ -230,76 +250,123 @@ void Menu<T>::SelectIndex(int index) {
 
 
 template<class T>
-void Menu<T>::Draw(SDL_Surface *dest, const geometry::Vector<int> &position) const {
+void Menu<T>::StartAnimation(app::Application &ctrl) {
+       if (cursorAnimation) {
+               animation.Start(ctrl);
+       }
+       if (selectedCursorAnimation) {
+               selectedAnimation.Start(ctrl);
+       }
+}
+
+template<class T>
+void Menu<T>::StartAnimation(app::State &ctrl) {
+       if (cursorAnimation) {
+               animation.Start(ctrl);
+       }
+       if (selectedCursorAnimation) {
+               selectedAnimation.Start(ctrl);
+       }
+}
+
+template<class T>
+void Menu<T>::StopAnimation() {
+       animation.Stop();
+       selectedAnimation.Stop();
+}
+
+
+template<class T>
+void Menu<T>::Draw(SDL_Surface *dest, const math::Vector<int> &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<int> iconOffset(
+               math::Vector<int> iconOffset(
                                (i % cols) * (ColWidth() + colGap),
                                (i / cols) * RowHeight());
 
-               // Third column hack!
-               // This fixes the position of the "DROP" item in the inventory menu.
-               if (i % cols == 2) {
-                       iconOffset += geometry::Vector<int>(font->CharWidth(), 0);
+               // This fixes the position of the third column of the inventory and capsule menus.
+               if (thirdColumnHack && i % cols == 2) {
+                       iconOffset += math::Vector<int>(font->CharWidth() * thirdColumnHack, 0);
                }
 
                if (entries[start + i].icon) {
                        entries[start + i].icon->Draw(dest, position + iconOffset);
                }
-               geometry::Vector<int> textOffset(iconOffset.X() + iconSpace, iconOffset.Y());
+               math::Vector<int> 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<int>(charsPerEntry * usedFont->CharWidth(), 0);
+               textOffset += math::Vector<int>(charsPerEntry * usedFont->CharWidth(), 0);
 
                if (charsPerAdditionalText) {
-                       textOffset += geometry::Vector<int>(additionalTextGap, 0);
+                       textOffset += math::Vector<int>(additionalTextGap, 0);
                        if (entries[start + i].additionalText) {
                                usedFont->DrawString(entries[start + i].additionalText, dest, position + textOffset, charsPerAdditionalText);
                        }
-                       textOffset += geometry::Vector<int>(charsPerAdditionalText * usedFont->CharWidth(), 0);
+                       textOffset += math::Vector<int>(charsPerAdditionalText * usedFont->CharWidth(), 0);
                }
 
                if (charsPerNumber) {
                        usedFont->DrawChar(delimiter, dest, position + textOffset);
-                       textOffset += geometry::Vector<int>(usedFont->CharWidth(), 0);
+                       textOffset += math::Vector<int>(usedFont->CharWidth(), 0);
                        usedFont->DrawNumber(entries[start + i].number, dest, position + textOffset, charsPerNumber);
                }
        }
-       geometry::Vector<int> cursorOffset(
+       math::Vector<int> cursorOffset(
                        (selected % cols) * (ColWidth() + colGap) - cursor->Width(),
                        ((selected - start) / cols) * RowHeight());
-       // Third column hack!
-       // This fixes the position of the "DROP" item in the inventory menu.
-       if (selected % cols == 2) {
-               cursorOffset += geometry::Vector<int>(font->CharWidth(), 0);
+       // This fixes the position of the third column of the inventory and capsule menus.
+       if (thirdColumnHack && selected % cols == 2) {
+               cursorOffset += math::Vector<int>(font->CharWidth() * thirdColumnHack, 0);
        }
        switch (state) {
                case STATE_INACTIVE:
                        break;
                case STATE_ACTIVE:
-                       cursor->Draw(dest, position + cursorOffset);
+                       DrawCursor(dest, position + cursorOffset);
                        break;
                case STATE_SELECTED:
-                       selectedCursor->Draw(dest, position + cursorOffset);
+                       DrawSelectedCursor(dest, position + cursorOffset);
                        break;
                case STATE_DUAL:
-                       cursor->Draw(dest, position + cursorOffset
-                                       - geometry::Vector<int>(selectedCursor->Width(), 0));
+                       DrawCursor(dest, position + cursorOffset
+                                       - math::Vector<int>(selectedCursor->Width(), 0));
                        if (secondarySelection >= start && secondarySelection <= end) {
-                               geometry::Vector<int> secondaryOffset(
+                               math::Vector<int> secondaryOffset(
                                                (secondarySelection % cols) * (ColWidth() + colGap) - cursor->Width(),
                                                ((secondarySelection - start) / cols) * RowHeight());
-                               selectedCursor->Draw(dest, position + secondaryOffset);
+                               DrawSelectedCursor(dest, position + secondaryOffset);
                        }
                        break;
        }
 }
 
+template<class T>
+void Menu<T>::DrawCursor(
+               SDL_Surface *dest,
+               const math::Vector<int> &position) const {
+       if (animation.Running()) {
+               animation.Draw(dest, position);
+       } else {
+               cursor->Draw(dest, position);
+       }
+}
+
+template<class T>
+void Menu<T>::DrawSelectedCursor(
+               SDL_Surface *dest,
+               const math::Vector<int> &position) const {
+       if (selectedAnimation.Running()) {
+               selectedAnimation.Draw(dest, position);
+       } else {
+               selectedCursor->Draw(dest, position);
+       }
+}
+
 }
 
-#endif /* GRAPHICS_MENU_H_ */
+#endif