1 // Copyright (C) 2002-2012 Nikolaus Gebhardt 2 // This file is part of the "Irrlicht Engine". 3 // For conditions of distribution and use, see copyright notice in irrlicht.h 4 5 #pragma once 6 7 #include "IrrCompileConfig.h" 8 9 #include <IGUIStaticText.h> 10 #include "irrlicht_changes/static_text.h" 11 #include "IGUIButton.h" 12 #include "IGUISpriteBank.h" 13 #include "ITexture.h" 14 #include "SColor.h" 15 #include "guiSkin.h" 16 #include "StyleSpec.h" 17 18 using namespace irr; 19 20 #if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR <= 8) 21 namespace irr { namespace gui { 22 23 //! State of buttons used for drawing texture images. 24 //! Note that only a single state is active at a time 25 //! Also when no image is defined for a state it will use images from another state 26 //! and if that state is not set from the replacement for that,etc. 27 //! So in many cases setting EGBIS_IMAGE_UP and EGBIS_IMAGE_DOWN is sufficient. 28 enum EGUI_BUTTON_IMAGE_STATE { 29 //! When no other states have images they will all use this one. 30 EGBIS_IMAGE_UP, 31 //! When not set EGBIS_IMAGE_UP is used. 32 EGBIS_IMAGE_UP_MOUSEOVER, 33 //! When not set EGBIS_IMAGE_UP_MOUSEOVER is used. 34 EGBIS_IMAGE_UP_FOCUSED, 35 //! When not set EGBIS_IMAGE_UP_FOCUSED is used. 36 EGBIS_IMAGE_UP_FOCUSED_MOUSEOVER, 37 //! When not set EGBIS_IMAGE_UP is used. 38 EGBIS_IMAGE_DOWN, 39 //! When not set EGBIS_IMAGE_DOWN is used. 40 EGBIS_IMAGE_DOWN_MOUSEOVER, 41 //! When not set EGBIS_IMAGE_DOWN_MOUSEOVER is used. 42 EGBIS_IMAGE_DOWN_FOCUSED, 43 //! When not set EGBIS_IMAGE_DOWN_FOCUSED is used. 44 EGBIS_IMAGE_DOWN_FOCUSED_MOUSEOVER, 45 //! When not set EGBIS_IMAGE_UP or EGBIS_IMAGE_DOWN are used (depending on button state). 46 EGBIS_IMAGE_DISABLED, 47 //! not used, counts the number of enumerated items 48 EGBIS_COUNT 49 }; 50 51 //! Names for gui button image states 52 const c8 *const GUIButtonImageStateNames[EGBIS_COUNT + 1] = 53 { 54 "Image", // not "ImageUp" as it otherwise breaks serialization of old files 55 "ImageUpOver", 56 "ImageUpFocused", 57 "ImageUpFocusedOver", 58 "PressedImage", // not "ImageDown" as it otherwise breaks serialization of old files 59 "ImageDownOver", 60 "ImageDownFocused", 61 "ImageDownFocusedOver", 62 "ImageDisabled", 63 0 // count 64 }; 65 66 }} 67 68 #endif 69 70 class ISimpleTextureSource; 71 72 class GUIButton : public gui::IGUIButton 73 { 74 public: 75 76 //! constructor 77 GUIButton(gui::IGUIEnvironment* environment, gui::IGUIElement* parent, 78 s32 id, core::rect<s32> rectangle, ISimpleTextureSource *tsrc, 79 bool noclip=false); 80 81 //! destructor 82 virtual ~GUIButton(); 83 84 //! called if an event happened. 85 virtual bool OnEvent(const SEvent& event) override; 86 87 //! draws the element and its children 88 virtual void draw() override; 89 90 //! sets another skin independent font. if this is set to zero, the button uses the font of the skin. 91 virtual void setOverrideFont(gui::IGUIFont* font=0) override; 92 93 //! Gets the override font (if any) 94 virtual gui::IGUIFont* getOverrideFont() const override; 95 96 //! Get the font which is used right now for drawing 97 virtual gui::IGUIFont* getActiveFont() const override; 98 99 //! Sets another color for the button text. 100 virtual void setOverrideColor(video::SColor color); 101 102 //! Gets the override color 103 virtual video::SColor getOverrideColor(void) const; 104 105 //! Sets if the button text should use the override color or the color in the gui skin. 106 virtual void enableOverrideColor(bool enable); 107 108 //! Checks if an override color is enabled 109 virtual bool isOverrideColorEnabled(void) const; 110 111 // PATCH 112 //! Sets an image which should be displayed on the button when it is in the given state. 113 virtual void setImage(gui::EGUI_BUTTON_IMAGE_STATE state, 114 video::ITexture* image=nullptr, 115 const core::rect<s32>& sourceRect=core::rect<s32>(0,0,0,0)); 116 117 //! Sets an image which should be displayed on the button when it is in normal state. 118 virtual void setImage(video::ITexture* image=nullptr) override; 119 120 //! Sets an image which should be displayed on the button when it is in normal state. 121 virtual void setImage(video::ITexture* image, const core::rect<s32>& pos) override; 122 123 //! Sets an image which should be displayed on the button when it is in pressed state. 124 virtual void setPressedImage(video::ITexture* image=nullptr) override; 125 126 //! Sets an image which should be displayed on the button when it is in pressed state. 127 virtual void setPressedImage(video::ITexture* image, const core::rect<s32>& pos) override; 128 129 //! Sets the text displayed by the button 130 virtual void setText(const wchar_t* text) override; 131 // END PATCH 132 133 //! Sets the sprite bank used by the button 134 virtual void setSpriteBank(gui::IGUISpriteBank* bank=0) override; 135 136 //! Sets the animated sprite for a specific button state 137 /** \param index: Number of the sprite within the sprite bank, use -1 for no sprite 138 \param state: State of the button to set the sprite for 139 \param index: The sprite number from the current sprite bank 140 \param color: The color of the sprite 141 */ 142 virtual void setSprite(gui::EGUI_BUTTON_STATE state, s32 index, 143 video::SColor color=video::SColor(255,255,255,255), 144 bool loop=false, bool scale=false); 145 146 #if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR <= 8) setSprite(gui::EGUI_BUTTON_STATE state,s32 index,video::SColor color,bool loop)147 void setSprite(gui::EGUI_BUTTON_STATE state, s32 index, video::SColor color, bool loop) override { 148 setSprite(state, index, color, loop, false); 149 } 150 #endif 151 152 //! Get the sprite-index for the given state or -1 when no sprite is set 153 virtual s32 getSpriteIndex(gui::EGUI_BUTTON_STATE state) const; 154 155 //! Get the sprite color for the given state. Color is only used when a sprite is set. 156 virtual video::SColor getSpriteColor(gui::EGUI_BUTTON_STATE state) const; 157 158 //! Returns if the sprite in the given state does loop 159 virtual bool getSpriteLoop(gui::EGUI_BUTTON_STATE state) const; 160 161 //! Returns if the sprite in the given state is scaled 162 virtual bool getSpriteScale(gui::EGUI_BUTTON_STATE state) const; 163 164 //! Sets if the button should behave like a push button. Which means it 165 //! can be in two states: Normal or Pressed. With a click on the button, 166 //! the user can change the state of the button. 167 virtual void setIsPushButton(bool isPushButton=true) override; 168 169 //! Checks whether the button is a push button 170 virtual bool isPushButton() const override; 171 172 //! Sets the pressed state of the button if this is a pushbutton 173 virtual void setPressed(bool pressed=true) override; 174 175 //! Returns if the button is currently pressed 176 virtual bool isPressed() const override; 177 178 // PATCH 179 //! Returns if this element (or one of its direct children) is hovered 180 bool isHovered() const; 181 // END PATCH 182 183 //! Sets if the button should use the skin to draw its border 184 virtual void setDrawBorder(bool border=true) override; 185 186 //! Checks if the button face and border are being drawn 187 virtual bool isDrawingBorder() const override; 188 189 //! Sets if the alpha channel should be used for drawing images on the button (default is false) 190 virtual void setUseAlphaChannel(bool useAlphaChannel=true) override; 191 192 //! Checks if the alpha channel should be used for drawing images on the button 193 virtual bool isAlphaChannelUsed() const override; 194 195 //! Sets if the button should scale the button images to fit 196 virtual void setScaleImage(bool scaleImage=true) override; 197 198 //! Checks whether the button scales the used images 199 virtual bool isScalingImage() const override; 200 201 //! Get if the shift key was pressed in last EGET_BUTTON_CLICKED event getClickShiftState()202 virtual bool getClickShiftState() const 203 { 204 return ClickShiftState; 205 } 206 207 //! Get if the control key was pressed in last EGET_BUTTON_CLICKED event getClickControlState()208 virtual bool getClickControlState() const 209 { 210 return ClickControlState; 211 } 212 213 //! Writes attributes of the element. 214 virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const override; 215 216 //! Reads attributes of the element 217 virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) override; 218 219 220 221 void setColor(video::SColor color); 222 // PATCH 223 //! Set element properties from a StyleSpec corresponding to the button state 224 void setFromState(); 225 226 //! Set element properties from a StyleSpec 227 virtual void setFromStyle(const StyleSpec& style); 228 229 //! Set the styles used for each state 230 void setStyles(const std::array<StyleSpec, StyleSpec::NUM_STATES>& styles); 231 // END PATCH 232 233 234 //! Do not drop returned handle 235 static GUIButton* addButton(gui::IGUIEnvironment *environment, 236 const core::rect<s32>& rectangle, ISimpleTextureSource *tsrc, 237 IGUIElement* parent, s32 id, const wchar_t* text, 238 const wchar_t *tooltiptext=L""); 239 240 protected: 241 void drawSprite(gui::EGUI_BUTTON_STATE state, u32 startTime, const core::position2di& center); 242 gui::EGUI_BUTTON_IMAGE_STATE getImageState(bool pressed) const; 243 getTextureSource()244 ISimpleTextureSource *getTextureSource() { return TSrc; } 245 246 struct ButtonImage 247 { ButtonImageButtonImage248 ButtonImage() : Texture(0), SourceRect(core::rect<s32>(0,0,0,0)) 249 { 250 } 251 ButtonImageButtonImage252 ButtonImage(const ButtonImage& other) : Texture(0), SourceRect(core::rect<s32>(0,0,0,0)) 253 { 254 *this = other; 255 } 256 ~ButtonImageButtonImage257 ~ButtonImage() 258 { 259 if ( Texture ) 260 Texture->drop(); 261 } 262 263 ButtonImage& operator=(const ButtonImage& other) 264 { 265 if ( this == &other ) 266 return *this; 267 268 if (other.Texture) 269 other.Texture->grab(); 270 if ( Texture ) 271 Texture->drop(); 272 Texture = other.Texture; 273 SourceRect = other.SourceRect; 274 return *this; 275 } 276 277 bool operator==(const ButtonImage& other) const 278 { 279 return Texture == other.Texture && SourceRect == other.SourceRect; 280 } 281 282 283 video::ITexture* Texture; 284 core::rect<s32> SourceRect; 285 }; 286 287 gui::EGUI_BUTTON_IMAGE_STATE getImageState(bool pressed, const ButtonImage* images) const; 288 289 private: 290 291 struct ButtonSprite 292 { ButtonSpriteButtonSprite293 ButtonSprite() : Index(-1), Loop(false), Scale(false) 294 { 295 } 296 297 bool operator==(const ButtonSprite& other) const 298 { 299 return Index == other.Index && Color == other.Color && Loop == other.Loop && Scale == other.Scale; 300 } 301 302 s32 Index; 303 video::SColor Color; 304 bool Loop; 305 bool Scale; 306 }; 307 308 ButtonSprite ButtonSprites[gui::EGBS_COUNT]; 309 gui::IGUISpriteBank* SpriteBank; 310 311 ButtonImage ButtonImages[gui::EGBIS_COUNT]; 312 313 std::array<StyleSpec, StyleSpec::NUM_STATES> Styles; 314 315 gui::IGUIFont* OverrideFont; 316 317 bool OverrideColorEnabled; 318 video::SColor OverrideColor; 319 320 u32 ClickTime, HoverTime, FocusTime; 321 322 bool ClickShiftState; 323 bool ClickControlState; 324 325 bool IsPushButton; 326 bool Pressed; 327 bool UseAlphaChannel; 328 bool DrawBorder; 329 bool ScaleImage; 330 331 video::SColor Colors[4]; 332 // PATCH 333 bool WasHovered = false; 334 ISimpleTextureSource *TSrc; 335 336 gui::IGUIStaticText *StaticText; 337 338 core::rect<s32> BgMiddle; 339 core::rect<s32> Padding; 340 core::vector2d<s32> ContentOffset; 341 video::SColor BgColor; 342 // END PATCH 343 }; 344