2019-12-30 00:18:59 +01:00
|
|
|
// 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
|
|
|
|
|
|
2011-11-28 11:56:39 +08:00
|
|
|
#include "CGUIImageButton.h"
|
2019-12-30 00:18:59 +01:00
|
|
|
#ifdef _IRR_COMPILE_WITH_GUI_
|
|
|
|
|
|
2020-04-16 10:11:57 +02:00
|
|
|
#include <IGUISkin.h>
|
|
|
|
|
#include <IGUISpriteBank.h>
|
|
|
|
|
#include <IGUIEnvironment.h>
|
|
|
|
|
#include <IVideoDriver.h>
|
|
|
|
|
#include <IGUIFont.h>
|
2025-02-09 13:01:57 +01:00
|
|
|
#include <ITimer.h>
|
2022-08-20 22:29:13 +02:00
|
|
|
#include "../config.h"
|
2025-02-09 13:01:57 +01:00
|
|
|
#include "../utils.h"
|
2011-11-28 11:56:39 +08:00
|
|
|
|
|
|
|
|
namespace irr {
|
|
|
|
|
namespace gui {
|
2023-02-10 21:27:16 +01:00
|
|
|
|
2026-04-19 01:16:03 +02:00
|
|
|
static bool isGLES(irr::video::IVideoDriver* driver) {
|
2026-08-05 23:10:43 +02:00
|
|
|
#if (IRRLICHT_VERSION_MAJOR==1 && IRRLICHT_VERSION_MINOR==9)
|
2026-04-19 01:16:03 +02:00
|
|
|
static const bool gles = [driver] {
|
|
|
|
|
auto driver_type = driver->getDriverType();
|
|
|
|
|
return driver_type == irr::video::EDT_OGLES1 || driver_type == irr::video::EDT_OGLES2;
|
|
|
|
|
}();
|
|
|
|
|
return gles;
|
2026-08-05 23:10:43 +02:00
|
|
|
#else
|
|
|
|
|
return false;
|
|
|
|
|
#endif
|
2020-05-26 12:16:46 +02:00
|
|
|
}
|
|
|
|
|
|
2011-11-28 11:56:39 +08:00
|
|
|
void Draw2DImageRotation(video::IVideoDriver* driver, video::ITexture* image, core::rect<s32> sourceRect,
|
2020-07-21 23:56:22 +02:00
|
|
|
core::vector2d<s32> position, core::vector2d<s32> rotationPoint, f32 rotation, core::vector2df scale, bool useAlphaChannel, video::SColor color) {
|
2011-11-28 11:56:39 +08:00
|
|
|
irr::video::SMaterial material;
|
|
|
|
|
irr::core::matrix4 oldProjMat = driver->getTransform(irr::video::ETS_PROJECTION);
|
|
|
|
|
driver->setTransform(irr::video::ETS_PROJECTION, irr::core::matrix4());
|
|
|
|
|
irr::core::matrix4 oldViewMat = driver->getTransform(irr::video::ETS_VIEW);
|
|
|
|
|
driver->setTransform(irr::video::ETS_VIEW, irr::core::matrix4());
|
|
|
|
|
irr::core::vector2df corner[4];
|
2020-07-21 23:56:22 +02:00
|
|
|
corner[0] = irr::core::vector2df((float)position.X, (float)position.Y);
|
|
|
|
|
corner[1] = irr::core::vector2df((float)(position.X + sourceRect.getWidth() * scale.X), (float)position.Y);
|
|
|
|
|
corner[2] = irr::core::vector2df((float)position.X, (float)(position.Y + sourceRect.getHeight() * scale.Y));
|
|
|
|
|
corner[3] = irr::core::vector2df((float)(position.X + sourceRect.getWidth() * scale.X), (float)(position.Y + sourceRect.getHeight() * scale.Y));
|
2019-12-30 00:18:59 +01:00
|
|
|
if(rotation != 0.0f) {
|
|
|
|
|
for(int x = 0; x < 4; x++)
|
2020-07-21 23:56:22 +02:00
|
|
|
corner[x].rotateBy(rotation, irr::core::vector2df((float)rotationPoint.X, (float)rotationPoint.Y));
|
2011-11-28 11:56:39 +08:00
|
|
|
}
|
|
|
|
|
irr::core::vector2df uvCorner[4];
|
2020-07-21 23:56:22 +02:00
|
|
|
uvCorner[0] = irr::core::vector2df((float)sourceRect.UpperLeftCorner.X, (float)sourceRect.UpperLeftCorner.Y);
|
|
|
|
|
uvCorner[1] = irr::core::vector2df((float)sourceRect.LowerRightCorner.X, (float)sourceRect.UpperLeftCorner.Y);
|
|
|
|
|
uvCorner[2] = irr::core::vector2df((float)sourceRect.UpperLeftCorner.X, (float)sourceRect.LowerRightCorner.Y);
|
|
|
|
|
uvCorner[3] = irr::core::vector2df((float)sourceRect.LowerRightCorner.X, (float)sourceRect.LowerRightCorner.Y);
|
2019-12-30 00:18:59 +01:00
|
|
|
for(int x = 0; x < 4; x++) {
|
2012-02-05 22:34:10 +08:00
|
|
|
float uvX = uvCorner[x].X / (float)image->getOriginalSize().Width;
|
|
|
|
|
float uvY = uvCorner[x].Y / (float)image->getOriginalSize().Height;
|
|
|
|
|
uvCorner[x] = irr::core::vector2df(uvX, uvY);
|
|
|
|
|
}
|
|
|
|
|
irr::video::S3DVertex vertices[4];
|
|
|
|
|
irr::u16 indices[6] = { 0, 1, 2, 3, 2, 1 };
|
2020-07-21 23:56:22 +02:00
|
|
|
float screenWidth = (float)driver->getScreenSize().Width;
|
|
|
|
|
float screenHeight = (float)driver->getScreenSize().Height;
|
2019-12-30 00:18:59 +01:00
|
|
|
for(int x = 0; x < 4; x++) {
|
2012-02-05 22:34:10 +08:00
|
|
|
float screenPosX = ((corner[x].X / screenWidth) - 0.5f) * 2.0f;
|
|
|
|
|
float screenPosY = ((corner[x].Y / screenHeight) - 0.5f) * -2.0f;
|
|
|
|
|
vertices[x].Pos = irr::core::vector3df(screenPosX, screenPosY, 1);
|
|
|
|
|
vertices[x].TCoords = uvCorner[x];
|
|
|
|
|
vertices[x].Color = color;
|
|
|
|
|
}
|
|
|
|
|
material.Lighting = false;
|
2021-03-29 13:17:47 +02:00
|
|
|
#if IRRLICHT_VERSION_MAJOR==1 && IRRLICHT_VERSION_MINOR==9
|
|
|
|
|
material.ZWriteEnable = irr::video::E_ZWRITE::EZW_OFF;
|
|
|
|
|
#else
|
2012-02-05 22:34:10 +08:00
|
|
|
material.ZWriteEnable = false;
|
2021-03-29 13:17:47 +02:00
|
|
|
#endif
|
2012-02-05 22:34:10 +08:00
|
|
|
material.TextureLayer[0].Texture = image;
|
2026-04-19 01:16:03 +02:00
|
|
|
if(isGLES(driver)) {
|
2020-01-21 23:51:41 +01:00
|
|
|
material.TextureLayer[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE;
|
|
|
|
|
material.TextureLayer[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE;
|
2019-12-30 00:18:59 +01:00
|
|
|
}
|
|
|
|
|
if(useAlphaChannel)
|
2012-02-05 22:34:10 +08:00
|
|
|
material.MaterialType = irr::video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
|
|
|
|
else material.MaterialType = irr::video::EMT_SOLID;
|
2019-12-30 00:18:59 +01:00
|
|
|
|
2012-02-05 22:34:10 +08:00
|
|
|
driver->setMaterial(material);
|
|
|
|
|
driver->drawIndexedTriangleList(&vertices[0], 4, &indices[0], 2);
|
|
|
|
|
driver->setTransform(irr::video::ETS_PROJECTION, oldProjMat);
|
|
|
|
|
driver->setTransform(irr::video::ETS_VIEW, oldViewMat);
|
|
|
|
|
}
|
|
|
|
|
void Draw2DImageQuad(video::IVideoDriver* driver, video::ITexture* image, core::rect<s32> sourceRect,
|
2020-07-21 23:56:22 +02:00
|
|
|
core::vector2d<s32> corner[4], bool useAlphaChannel, video::SColor color) {
|
2012-02-05 22:34:10 +08:00
|
|
|
irr::video::SMaterial material;
|
|
|
|
|
irr::core::matrix4 oldProjMat = driver->getTransform(irr::video::ETS_PROJECTION);
|
|
|
|
|
driver->setTransform(irr::video::ETS_PROJECTION, irr::core::matrix4());
|
|
|
|
|
irr::core::matrix4 oldViewMat = driver->getTransform(irr::video::ETS_VIEW);
|
|
|
|
|
driver->setTransform(irr::video::ETS_VIEW, irr::core::matrix4());
|
|
|
|
|
irr::core::vector2df uvCorner[4];
|
2020-07-21 23:56:22 +02:00
|
|
|
uvCorner[0] = irr::core::vector2df((float)sourceRect.UpperLeftCorner.X, (float)sourceRect.UpperLeftCorner.Y);
|
|
|
|
|
uvCorner[1] = irr::core::vector2df((float)sourceRect.LowerRightCorner.X, (float)sourceRect.UpperLeftCorner.Y);
|
|
|
|
|
uvCorner[2] = irr::core::vector2df((float)sourceRect.UpperLeftCorner.X, (float)sourceRect.LowerRightCorner.Y);
|
|
|
|
|
uvCorner[3] = irr::core::vector2df((float)sourceRect.LowerRightCorner.X, (float)sourceRect.LowerRightCorner.Y);
|
2019-12-30 00:18:59 +01:00
|
|
|
for(int x = 0; x < 4; x++) {
|
2012-02-03 20:36:19 +08:00
|
|
|
float uvX = uvCorner[x].X / (float)image->getOriginalSize().Width;
|
|
|
|
|
float uvY = uvCorner[x].Y / (float)image->getOriginalSize().Height;
|
2011-11-28 11:56:39 +08:00
|
|
|
uvCorner[x] = irr::core::vector2df(uvX, uvY);
|
|
|
|
|
}
|
|
|
|
|
irr::video::S3DVertex vertices[4];
|
|
|
|
|
irr::u16 indices[6] = { 0, 1, 2, 3, 2, 1 };
|
2020-07-21 23:56:22 +02:00
|
|
|
float screenWidth = (float)driver->getScreenSize().Width;
|
|
|
|
|
float screenHeight = (float)driver->getScreenSize().Height;
|
2019-12-30 00:18:59 +01:00
|
|
|
for(int x = 0; x < 4; x++) {
|
2011-11-28 11:56:39 +08:00
|
|
|
float screenPosX = ((corner[x].X / screenWidth) - 0.5f) * 2.0f;
|
|
|
|
|
float screenPosY = ((corner[x].Y / screenHeight) - 0.5f) * -2.0f;
|
|
|
|
|
vertices[x].Pos = irr::core::vector3df(screenPosX, screenPosY, 1);
|
|
|
|
|
vertices[x].TCoords = uvCorner[x];
|
|
|
|
|
vertices[x].Color = color;
|
|
|
|
|
}
|
|
|
|
|
material.Lighting = false;
|
2021-03-29 13:17:47 +02:00
|
|
|
#if IRRLICHT_VERSION_MAJOR==1 && IRRLICHT_VERSION_MINOR==9
|
|
|
|
|
material.ZWriteEnable = irr::video::E_ZWRITE::EZW_OFF;
|
|
|
|
|
#else
|
2011-11-28 11:56:39 +08:00
|
|
|
material.ZWriteEnable = false;
|
2021-03-29 13:17:47 +02:00
|
|
|
#endif
|
2011-11-28 11:56:39 +08:00
|
|
|
material.TextureLayer[0].Texture = image;
|
2026-04-19 01:16:03 +02:00
|
|
|
if(isGLES(driver)) {
|
2020-01-21 23:51:41 +01:00
|
|
|
material.TextureLayer[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE;
|
|
|
|
|
material.TextureLayer[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE;
|
2019-12-30 00:18:59 +01:00
|
|
|
}
|
|
|
|
|
if(useAlphaChannel)
|
2011-11-28 11:56:39 +08:00
|
|
|
material.MaterialType = irr::video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
|
|
|
|
else material.MaterialType = irr::video::EMT_SOLID;
|
|
|
|
|
driver->setMaterial(material);
|
|
|
|
|
driver->drawIndexedTriangleList(&vertices[0], 4, &indices[0], 2);
|
|
|
|
|
driver->setTransform(irr::video::ETS_PROJECTION, oldProjMat);
|
|
|
|
|
driver->setTransform(irr::video::ETS_VIEW, oldViewMat);
|
|
|
|
|
}
|
2019-12-30 00:18:59 +01:00
|
|
|
//! constructor
|
|
|
|
|
CGUIImageButton::CGUIImageButton(IGUIEnvironment* environment, IGUIElement* parent,
|
|
|
|
|
s32 id, core::rect<s32> rectangle, bool noclip)
|
|
|
|
|
: IGUIButton(environment, parent, id, rectangle),
|
|
|
|
|
SpriteBank(0), OverrideFont(0), Image(0), PressedImage(0),
|
|
|
|
|
ClickTime(0), HoverTime(0), FocusTime(0),
|
|
|
|
|
IsPushButton(false), Pressed(false),
|
2020-07-01 22:26:39 -04:00
|
|
|
UseAlphaChannel(false), DrawBorder(true), ScaleImage(false),
|
|
|
|
|
ClickShiftState(false) {
|
2019-12-30 00:18:59 +01:00
|
|
|
#ifdef _DEBUG
|
|
|
|
|
setDebugName("CGUIImageButton");
|
|
|
|
|
#endif
|
|
|
|
|
setNotClipped(noclip);
|
|
|
|
|
|
|
|
|
|
// Initialize the sprites.
|
|
|
|
|
for(u32 i = 0; i < EGBS_COUNT; ++i)
|
|
|
|
|
ButtonSprites[i].Index = -1;
|
|
|
|
|
|
|
|
|
|
// This element can be tabbed.
|
|
|
|
|
setTabStop(true);
|
|
|
|
|
setTabOrder(-1);
|
2011-11-28 11:56:39 +08:00
|
|
|
isDrawImage = true;
|
2019-06-17 12:46:17 +08:00
|
|
|
isFixedSize = false;
|
2011-11-28 11:56:39 +08:00
|
|
|
imageRotation = 0.0f;
|
|
|
|
|
imageScale = core::vector2df(1.0f, 1.0f);
|
2019-06-17 12:46:17 +08:00
|
|
|
imageSize = core::dimension2di(rectangle.getWidth(), rectangle.getHeight());
|
2011-11-28 11:56:39 +08:00
|
|
|
}
|
2019-12-30 00:18:59 +01:00
|
|
|
|
2011-11-28 11:56:39 +08:00
|
|
|
CGUIImageButton* CGUIImageButton::addImageButton(IGUIEnvironment *env, const core::rect<s32>& rectangle, IGUIElement* parent, s32 id) {
|
2011-12-26 08:51:48 +08:00
|
|
|
CGUIImageButton* button = new CGUIImageButton(env, parent ? parent : 0, id, rectangle);
|
2011-11-28 11:56:39 +08:00
|
|
|
button->drop();
|
|
|
|
|
return button;
|
|
|
|
|
}
|
2019-12-30 00:18:59 +01:00
|
|
|
|
|
|
|
|
//! destructor
|
|
|
|
|
CGUIImageButton::~CGUIImageButton() {
|
|
|
|
|
if(OverrideFont)
|
|
|
|
|
OverrideFont->drop();
|
|
|
|
|
|
|
|
|
|
if(Image)
|
|
|
|
|
Image->drop();
|
|
|
|
|
|
|
|
|
|
if(PressedImage)
|
|
|
|
|
PressedImage->drop();
|
|
|
|
|
|
|
|
|
|
if(SpriteBank)
|
|
|
|
|
SpriteBank->drop();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//! Sets if the images should be scaled to fit the button
|
|
|
|
|
void CGUIImageButton::setScaleImage(bool scaleImage) {
|
|
|
|
|
ScaleImage = scaleImage;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//! Returns whether the button scale the used images
|
|
|
|
|
bool CGUIImageButton::isScalingImage() const {
|
|
|
|
|
return ScaleImage;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//! Sets if the button should use the skin to draw its border
|
|
|
|
|
void CGUIImageButton::setDrawBorder(bool border) {
|
|
|
|
|
DrawBorder = border;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CGUIImageButton::setSpriteBank(IGUISpriteBank* sprites) {
|
|
|
|
|
if(sprites)
|
|
|
|
|
sprites->grab();
|
|
|
|
|
|
|
|
|
|
if(SpriteBank)
|
|
|
|
|
SpriteBank->drop();
|
|
|
|
|
|
|
|
|
|
SpriteBank = sprites;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2020-01-01 23:22:15 +01:00
|
|
|
#if IRRLICHT_VERSION_MAJOR==1 && IRRLICHT_VERSION_MINOR==9
|
2019-12-30 00:18:59 +01:00
|
|
|
void CGUIImageButton::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;
|
|
|
|
|
}
|
2020-01-01 23:22:15 +01:00
|
|
|
#else
|
|
|
|
|
void CGUIImageButton::setSprite(EGUI_BUTTON_STATE state, s32 index, video::SColor color, bool loop) {
|
|
|
|
|
if(SpriteBank) {
|
|
|
|
|
ButtonSprites[(u32)state].Index = index;
|
|
|
|
|
ButtonSprites[(u32)state].Color = color;
|
|
|
|
|
ButtonSprites[(u32)state].Loop = loop;
|
|
|
|
|
} else {
|
|
|
|
|
ButtonSprites[(u32)state].Index = -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2019-12-30 00:18:59 +01:00
|
|
|
|
|
|
|
|
//! Get the sprite-index for the given state or -1 when no sprite is set
|
|
|
|
|
s32 CGUIImageButton::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 CGUIImageButton::getSpriteColor(EGUI_BUTTON_STATE state) const {
|
|
|
|
|
return ButtonSprites[(u32)state].Color;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//! Returns if the sprite in the given state does loop
|
|
|
|
|
bool CGUIImageButton::getSpriteLoop(EGUI_BUTTON_STATE state) const {
|
|
|
|
|
return ButtonSprites[(u32)state].Loop;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//! Returns if the sprite in the given state is scaled
|
|
|
|
|
bool CGUIImageButton::getSpriteScale(EGUI_BUTTON_STATE state) const {
|
|
|
|
|
return ButtonSprites[(u32)state].Scale;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//! called if an event happened.
|
|
|
|
|
bool CGUIImageButton::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) {
|
2020-07-01 22:26:39 -04:00
|
|
|
ClickShiftState = event.KeyInput.Shift;
|
|
|
|
|
|
2019-12-30 00:18:59 +01:00
|
|
|
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);
|
2025-02-09 13:01:57 +01:00
|
|
|
FocusTime = ygo::Utils::irrTimer->getTime();
|
2019-12-30 00:18:59 +01:00
|
|
|
} else if(event.GUIEvent.EventType == EGET_ELEMENT_FOCUSED) {
|
2025-02-09 13:01:57 +01:00
|
|
|
FocusTime = ygo::Utils::irrTimer->getTime();
|
2019-12-30 00:18:59 +01:00
|
|
|
} else if(event.GUIEvent.EventType == EGET_ELEMENT_HOVERED || event.GUIEvent.EventType == EGET_ELEMENT_LEFT) {
|
2025-02-09 13:01:57 +01:00
|
|
|
HoverTime = ygo::Utils::irrTimer->getTime();
|
2019-12-30 00:18:59 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case EET_MOUSE_INPUT_EVENT:
|
|
|
|
|
if(event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN) {
|
|
|
|
|
if(Environment->hasFocus(this) &&
|
2023-08-21 11:53:59 +02:00
|
|
|
!AbsoluteClippingRect.isPointInside(core::vector2d<s32>(event.MouseInput.X, event.MouseInput.Y))) {
|
2019-12-30 00:18:59 +01:00
|
|
|
Environment->removeFocus(this);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(!IsPushButton)
|
|
|
|
|
setPressed(true);
|
|
|
|
|
|
|
|
|
|
Environment->setFocus(this);
|
|
|
|
|
return true;
|
|
|
|
|
} else
|
|
|
|
|
if(event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP) {
|
|
|
|
|
bool wasPressed = Pressed;
|
|
|
|
|
|
2023-08-21 11:53:59 +02:00
|
|
|
if(!AbsoluteClippingRect.isPointInside(core::vector2d<s32>(event.MouseInput.X, event.MouseInput.Y))) {
|
2019-12-30 00:18:59 +01:00
|
|
|
if(!IsPushButton)
|
|
|
|
|
setPressed(false);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(!IsPushButton)
|
|
|
|
|
setPressed(false);
|
|
|
|
|
else {
|
|
|
|
|
setPressed(!Pressed);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if((!IsPushButton && wasPressed && Parent) ||
|
|
|
|
|
(IsPushButton && wasPressed != Pressed)) {
|
2020-07-01 22:26:39 -04:00
|
|
|
ClickShiftState = event.MouseInput.Shift;
|
|
|
|
|
|
2019-12-30 00:18:59 +01:00
|
|
|
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
|
2011-11-28 11:56:39 +08:00
|
|
|
void CGUIImageButton::draw() {
|
2019-12-30 00:18:59 +01:00
|
|
|
if(!IsVisible)
|
2011-11-28 11:56:39 +08:00
|
|
|
return;
|
|
|
|
|
IGUISkin* skin = Environment->getSkin();
|
|
|
|
|
video::IVideoDriver* driver = Environment->getVideoDriver();
|
2023-08-21 11:53:59 +02:00
|
|
|
core::vector2di center = AbsoluteRect.getCenter();
|
|
|
|
|
core::vector2di pos = center;
|
2011-11-28 11:56:39 +08:00
|
|
|
pos.X -= (s32)(ImageRect.getWidth() * imageScale.X * 0.5f);
|
|
|
|
|
pos.Y -= (s32)(ImageRect.getHeight() * imageScale.Y * 0.5f);
|
|
|
|
|
if(Pressed) {
|
|
|
|
|
pos.X += 1;
|
|
|
|
|
pos.Y += 1;
|
|
|
|
|
center.X += 1;
|
|
|
|
|
center.Y += 1;
|
2019-12-30 00:18:59 +01:00
|
|
|
if(DrawBorder)
|
2011-11-28 11:56:39 +08:00
|
|
|
skin->draw3DButtonPanePressed(this, AbsoluteRect, &AbsoluteClippingRect);
|
|
|
|
|
} else {
|
2019-12-30 00:18:59 +01:00
|
|
|
if(DrawBorder)
|
2011-11-28 11:56:39 +08:00
|
|
|
skin->draw3DButtonPaneStandard(this, AbsoluteRect, &AbsoluteClippingRect);
|
|
|
|
|
}
|
|
|
|
|
if(Image && isDrawImage)
|
|
|
|
|
irr::gui::Draw2DImageRotation(driver, Image, ImageRect, pos, center, imageRotation, imageScale);
|
|
|
|
|
IGUIElement::draw();
|
|
|
|
|
}
|
2019-12-30 00:18:59 +01:00
|
|
|
|
2020-01-01 23:22:15 +01:00
|
|
|
#if IRRLICHT_VERSION_MAJOR==1 && IRRLICHT_VERSION_MINOR==9
|
2023-08-21 11:53:59 +02:00
|
|
|
void CGUIImageButton::drawSprite(EGUI_BUTTON_STATE state, u32 startTime, const core::vector2di& center) {
|
2019-12-30 00:18:59 +01:00
|
|
|
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,
|
|
|
|
|
&AbsoluteClippingRect, colors,
|
2025-02-09 13:01:57 +01:00
|
|
|
ygo::Utils::irrTimer->getTime() - startTime, ButtonSprites[stateIdx].Loop);
|
2019-12-30 00:18:59 +01:00
|
|
|
} else {
|
|
|
|
|
SpriteBank->draw2DSprite(ButtonSprites[stateIdx].Index, center,
|
2025-02-09 13:01:57 +01:00
|
|
|
&AbsoluteClippingRect, ButtonSprites[stateIdx].Color, startTime, ygo::Utils::irrTimer->getTime(),
|
2019-12-30 00:18:59 +01:00
|
|
|
ButtonSprites[stateIdx].Loop, true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-01-01 23:22:15 +01:00
|
|
|
#endif
|
2019-12-30 00:18:59 +01:00
|
|
|
|
|
|
|
|
//! sets another skin independent font. if this is set to zero, the button uses the font of the skin.
|
|
|
|
|
void CGUIImageButton::setOverrideFont(IGUIFont* font) {
|
|
|
|
|
if(OverrideFont == font)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if(OverrideFont)
|
|
|
|
|
OverrideFont->drop();
|
|
|
|
|
|
|
|
|
|
OverrideFont = font;
|
|
|
|
|
|
|
|
|
|
if(OverrideFont)
|
|
|
|
|
OverrideFont->grab();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IGUIFont* CGUIImageButton::getOverrideFont(void) const {
|
|
|
|
|
IGUISkin* skin = Environment->getSkin();
|
|
|
|
|
if(!skin)
|
|
|
|
|
return NULL;
|
|
|
|
|
return skin->getFont();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IGUIFont* CGUIImageButton::getActiveFont() const {
|
|
|
|
|
IGUISkin* skin = Environment->getSkin();
|
|
|
|
|
if(!skin)
|
|
|
|
|
return NULL;
|
|
|
|
|
return skin->getFont();
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-01 23:22:15 +01:00
|
|
|
#if IRRLICHT_VERSION_MAJOR==1 && IRRLICHT_VERSION_MINOR==9
|
2019-12-30 00:18:59 +01:00
|
|
|
void CGUIImageButton::setImage(EGUI_BUTTON_IMAGE_STATE state, video::ITexture* image, const core::rect<s32>& sourceRect) {
|
|
|
|
|
setImage(image);
|
|
|
|
|
ImageRect = sourceRect;
|
|
|
|
|
}
|
2020-01-01 23:22:15 +01:00
|
|
|
#endif
|
2019-12-30 00:18:59 +01:00
|
|
|
|
|
|
|
|
//! Sets an image which should be displayed on the button when it is in normal state.
|
|
|
|
|
void CGUIImageButton::setImage(video::ITexture* image) {
|
2019-06-17 12:46:17 +08:00
|
|
|
if(image)
|
|
|
|
|
image->grab();
|
|
|
|
|
if(Image)
|
|
|
|
|
Image->drop();
|
|
|
|
|
|
|
|
|
|
Image = image;
|
|
|
|
|
if(image) {
|
2023-08-21 11:53:59 +02:00
|
|
|
ImageRect = core::rect<s32>(core::vector2d<s32>(0, 0), image->getOriginalSize());
|
2019-06-17 12:46:17 +08:00
|
|
|
if(isFixedSize)
|
2026-04-18 22:56:52 +02:00
|
|
|
imageScale = core::vector2df((irr::f32)imageSize.Width / image->getOriginalSize().Width, (irr::f32)imageSize.Height / image->getOriginalSize().Height);
|
2019-06-17 12:46:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(!PressedImage)
|
|
|
|
|
setPressedImage(Image);
|
|
|
|
|
}
|
2019-12-30 00:18:59 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
//! Sets the image which should be displayed on the button when it is in its normal state.
|
|
|
|
|
void CGUIImageButton::setImage(video::ITexture* image, const core::rect<s32>& pos) {
|
|
|
|
|
setImage(image);
|
|
|
|
|
ImageRect = pos;
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-28 11:56:39 +08:00
|
|
|
void CGUIImageButton::setDrawImage(bool b) {
|
|
|
|
|
isDrawImage = b;
|
|
|
|
|
}
|
2019-12-30 00:18:59 +01:00
|
|
|
|
2011-11-28 11:56:39 +08:00
|
|
|
void CGUIImageButton::setImageRotation(f32 r) {
|
|
|
|
|
imageRotation = r;
|
|
|
|
|
}
|
2019-12-30 00:18:59 +01:00
|
|
|
|
2011-11-28 11:56:39 +08:00
|
|
|
void CGUIImageButton::setImageScale(core::vector2df s) {
|
|
|
|
|
imageScale = s;
|
|
|
|
|
}
|
2019-12-30 00:18:59 +01:00
|
|
|
|
2019-06-17 12:46:17 +08:00
|
|
|
void CGUIImageButton::setImageSize(core::dimension2di s) {
|
|
|
|
|
isFixedSize = true;
|
|
|
|
|
imageSize = s;
|
|
|
|
|
}
|
2011-11-28 11:56:39 +08:00
|
|
|
|
2019-12-30 00:18:59 +01:00
|
|
|
|
|
|
|
|
//! Sets an image which should be displayed on the button when it is in pressed state.
|
|
|
|
|
void CGUIImageButton::setPressedImage(video::ITexture* image) {
|
|
|
|
|
if(image)
|
|
|
|
|
image->grab();
|
|
|
|
|
|
|
|
|
|
if(PressedImage)
|
|
|
|
|
PressedImage->drop();
|
|
|
|
|
|
|
|
|
|
PressedImage = image;
|
|
|
|
|
if(image)
|
2023-08-21 11:53:59 +02:00
|
|
|
PressedImageRect = core::rect<s32>(core::vector2d<s32>(0, 0), image->getOriginalSize());
|
2013-04-12 18:10:31 +08:00
|
|
|
}
|
|
|
|
|
|
2019-12-30 00:18:59 +01:00
|
|
|
|
|
|
|
|
//! Sets the image which should be displayed on the button when it is in its pressed state.
|
|
|
|
|
void CGUIImageButton::setPressedImage(video::ITexture* image, const core::rect<s32>& pos) {
|
|
|
|
|
setPressedImage(image);
|
|
|
|
|
PressedImageRect = pos;
|
2013-04-12 18:10:31 +08:00
|
|
|
}
|
|
|
|
|
|
2019-12-30 00:18:59 +01:00
|
|
|
|
|
|
|
|
//! 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 CGUIImageButton::setIsPushButton(bool isPushButton) {
|
|
|
|
|
IsPushButton = isPushButton;
|
2011-11-28 11:56:39 +08:00
|
|
|
}
|
2019-12-30 00:18:59 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
//! Returns if the button is currently pressed
|
|
|
|
|
bool CGUIImageButton::isPressed() const {
|
|
|
|
|
return Pressed;
|
2011-11-28 11:56:39 +08:00
|
|
|
}
|
2019-12-30 00:18:59 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
//! Sets the pressed state of the button if this is a pushbutton
|
|
|
|
|
void CGUIImageButton::setPressed(bool pressed) {
|
|
|
|
|
if(Pressed != pressed) {
|
2025-02-09 13:01:57 +01:00
|
|
|
ClickTime = ygo::Utils::irrTimer->getTime();
|
2019-12-30 00:18:59 +01:00
|
|
|
Pressed = pressed;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//! Returns whether the button is a push button
|
|
|
|
|
bool CGUIImageButton::isPushButton() const {
|
|
|
|
|
return IsPushButton;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//! Sets if the alpha channel should be used for drawing images on the button (default is false)
|
|
|
|
|
void CGUIImageButton::setUseAlphaChannel(bool useAlphaChannel) {
|
|
|
|
|
UseAlphaChannel = useAlphaChannel;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//! Returns if the alpha channel should be used for drawing images on the button
|
|
|
|
|
bool CGUIImageButton::isAlphaChannelUsed() const {
|
|
|
|
|
return UseAlphaChannel;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool CGUIImageButton::isDrawingBorder() const {
|
|
|
|
|
return DrawBorder;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//! Writes attributes of the element.
|
|
|
|
|
void CGUIImageButton::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options = 0) const {
|
|
|
|
|
IGUIButton::serializeAttributes(out, options);
|
|
|
|
|
|
|
|
|
|
out->addBool("PushButton", IsPushButton);
|
|
|
|
|
if(IsPushButton)
|
|
|
|
|
out->addBool("Pressed", Pressed);
|
|
|
|
|
|
|
|
|
|
out->addTexture("Image", Image);
|
|
|
|
|
out->addRect("ImageRect", ImageRect);
|
|
|
|
|
out->addTexture("PressedImage", PressedImage);
|
|
|
|
|
out->addRect("PressedImageRect", PressedImageRect);
|
|
|
|
|
|
|
|
|
|
out->addBool("UseAlphaChannel", isAlphaChannelUsed());
|
|
|
|
|
out->addBool("Border", isDrawingBorder());
|
|
|
|
|
out->addBool("ScaleImage", isScalingImage());
|
|
|
|
|
|
|
|
|
|
// out->addString ("OverrideFont", OverrideFont);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//! Reads attributes of the element
|
|
|
|
|
void CGUIImageButton::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();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} // end namespace gui
|
|
|
|
|
} // end namespace irr
|
|
|
|
|
|
|
|
|
|
#endif // _IRR_COMPILE_WITH_GUI_
|
|
|
|
|
|