/* =========================================================================== blockattack - Block Attack - Rise of the Blocks Copyright (C) 2005-2012 Poul Sander 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 (at your option) 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, see http://www.gnu.org/licenses/ Source information and contacts persons can be found at http://blockattack.net =========================================================================== */ #ifndef _MENUSYSTEM_H #define _MENUSYSTEM_H #include #include "SDL.h" #include #include #include "sago/SagoSprite.hpp" #include "sago/GameStateInterface.hpp" #include #include "sago/SagoTextField.hpp" //The ButtonGfx object hold common media for all buttons, so we can reskin them by only changeing one pointer struct ButtonGfx { //The size of the buttons, so we don't have to ask w and h from the SDL Surfaces each time int xsize = 0; int ysize = 0; sago::SagoTextField* getLabel(const std::string& text, bool marked) const; void setSurfaces(); std::string menu_marked = "menu_marked"; std::string menu_unmarked = "menu_unmarked"; private: mutable std::map > labels; mutable std::map > labels_marked; }; //A button class Button { private: //Pointer to a callback function. void (*action)(void) = nullptr; //If true the menu should also be closed then the button is clicked bool popOnRun = false; //The label. This is written on the button std::string label; public: //Is the button marked? bool marked = false; //Where is the button on the screen int x = 0; int y = 0; ButtonGfx standardButton; Button() = default; Button(const Button& b); Button& operator=(const Button& other); virtual ~Button() = default; //Set the text to write on the button void setLabel(const std::string& text); //Set the action to run void setAction(void (*action2run)(void)); virtual void doAction(); //Run the callback function virtual void doLeft() {}; //Handle left input (for adjustment buttons) virtual void doRight() {}; //Handle right input (for adjustment buttons) void setPopOnRun(bool popOnRun); bool isPopOnRun() const; virtual const std::string& getLabel() const {return this->label; }; virtual bool hasAdjustmentButtons() const { return false; }; virtual void drawToScreen(SDL_Renderer* target) const; virtual bool isClickedAdjustLeft(int /*x*/, int /*y*/) const { return false; }; virtual bool isClickedAdjustRight(int /*x*/, int /*y*/) const { return false; }; virtual int getTotalWidth() const { return standardButton.xsize; }; //May hold any other information the callback might need int iGeneric1 = 0; }; //A button with left/right adjustment controls class ButtonWithAdjustment : public Button { public: ButtonWithAdjustment() = default; virtual ~ButtonWithAdjustment() = default; virtual bool hasAdjustmentButtons() const override { return true; }; virtual void drawToScreen(SDL_Renderer* target) const override; virtual bool isClickedAdjustLeft(int x, int y) const override; virtual bool isClickedAdjustRight(int x, int y) const override; virtual int getTotalWidth() const override { int adjustSize = getAdjustButtonSize(); return adjustSize + 10 + standardButton.xsize + 10 + adjustSize; }; int getAdjustButtonSize() const { return standardButton.ysize / 2; }; }; class Menu : public sago::GameStateInterface { private: bool isSubmenu = false; //True if the menu is a submenu int marked = 0; //The index of the marked button (for keyboard up/down) bool running = true; //The menu is running. The menu will terminate then this is false SDL_Renderer *screen = nullptr; //Pointer to the screen to draw to std::string title; bool bMouseUp = false; public: //numberOfItems is the expected numberOfItems for vector initialization //SubMenu is true by default Menu(SDL_Renderer *screen,bool isSubmenu); explicit Menu(SDL_Renderer *screen); Menu(SDL_Renderer *screen, const std::string& title, bool isSubmenu); virtual ~Menu() {} //Add a button to the menu void addButton(Button *b); bool IsActive() override; void Draw(SDL_Renderer* target) override; void ProcessInput(const SDL_Event& event, bool &processed) override; void Update() override; void drawSelf(SDL_Renderer* target); //Private function to draw the screen virtual void placeButtons(); //Rearanges the buttons to the correct place. std::vector buttons; //Vector holder the buttons Button exit; //The exit button is special since it does not have a callback function }; class FileMenu { private: std::string pm_path; std::string pm_fileending; bool pm_hidden_files = false; public: FileMenu(const std::string& path, const std::string& fileending, bool hidden_files = false); std::string getFile(SDL_Surface **screen); }; bool isUpEvent(const SDL_Event& event); bool isDownEvent(const SDL_Event& event); bool isLeftEvent(const SDL_Event& event); bool isRightEvent(const SDL_Event& event); bool isEscapeEvent(const SDL_Event& event); bool isConfirmEvent(const SDL_Event& event); #endif /* _MENUSYSTEM_H */