summaryrefslogtreecommitdiff
path: root/src/util/string.h
Commit message (Collapse)AuthorAge
* Revert "Extend minetest.is_yes()"sfan52017-01-07
| | | | This reverts commit c435eabf3ffb77eab955d5faeb5450da1befc149.
* Extend minetest.is_yes()red-0012017-01-07
|
* Use more unordered_maps to improve performance in c++11 buildsLoic Blot2016-10-06
|
* Use the standard to_string() functions for C++11 (#4279)Rogier-52016-08-11
| | | | | | | | | | | | If compiling according to a C++ version before C++11, then define std::to_string ourselves. Add a to_wstring version as well As std::to_string() for floating point types uses %.6f as floating point format converter, instead of %G, it needs special care. To preserve ftos() behavior (which is expected to use the %G format converter), it no longer uses to_string().
* Random misc. warning fixes and cleanupskwolekr2016-06-11
| | | | | | - Fix unused c_sand member warning in Valleys Mapgen - Fix some code style - Make some std::string params const ref
* Add colored text (not only colored chat).Ekdohibs2016-05-31
| | | | | Add documentation, move files to a proper place and avoid memory leaks. Make it work with most kind of texts, and allow backgrounds too.
* Escape more strings: formspecs, item descriptions, infotexts...Ekdohibs2016-04-24
| | | | | | Also, change the escape character to the more standard \x1b Thus, it can be used in the future for translation or colored text, for example.
* Remove chat escape sequences from chat messages, for future colored chat.Ekdohibs2016-03-15
|
* Add minetest.register_lbm() to run code on block load onlyest312016-03-07
|
* Add server side ncurses terminalest312015-11-06
| | | | | | | | | | | | | | | | | | | | | | | | This adds a chat console the server owner can use for administration or to talk with players. It runs in its own thread, which makes the user interface immune to the server's lag, behaving just like a client, except timeout. As it uses the same console code as the f10 console, things like nick completion or a scroll buffer basically come for free. The terminal itself is written in a general way so that adding a client version later on is just about implementing an interface. Fatal errors are printed after the console exists and the ncurses terminal buffer gets cleaned up with endwin(), so that the error still remains visible. The server owner can chose their username their entered text will have in chat and where players can send PMs to. Once the username is secured with a password to prevent anybody to take over the server, the owner can execute admin tasks over the console. This change includes a contribution by @kahrl who has improved ncurses library detection.
* Use UTF-8 instead of narrowest312015-07-08
| | | | | Use wide_to_utf8 and utf8_to_wide instead of wide_to_narrow and narrow_to_wide at almost all places. Only exceptions: test functions for narrow conversion, and chat, which is done in a separate commit.
* More correct wrap_rows implementationfigec2015-06-20
|
* Fix wrap_rows at inner byte of multibyte sequencefigec2015-06-18
| | | | Also fix UTF-8 inner byte bounds and make unittest for case this fixes.
* Make wrap_rows not wrap inside utf-8 multibyte sequencesest312015-06-17
| | | | | | Also count multibyte sequences as "one" character. Adds unittest for the bug reporter's case. Fixes #2796.
* Add utf-8 conversion utilities and re-add intlGUIEditBoxest312015-06-13
|
* Split ObjDef/ObjDefManager out to objdef.cppkwolekr2015-05-18
|
* Make early protocol auth mechanism generic, and add SRPest312015-05-11
| | | | | | | Adds everything needed for SRP (and everything works too), but still deactivated, as protocol v25 init packets aren't final yet. Can be activated by changing the LATEST_PROTOCOL_VERSION header to 25 inside networkprotocol.h.
* Fix fast leaves with texture_clean_transparent enabled.Aaron Suen2015-04-26
|
* Refactor around translatePasswordest312015-04-17
| | | | | | | Change types for passed password from wstring to string, which removes converting back and forth in most cases. Move the narrow_to_wide conversion, where its neccessary, closer to irrlicht. Remove trailing spaces in guiPasswordChange.cpp. Make parameters for translatePassword passed as const reference.
* Fix Android text bug (no text displaying)Craig Robbins2015-03-07
|
* Reduce gettext wide/narrow and string/char* conversionsShadowNinja2015-02-05
|
* Make minor style change(unescape_string())Craig Robbins2015-01-16
|
* Fix unescape_string removing all backslashesShadowNinja2015-01-15
|
* Deduplicate code and use stdlib in string functionsShadowNinja2015-01-03
|
* Fixes for Android build errors. Enable sensor landscape rotation.KodexKy2014-11-25
| | | | | | | | | | | Fix typo in Android Makefile ndk path. Fix touchscreen parts of game.cpp to work after Zeno's refactor. Fix isdigit and isspace overload conflict with Android Irrlicht in string.h Enable sensor landscape rotation in Android Manifiest. Add mapgen v5 to Android build. Fix Makefile not checking leveldb. Signed-off-by: Craig Robbins <kde.psych@gmail.com>
* Cleanup and (mostly) document util/string.h and (very) minor refactoringCraig Robbins2014-11-02
| | | | | Updated: Incorporated feedback from 'kahrl' Updated: Moved MinetestApp::boolToCStr() from game.cpp into string.h renaming it bool_to_cstr()
* Fix bug introduced by me (Zeno)Craig Robbins2014-10-29
|
* Added names colours and refactored parseColorString()Craig Robbins2014-10-29
|
* Add [colorize modifierBlockMen2014-10-05
|
* Standardize tooltip row detectionBlockMen2014-09-28
|
* Use const references for Settings methodsShadowNinja2014-09-21
| | | | Also check for (this == &other) before locking mutexes.
* Fix msvc2012 buildsapier2014-06-29
|
* Add formspec api versioningsapier2014-06-29
|
* Replace usage of long long with u64/s64ShadowNinja2014-03-12
|
* Add capability to read table flag fields from Lua APIkwolekr2014-02-09
|
* Make flag strings clear specified flag with 'no' prefixkwolekr2014-02-08
| | | | | Remove flagmask field from set_mapgen_params table Add small bits of needed documentation
* Revert "Fix settings to honor numeric conversion errors"kwolekr2014-02-05
| | | | This reverts commit 3f376a092e1c16429fb52f24736e9da98aff4cd5.
* Fix settings to honor numeric conversion errorssapier2014-02-04
| | | | Rename try* non exceptioning functions to *NoEx
* Implement urlencode and urldecodeKahrl2013-12-13
|
* Accept hexadecimal and string values for seedskwolekr2013-11-04
|
* Change mainmenu texture handling + small misc changesKahrl2013-09-11
| | | | | | | | | | | | | | Texture names must now be escaped in formspec elements image[], background[], image_button[], image_button_exit[]. Instead of special-case handling of texture loading (and unloading which was missing) in guiFormSpecMenu.cpp, use the newly created ISimpleTextureSource interface which is a minimal subset of ITextureSource. There is an implementation of this interface used by GUIEngine (MenuTextureSource). Fix an off-by-one bug in unescape_string; it caused requests for a texture called "\0".
* Add dummy and LevelDB database backendsIlya Zhuravlev2013-09-09
|
* Omnicleanup: header cleanup, add ModApiUtil shared between game and mainmenuKahrl2013-08-14
|
* Settings: everything != 0 equals true; remove .asm shadersPilzAdam2013-07-08
|
* Allow any character in formspec strings with escape charkwolekr2013-03-05
|
* Update Copyright YearsSfan52013-02-24
|
* Change Minetest-c55 to MinetestPilzAdam2013-02-24
|
* Add flag string settings, flat map optionkwolekr2013-02-06
|
* Fix compile under MingWkwolekr2013-01-23
|
* Added ability to fetch media from remote server (using cURL library)Ilya Zhuravlev2012-12-16
|
opt">(environment, parent, id, rectangle), SpriteBank(0), OverrideFont(0), OverrideColorEnabled(false), OverrideColor(video::SColor(101,255,255,255)), ClickTime(0), HoverTime(0), FocusTime(0), ClickShiftState(false), ClickControlState(false), IsPushButton(false), Pressed(false), UseAlphaChannel(false), DrawBorder(true), ScaleImage(false), TSrc(tsrc) { setNotClipped(noclip); // This element can be tabbed. setTabStop(true); setTabOrder(-1); // PATCH for (size_t i = 0; i < 4; i++) { Colors[i] = Environment->getSkin()->getColor((EGUI_DEFAULT_COLOR)i); } StaticText = gui::StaticText::add(Environment, Text.c_str(), core::rect<s32>(0,0,rectangle.getWidth(),rectangle.getHeight()), false, false, this, id); StaticText->setTextAlignment(EGUIA_CENTER, EGUIA_CENTER); // END PATCH } //! destructor GUIButton::~GUIButton() { if (OverrideFont) OverrideFont->drop(); if (SpriteBank) SpriteBank->drop(); } //! Sets if the images should be scaled to fit the button void GUIButton::setScaleImage(bool scaleImage) { ScaleImage = scaleImage; } //! Returns whether the button scale the used images bool GUIButton::isScalingImage() const { return ScaleImage; } //! Sets if the button should use the skin to draw its border void GUIButton::setDrawBorder(bool border) { DrawBorder = border; } void GUIButton::setSpriteBank(IGUISpriteBank* sprites) { if (sprites) sprites->grab(); if (SpriteBank) SpriteBank->drop(); SpriteBank = sprites; } void GUIButton::setSprite(EGUI_BUTTON_STATE state, s32 index, video::SColor color, bool loop, bool scale) { ButtonSprites[(u32)state].Index = index; ButtonSprites[(u32)state].Color = color; ButtonSprites[(u32)state].Loop = loop; ButtonSprites[(u32)state].Scale = scale; } //! Get the sprite-index for the given state or -1 when no sprite is set s32 GUIButton::getSpriteIndex(EGUI_BUTTON_STATE state) const { return ButtonSprites[(u32)state].Index; } //! Get the sprite color for the given state. Color is only used when a sprite is set. video::SColor GUIButton::getSpriteColor(EGUI_BUTTON_STATE state) const { return ButtonSprites[(u32)state].Color; } //! Returns if the sprite in the given state does loop bool GUIButton::getSpriteLoop(EGUI_BUTTON_STATE state) const { return ButtonSprites[(u32)state].Loop; } //! Returns if the sprite in the given state is scaled bool GUIButton::getSpriteScale(EGUI_BUTTON_STATE state) const { return ButtonSprites[(u32)state].Scale; } //! called if an event happened. bool GUIButton::OnEvent(const SEvent& event) { if (!isEnabled()) return IGUIElement::OnEvent(event); switch(event.EventType) { case EET_KEY_INPUT_EVENT: if (event.KeyInput.PressedDown && (event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE)) { if (!IsPushButton) setPressed(true); else setPressed(!Pressed); return true; } if (Pressed && !IsPushButton && event.KeyInput.PressedDown && event.KeyInput.Key == KEY_ESCAPE) { setPressed(false); return true; } else if (!event.KeyInput.PressedDown && Pressed && (event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE)) { if (!IsPushButton) setPressed(false); if (Parent) { ClickShiftState = event.KeyInput.Shift; ClickControlState = event.KeyInput.Control; SEvent newEvent; newEvent.EventType = EET_GUI_EVENT; newEvent.GUIEvent.Caller = this; newEvent.GUIEvent.Element = 0; newEvent.GUIEvent.EventType = EGET_BUTTON_CLICKED; Parent->OnEvent(newEvent); } return true; } break; case EET_GUI_EVENT: if (event.GUIEvent.Caller == this) { if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUS_LOST) { if (!IsPushButton) setPressed(false); FocusTime = (u32)porting::getTimeMs(); } else if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUSED) { FocusTime = (u32)porting::getTimeMs(); } else if (event.GUIEvent.EventType == EGET_ELEMENT_HOVERED || event.GUIEvent.EventType == EGET_ELEMENT_LEFT) { HoverTime = (u32)porting::getTimeMs(); } } break; case EET_MOUSE_INPUT_EVENT: if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN) { // Sometimes formspec elements can receive mouse events when the // mouse is outside of the formspec. Thus, we test the position here. if ( !IsPushButton && AbsoluteClippingRect.isPointInside( core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y ))) { setPressed(true); } return true; } else if (event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP) { bool wasPressed = Pressed; if ( !AbsoluteClippingRect.isPointInside( core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y ) ) ) { if (!IsPushButton) setPressed(false); return true; } if (!IsPushButton) setPressed(false); else { setPressed(!Pressed); } if ((!IsPushButton && wasPressed && Parent) || (IsPushButton && wasPressed != Pressed)) { ClickShiftState = event.MouseInput.Shift; ClickControlState = event.MouseInput.Control; SEvent newEvent; newEvent.EventType = EET_GUI_EVENT; newEvent.GUIEvent.Caller = this; newEvent.GUIEvent.Element = 0; newEvent.GUIEvent.EventType = EGET_BUTTON_CLICKED; Parent->OnEvent(newEvent); } return true; } break; default: break; } return Parent ? Parent->OnEvent(event) : false; } //! draws the element and its children void GUIButton::draw() { if (!IsVisible) return; // PATCH // Track hovered state, if it has changed then we need to update the style. bool hovered = isHovered(); if (hovered != WasHovered) { WasHovered = hovered; setFromState(); } GUISkin* skin = dynamic_cast<GUISkin*>(Environment->getSkin()); video::IVideoDriver* driver = Environment->getVideoDriver(); // END PATCH if (DrawBorder) { if (!Pressed) { // PATCH skin->drawColored3DButtonPaneStandard(this, AbsoluteRect, &AbsoluteClippingRect, Colors); // END PATCH } else { // PATCH skin->drawColored3DButtonPanePressed(this, AbsoluteRect, &AbsoluteClippingRect, Colors); // END PATCH } } const core::position2di buttonCenter(AbsoluteRect.getCenter()); // PATCH // The image changes based on the state, so we use the default every time. EGUI_BUTTON_IMAGE_STATE imageState = EGBIS_IMAGE_UP; // END PATCH if ( ButtonImages[(u32)imageState].Texture ) { core::position2d<s32> pos(buttonCenter); core::rect<s32> sourceRect(ButtonImages[(u32)imageState].SourceRect); if ( sourceRect.getWidth() == 0 && sourceRect.getHeight() == 0 ) sourceRect = core::rect<s32>(core::position2di(0,0), ButtonImages[(u32)imageState].Texture->getOriginalSize()); pos.X -= sourceRect.getWidth() / 2; pos.Y -= sourceRect.getHeight() / 2; if ( Pressed ) { // Create a pressed-down effect by moving the image when it looks identical to the unpressed state image EGUI_BUTTON_IMAGE_STATE unpressedState = getImageState(false); if ( unpressedState == imageState || ButtonImages[(u32)imageState] == ButtonImages[(u32)unpressedState] ) { pos.X += skin->getSize(EGDS_BUTTON_PRESSED_IMAGE_OFFSET_X); pos.Y += skin->getSize(EGDS_BUTTON_PRESSED_IMAGE_OFFSET_Y); } } // PATCH video::ITexture* texture = ButtonImages[(u32)imageState].Texture; video::SColor image_colors[] = { BgColor, BgColor, BgColor, BgColor }; if (BgMiddle.getArea() == 0) { driver->draw2DImage(texture, ScaleImage? AbsoluteRect : core::rect<s32>(pos, sourceRect.getSize()), sourceRect, &AbsoluteClippingRect, image_colors, UseAlphaChannel); } else { core::rect<s32> middle = BgMiddle; // `-x` is interpreted as `w - x` if (middle.LowerRightCorner.X < 0) middle.LowerRightCorner.X += texture->getOriginalSize().Width; if (middle.LowerRightCorner.Y < 0) middle.LowerRightCorner.Y += texture->getOriginalSize().Height; draw2DImage9Slice(driver, texture, ScaleImage ? AbsoluteRect : core::rect<s32>(pos, sourceRect.getSize()), middle, &AbsoluteClippingRect, image_colors); } // END PATCH } if (SpriteBank) { core::position2di pos(buttonCenter); if (isEnabled()) { // pressed / unpressed animation EGUI_BUTTON_STATE state = Pressed ? EGBS_BUTTON_DOWN : EGBS_BUTTON_UP; drawSprite(state, ClickTime, pos); // focused / unfocused animation state = Environment->hasFocus(this) ? EGBS_BUTTON_FOCUSED : EGBS_BUTTON_NOT_FOCUSED; drawSprite(state, FocusTime, pos); // mouse over / off animation state = isHovered() ? EGBS_BUTTON_MOUSE_OVER : EGBS_BUTTON_MOUSE_OFF; drawSprite(state, HoverTime, pos); } else { // draw disabled // drawSprite(EGBS_BUTTON_DISABLED, 0, pos); } } IGUIElement::draw(); } void GUIButton::drawSprite(EGUI_BUTTON_STATE state, u32 startTime, const core::position2di& center) { u32 stateIdx = (u32)state; if (ButtonSprites[stateIdx].Index != -1) { if ( ButtonSprites[stateIdx].Scale ) { const video::SColor colors[] = {ButtonSprites[stateIdx].Color,ButtonSprites[stateIdx].Color,ButtonSprites[stateIdx].Color,ButtonSprites[stateIdx].Color}; SpriteBank->draw2DSprite(ButtonSprites[stateIdx].Index, AbsoluteRect.UpperLeftCorner, &AbsoluteClippingRect, colors[0], // FIXME: remove [0] porting::getTimeMs()-startTime, ButtonSprites[stateIdx].Loop); } else { SpriteBank->draw2DSprite(ButtonSprites[stateIdx].Index, center, &AbsoluteClippingRect, ButtonSprites[stateIdx].Color, startTime, porting::getTimeMs(), ButtonSprites[stateIdx].Loop, true); } } } EGUI_BUTTON_IMAGE_STATE GUIButton::getImageState(bool pressed) const { // PATCH return getImageState(pressed, ButtonImages); // END PATCH } EGUI_BUTTON_IMAGE_STATE GUIButton::getImageState(bool pressed, const ButtonImage* images) const { // figure state we should have EGUI_BUTTON_IMAGE_STATE state = EGBIS_IMAGE_DISABLED; bool focused = Environment->hasFocus((IGUIElement*)this); bool mouseOver = isHovered(); if (isEnabled()) { if ( pressed ) { if ( focused && mouseOver ) state = EGBIS_IMAGE_DOWN_FOCUSED_MOUSEOVER; else if ( focused ) state = EGBIS_IMAGE_DOWN_FOCUSED; else if ( mouseOver ) state = EGBIS_IMAGE_DOWN_MOUSEOVER; else state = EGBIS_IMAGE_DOWN; } else // !pressed { if ( focused && mouseOver ) state = EGBIS_IMAGE_UP_FOCUSED_MOUSEOVER; else if ( focused ) state = EGBIS_IMAGE_UP_FOCUSED; else if ( mouseOver ) state = EGBIS_IMAGE_UP_MOUSEOVER; else state = EGBIS_IMAGE_UP; } } // find a compatible state that has images while ( state != EGBIS_IMAGE_UP && !images[(u32)state].Texture ) { // PATCH switch ( state ) { case EGBIS_IMAGE_UP_FOCUSED: state = EGBIS_IMAGE_UP; break; case EGBIS_IMAGE_UP_FOCUSED_MOUSEOVER: state = EGBIS_IMAGE_UP_FOCUSED; break; case EGBIS_IMAGE_DOWN_MOUSEOVER: state = EGBIS_IMAGE_DOWN; break; case EGBIS_IMAGE_DOWN_FOCUSED: state = EGBIS_IMAGE_DOWN; break; case EGBIS_IMAGE_DOWN_FOCUSED_MOUSEOVER: state = EGBIS_IMAGE_DOWN_FOCUSED; break; case EGBIS_IMAGE_DISABLED: if ( pressed ) state = EGBIS_IMAGE_DOWN; else state = EGBIS_IMAGE_UP; break; default: state = EGBIS_IMAGE_UP; } // END PATCH } return state; } //! sets another skin independent font. if this is set to zero, the button uses the font of the skin. void GUIButton::setOverrideFont(IGUIFont* font) { if (OverrideFont == font) return; if (OverrideFont) OverrideFont->drop(); OverrideFont = font; if (OverrideFont) OverrideFont->grab(); StaticText->setOverrideFont(font); } //! Gets the override font (if any) IGUIFont * GUIButton::getOverrideFont() const { return OverrideFont; } //! Get the font which is used right now for drawing IGUIFont* GUIButton::getActiveFont() const { if ( OverrideFont ) return OverrideFont; IGUISkin* skin = Environment->getSkin(); if (skin) return skin->getFont(EGDF_BUTTON); return 0; } //! Sets another color for the text. void GUIButton::setOverrideColor(video::SColor color) { OverrideColor = color; OverrideColorEnabled = true; StaticText->setOverrideColor(color); } video::SColor GUIButton::getOverrideColor() const { return OverrideColor; } #if IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR > 8 video::SColor GUIButton::getActiveColor() const { return video::SColor(0,0,0,0); // unused? } #endif void GUIButton::enableOverrideColor(bool enable) { OverrideColorEnabled = enable; } bool GUIButton::isOverrideColorEnabled() const { return OverrideColorEnabled; } void GUIButton::setImage(EGUI_BUTTON_IMAGE_STATE state, video::ITexture* image, const core::rect<s32>& sourceRect) { if ( state >= EGBIS_COUNT ) return; if ( image ) image->grab(); u32 stateIdx = (u32)state; if ( ButtonImages[stateIdx].Texture ) ButtonImages[stateIdx].Texture->drop(); ButtonImages[stateIdx].Texture = image; ButtonImages[stateIdx].SourceRect = sourceRect; } // PATCH void GUIButton::setImage(video::ITexture* image) { setImage(gui::EGBIS_IMAGE_UP, image); } void GUIButton::setImage(video::ITexture* image, const core::rect<s32>& pos) { setImage(gui::EGBIS_IMAGE_UP, image, pos); } void GUIButton::setPressedImage(video::ITexture* image) { setImage(gui::EGBIS_IMAGE_DOWN, image); } void GUIButton::setPressedImage(video::ITexture* image, const core::rect<s32>& pos) { setImage(gui::EGBIS_IMAGE_DOWN, image, pos); } //! Sets the text displayed by the button void GUIButton::setText(const wchar_t* text) { StaticText->setText(text); IGUIButton::setText(text); } // END PATCH //! Sets if the button should behave like a push button. Which means it //! can be in two states: Normal or Pressed. With a click on the button, //! the user can change the state of the button. void GUIButton::setIsPushButton(bool isPushButton) { IsPushButton = isPushButton; } //! Returns if the button is currently pressed bool GUIButton::isPressed() const { return Pressed; } // PATCH //! Returns if this element (or one of its direct children) is hovered bool GUIButton::isHovered() const { IGUIElement *hovered = Environment->getHovered(); return hovered == this || (hovered != nullptr && hovered->getParent() == this); } // END PATCH //! Sets the pressed state of the button if this is a pushbutton void GUIButton::setPressed(bool pressed) { if (Pressed != pressed) { ClickTime = porting::getTimeMs(); Pressed = pressed; setFromState(); } } //! Returns whether the button is a push button bool GUIButton::isPushButton() const { return IsPushButton; } //! Sets if the alpha channel should be used for drawing images on the button (default is false) void GUIButton::setUseAlphaChannel(bool useAlphaChannel) { UseAlphaChannel = useAlphaChannel; } //! Returns if the alpha channel should be used for drawing images on the button bool GUIButton::isAlphaChannelUsed() const { return UseAlphaChannel; } bool GUIButton::isDrawingBorder() const { return DrawBorder; } //! Writes attributes of the element. void GUIButton::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const { IGUIButton::serializeAttributes(out,options); out->addBool ("PushButton", IsPushButton ); if (IsPushButton) out->addBool("Pressed", Pressed); for ( u32 i=0; i<(u32)EGBIS_COUNT; ++i ) { if ( ButtonImages[i].Texture ) { core::stringc name( GUIButtonImageStateNames[i] ); out->addTexture(name.c_str(), ButtonImages[i].Texture); name += "Rect"; out->addRect(name.c_str(), ButtonImages[i].SourceRect); } } out->addBool ("UseAlphaChannel", UseAlphaChannel); out->addBool ("Border", DrawBorder); out->addBool ("ScaleImage", ScaleImage); for ( u32 i=0; i<(u32)EGBS_COUNT; ++i ) { if ( ButtonSprites[i].Index >= 0 ) { core::stringc nameIndex( GUIButtonStateNames[i] ); nameIndex += "Index"; out->addInt(nameIndex.c_str(), ButtonSprites[i].Index ); core::stringc nameColor( GUIButtonStateNames[i] ); nameColor += "Color"; out->addColor(nameColor.c_str(), ButtonSprites[i].Color ); core::stringc nameLoop( GUIButtonStateNames[i] ); nameLoop += "Loop"; out->addBool(nameLoop.c_str(), ButtonSprites[i].Loop ); core::stringc nameScale( GUIButtonStateNames[i] ); nameScale += "Scale"; out->addBool(nameScale.c_str(), ButtonSprites[i].Scale ); } } // out->addString ("OverrideFont", OverrideFont); } //! Reads attributes of the element void GUIButton::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) { IGUIButton::deserializeAttributes(in,options); IsPushButton = in->getAttributeAsBool("PushButton"); Pressed = IsPushButton ? in->getAttributeAsBool("Pressed") : false; core::rect<s32> rec = in->getAttributeAsRect("ImageRect"); if (rec.isValid()) setImage( in->getAttributeAsTexture("Image"), rec); else setImage( in->getAttributeAsTexture("Image") ); rec = in->getAttributeAsRect("PressedImageRect"); if (rec.isValid()) setPressedImage( in->getAttributeAsTexture("PressedImage"), rec); else setPressedImage( in->getAttributeAsTexture("PressedImage") ); setDrawBorder(in->getAttributeAsBool("Border")); setUseAlphaChannel(in->getAttributeAsBool("UseAlphaChannel")); setScaleImage(in->getAttributeAsBool("ScaleImage")); // setOverrideFont(in->getAttributeAsString("OverrideFont")); updateAbsolutePosition(); } // PATCH GUIButton* GUIButton::addButton(IGUIEnvironment *environment, const core::rect<s32>& rectangle, ISimpleTextureSource *tsrc, IGUIElement* parent, s32 id, const wchar_t* text, const wchar_t *tooltiptext) { GUIButton* button = new GUIButton(environment, parent ? parent : environment->getRootGUIElement(), id, rectangle, tsrc); if (text) button->setText(text); if ( tooltiptext ) button->setToolTipText ( tooltiptext ); button->drop(); return button; } void GUIButton::setColor(video::SColor color) { BgColor = color; float d = 0.65f; for (size_t i = 0; i < 4; i++) { video::SColor base = Environment->getSkin()->getColor((gui::EGUI_DEFAULT_COLOR)i); Colors[i] = base.getInterpolated(color, d); } } //! Set element properties from a StyleSpec corresponding to the button state void GUIButton::setFromState() { StyleSpec::State state = StyleSpec::STATE_DEFAULT; if (isPressed()) state = static_cast<StyleSpec::State>(state | StyleSpec::STATE_PRESSED); if (isHovered()) state = static_cast<StyleSpec::State>(state | StyleSpec::STATE_HOVERED); setFromStyle(StyleSpec::getStyleFromStatePropagation(Styles, state)); } //! Set element properties from a StyleSpec void GUIButton::setFromStyle(const StyleSpec& style) { bool hovered = (style.getState() & StyleSpec::STATE_HOVERED) != 0; bool pressed = (style.getState() & StyleSpec::STATE_PRESSED) != 0; if (style.isNotDefault(StyleSpec::BGCOLOR)) { setColor(style.getColor(StyleSpec::BGCOLOR)); // If we have a propagated hover/press color, we need to automatically // lighten/darken it if (!Styles[style.getState()].isNotDefault(StyleSpec::BGCOLOR)) { if (pressed) { BgColor = multiplyColorValue(BgColor, COLOR_PRESSED_MOD); for (size_t i = 0; i < 4; i++) Colors[i] = multiplyColorValue(Colors[i], COLOR_PRESSED_MOD); } else if (hovered) { BgColor = multiplyColorValue(BgColor, COLOR_HOVERED_MOD); for (size_t i = 0; i < 4; i++) Colors[i] = multiplyColorValue(Colors[i], COLOR_HOVERED_MOD); } } } else { BgColor = video::SColor(255, 255, 255, 255); for (size_t i = 0; i < 4; i++) { video::SColor base = Environment->getSkin()->getColor((gui::EGUI_DEFAULT_COLOR)i); if (pressed) { Colors[i] = multiplyColorValue(base, COLOR_PRESSED_MOD); } else if (hovered) { Colors[i] = multiplyColorValue(base, COLOR_HOVERED_MOD); } else { Colors[i] = base; } } } if (style.isNotDefault(StyleSpec::TEXTCOLOR)) { setOverrideColor(style.getColor(StyleSpec::TEXTCOLOR)); } else { setOverrideColor(video::SColor(255,255,255,255)); OverrideColorEnabled = false; } setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); setDrawBorder(style.getBool(StyleSpec::BORDER, true)); setUseAlphaChannel(style.getBool(StyleSpec::ALPHA, true)); setOverrideFont(style.getFont()); if (style.isNotDefault(StyleSpec::BGIMG)) { video::ITexture *texture = style.getTexture(StyleSpec::BGIMG, getTextureSource()); setImage(guiScalingImageButton( Environment->getVideoDriver(), texture, AbsoluteRect.getWidth(), AbsoluteRect.getHeight())); setScaleImage(true); } else { setImage(nullptr); } BgMiddle = style.getRect(StyleSpec::BGIMG_MIDDLE, BgMiddle); // Child padding and offset Padding = style.getRect(StyleSpec::PADDING, core::rect<s32>()); Padding = core::rect<s32>( Padding.UpperLeftCorner + BgMiddle.UpperLeftCorner, Padding.LowerRightCorner + BgMiddle.LowerRightCorner); GUISkin* skin = dynamic_cast<GUISkin*>(Environment->getSkin()); core::vector2d<s32> defaultPressOffset( skin->getSize(irr::gui::EGDS_BUTTON_PRESSED_IMAGE_OFFSET_X), skin->getSize(irr::gui::EGDS_BUTTON_PRESSED_IMAGE_OFFSET_Y)); ContentOffset = style.getVector2i(StyleSpec::CONTENT_OFFSET, isPressed() ? defaultPressOffset : core::vector2d<s32>(0)); core::rect<s32> childBounds( Padding.UpperLeftCorner.X + ContentOffset.X, Padding.UpperLeftCorner.Y + ContentOffset.Y, AbsoluteRect.getWidth() + Padding.LowerRightCorner.X + ContentOffset.X, AbsoluteRect.getHeight() + Padding.LowerRightCorner.Y + ContentOffset.Y); for (IGUIElement *child : getChildren()) { child->setRelativePosition(childBounds); } } //! Set the styles used for each state void GUIButton::setStyles(const std::array<StyleSpec, StyleSpec::NUM_STATES>& styles) { Styles = styles; setFromState(); } // END PATCH