aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorrubenwardy <rw@rubenwardy.com>2019-03-15 18:39:23 +0000
committerrubenwardy <rw@rubenwardy.com>2019-08-03 19:36:30 +0100
commitd1a1c5cbf055e7eacbc4aeaa53174749d4c64d87 (patch)
tree3cbc94b9dd827f01b33575acd0faa58ea7f44dd3 /src
parent41ad0f4f202b47daab0841a56bf27c3990670344 (diff)
downloadminetest-d1a1c5cbf055e7eacbc4aeaa53174749d4c64d87.tar.gz
minetest-d1a1c5cbf055e7eacbc4aeaa53174749d4c64d87.tar.bz2
minetest-d1a1c5cbf055e7eacbc4aeaa53174749d4c64d87.zip
Add custom colorable GUIButton implementation
Diffstat (limited to 'src')
-rw-r--r--src/client/renderingengine.cpp64
-rw-r--r--src/gui/CMakeLists.txt2
-rw-r--r--src/gui/guiButton.cpp649
-rw-r--r--src/gui/guiButton.h306
-rw-r--r--src/gui/guiFormSpecMenu.cpp4
-rw-r--r--src/gui/guiSkin.cpp1084
-rw-r--r--src/gui/guiSkin.h376
7 files changed, 2466 insertions, 19 deletions
diff --git a/src/client/renderingengine.cpp b/src/client/renderingengine.cpp
index b18e91f6e..e56367afe 100644
--- a/src/client/renderingengine.cpp
+++ b/src/client/renderingengine.cpp
@@ -35,6 +35,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "render/factory.h"
#include "inputhandler.h"
#include "gettext.h"
+#include "../gui/guiSkin.h"
#if !defined(_WIN32) && !defined(__APPLE__) && !defined(__ANDROID__) && \
!defined(SERVER) && !defined(__HAIKU__)
@@ -44,6 +45,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
+
#endif
#ifdef __ANDROID__
@@ -52,6 +54,29 @@ with this program; if not, write to the Free Software Foundation, Inc.,
RenderingEngine *RenderingEngine::s_singleton = nullptr;
+
+static gui::GUISkin* createSkin(gui::IGUIEnvironment *environment,
+ gui::EGUI_SKIN_TYPE type, video::IVideoDriver *driver)
+{
+ gui::GUISkin* skin = new gui::GUISkin(type, driver);
+
+ gui::IGUIFont* builtinfont = environment->getBuiltInFont();
+ gui::IGUIFontBitmap* bitfont = 0;
+ if (builtinfont && builtinfont->getType() == gui::EGFT_BITMAP)
+ bitfont = (gui::IGUIFontBitmap*)builtinfont;
+
+ gui::IGUISpriteBank* bank = 0;
+ skin->setFont(builtinfont);
+
+ if (bitfont)
+ bank = bitfont->getSpriteBank();
+
+ skin->setSpriteBank(bank);
+
+ return skin;
+}
+
+
RenderingEngine::RenderingEngine(IEventReceiver *receiver)
{
sanity_check(!s_singleton);
@@ -112,6 +137,11 @@ RenderingEngine::RenderingEngine(IEventReceiver *receiver)
driver = m_device->getVideoDriver();
s_singleton = this;
+
+ auto skin = createSkin(m_device->getGUIEnvironment(),
+ gui::EGST_WINDOWS_METALLIC, driver);
+ m_device->getGUIEnvironment()->setSkin(skin);
+ skin->drop();
}
RenderingEngine::~RenderingEngine()
@@ -193,7 +223,7 @@ bool RenderingEngine::setupTopLevelWindow(const std::string &name)
// sort here that would call the correct toplevel setup methods for
// the environment Minetest is running in but for now not deviating
// from the original pattern.
-
+
/* Setting Xorg properties for the top level window */
setupTopLevelXorgWindow(name);
/* Done with Xorg properties */
@@ -211,7 +241,7 @@ bool RenderingEngine::setupTopLevelWindow(const std::string &name)
/* Done with general properties */
// FIXME: setWindowIcon returns a bool result but it is unused.
- // For now continue to return this result.
+ // For now continue to return this result.
return result;
}
@@ -223,7 +253,7 @@ void RenderingEngine::setupTopLevelXorgWindow(const std::string &name)
Display *x11_dpl = reinterpret_cast<Display *>(exposedData.OpenGLLinux.X11Display);
if (x11_dpl == NULL) {
warningstream << "Client: Could not find X11 Display in ExposedVideoData"
- << std::endl;
+ << std::endl;
return;
}
@@ -244,30 +274,30 @@ void RenderingEngine::setupTopLevelXorgWindow(const std::string &name)
// FIXME: In the future WMNormalHints should be set ... e.g see the
// gtk/gdk code (gdk/x11/gdksurface-x11.c) for the setup_top_level
- // method. But for now (as it would require some significant changes)
- // leave the code as is.
-
+ // method. But for now (as it would require some significant changes)
+ // leave the code as is.
+
// The following is borrowed from the above gdk source for setting top
// level windows. The source indicates and the Xlib docs suggest that
- // this will set the WM_CLIENT_MACHINE and WM_LOCAL_NAME. This will not
- // set the WM_CLIENT_MACHINE to a Fully Qualified Domain Name (FQDN) which is
+ // this will set the WM_CLIENT_MACHINE and WM_LOCAL_NAME. This will not
+ // set the WM_CLIENT_MACHINE to a Fully Qualified Domain Name (FQDN) which is
// required by the Extended Window Manager Hints (EWMH) spec when setting
// the _NET_WM_PID (see further down) but running Minetest in an env
// where the window manager is on another machine from Minetest (therefore
// making the PID useless) is not expected to be a problem. Further
// more, using gtk/gdk as the model it would seem that not using a FQDN is
// not an issue for modern Xorg window managers.
-
+
verbosestream << "Client: Setting Xorg window manager Properties"
<< std::endl;
XSetWMProperties (x11_dpl, x11_win, NULL, NULL, NULL, 0, NULL, NULL, NULL);
- // Set the _NET_WM_PID window property according to the EWMH spec. _NET_WM_PID
- // (in conjunction with WM_CLIENT_MACHINE) can be used by window managers to
- // force a shutdown of an application if it doesn't respond to the destroy
- // window message.
-
+ // Set the _NET_WM_PID window property according to the EWMH spec. _NET_WM_PID
+ // (in conjunction with WM_CLIENT_MACHINE) can be used by window managers to
+ // force a shutdown of an application if it doesn't respond to the destroy
+ // window message.
+
verbosestream << "Client: Setting Xorg _NET_WM_PID extened window manager property"
<< std::endl;
@@ -277,12 +307,12 @@ void RenderingEngine::setupTopLevelXorgWindow(const std::string &name)
infostream << "Client: PID is '" << static_cast<long>(pid) << "'"
<< std::endl;
- XChangeProperty(x11_dpl, x11_win, NET_WM_PID,
- XA_CARDINAL, 32, PropModeReplace,
+ XChangeProperty(x11_dpl, x11_win, NET_WM_PID,
+ XA_CARDINAL, 32, PropModeReplace,
reinterpret_cast<unsigned char *>(&pid),1);
// Set the WM_CLIENT_LEADER window property here. Minetest has only one
- // window and that window will always be the leader.
+ // window and that window will always be the leader.
verbosestream << "Client: Setting Xorg WM_CLIENT_LEADER property"
<< std::endl;
diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt
index 48ba3fa8c..2307856a4 100644
--- a/src/gui/CMakeLists.txt
+++ b/src/gui/CMakeLists.txt
@@ -1,4 +1,5 @@
set(gui_SRCS
+ ${CMAKE_CURRENT_SOURCE_DIR}/guiButton.cpp
${CMAKE_CURRENT_SOURCE_DIR}/guiChatConsole.cpp
${CMAKE_CURRENT_SOURCE_DIR}/guiConfirmRegistration.cpp
${CMAKE_CURRENT_SOURCE_DIR}/guiEditBoxWithScrollbar.cpp
@@ -8,6 +9,7 @@ set(gui_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/guiPasswordChange.cpp
${CMAKE_CURRENT_SOURCE_DIR}/guiPathSelectMenu.cpp
${CMAKE_CURRENT_SOURCE_DIR}/guiScrollBar.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/guiSkin.cpp
${CMAKE_CURRENT_SOURCE_DIR}/guiTable.cpp
${CMAKE_CURRENT_SOURCE_DIR}/guiVolumeChange.cpp
${CMAKE_CURRENT_SOURCE_DIR}/intlGUIEditBox.cpp
diff --git a/src/gui/guiButton.cpp b/src/gui/guiButton.cpp
new file mode 100644
index 000000000..60d330f4a
--- /dev/null
+++ b/src/gui/guiButton.cpp
@@ -0,0 +1,649 @@
+// Copyright (C) 2002-2012 Nikolaus Gebhardt
+// This file is part of the "Irrlicht Engine".
+// For conditions of distribution and use, see copyright notice in irrlicht.h
+
+#include "guiButton.h"
+
+
+#include "IGUISkin.h"
+#include "IGUIEnvironment.h"
+#include "IVideoDriver.h"
+#include "IGUIFont.h"
+#include "porting.h"
+
+using namespace irr;
+using namespace gui;
+
+//! constructor
+GUIButton::GUIButton(IGUIEnvironment* environment, IGUIElement* parent,
+ s32 id, core::rect<s32> rectangle, bool noclip)
+: IGUIButton(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)
+{
+ 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);
+ }
+ // 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)
+ {
+ if (!IsPushButton)
+ 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
+ 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());
+ EGUI_BUTTON_IMAGE_STATE imageState = getImageState(Pressed);
+ 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);
+ }
+ }
+
+ driver->draw2DImage(ButtonImages[(u32)imageState].Texture,
+ ScaleImage? AbsoluteRect : core::rect<s32>(pos, sourceRect.getSize()),
+ sourceRect, &AbsoluteClippingRect,
+ 0, UseAlphaChannel);
+ }
+
+ 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 = Environment->getHovered() == this ? EGBS_BUTTON_MOUSE_OVER : EGBS_BUTTON_MOUSE_OFF;
+ drawSprite(state, HoverTime, pos);
+ }
+ else
+ {
+ // draw disabled
+// drawSprite(EGBS_BUTTON_DISABLED, 0, pos);
+ }
+ }
+
+ if (Text.size())
+ {
+ IGUIFont* font = getActiveFont();
+
+ core::rect<s32> rect = AbsoluteRect;
+ if (Pressed)
+ {
+ rect.UpperLeftCorner.X += skin->getSize(EGDS_BUTTON_PRESSED_TEXT_OFFSET_X);
+ rect.UpperLeftCorner.Y += skin->getSize(EGDS_BUTTON_PRESSED_TEXT_OFFSET_Y);
+ }
+
+ if (font)
+ font->draw(Text.c_str(), rect,
+ OverrideColorEnabled ? OverrideColor : skin->getColor(isEnabled() ? EGDC_BUTTON_TEXT : EGDC_GRAY_TEXT),
+ true, true, &AbsoluteClippingRect);
+ }
+
+ 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
+{
+ // figure state we should have
+ EGUI_BUTTON_IMAGE_STATE state = EGBIS_IMAGE_DISABLED;
+ bool focused = Environment->hasFocus((IGUIElement*)this);
+ bool mouseOver = static_cast<const IGUIElement*>(Environment->getHovered()) == this; // (static cast for Borland)
+ 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 && !ButtonImages[(u32)state].Texture )
+ {
+ switch ( state )
+ {
+ case EGBIS_IMAGE_UP_FOCUSED:
+ state = EGBIS_IMAGE_UP_MOUSEOVER;
+ 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_MOUSEOVER;
+ 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;
+ }
+ }
+
+ 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();
+}
+
+//! 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;
+}
+
+video::SColor GUIButton::getOverrideColor() const
+{
+ return OverrideColor;
+}
+
+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;
+}
+
+//! 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;
+}
+
+
+//! 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;
+ }
+}
+
+
+//! 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,
+ IGUIElement* parent, s32 id, const wchar_t* text, const wchar_t *tooltiptext)
+{
+ GUIButton* button = new GUIButton(environment, parent ? parent : environment->getRootGUIElement(), id, rectangle);
+ if (text)
+ button->setText(text);
+
+ if ( tooltiptext )
+ button->setToolTipText ( tooltiptext );
+
+ button->drop();
+ return button;
+}
+
+void GUIButton::setColor(video::SColor 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);
+ }
+}
+// END PATCH
diff --git a/src/gui/guiButton.h b/src/gui/guiButton.h
new file mode 100644
index 000000000..04c24d40e
--- /dev/null
+++ b/src/gui/guiButton.h
@@ -0,0 +1,306 @@
+// Copyright (C) 2002-2012 Nikolaus Gebhardt
+// This file is part of the "Irrlicht Engine".
+// For conditions of distribution and use, see copyright notice in irrlicht.h
+
+#pragma once
+
+#include "IrrCompileConfig.h"
+
+#include "IGUIButton.h"
+#include "IGUISpriteBank.h"
+#include "ITexture.h"
+#include "SColor.h"
+#include "guiSkin.h"
+
+using namespace irr;
+
+#if (IRRLICHT_VERSION_MAJOR > 1 || IRRLICHT_VERSION_MINOR != 8 || IRRLICHT_VERSION_REVISION < 5)
+ namespace irr { namespace gui {
+
+ //! State of buttons used for drawing texture images.
+ //! Note that only a single state is active at a time
+ //! Also when no image is defined for a state it will use images from another state
+ //! and if that state is not set from the replacement for that,etc.
+ //! So in many cases setting EGBIS_IMAGE_UP and EGBIS_IMAGE_DOWN is sufficient.
+ enum EGUI_BUTTON_IMAGE_STATE {
+ //! When no other states have images they will all use this one.
+ EGBIS_IMAGE_UP,
+ //! When not set EGBIS_IMAGE_UP is used.
+ EGBIS_IMAGE_UP_MOUSEOVER,
+ //! When not set EGBIS_IMAGE_UP_MOUSEOVER is used.
+ EGBIS_IMAGE_UP_FOCUSED,
+ //! When not set EGBIS_IMAGE_UP_FOCUSED is used.
+ EGBIS_IMAGE_UP_FOCUSED_MOUSEOVER,
+ //! When not set EGBIS_IMAGE_UP is used.
+ EGBIS_IMAGE_DOWN,
+ //! When not set EGBIS_IMAGE_DOWN is used.
+ EGBIS_IMAGE_DOWN_MOUSEOVER,
+ //! When not set EGBIS_IMAGE_DOWN_MOUSEOVER is used.
+ EGBIS_IMAGE_DOWN_FOCUSED,
+ //! When not set EGBIS_IMAGE_DOWN_FOCUSED is used.
+ EGBIS_IMAGE_DOWN_FOCUSED_MOUSEOVER,
+ //! When not set EGBIS_IMAGE_UP or EGBIS_IMAGE_DOWN are used (depending on button state).
+ EGBIS_IMAGE_DISABLED,
+ //! not used, counts the number of enumerated items
+ EGBIS_COUNT
+ };
+
+ //! Names for gui button image states
+ const c8 *const GUIButtonImageStateNames[EGBIS_COUNT + 1] =
+ {
+ "Image", // not "ImageUp" as it otherwise breaks serialization of old files
+ "ImageUpOver",
+ "ImageUpFocused",
+ "ImageUpFocusedOver",
+ "PressedImage", // not "ImageDown" as it otherwise breaks serialization of old files
+ "ImageDownOver",
+ "ImageDownFocused",
+ "ImageDownFocusedOver",
+ "ImageDisabled",
+ 0 // count
+ };
+
+ }}
+
+#endif
+
+class GUIButton : public gui::IGUIButton
+{
+public:
+
+ //! constructor
+ GUIButton(gui::IGUIEnvironment* environment, gui::IGUIElement* parent,
+ s32 id, core::rect<s32> rectangle, bool noclip=false);
+
+ //! destructor
+ virtual ~GUIButton();
+
+ //! called if an event happened.
+ virtual bool OnEvent(const SEvent& event);
+
+ //! draws the element and its children
+ virtual void draw();
+
+ //! sets another skin independent font. if this is set to zero, the button uses the font of the skin.
+ virtual void setOverrideFont(gui::IGUIFont* font=0);
+
+ //! Gets the override font (if any)
+ virtual gui::IGUIFont* getOverrideFont() const;
+
+ //! Get the font which is used right now for drawing
+ virtual gui::IGUIFont* getActiveFont() const;
+
+ //! Sets another color for the button text.
+ virtual void setOverrideColor(video::SColor color);
+
+ //! Gets the override color
+ virtual video::SColor getOverrideColor(void) const;
+
+ //! Sets if the button text should use the override color or the color in the gui skin.
+ virtual void enableOverrideColor(bool enable);
+
+ //! Checks if an override color is enabled
+ virtual bool isOverrideColorEnabled(void) const;
+
+ //! Sets an image which should be displayed on the button when it is in the given state.
+ virtual void setImage(gui::EGUI_BUTTON_IMAGE_STATE state, video::ITexture* image=0, const core::rect<s32>& sourceRect=core::rect<s32>(0,0,0,0));
+
+ //! Sets an image which should be displayed on the button when it is in normal state.
+ virtual void setImage(video::ITexture* image=0)
+ {
+ setImage(gui::EGBIS_IMAGE_UP, image);
+ }
+
+ //! Sets an image which should be displayed on the button when it is in normal state.
+ virtual void setImage(video::ITexture* image, const core::rect<s32>& pos)
+ {
+ setImage(gui::EGBIS_IMAGE_UP, image, pos);
+ }
+
+ //! Sets an image which should be displayed on the button when it is in pressed state.
+ virtual void setPressedImage(video::ITexture* image=0)
+ {
+ setImage(gui::EGBIS_IMAGE_DOWN, image);
+ }
+
+ //! Sets an image which should be displayed on the button when it is in pressed state.
+ virtual void setPressedImage(video::ITexture* image, const core::rect<s32>& pos)
+ {
+ setImage(gui::EGBIS_IMAGE_DOWN, image, pos);
+ }
+
+ //! Sets the sprite bank used by the button
+ virtual void setSpriteBank(gui::IGUISpriteBank* bank=0);
+
+ //! Sets the animated sprite for a specific button state
+ /** \param index: Number of the sprite within the sprite bank, use -1 for no sprite
+ \param state: State of the button to set the sprite for
+ \param index: The sprite number from the current sprite bank
+ \param color: The color of the sprite
+ */
+ virtual void setSprite(gui::EGUI_BUTTON_STATE state, s32 index,
+ video::SColor color=video::SColor(255,255,255,255),
+ bool loop=false, bool scale=false);
+
+ void setSprite(gui::EGUI_BUTTON_STATE state, s32 index, video::SColor color, bool loop) override {
+ setSprite(state, index, color, loop, false);
+ }
+
+ //! Get the sprite-index for the given state or -1 when no sprite is set
+ virtual s32 getSpriteIndex(gui::EGUI_BUTTON_STATE state) const;
+
+ //! Get the sprite color for the given state. Color is only used when a sprite is set.
+ virtual video::SColor getSpriteColor(gui::EGUI_BUTTON_STATE state) const;
+
+ //! Returns if the sprite in the given state does loop
+ virtual bool getSpriteLoop(gui::EGUI_BUTTON_STATE state) const;
+
+ //! Returns if the sprite in the given state is scaled
+ virtual bool getSpriteScale(gui::EGUI_BUTTON_STATE state) const;
+
+ //! 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.
+ virtual void setIsPushButton(bool isPushButton=true);
+
+ //! Checks whether the button is a push button
+ virtual bool isPushButton() const;
+
+ //! Sets the pressed state of the button if this is a pushbutton
+ virtual void setPressed(bool pressed=true);
+
+ //! Returns if the button is currently pressed
+ virtual bool isPressed() const;
+
+ //! Sets if the button should use the skin to draw its border
+ virtual void setDrawBorder(bool border=true);
+
+ //! Checks if the button face and border are being drawn
+ virtual bool isDrawingBorder() const;
+
+ //! Sets if the alpha channel should be used for drawing images on the button (default is false)
+ virtual void setUseAlphaChannel(bool useAlphaChannel=true);
+
+ //! Checks if the alpha channel should be used for drawing images on the button
+ virtual bool isAlphaChannelUsed() const;
+
+ //! Sets if the button should scale the button images to fit
+ virtual void setScaleImage(bool scaleImage=true);
+
+ //! Checks whether the button scales the used images
+ virtual bool isScalingImage() const;
+
+ //! Get if the shift key was pressed in last EGET_BUTTON_CLICKED event
+ virtual bool getClickShiftState() const
+ {
+ return ClickShiftState;
+ }
+
+ //! Get if the control key was pressed in last EGET_BUTTON_CLICKED event
+ virtual bool getClickControlState() const
+ {
+ return ClickControlState;
+ }
+
+ //! Writes attributes of the element.
+ virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const;
+
+ //! Reads attributes of the element
+ virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options);
+
+
+
+ void setColor(video::SColor color);
+
+
+ //! Do not drop returned handle
+ static GUIButton* addButton(gui::IGUIEnvironment *environment, const core::rect<s32>& rectangle,
+ IGUIElement* parent, s32 id, const wchar_t* text, const wchar_t *tooltiptext=L"");
+
+protected:
+ void drawSprite(gui::EGUI_BUTTON_STATE state, u32 startTime, const core::position2di& center);
+ gui::EGUI_BUTTON_IMAGE_STATE getImageState(bool pressed) const;
+
+private:
+
+ struct ButtonSprite
+ {
+ ButtonSprite() : Index(-1), Loop(false), Scale(false)
+ {
+ }
+
+ bool operator==(const ButtonSprite& other) const
+ {
+ return Index == other.Index && Color == other.Color && Loop == other.Loop && Scale == other.Scale;
+ }
+
+ s32 Index;
+ video::SColor Color;
+ bool Loop;
+ bool Scale;
+ };
+
+ ButtonSprite ButtonSprites[gui::EGBS_COUNT];
+ gui::IGUISpriteBank* SpriteBank;
+
+ struct ButtonImage
+ {
+ ButtonImage() : Texture(0), SourceRect(core::rect<s32>(0,0,0,0))
+ {
+ }
+
+ ButtonImage(const ButtonImage& other) : Texture(0), SourceRect(core::rect<s32>(0,0,0,0))
+ {
+ *this = other;
+ }
+
+ ~ButtonImage()
+ {
+ if ( Texture )
+ Texture->drop();
+ }
+
+ ButtonImage& operator=(const ButtonImage& other)
+ {
+ if ( this == &other )
+ return *this;
+
+ if (other.Texture)
+ other.Texture->grab();
+ if ( Texture )
+ Texture->drop();
+ Texture = other.Texture;
+ SourceRect = other.SourceRect;
+ return *this;
+ }
+
+ bool operator==(const ButtonImage& other) const
+ {
+ return Texture == other.Texture && SourceRect == other.SourceRect;
+ }
+
+
+ video::ITexture* Texture;
+ core::rect<s32> SourceRect;
+ };
+
+ ButtonImage ButtonImages[gui::EGBIS_COUNT];
+
+ gui::IGUIFont* OverrideFont;
+
+ bool OverrideColorEnabled;
+ video::SColor OverrideColor;
+
+ u32 ClickTime, HoverTime, FocusTime;
+
+ bool ClickShiftState;
+ bool ClickControlState;
+
+ bool IsPushButton;
+ bool Pressed;
+ bool UseAlphaChannel;
+ bool DrawBorder;
+ bool ScaleImage;
+
+ video::SColor Colors[4];
+};
diff --git a/src/gui/guiFormSpecMenu.cpp b/src/gui/guiFormSpecMenu.cpp
index 4d3409f3b..382fbbd54 100644
--- a/src/gui/guiFormSpecMenu.cpp
+++ b/src/gui/guiFormSpecMenu.cpp
@@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <iterator>
#include <sstream>
#include <limits>
+#include "guiButton.h"
#include "guiFormSpecMenu.h"
#include "guiTable.h"
#include "constants.h"
@@ -698,9 +699,8 @@ void GUIFormSpecMenu::parseButton(parserData* data, const std::string &element,
spec.ftype = f_Button;
if(type == "button_exit")
spec.is_exit = true;
- gui::IGUIButton* e = Environment->addButton(rect, this, spec.fid,
- spec.flabel.c_str());
+ GUIButton *e = GUIButton::addButton(Environment, rect, this, spec.fid, spec.flabel.c_str());
if (spec.fname == data->focused_fieldname) {
Environment->setFocus(e);
}
diff --git a/src/gui/guiSkin.cpp b/src/gui/guiSkin.cpp
new file mode 100644
index 000000000..8892a00b4
--- /dev/null
+++ b/src/gui/guiSkin.cpp
@@ -0,0 +1,1084 @@
+// Copyright (C) 2002-2012 Nikolaus Gebhardt
+// Copyright (C) 2019 Irrlick
+//
+// This file is part of the "Irrlicht Engine".
+// For conditions of distribution and use, see copyright notice in irrlicht.h
+
+#include "guiSkin.h"
+#ifdef _IRR_COMPILE_WITH_GUI_
+
+#include "IGUIFont.h"
+#include "IGUISpriteBank.h"
+#include "IGUIElement.h"
+#include "IVideoDriver.h"
+#include "IAttributes.h"
+
+namespace irr
+{
+namespace gui
+{
+
+GUISkin::GUISkin(EGUI_SKIN_TYPE type, video::IVideoDriver* driver)
+: SpriteBank(0), Driver(driver), Type(type)
+{
+ #ifdef _DEBUG
+ setDebugName("GUISkin");
+ #endif
+
+ if ((Type == EGST_WINDOWS_CLASSIC) || (Type == EGST_WINDOWS_METALLIC))
+ {
+ Colors[EGDC_3D_DARK_SHADOW] = video::SColor(101,50,50,50);
+ Colors[EGDC_3D_SHADOW] = video::SColor(101,130,130,130);
+ Colors[EGDC_3D_FACE] = video::SColor(101,210,210,210);
+ Colors[EGDC_3D_HIGH_LIGHT] = video::SColor(101,255,255,255);
+ Colors[EGDC_3D_LIGHT] = video::SColor(101,210,210,210);
+ Colors[EGDC_ACTIVE_BORDER] = video::SColor(101,16,14,115);
+ Colors[EGDC_ACTIVE_CAPTION] = video::SColor(255,255,255,255);
+ Colors[EGDC_APP_WORKSPACE] = video::SColor(101,100,100,100);
+ Colors[EGDC_BUTTON_TEXT] = video::SColor(240,10,10,10);
+ Colors[EGDC_GRAY_TEXT] = video::SColor(240,130,130,130);
+ Colors[EGDC_HIGH_LIGHT] = video::SColor(101,8,36,107);
+ Colors[EGDC_HIGH_LIGHT_TEXT] = video::SColor(240,255,255,255);
+ Colors[EGDC_INACTIVE_BORDER] = video::SColor(101,165,165,165);
+ Colors[EGDC_INACTIVE_CAPTION] = video::SColor(255,30,30,30);
+ Colors[EGDC_TOOLTIP] = video::SColor(200,0,0,0);
+ Colors[EGDC_TOOLTIP_BACKGROUND] = video::SColor(200,255,255,225);
+ Colors[EGDC_SCROLLBAR] = video::SColor(101,230,230,230);
+ Colors[EGDC_WINDOW] = video::SColor(101,255,255,255);
+ Colors[EGDC_WINDOW_SYMBOL] = video::SColor(200,10,10,10);
+ Colors[EGDC_ICON] = video::SColor(200,255,255,255);
+ Colors[EGDC_ICON_HIGH_LIGHT] = video::SColor(200,8,36,107);
+ Colors[EGDC_GRAY_WINDOW_SYMBOL] = video::SColor(240,100,100,100);
+ Colors[EGDC_EDITABLE] = video::SColor(255,255,255,255);
+ Colors[EGDC_GRAY_EDITABLE] = video::SColor(255,120,120,120);
+ Colors[EGDC_FOCUSED_EDITABLE] = video::SColor(255,240,240,255);
+
+
+ Sizes[EGDS_SCROLLBAR_SIZE] = 14;
+ Sizes[EGDS_MENU_HEIGHT] = 30;
+ Sizes[EGDS_WINDOW_BUTTON_WIDTH] = 15;
+ Sizes[EGDS_CHECK_BOX_WIDTH] = 18;
+ Sizes[EGDS_MESSAGE_BOX_WIDTH] = 500;
+ Sizes[EGDS_MESSAGE_BOX_HEIGHT] = 200;
+ Sizes[EGDS_BUTTON_WIDTH] = 80;
+ Sizes[EGDS_BUTTON_HEIGHT] = 30;
+
+ Sizes[EGDS_TEXT_DISTANCE_X] = 2;
+ Sizes[EGDS_TEXT_DISTANCE_Y] = 0;
+
+ Sizes[EGDS_TITLEBARTEXT_DISTANCE_X] = 2;
+ Sizes[EGDS_TITLEBARTEXT_DISTANCE_Y] = 0;
+ }
+ else
+ {
+ //0x80a6a8af
+ Colors[EGDC_3D_DARK_SHADOW] = 0x60767982;
+ //Colors[EGDC_3D_FACE] = 0xc0c9ccd4; // tab background
+ Colors[EGDC_3D_FACE] = 0xc0cbd2d9; // tab background
+ Colors[EGDC_3D_SHADOW] = 0x50e4e8f1; // tab background, and left-top highlight
+ Colors[EGDC_3D_HIGH_LIGHT] = 0x40c7ccdc;
+ Colors[EGDC_3D_LIGHT] = 0x802e313a;
+ Colors[EGDC_ACTIVE_BORDER] = 0x80404040; // window title
+ Colors[EGDC_ACTIVE_CAPTION] = 0xffd0d0d0;
+ Colors[EGDC_APP_WORKSPACE] = 0xc0646464; // unused
+ Colors[EGDC_BUTTON_TEXT] = 0xd0161616;
+ Colors[EGDC_GRAY_TEXT] = 0x3c141414;
+ Colors[EGDC_HIGH_LIGHT] = 0x6c606060;
+ Colors[EGDC_HIGH_LIGHT_TEXT] = 0xd0e0e0e0;
+ Colors[EGDC_INACTIVE_BORDER] = 0xf0a5a5a5;
+ Colors[EGDC_INACTIVE_CAPTION] = 0xffd2d2d2;
+ Colors[EGDC_TOOLTIP] = 0xf00f2033;
+ Colors[EGDC_TOOLTIP_BACKGROUND] = 0xc0cbd2d9;
+ Colors[EGDC_SCROLLBAR] = 0xf0e0e0e0;
+ Colors[EGDC_WINDOW] = 0xf0f0f0f0;
+ Colors[EGDC_WINDOW_SYMBOL] = 0xd0161616;
+ Colors[EGDC_ICON] = 0xd0161616;
+ Colors[EGDC_ICON_HIGH_LIGHT] = 0xd0606060;
+ Colors[EGDC_GRAY_WINDOW_SYMBOL] = 0x3c101010;
+ Colors[EGDC_EDITABLE] = 0xf0ffffff;
+ Colors[EGDC_GRAY_EDITABLE] = 0xf0cccccc;
+ Colors[EGDC_FOCUSED_EDITABLE] = 0xf0fffff0;
+
+ Sizes[EGDS_SCROLLBAR_SIZE] = 14;
+ Sizes[EGDS_MENU_HEIGHT] = 48;
+ Sizes[EGDS_WINDOW_BUTTON_WIDTH] = 15;
+ Sizes[EGDS_CHECK_BOX_WIDTH] = 18;
+ Sizes[EGDS_MESSAGE_BOX_WIDTH] = 500;
+ Sizes[EGDS_MESSAGE_BOX_HEIGHT] = 200;
+ Sizes[EGDS_BUTTON_WIDTH] = 80;
+ Sizes[EGDS_BUTTON_HEIGHT] = 30;
+
+ Sizes[EGDS_TEXT_DISTANCE_X] = 3;
+ Sizes[EGDS_TEXT_DISTANCE_Y] = 2;
+
+ Sizes[EGDS_TITLEBARTEXT_DISTANCE_X] = 3;
+ Sizes[EGDS_TITLEBARTEXT_DISTANCE_Y] = 2;
+ }
+
+ Sizes[EGDS_MESSAGE_BOX_GAP_SPACE] = 15;
+ Sizes[EGDS_MESSAGE_BOX_MIN_TEXT_WIDTH] = 0;
+ Sizes[EGDS_MESSAGE_BOX_MAX_TEXT_WIDTH] = 500;
+ Sizes[EGDS_MESSAGE_BOX_MIN_TEXT_HEIGHT] = 0;
+ Sizes[EGDS_MESSAGE_BOX_MAX_TEXT_HEIGHT] = 99999;
+
+ Sizes[EGDS_BUTTON_PRESSED_IMAGE_OFFSET_X] = 1;
+ Sizes[EGDS_BUTTON_PRESSED_IMAGE_OFFSET_Y] = 1;
+ Sizes[EGDS_BUTTON_PRESSED_TEXT_OFFSET_X] = 0;
+ Sizes[EGDS_BUTTON_PRESSED_TEXT_OFFSET_Y] = 2;
+
+ Texts[EGDT_MSG_BOX_OK] = L"OK";
+ Texts[EGDT_MSG_BOX_CANCEL] = L"Cancel";
+ Texts[EGDT_MSG_BOX_YES] = L"Yes";
+ Texts[EGDT_MSG_BOX_NO] = L"No";
+ Texts[EGDT_WINDOW_CLOSE] = L"Close";
+ Texts[EGDT_WINDOW_RESTORE] = L"Restore";
+ Texts[EGDT_WINDOW_MINIMIZE] = L"Minimize";
+ Texts[EGDT_WINDOW_MAXIMIZE] = L"Maximize";
+
+ Icons[EGDI_WINDOW_MAXIMIZE] = 225;
+ Icons[EGDI_WINDOW_RESTORE] = 226;
+ Icons[EGDI_WINDOW_CLOSE] = 227;
+ Icons[EGDI_WINDOW_MINIMIZE] = 228;
+ Icons[EGDI_CURSOR_UP] = 229;
+ Icons[EGDI_CURSOR_DOWN] = 230;
+ Icons[EGDI_CURSOR_LEFT] = 231;
+ Icons[EGDI_CURSOR_RIGHT] = 232;
+ Icons[EGDI_MENU_MORE] = 232;
+ Icons[EGDI_CHECK_BOX_CHECKED] = 233;
+ Icons[EGDI_DROP_DOWN] = 234;
+ Icons[EGDI_SMALL_CURSOR_UP] = 235;
+ Icons[EGDI_SMALL_CURSOR_DOWN] = 236;
+ Icons[EGDI_RADIO_BUTTON_CHECKED] = 237;
+ Icons[EGDI_MORE_LEFT] = 238;
+ Icons[EGDI_MORE_RIGHT] = 239;
+ Icons[EGDI_MORE_UP] = 240;
+ Icons[EGDI_MORE_DOWN] = 241;
+ Icons[EGDI_WINDOW_RESIZE] = 242;
+ Icons[EGDI_EXPAND] = 243;
+ Icons[EGDI_COLLAPSE] = 244;
+
+ Icons[EGDI_FILE] = 245;
+ Icons[EGDI_DIRECTORY] = 246;
+
+ for (u32 i=0; i<EGDF_COUNT; ++i)
+ Fonts[i] = 0;
+
+ UseGradient = (Type == EGST_WINDOWS_METALLIC) || (Type == EGST_BURNING_SKIN) ;
+}
+
+
+//! destructor
+GUISkin::~GUISkin()
+{
+ for (u32 i=0; i<EGDF_COUNT; ++i)
+ {
+ if (Fonts[i])
+ Fonts[i]->drop();
+ }
+
+ if (SpriteBank)
+ SpriteBank->drop();
+}
+
+
+//! returns default color
+video::SColor GUISkin::getColor(EGUI_DEFAULT_COLOR color) const
+{
+ if ((u32)color < EGDC_COUNT)
+ return Colors[color];
+ else
+ return video::SColor();
+}
+
+
+//! sets a default color
+void GUISkin::setColor(EGUI_DEFAULT_COLOR which, video::SColor newColor)
+{
+ if ((u32)which < EGDC_COUNT)
+ Colors[which] = newColor;
+}
+
+
+//! returns size for the given size type
+s32 GUISkin::getSize(EGUI_DEFAULT_SIZE size) const
+{
+ if ((u32)size < EGDS_COUNT)
+ return Sizes[size];
+ else
+ return 0;
+}
+
+
+//! sets a default size
+void GUISkin::setSize(EGUI_DEFAULT_SIZE which, s32 size)
+{
+ if ((u32)which < EGDS_COUNT)
+ Sizes[which] = size;
+}
+
+
+//! returns the default font
+IGUIFont* GUISkin::getFont(EGUI_DEFAULT_FONT which) const
+{
+ if (((u32)which < EGDF_COUNT) && Fonts[which])
+ return Fonts[which];
+ else
+ return Fonts[EGDF_DEFAULT];
+}
+
+
+//! sets a default font
+void GUISkin::setFont(IGUIFont* font, EGUI_DEFAULT_FONT which)
+{
+ if ((u32)which >= EGDF_COUNT)
+ return;
+
+ if (font)
+ {
+ font->grab();
+ if (Fonts[which])
+ Fonts[which]->drop();
+
+ Fonts[which] = font;
+ }
+}
+
+
+//! gets the sprite bank stored
+IGUISpriteBank* GUISkin::getSpriteBank() const
+{
+ return SpriteBank;
+}
+
+
+//! set a new sprite bank or remove one by passing 0
+void GUISkin::setSpriteBank(IGUISpriteBank* bank)
+{
+ if (bank)
+ bank->grab();
+
+ if (SpriteBank)
+ SpriteBank->drop();
+
+ SpriteBank = bank;
+}
+
+
+//! Returns a default icon
+u32 GUISkin::getIcon(EGUI_DEFAULT_ICON icon) const
+{
+ if ((u32)icon < EGDI_COUNT)
+ return Icons[icon];
+ else
+ return 0;
+}
+
+
+//! Sets a default icon
+void GUISkin::setIcon(EGUI_DEFAULT_ICON icon, u32 index)
+{
+ if ((u32)icon < EGDI_COUNT)
+ Icons[icon] = index;
+}
+
+
+//! Returns a default text. For example for Message box button captions:
+//! "OK", "Cancel", "Yes", "No" and so on.
+const wchar_t* GUISkin::getDefaultText(EGUI_DEFAULT_TEXT text) const
+{
+ if ((u32)text < EGDT_COUNT)
+ return Texts[text].c_str();
+ else
+ return Texts[0].c_str();
+}
+
+
+//! Sets a default text. For example for Message box button captions:
+//! "OK", "Cancel", "Yes", "No" and so on.
+void GUISkin::setDefaultText(EGUI_DEFAULT_TEXT which, const wchar_t* newText)
+{
+ if ((u32)which < EGDT_COUNT)
+ Texts[which] = newText;
+}
+
+
+//! draws a standard 3d button pane
+/** Used for drawing for example buttons in normal state.
+It uses the colors EGDC_3D_DARK_SHADOW, EGDC_3D_HIGH_LIGHT, EGDC_3D_SHADOW and
+EGDC_3D_FACE for this. See EGUI_DEFAULT_COLOR for details.
+\param rect: Defining area where to draw.
+\param clip: Clip area.
+\param element: Pointer to the element which wishes to draw this. This parameter
+is usually not used by ISkin, but can be used for example by more complex
+implementations to find out how to draw the part exactly. */
+// PATCH
+void GUISkin::drawColored3DButtonPaneStandard(IGUIElement* element,
+ const core::rect<s32>& r,
+ const core::rect<s32>* clip,
+ const video::SColor* colors)
+{
+ if (!Driver)
+ return;
+
+ if (!colors)
+ colors = Colors;
+
+ core::rect<s32> rect = r;
+
+ if ( Type == EGST_BURNING_SKIN )
+ {
+ rect.UpperLeftCorner.X -= 1;
+ rect.UpperLeftCorner.Y -= 1;
+ rect.LowerRightCorner.X += 1;
+ rect.LowerRightCorner.Y += 1;
+ draw3DSunkenPane(element,
+ colors[ EGDC_WINDOW ].getInterpolated( 0xFFFFFFFF, 0.9f )
+ ,false, true, rect, clip);
+ return;
+ }
+
+ Driver->draw2DRectangle(colors[EGDC_3D_DARK_SHADOW], rect, clip);
+
+ rect.LowerRightCorner.X -= 1;
+ rect.LowerRightCorner.Y -= 1;
+ Driver->draw2DRectangle(colors[EGDC_3D_HIGH_LIGHT], rect, clip);
+
+ rect.UpperLeftCorner.X += 1;
+ rect.UpperLeftCorner.Y += 1;
+ Driver->draw2DRectangle(colors[EGDC_3D_SHADOW], rect, clip);
+
+ rect.LowerRightCorner.X -= 1;
+ rect.LowerRightCorner.Y -= 1;
+
+ if (!UseGradient)
+ {
+ Driver->draw2DRectangle(colors[EGDC_3D_FACE], rect, clip);
+ }
+ else
+ {
+ const video::SColor c1 = colors[EGDC_3D_FACE];
+ const video::SColor c2 = c1.getInterpolated(colors[EGDC_3D_DARK_SHADOW], 0.4f);
+ Driver->draw2DRectangle(rect, c1, c1, c2, c2, clip);
+ }
+}
+// END PATCH
+
+
+//! draws a pressed 3d button pane
+/** Used for drawing for example buttons in pressed state.
+It uses the colors EGDC_3D_DARK_SHADOW, EGDC_3D_HIGH_LIGHT, EGDC_3D_SHADOW and
+EGDC_3D_FACE for this. See EGUI_DEFAULT_COLOR for details.
+\param rect: Defining area where to draw.
+\param clip: Clip area.
+\param element: Pointer to the element which wishes to draw this. This parameter
+is usually not used by ISkin, but can be used for example by more complex
+implementations to find out how to draw the part exactly. */
+// PATCH
+void GUISkin::drawColored3DButtonPanePressed(IGUIElement* element,
+ const core::rect<s32>& r,
+ const core::rect<s32>* clip,
+ const video::SColor* colors)
+{
+ if (!Driver)
+ return;
+
+ if (!colors)
+ colors = Colors;
+
+ core::rect<s32> rect = r;
+ Driver->draw2DRectangle(colors[EGDC_3D_HIGH_LIGHT], rect, clip);
+
+ rect.LowerRightCorner.X -= 1;
+ rect.LowerRightCorner.Y -= 1;
+ Driver->draw2DRectangle(colors[EGDC_3D_DARK_SHADOW], rect, clip);
+
+ rect.UpperLeftCorner.X += 1;
+ rect.UpperLeftCorner.Y += 1;
+ Driver->draw2DRectangle(colors[EGDC_3D_SHADOW], rect, clip);
+
+ rect.UpperLeftCorner.X += 1;
+ rect.UpperLeftCorner.Y += 1;
+
+ if (!UseGradient)
+ {
+ Driver->draw2DRectangle(colors[EGDC_3D_FACE], rect, clip);
+ }
+ else
+ {
+ const video::SColor c1 = colors[EGDC_3D_FACE];
+ const video::SColor c2 = c1.getInterpolated(colors[EGDC_3D_DARK_SHADOW], 0.4f);
+ Driver->draw2DRectangle(rect, c1, c1, c2, c2, clip);
+ }
+}
+// END PATCH
+
+
+//! draws a sunken 3d pane
+/** Used for drawing the background of edit, combo or check boxes.
+\param element: Pointer to the element which wishes to draw this. This parameter
+is usually not used by ISkin, but can be used for example by more complex
+implementations to find out how to draw the part exactly.
+\param bgcolor: Background color.
+\param flat: Specifies if the sunken pane should be flat or displayed as sunken
+deep into the ground.
+\param rect: Defining area where to draw.
+\param clip: Clip area. */
+// PATCH
+void GUISkin::drawColored3DSunkenPane(IGUIElement* element, video::SColor bgcolor,
+ bool flat, bool fillBackGround,
+ const core::rect<s32>& r,
+ const core::rect<s32>* clip,
+ const video::SColor* colors)
+{
+ if (!Driver)
+ return;
+
+ if (!colors)
+ colors = Colors;
+
+ core::rect<s32> rect = r;
+
+ if (fillBackGround)
+ Driver->draw2DRectangle(bgcolor, rect, clip);
+
+ if (flat)
+ {
+ // draw flat sunken pane
+
+ rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + 1;
+ Driver->draw2DRectangle(colors[EGDC_3D_SHADOW], rect, clip); // top
+
+ ++rect.UpperLeftCorner.Y;
+ rect.LowerRightCorner.Y = r.LowerRightCorner.Y;
+ rect.LowerRightCorner.X = rect.UpperLeftCorner.X + 1;
+ Driver->draw2DRectangle(colors[EGDC_3D_SHADOW], rect, clip); // left
+
+ rect = r;
+ ++rect.UpperLeftCorner.Y;
+ rect.UpperLeftCorner.X = rect.LowerRightCorner.X - 1;
+ Driver->draw2DRectangle(colors[EGDC_3D_HIGH_LIGHT], rect, clip); // right
+
+ rect = r;
+ ++rect.UpperLeftCorner.X;
+ rect.UpperLeftCorner.Y = r.LowerRightCorner.Y - 1;
+ --rect.LowerRightCorner.X;
+ Driver->draw2DRectangle(colors[EGDC_3D_HIGH_LIGHT], rect, clip); // bottom
+ }
+ else
+ {
+ // draw deep sunken pane
+ rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + 1;
+ Driver->draw2DRectangle(colors[EGDC_3D_SHADOW], rect, clip); // top
+ ++rect.UpperLeftCorner.X;
+ ++rect.UpperLeftCorner.Y;
+ --rect.LowerRightCorner.X;
+ ++rect.LowerRightCorner.Y;
+ Driver->draw2DRectangle(colors[EGDC_3D_DARK_SHADOW], rect, clip);
+
+ rect.UpperLeftCorner.X = r.UpperLeftCorner.X;
+ rect.UpperLeftCorner.Y = r.UpperLeftCorner.Y+1;
+ rect.LowerRightCorner.X = rect.UpperLeftCorner.X + 1;
+ rect.LowerRightCorner.Y = r.LowerRightCorner.Y;
+ Driver->draw2DRectangle(colors[EGDC_3D_SHADOW], rect, clip); // left
+ ++rect.UpperLeftCorner.X;
+ ++rect.UpperLeftCorner.Y;
+ ++rect.LowerRightCorner.X;
+ --rect.LowerRightCorner.Y;
+ Driver->draw2DRectangle(colors[EGDC_3D_DARK_SHADOW], rect, clip);
+
+ rect = r;
+ rect.UpperLeftCorner.X = rect.LowerRightCorner.X - 1;
+ ++rect.UpperLeftCorner.Y;
+ Driver->draw2DRectangle(colors[EGDC_3D_HIGH_LIGHT], rect, clip); // right
+ --rect.UpperLeftCorner.X;
+ ++rect.UpperLeftCorner.Y;
+ --rect.LowerRightCorner.X;
+ --rect.LowerRightCorner.Y;
+ Driver->draw2DRectangle(colors[EGDC_3D_LIGHT], rect, clip);
+
+ rect = r;
+ ++rect.UpperLeftCorner.X;
+ rect.UpperLeftCorner.Y = r.LowerRightCorner.Y - 1;
+ --rect.LowerRightCorner.X;
+ Driver->draw2DRectangle(colors[EGDC_3D_HIGH_LIGHT], rect, clip); // bottom
+ ++rect.UpperLeftCorner.X;
+ --rect.UpperLeftCorner.Y;
+ --rect.LowerRightCorner.X;
+ --rect.LowerRightCorner.Y;
+ Driver->draw2DRectangle(colors[EGDC_3D_LIGHT], rect, clip);
+ }
+}
+// END PATCH
+
+//! draws a window background
+// return where to draw title bar text.
+// PATCH
+core::rect<s32> GUISkin::drawColored3DWindowBackground(IGUIElement* element,
+ bool drawTitleBar, video::SColor titleBarColor,
+ const core::rect<s32>& r,
+ const core::rect<s32>* clip,
+ core::rect<s32>* checkClientArea,
+ const video::SColor* colors)
+{
+ if (!Driver)
+ {
+ if ( checkClientArea )
+ {
+ *checkClientArea = r;
+ }
+ return r;
+ }
+
+ if (!colors)
+ colors = Colors;
+
+ core::rect<s32> rect = r;
+
+ // top border
+ rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + 1;
+ if ( !checkClientArea )
+ {
+ Driver->draw2DRectangle(colors[EGDC_3D_HIGH_LIGHT], rect, clip);
+ }
+
+ // left border
+ rect.LowerRightCorner.Y = r.LowerRightCorner.Y;
+ rect.LowerRightCorner.X = rect.UpperLeftCorner.X + 1;
+ if ( !checkClientArea )
+ {
+ Driver->draw2DRectangle(colors[EGDC_3D_HIGH_LIGHT], rect, clip);
+ }
+
+ // right border dark outer line
+ rect.UpperLeftCorner.X = r.LowerRightCorner.X - 1;
+ rect.LowerRightCorner.X = r.LowerRightCorner.X;
+ rect.UpperLeftCorner.Y = r.UpperLeftCorner.Y;
+ rect.LowerRightCorner.Y = r.LowerRightCorner.Y;
+ if ( !checkClientArea )
+ {
+ Driver->draw2DRectangle(colors[EGDC_3D_DARK_SHADOW], rect, clip);
+ }
+
+ // right border bright innner line
+ rect.UpperLeftCorner.X -= 1;
+ rect.LowerRightCorner.X -= 1;
+ rect.UpperLeftCorner.Y += 1;
+ rect.LowerRightCorner.Y -= 1;
+ if ( !checkClientArea )
+ {
+ Driver->draw2DRectangle(colors[EGDC_3D_SHADOW], rect, clip);
+ }
+
+ // bottom border dark outer line
+ rect.UpperLeftCorner.X = r.UpperLeftCorner.X;
+ rect.UpperLeftCorner.Y = r.LowerRightCorner.Y - 1;
+ rect.LowerRightCorner.Y = r.LowerRightCorner.Y;
+ rect.LowerRightCorner.X = r.LowerRightCorner.X;
+ if ( !checkClientArea )
+ {
+ Driver->draw2DRectangle(colors[EGDC_3D_DARK_SHADOW], rect, clip);
+ }
+
+ // bottom border bright inner line
+ rect.UpperLeftCorner.X += 1;
+ rect.LowerRightCorner.X -= 1;
+ rect.UpperLeftCorner.Y -= 1;
+ rect.LowerRightCorner.Y -= 1;
+ if ( !checkClientArea )
+ {
+ Driver->draw2DRectangle(colors[EGDC_3D_SHADOW], rect, clip);
+ }
+
+ // client area for background
+ rect = r;
+ rect.UpperLeftCorner.X +=1;
+ rect.UpperLeftCorner.Y +=1;
+ rect.LowerRightCorner.X -= 2;
+ rect.LowerRightCorner.Y -= 2;
+ if (checkClientArea)
+ {
+ *checkClientArea = rect;
+ }
+
+ if ( !checkClientArea )
+ {
+ if (!UseGradient)
+ {
+ Driver->draw2DRectangle(colors[EGDC_3D_FACE], rect, clip);
+ }
+ else if ( Type == EGST_BURNING_SKIN )
+ {
+ const video::SColor c1 = colors[EGDC_WINDOW].getInterpolated ( 0xFFFFFFFF, 0.9f );
+ const video::SColor c2 = colors[EGDC_WINDOW].getInterpolated ( 0xFFFFFFFF, 0.8f );
+
+ Driver->draw2DRectangle(rect, c1, c1, c2, c2, clip);
+ }
+ else
+ {
+ const video::SColor c2 = colors[EGDC_3D_SHADOW];
+ const video::SColor c1 = colors[EGDC_3D_FACE];
+ Driver->draw2DRectangle(rect, c1, c1, c1, c2, clip);
+ }
+ }
+
+ // title bar
+ rect = r;
+ rect.UpperLeftCorner.X += 2;
+ rect.UpperLeftCorner.Y += 2;
+ rect.LowerRightCorner.X -= 2;
+ rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + getSize(EGDS_WINDOW_BUTTON_WIDTH) + 2;
+
+ if (drawTitleBar )
+ {
+ if (checkClientArea)
+ {
+ (*checkClientArea).UpperLeftCorner.Y = rect.LowerRightCorner.Y;
+ }
+ else
+ {
+ // draw title bar
+ //if (!UseGradient)
+ // Driver->draw2DRectangle(titleBarColor, rect, clip);
+ //else
+ if ( Type == EGST_BURNING_SKIN )
+ {
+ const video::SColor c = titleBarColor.getInterpolated( video::SColor(titleBarColor.getAlpha(),255,255,255), 0.8f);
+ Driver->draw2DRectangle(rect, titleBarColor, titleBarColor, c, c, clip);
+ }
+ else
+ {
+ const video::SColor c = titleBarColor.getInterpolated(video::SColor(titleBarColor.getAlpha(),0,0,0), 0.2f);
+ Driver->draw2DRectangle(rect, titleBarColor, c, titleBarColor, c, clip);
+ }
+ }
+ }
+
+ return rect;
+}
+// END PATCH
+
+
+//! draws a standard 3d menu pane
+/** Used for drawing for menus and context menus.
+It uses the colors EGDC_3D_DARK_SHADOW, EGDC_3D_HIGH_LIGHT, EGDC_3D_SHADOW and
+EGDC_3D_FACE for this. See EGUI_DEFAULT_COLOR for details.
+\param element: Pointer to the element which wishes to draw this. This parameter
+is usually not used by ISkin, but can be used for example by more complex
+implementations to find out how to draw the part exactly.
+\param rect: Defining area where to draw.
+\param clip: Clip area. */
+// PATCH
+void GUISkin::drawColored3DMenuPane(IGUIElement* element,
+ const core::rect<s32>& r, const core::rect<s32>* clip,
+ const video::SColor* colors)
+{
+ if (!Driver)
+ return;
+
+ if (!colors)
+ colors = Colors;
+
+ core::rect<s32> rect = r;
+
+ if ( Type == EGST_BURNING_SKIN )
+ {
+ rect.UpperLeftCorner.Y -= 3;
+ draw3DButtonPaneStandard(element, rect, clip);
+ return;
+ }
+
+ // in this skin, this is exactly what non pressed buttons look like,
+ // so we could simply call
+ // draw3DButtonPaneStandard(element, rect, clip);
+ // here.
+ // but if the skin is transparent, this doesn't look that nice. So
+ // We draw it a little bit better, with some more draw2DRectangle calls,
+ // but there aren't that much menus visible anyway.
+
+ rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + 1;
+ Driver->draw2DRectangle(colors[EGDC_3D_HIGH_LIGHT], rect, clip);
+
+ rect.LowerRightCorner.Y = r.LowerRightCorner.Y;
+ rect.LowerRightCorner.X = rect.UpperLeftCorner.X + 1;
+ Driver->draw2DRectangle(colors[EGDC_3D_HIGH_LIGHT], rect, clip);
+
+ rect.UpperLeftCorner.X = r.LowerRightCorner.X - 1;
+ rect.LowerRightCorner.X = r.LowerRightCorner.X;
+ rect.UpperLeftCorner.Y = r.UpperLeftCorner.Y;
+ rect.LowerRightCorner.Y = r.LowerRightCorner.Y;
+ Driver->draw2DRectangle(colors[EGDC_3D_DARK_SHADOW], rect, clip);
+
+ rect.UpperLeftCorner.X -= 1;
+ rect.LowerRightCorner.X -= 1;
+ rect.UpperLeftCorner.Y += 1;
+ rect.LowerRightCorner.Y -= 1;
+ Driver->draw2DRectangle(colors[EGDC_3D_SHADOW], rect, clip);
+
+ rect.UpperLeftCorner.X = r.UpperLeftCorner.X;
+ rect.UpperLeftCorner.Y = r.LowerRightCorner.Y - 1;
+ rect.LowerRightCorner.Y = r.LowerRightCorner.Y;
+ rect.LowerRightCorner.X = r.LowerRightCorner.X;
+ Driver->draw2DRectangle(colors[EGDC_3D_DARK_SHADOW], rect, clip);
+
+ rect.UpperLeftCorner.X += 1;
+ rect.LowerRightCorner.X -= 1;
+ rect.UpperLeftCorner.Y -= 1;
+ rect.LowerRightCorner.Y -= 1;
+ Driver->draw2DRectangle(colors[EGDC_3D_SHADOW], rect, clip);
+
+ rect = r;
+ rect.UpperLeftCorner.X +=1;
+ rect.UpperLeftCorner.Y +=1;
+ rect.LowerRightCorner.X -= 2;
+ rect.LowerRightCorner.Y -= 2;
+
+ if (!UseGradient)
+ Driver->draw2DRectangle(colors[EGDC_3D_FACE], rect, clip);
+ else
+ {
+ const video::SColor c1 = colors[EGDC_3D_FACE];
+ const video::SColor c2 = colors[EGDC_3D_SHADOW];
+ Driver->draw2DRectangle(rect, c1, c1, c2, c2, clip);
+ }
+}
+// END PATCH
+
+
+//! draws a standard 3d tool bar
+/** Used for drawing for toolbars and menus.
+\param element: Pointer to the element which wishes to draw this. This parameter
+is usually not used by ISkin, but can be used for example by more complex
+implementations to find out how to draw the part exactly.
+\param rect: Defining area where to draw.
+\param clip: Clip area. */
+// PATCH
+void GUISkin::drawColored3DToolBar(IGUIElement* element,
+ const core::rect<s32>& r,
+ const core::rect<s32>* clip,
+ const video::SColor* colors)
+{
+ if (!Driver)
+ return;
+
+ if (!colors)
+ colors = Colors;
+
+ core::rect<s32> rect = r;
+
+ rect.UpperLeftCorner.X = r.UpperLeftCorner.X;
+ rect.UpperLeftCorner.Y = r.LowerRightCorner.Y - 1;
+ rect.LowerRightCorner.Y = r.LowerRightCorner.Y;
+ rect.LowerRightCorner.X = r.LowerRightCorner.X;
+ Driver->draw2DRectangle(colors[EGDC_3D_SHADOW], rect, clip);
+
+ rect = r;
+ rect.LowerRightCorner.Y -= 1;
+
+ if (!UseGradient)
+ {
+ Driver->draw2DRectangle(colors[EGDC_3D_FACE], rect, clip);
+ }
+ else
+ if ( Type == EGST_BURNING_SKIN )
+ {
+ const video::SColor c1 = 0xF0000000 | colors[EGDC_3D_FACE].color;
+ const video::SColor c2 = 0xF0000000 | colors[EGDC_3D_SHADOW].color;
+
+ rect.LowerRightCorner.Y += 1;
+ Driver->draw2DRectangle(rect, c1, c2, c1, c2, clip);
+ }
+ else
+ {
+ const video::SColor c1 = colors[EGDC_3D_FACE];
+ const video::SColor c2 = colors[EGDC_3D_SHADOW];
+ Driver->draw2DRectangle(rect, c1, c1, c2, c2, clip);
+ }
+}
+// END PATCH
+
+//! draws a tab button
+/** Used for drawing for tab buttons on top of tabs.
+\param element: Pointer to the element which wishes to draw this. This parameter
+is usually not used by ISkin, but can be used for example by more complex
+implementations to find out how to draw the part exactly.
+\param active: Specifies if the tab is currently active.
+\param rect: Defining area where to draw.
+\param clip: Clip area. */
+// PATCH
+void GUISkin::drawColored3DTabButton(IGUIElement* element, bool active,
+ const core::rect<s32>& frameRect, const core::rect<s32>* clip, EGUI_ALIGNMENT alignment,
+ const video::SColor* colors)
+{
+ if (!Driver)
+ return;
+
+ if (!colors)
+ colors = Colors;
+
+ core::rect<s32> tr = frameRect;
+
+ if ( alignment == EGUIA_UPPERLEFT )
+ {
+ tr.LowerRightCorner.X -= 2;
+ tr.LowerRightCorner.Y = tr.UpperLeftCorner.Y + 1;
+ tr.UpperLeftCorner.X += 1;
+ Driver->draw2DRectangle(colors[EGDC_3D_HIGH_LIGHT], tr, clip);
+
+ // draw left highlight
+ tr = frameRect;
+ tr.LowerRightCorner.X = tr.UpperLeftCorner.X + 1;
+ tr.UpperLeftCorner.Y += 1;
+ Driver->draw2DRectangle(colors[EGDC_3D_HIGH_LIGHT], tr, clip);
+
+ // draw grey background
+ tr = frameRect;
+ tr.UpperLeftCorner.X += 1;
+ tr.UpperLeftCorner.Y += 1;
+ tr.LowerRightCorner.X -= 2;
+ Driver->draw2DRectangle(colors[EGDC_3D_FACE], tr, clip);
+
+ // draw right middle gray shadow
+ tr.LowerRightCorner.X += 1;
+ tr.UpperLeftCorner.X = tr.LowerRightCorner.X - 1;
+ Driver->draw2DRectangle(colors[EGDC_3D_SHADOW], tr, clip);
+
+ tr.LowerRightCorner.X += 1;
+ tr.UpperLeftCorner.X += 1;
+ tr.UpperLeftCorner.Y += 1;
+ Driver->draw2DRectangle(colors[EGDC_3D_DARK_SHADOW], tr, clip);
+ }
+ else
+ {
+ tr.LowerRightCorner.X -= 2;
+ tr.UpperLeftCorner.Y = tr.LowerRightCorner.Y - 1;
+ tr.UpperLeftCorner.X += 1;
+ Driver->draw2DRectangle(colors[EGDC_3D_HIGH_LIGHT], tr, clip);
+
+ // draw left highlight
+ tr = frameRect;
+ tr.LowerRightCorner.X = tr.UpperLeftCorner.X + 1;
+ tr.LowerRightCorner.Y -= 1;
+ Driver->draw2DRectangle(colors[EGDC_3D_HIGH_LIGHT], tr, clip);
+
+ // draw grey background
+ tr = frameRect;
+ tr.UpperLeftCorner.X += 1;
+ tr.UpperLeftCorner.Y -= 1;
+ tr.LowerRightCorner.X -= 2;
+ tr.LowerRightCorner.Y -= 1;
+ Driver->draw2DRectangle(colors[EGDC_3D_FACE], tr, clip);
+
+ // draw right middle gray shadow
+ tr.LowerRightCorner.X += 1;
+ tr.UpperLeftCorner.X = tr.LowerRightCorner.X - 1;
+ //tr.LowerRightCorner.Y -= 1;
+ Driver->draw2DRectangle(colors[EGDC_3D_SHADOW], tr, clip);
+
+ tr.LowerRightCorner.X += 1;
+ tr.UpperLeftCorner.X += 1;
+ tr.LowerRightCorner.Y -= 1;
+ Driver->draw2DRectangle(colors[EGDC_3D_DARK_SHADOW], tr, clip);
+ }
+}
+// END PATCH
+
+
+//! draws a tab control body
+/** \param element: Pointer to the element which wishes to draw this. This parameter
+is usually not used by ISkin, but can be used for example by more complex
+implementations to find out how to draw the part exactly.
+\param border: Specifies if the border should be drawn.
+\param background: Specifies if the background should be drawn.
+\param rect: Defining area where to draw.
+\param clip: Clip area. */
+// PATCH
+void GUISkin::drawColored3DTabBody(IGUIElement* element, bool border, bool background,
+ const core::rect<s32>& rect, const core::rect<s32>* clip, s32 tabHeight, EGUI_ALIGNMENT alignment,
+ const video::SColor* colors)
+{
+ if (!Driver)
+ return;
+
+ if (!colors)
+ colors = Colors;
+
+ core::rect<s32> tr = rect;
+
+ if ( tabHeight == -1 )
+ tabHeight = getSize(gui::EGDS_BUTTON_HEIGHT);
+
+ // draw border.
+ if (border)
+ {
+ if ( alignment == EGUIA_UPPERLEFT )
+ {
+ // draw left hightlight
+ tr.UpperLeftCorner.Y += tabHeight + 2;
+ tr.LowerRightCorner.X = tr.UpperLeftCorner.X + 1;
+ Driver->draw2DRectangle(colors[EGDC_3D_HIGH_LIGHT], tr, clip);
+
+ // draw right shadow
+ tr.UpperLeftCorner.X = rect.LowerRightCorner.X - 1;
+ tr.LowerRightCorner.X = tr.UpperLeftCorner.X + 1;
+ Driver->draw2DRectangle(colors[EGDC_3D_SHADOW], tr, clip);
+
+ // draw lower shadow
+ tr = rect;
+ tr.UpperLeftCorner.Y = tr.LowerRightCorner.Y - 1;
+ Driver->draw2DRectangle(colors[EGDC_3D_SHADOW], tr, clip);
+ }
+ else
+ {
+ // draw left hightlight
+ tr.LowerRightCorner.Y -= tabHeight + 2;
+ tr.LowerRightCorner.X = tr.UpperLeftCorner.X + 1;
+ Driver->draw2DRectangle(colors[EGDC_3D_HIGH_LIGHT], tr, clip);
+
+ // draw right shadow
+ tr.UpperLeftCorner.X = rect.LowerRightCorner.X - 1;
+ tr.LowerRightCorner.X = tr.UpperLeftCorner.X + 1;
+ Driver->draw2DRectangle(colors[EGDC_3D_SHADOW], tr, clip);
+
+ // draw lower shadow
+ tr = rect;
+ tr.LowerRightCorner.Y = tr.UpperLeftCorner.Y + 1;
+ Driver->draw2DRectangle(colors[EGDC_3D_HIGH_LIGHT], tr, clip);
+ }
+ }
+
+ if (background)
+ {
+ if ( alignment == EGUIA_UPPERLEFT )
+ {
+ tr = rect;
+ tr.UpperLeftCorner.Y += tabHeight + 2;
+ tr.LowerRightCorner.X -= 1;
+ tr.UpperLeftCorner.X += 1;
+ tr.LowerRightCorner.Y -= 1;
+ }
+ else
+ {
+ tr = rect;
+ tr.UpperLeftCorner.X += 1;
+ tr.UpperLeftCorner.Y -= 1;
+ tr.LowerRightCorner.X -= 1;
+ tr.LowerRightCorner.Y -= tabHeight + 2;
+ //tr.UpperLeftCorner.X += 1;
+ }
+
+ if (!UseGradient)
+ Driver->draw2DRectangle(colors[EGDC_3D_FACE], tr, clip);
+ else
+ {
+ video::SColor c1 = colors[EGDC_3D_FACE];
+ video::SColor c2 = colors[EGDC_3D_SHADOW];
+ Driver->draw2DRectangle(tr, c1, c1, c2, c2, clip);
+ }
+ }
+}
+// END PATCH
+
+
+//! draws an icon, usually from the skin's sprite bank
+/** \param parent: Pointer to the element which wishes to draw this icon.
+This parameter is usually not used by IGUISkin, but can be used for example
+by more complex implementations to find out how to draw the part exactly.
+\param icon: Specifies the icon to be drawn.
+\param position: The position to draw the icon
+\param starttime: The time at the start of the animation
+\param currenttime: The present time, used to calculate the frame number
+\param loop: Whether the animation should loop or not
+\param clip: Clip area. */
+// PATCH
+void GUISkin::drawColoredIcon(IGUIElement* element, EGUI_DEFAULT_ICON icon,
+ const core::position2di position,
+ u32 starttime, u32 currenttime,
+ bool loop, const core::rect<s32>* clip,
+ const video::SColor* colors)
+{
+ if (!SpriteBank)
+ return;
+
+ if (!colors)
+ colors = Colors;
+
+ bool gray = element && !element->isEnabled();
+ SpriteBank->draw2DSprite(Icons[icon], position, clip,
+ colors[gray? EGDC_GRAY_WINDOW_SYMBOL : EGDC_WINDOW_SYMBOL], starttime, currenttime, loop, true);
+}
+// END PATCH
+
+
+EGUI_SKIN_TYPE GUISkin::getType() const
+{
+ return Type;
+}
+
+
+//! draws a 2d rectangle.
+void GUISkin::draw2DRectangle(IGUIElement* element,
+ const video::SColor &color, const core::rect<s32>& pos,
+ const core::rect<s32>* clip)
+{
+ Driver->draw2DRectangle(color, pos, clip);
+}
+
+
+//! Writes attributes of the object.
+//! Implement this to expose the attributes of your scene node animator for
+//! scripting languages, editors, debuggers or xml serialization purposes.
+void GUISkin::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
+{
+ u32 i;
+ for (i=0; i<EGDC_COUNT; ++i)
+ out->addColor(GUISkinColorNames[i], Colors[i]);
+
+ for (i=0; i<EGDS_COUNT; ++i)
+ out->addInt(GUISkinSizeNames[i], Sizes[i]);
+
+ for (i=0; i<EGDT_COUNT; ++i)
+ out->addString(GUISkinTextNames[i], Texts[i].c_str());
+
+ for (i=0; i<EGDI_COUNT; ++i)
+ out->addInt(GUISkinIconNames[i], Icons[i]);
+}
+
+
+//! Reads attributes of the object.
+//! Implement this to set the attributes of your scene node animator for
+//! scripting languages, editors, debuggers or xml deserialization purposes.
+void GUISkin::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
+{
+ // TODO: This is not nice code for downward compatibility, whenever new values are added and users
+ // load an old skin the corresponding values will be set to 0.
+ u32 i;
+ for (i=0; i<EGDC_COUNT; ++i)
+ Colors[i] = in->getAttributeAsColor(GUISkinColorNames[i]);
+
+ for (i=0; i<EGDS_COUNT; ++i)
+ Sizes[i] = in->getAttributeAsInt(GUISkinSizeNames[i]);
+
+ for (i=0; i<EGDT_COUNT; ++i)
+ Texts[i] = in->getAttributeAsStringW(GUISkinTextNames[i]);
+
+ for (i=0; i<EGDI_COUNT; ++i)
+ Icons[i] = in->getAttributeAsInt(GUISkinIconNames[i]);
+}
+
+
+//! gets the colors
+// PATCH
+void GUISkin::getColors(video::SColor* colors)
+{
+ u32 i;
+ for (i=0; i<EGDC_COUNT; ++i)
+ colors[i] = Colors[i];
+}
+// END PATCH
+
+} // end namespace gui
+} // end namespace irr
+
+
+#endif // _IRR_COMPILE_WITH_GUI_
+
diff --git a/src/gui/guiSkin.h b/src/gui/guiSkin.h
new file mode 100644
index 000000000..bbb900f9f
--- /dev/null
+++ b/src/gui/guiSkin.h
@@ -0,0 +1,376 @@
+// Copyright (C) 2002-2012 Nikolaus Gebhardt
+// This file is part of the "Irrlicht Engine".
+// For conditions of distribution and use, see copyright notice in irrlicht.h
+
+#ifndef __GUI_SKIN_H_INCLUDED__
+#define __GUI_SKIN_H_INCLUDED__
+
+#include "IrrCompileConfig.h"
+#ifdef _IRR_COMPILE_WITH_GUI_
+
+#include "IGUISkin.h"
+#include "irrString.h"
+#include <string>
+#include "ITexture.h"
+
+namespace irr
+{
+namespace video
+{
+ class IVideoDriver;
+}
+namespace gui
+{
+ class GUISkin : public IGUISkin
+ {
+ public:
+
+ GUISkin(EGUI_SKIN_TYPE type, video::IVideoDriver* driver);
+
+ //! destructor
+ virtual ~GUISkin();
+
+ //! returns default color
+ virtual video::SColor getColor(EGUI_DEFAULT_COLOR color) const;
+
+ //! sets a default color
+ virtual void setColor(EGUI_DEFAULT_COLOR which, video::SColor newColor);
+
+ //! returns size for the given size type
+ virtual s32 getSize(EGUI_DEFAULT_SIZE size) const;
+
+ //! sets a default size
+ virtual void setSize(EGUI_DEFAULT_SIZE which, s32 size);
+
+ //! returns the default font
+ virtual IGUIFont* getFont(EGUI_DEFAULT_FONT which=EGDF_DEFAULT) const;
+
+ //! sets a default font
+ virtual void setFont(IGUIFont* font, EGUI_DEFAULT_FONT which=EGDF_DEFAULT);
+
+ //! sets the sprite bank used for drawing icons
+ virtual void setSpriteBank(IGUISpriteBank* bank);
+
+ //! gets the sprite bank used for drawing icons
+ virtual IGUISpriteBank* getSpriteBank() const;
+
+ //! Returns a default icon
+ /** Returns the sprite index within the sprite bank */
+ virtual u32 getIcon(EGUI_DEFAULT_ICON icon) const;
+
+ //! Sets a default icon
+ /** Sets the sprite index used for drawing icons like arrows,
+ close buttons and ticks in checkboxes
+ \param icon: Enum specifying which icon to change
+ \param index: The sprite index used to draw this icon */
+ virtual void setIcon(EGUI_DEFAULT_ICON icon, u32 index);
+
+ //! Returns a default text.
+ /** For example for Message box button captions:
+ "OK", "Cancel", "Yes", "No" and so on. */
+ virtual const wchar_t* getDefaultText(EGUI_DEFAULT_TEXT text) const;
+
+ //! Sets a default text.
+ /** For example for Message box button captions:
+ "OK", "Cancel", "Yes", "No" and so on. */
+ virtual void setDefaultText(EGUI_DEFAULT_TEXT which, const wchar_t* newText);
+
+ //! draws a standard 3d button pane
+ /** Used for drawing for example buttons in normal state.
+ It uses the colors EGDC_3D_DARK_SHADOW, EGDC_3D_HIGH_LIGHT, EGDC_3D_SHADOW and
+ EGDC_3D_FACE for this. See EGUI_DEFAULT_COLOR for details.
+ \param rect: Defining area where to draw.
+ \param clip: Clip area.
+ \param element: Pointer to the element which wishes to draw this. This parameter
+ is usually not used by ISkin, but can be used for example by more complex
+ implementations to find out how to draw the part exactly. */
+ virtual void draw3DButtonPaneStandard(IGUIElement* element,
+ const core::rect<s32>& rect,
+ const core::rect<s32>* clip=0)
+ {
+ drawColored3DButtonPaneStandard(element, rect,clip);
+ }
+
+ virtual void drawColored3DButtonPaneStandard(IGUIElement* element,
+ const core::rect<s32>& rect,
+ const core::rect<s32>* clip=0,
+ const video::SColor* colors=0);
+
+ //! draws a pressed 3d button pane
+ /** Used for drawing for example buttons in pressed state.
+ It uses the colors EGDC_3D_DARK_SHADOW, EGDC_3D_HIGH_LIGHT, EGDC_3D_SHADOW and
+ EGDC_3D_FACE for this. See EGUI_DEFAULT_COLOR for details.
+ \param rect: Defining area where to draw.
+ \param clip: Clip area.
+ \param element: Pointer to the element which wishes to draw this. This parameter
+ is usually not used by ISkin, but can be used for example by more complex
+ implementations to find out how to draw the part exactly. */
+ virtual void draw3DButtonPanePressed(IGUIElement* element,
+ const core::rect<s32>& rect,
+ const core::rect<s32>* clip=0)
+ {
+ drawColored3DButtonPanePressed(element, rect, clip);
+ }
+
+ virtual void drawColored3DButtonPanePressed(IGUIElement* element,
+ const core::rect<s32>& rect,
+ const core::rect<s32>* clip=0,
+ const video::SColor* colors=0);
+
+ //! draws a sunken 3d pane
+ /** Used for drawing the background of edit, combo or check boxes.
+ \param element: Pointer to the element which wishes to draw this. This parameter
+ is usually not used by ISkin, but can be used for example by more complex
+ implementations to find out how to draw the part exactly.
+ \param bgcolor: Background color.
+ \param flat: Specifies if the sunken pane should be flat or displayed as sunken
+ deep into the ground.
+ \param rect: Defining area where to draw.
+ \param clip: Clip area. */
+ virtual void draw3DSunkenPane(IGUIElement* element,
+ video::SColor bgcolor, bool flat,
+ bool fillBackGround,
+ const core::rect<s32>& rect,
+ const core::rect<s32>* clip=0)
+ {
+ drawColored3DSunkenPane(element, bgcolor, flat, fillBackGround, rect, clip);
+ }
+
+ virtual void drawColored3DSunkenPane(IGUIElement* element,
+ video::SColor bgcolor, bool flat,
+ bool fillBackGround,
+ const core::rect<s32>& rect,
+ const core::rect<s32>* clip=0,
+ const video::SColor* colors=0);
+
+ //! draws a window background
+ /** Used for drawing the background of dialogs and windows.
+ \param element: Pointer to the element which wishes to draw this. This parameter
+ is usually not used by ISkin, but can be used for example by more complex
+ implementations to find out how to draw the part exactly.
+ \param titleBarColor: Title color.
+ \param drawTitleBar: True to enable title drawing.
+ \param rect: Defining area where to draw.
+ \param clip: Clip area.
+ \param checkClientArea: When set to non-null the function will not draw anything,
+ but will instead return the clientArea which can be used for drawing by the calling window.
+ That is the area without borders and without titlebar.
+ \return Returns rect where it would be good to draw title bar text. This will
+ work even when checkClientArea is set to a non-null value.*/
+ virtual core::rect<s32> draw3DWindowBackground(IGUIElement* element,
+ bool drawTitleBar, video::SColor titleBarColor,
+ const core::rect<s32>& rect,
+ const core::rect<s32>* clip,
+ core::rect<s32>* checkClientArea)
+ {
+ return drawColored3DWindowBackground(element, drawTitleBar, titleBarColor,
+ rect, clip, checkClientArea);
+ }
+
+ virtual core::rect<s32> drawColored3DWindowBackground(IGUIElement* element,
+ bool drawTitleBar, video::SColor titleBarColor,
+ const core::rect<s32>& rect,
+ const core::rect<s32>* clip,
+ core::rect<s32>* checkClientArea,
+ const video::SColor* colors=0);
+
+ //! draws a standard 3d menu pane
+ /** Used for drawing for menus and context menus.
+ It uses the colors EGDC_3D_DARK_SHADOW, EGDC_3D_HIGH_LIGHT, EGDC_3D_SHADOW and
+ EGDC_3D_FACE for this. See EGUI_DEFAULT_COLOR for details.
+ \param element: Pointer to the element which wishes to draw this. This parameter
+ is usually not used by ISkin, but can be used for example by more complex
+ implementations to find out how to draw the part exactly.
+ \param rect: Defining area where to draw.
+ \param clip: Clip area. */
+ virtual void draw3DMenuPane(IGUIElement* element,
+ const core::rect<s32>& rect,
+ const core::rect<s32>* clip=0)
+ {
+ drawColored3DMenuPane(element, rect, clip);
+ }
+
+ virtual void drawColored3DMenuPane(IGUIElement* element,
+ const core::rect<s32>& rect,
+ const core::rect<s32>* clip=0,
+ const video::SColor* colors=0);
+
+ //! draws a standard 3d tool bar
+ /** Used for drawing for toolbars and menus.
+ \param element: Pointer to the element which wishes to draw this. This parameter
+ is usually not used by ISkin, but can be used for example by more complex
+ implementations to find out how to draw the part exactly.
+ \param rect: Defining area where to draw.
+ \param clip: Clip area. */
+ virtual void draw3DToolBar(IGUIElement* element,
+ const core::rect<s32>& rect,
+ const core::rect<s32>* clip=0)
+ {
+ drawColored3DToolBar(element, rect, clip);
+ }
+
+ virtual void drawColored3DToolBar(IGUIElement* element,
+ const core::rect<s32>& rect,
+ const core::rect<s32>* clip=0,
+ const video::SColor* colors=0);
+
+ //! draws a tab button
+ /** Used for drawing for tab buttons on top of tabs.
+ \param element: Pointer to the element which wishes to draw this. This parameter
+ is usually not used by ISkin, but can be used for example by more complex
+ implementations to find out how to draw the part exactly.
+ \param active: Specifies if the tab is currently active.
+ \param rect: Defining area where to draw.
+ \param clip: Clip area. */
+ virtual void draw3DTabButton(IGUIElement* element, bool active,
+ const core::rect<s32>& rect, const core::rect<s32>* clip=0, EGUI_ALIGNMENT alignment=EGUIA_UPPERLEFT)
+ {
+ drawColored3DTabButton(element, active, rect, clip, alignment);
+ }
+
+ virtual void drawColored3DTabButton(IGUIElement* element, bool active,
+ const core::rect<s32>& rect, const core::rect<s32>* clip=0, EGUI_ALIGNMENT alignment=EGUIA_UPPERLEFT,
+ const video::SColor* colors=0);
+
+ //! draws a tab control body
+ /** \param element: Pointer to the element which wishes to draw this. This parameter
+ is usually not used by ISkin, but can be used for example by more complex
+ implementations to find out how to draw the part exactly.
+ \param border: Specifies if the border should be drawn.
+ \param background: Specifies if the background should be drawn.
+ \param rect: Defining area where to draw.
+ \param clip: Clip area. */
+ virtual void draw3DTabBody(IGUIElement* element, bool border, bool background,
+ const core::rect<s32>& rect, const core::rect<s32>* clip=0, s32 tabHeight=-1, EGUI_ALIGNMENT alignment=EGUIA_UPPERLEFT)
+ {
+ drawColored3DTabBody(element, border, background, rect, clip, tabHeight, alignment);
+ }
+
+ virtual void drawColored3DTabBody(IGUIElement* element, bool border, bool background,
+ const core::rect<s32>& rect, const core::rect<s32>* clip=0, s32 tabHeight=-1, EGUI_ALIGNMENT alignment=EGUIA_UPPERLEFT,
+ const video::SColor* colors=0);
+
+ //! draws an icon, usually from the skin's sprite bank
+ /** \param element: Pointer to the element which wishes to draw this icon.
+ This parameter is usually not used by IGUISkin, but can be used for example
+ by more complex implementations to find out how to draw the part exactly.
+ \param icon: Specifies the icon to be drawn.
+ \param position: The position to draw the icon
+ \param starttime: The time at the start of the animation
+ \param currenttime: The present time, used to calculate the frame number
+ \param loop: Whether the animation should loop or not
+ \param clip: Clip area. */
+ virtual void drawIcon(IGUIElement* element, EGUI_DEFAULT_ICON icon,
+ const core::position2di position,
+ u32 starttime=0, u32 currenttime=0,
+ bool loop=false, const core::rect<s32>* clip=0)
+ {
+ drawColoredIcon(element, icon, position, starttime, currenttime, loop, clip);
+ }
+
+ virtual void drawColoredIcon(IGUIElement* element, EGUI_DEFAULT_ICON icon,
+ const core::position2di position,
+ u32 starttime=0, u32 currenttime=0,
+ bool loop=false, const core::rect<s32>* clip=0,
+ const video::SColor* colors=0);
+
+ //! draws a 2d rectangle.
+ /** \param element: Pointer to the element which wishes to draw this icon.
+ This parameter is usually not used by IGUISkin, but can be used for example
+ by more complex implementations to find out how to draw the part exactly.
+ \param color: Color of the rectangle to draw. The alpha component specifies how
+ transparent the rectangle will be.
+ \param pos: Position of the rectangle.
+ \param clip: Pointer to rectangle against which the rectangle will be clipped.
+ If the pointer is null, no clipping will be performed. */
+ virtual void draw2DRectangle(IGUIElement* element, const video::SColor &color,
+ const core::rect<s32>& pos, const core::rect<s32>* clip = 0);
+
+
+ //! get the type of this skin
+ virtual EGUI_SKIN_TYPE getType() const;
+
+ //! Writes attributes of the object.
+ //! Implement this to expose the attributes of your scene node animator for
+ //! scripting languages, editors, debuggers or xml serialization purposes.
+ virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const;
+
+ //! Reads attributes of the object.
+ //! Implement this to set the attributes of your scene node animator for
+ //! scripting languages, editors, debuggers or xml deserialization purposes.
+ virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0);
+
+ //! gets the colors
+ virtual void getColors(video::SColor* colors); // ::PATCH:
+
+ private:
+
+ video::SColor Colors[EGDC_COUNT];
+ s32 Sizes[EGDS_COUNT];
+ u32 Icons[EGDI_COUNT];
+ IGUIFont* Fonts[EGDF_COUNT];
+ IGUISpriteBank* SpriteBank;
+ core::stringw Texts[EGDT_COUNT];
+ video::IVideoDriver* Driver;
+ bool UseGradient;
+
+ EGUI_SKIN_TYPE Type;
+ };
+
+ #define set3DSkinColors(skin, button_color) \
+ { \
+ skin->setColor(EGDC_3D_FACE, button_color); \
+ skin->setColor(EGDC_3D_DARK_SHADOW, button_color, 0.25f); \
+ skin->setColor(EGDC_3D_SHADOW, button_color, 0.5f); \
+ skin->setColor(EGDC_3D_LIGHT, button_color); \
+ skin->setColor(EGDC_3D_HIGH_LIGHT, button_color, 1.5f); \
+ }
+
+ #define getElementSkinColor(color) \
+ { \
+ if (!Colors) \
+ { \
+ IGUISkin* skin = Environment->getSkin(); \
+ if (skin) \
+ return skin->getColor(color); \
+ } \
+ return Colors[color]; \
+ }
+
+ #define setElementSkinColor(which, newColor, shading) \
+ { \
+ if (!Colors) \
+ { \
+ Colors = new video::SColor[EGDC_COUNT]; \
+ GUISkin* skin = (GUISkin *)Environment->getSkin(); \
+ if (skin) \
+ skin->getColors(Colors); \
+ } \
+ Colors[which] = newColor; \
+ setShading(Colors[which],shading); \
+ }
+} // end namespace gui
+//! Sets the shading
+inline void setShading(video::SColor &color,f32 s) // :PATCH:
+{
+ if (s < 1.0f)
+ {
+ color.setRed(color.getRed() * s);
+ color.setGreen(color.getGreen() * s);
+ color.setBlue(color.getBlue() * s);
+ }
+ else if (s > 1.0f)
+ {
+ s -= 1.0f;
+
+ color.setRed(color.getRed() + (255 - color.getRed()) * s);
+ color.setGreen(color.getGreen() + (255 - color.getGreen()) * s);
+ color.setBlue(color.getBlue() + (255 - color.getBlue()) * s);
+ }
+}
+} // end namespace irr
+
+
+#endif // _IRR_COMPILE_WITH_GUI_
+
+#endif