Moved Texture property from Picture to PictureRenderer, together with the IgnoreTransparentParts property (previously called FullyClickable)

0.8
Bruno Van de Velde 2017-09-05 22:55:07 +02:00
parent 6926f29dea
commit af77406789
8 changed files with 193 additions and 108 deletions

View File

@ -0,0 +1,86 @@
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// TGUI - Texus' Graphical User Interface
// Copyright (C) 2012-2017 Bruno Van de Velde (vdv_b@tgui.eu)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef TGUI_PICTURE_RENDERER_HPP
#define TGUI_PICTURE_RENDERER_HPP
#include <TGUI/Renderers/WidgetRenderer.hpp>
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
namespace tgui
{
class TGUI_API PictureRenderer : public WidgetRenderer
{
public:
using WidgetRenderer::WidgetRenderer;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Change the image that is displayed
///
/// @param texture The new texture
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void setTexture(const Texture& texture);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Returns the image that is displayed
///
/// @return texture of the image
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Texture& getTexture() const;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Sets whether mouse events should be ignored on transparent parts of the texture
///
/// @brief ignoreTransparentParts Should mouse events on transparent texture parts be ignored?
///
/// When mouse events are ignored, they are passed to the other widget behind the widget.
/// By default, mouse events are NOT ignored and the widget will receive mouse events even on transparent texture parts.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void setIgnoreTransparentParts(bool ignoreTransparentParts);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Returns whether mouse events should be ignored on transparent parts of the texture
///
/// @brief Whether mouse events on transparent texture parts are ignored
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool getIgnoreTransparentParts() const;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#endif // TGUI_PICTURE_RENDERER_HPP

View File

@ -28,6 +28,7 @@
#include <TGUI/Widgets/ClickableWidget.hpp> #include <TGUI/Widgets/ClickableWidget.hpp>
#include <TGUI/Renderers/PictureRenderer.hpp>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -106,42 +107,15 @@ namespace tgui
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Changes the image /// @brief Returns the renderer, which gives access to functions that determine how the widget is displayed
/// ///
/// @param texture The texture to load the picture from /// @return Temporary pointer to the renderer
/// @param fullyClickable This affects what happens when clicking on a transparent pixel in the image.
/// Is the click caught by the picture, or does the event pass to the widgets behind it?
///
/// @code
/// picture1->setTexture("image.png");
///
/// picture2->setTexture({"image.png", {20, 15, 60, 40}}); // Only load the part of the image from (20,15) to (80,55)
///
/// sf::Texture texture;
/// texture.loadFromFile("image.png", {20, 15, 60, 40});
/// picture3->setTexture(texture);
/// @endcode
/// ///
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void setTexture(const Texture& texture, bool fullyClickable = true); PictureRenderer* getRenderer() const
{
return aurora::downcast<PictureRenderer*>(m_renderer.get());
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }
/// @brief Returns the texture used by the picture
///
/// @return Internal texture
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
const Texture& getTexture() const;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Returns the texture used by the picture
///
/// @return Reference to the internal texture
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Texture& getTexture();
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -234,8 +208,8 @@ namespace tgui
Sprite m_sprite; Sprite m_sprite;
// Set to false when clicks on transparent parts of the picture should go to the widgets behind the picture // Set to true when clicks on transparent parts of the picture should go to the widgets behind the picture
bool m_fullyClickable = true; bool m_ignoreTransparentParts = true;
// Will be set to true after the first click, but gets reset to false when the second click does not occur soon after // Will be set to true after the first click, but gets reset to false when the second click does not occur soon after
bool m_possibleDoubleClick = false; bool m_possibleDoubleClick = false;

View File

@ -36,6 +36,7 @@ set(TGUI_SRC
Renderers/MenuBarRenderer.cpp Renderers/MenuBarRenderer.cpp
Renderers/MessageBoxRenderer.cpp Renderers/MessageBoxRenderer.cpp
Renderers/PanelRenderer.cpp Renderers/PanelRenderer.cpp
Renderers/PictureRenderer.cpp
Renderers/ProgressBarRenderer.cpp Renderers/ProgressBarRenderer.cpp
Renderers/RadioButtonRenderer.cpp Renderers/RadioButtonRenderer.cpp
Renderers/RangeSliderRenderer.cpp Renderers/RangeSliderRenderer.cpp

View File

@ -865,9 +865,6 @@ namespace tgui
else else
picture = Picture::create(); picture = Picture::create();
if (node->propertyValuePairs["texture"])
picture = Picture::create(Deserializer::deserialize(ObjectConverter::Type::Texture, node->propertyValuePairs["texture"]->value).getTexture());
loadWidget(node, picture); loadWidget(node, picture);
return picture; return picture;

View File

@ -534,10 +534,6 @@ namespace tgui
{ {
auto picture = std::static_pointer_cast<Picture>(widget); auto picture = std::static_pointer_cast<Picture>(widget);
auto node = WidgetSaver::getSaveFunction("widget")(picture); auto node = WidgetSaver::getSaveFunction("widget")(picture);
if (!picture->getTexture().getId().isEmpty())
SET_PROPERTY("Texture", Serializer::serialize(picture->getTexture()));
return node; return node;
} }

View File

@ -0,0 +1,54 @@
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// TGUI - Texus' Graphical User Interface
// Copyright (C) 2012-2017 Bruno Van de Velde (vdv_b@tgui.eu)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <TGUI/Renderers/PictureRenderer.hpp>
#include <TGUI/RendererDefines.hpp>
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
namespace tgui
{
TGUI_RENDERER_PROPERTY_TEXTURE(PictureRenderer, Texture)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void PictureRenderer::setIgnoreTransparentParts(bool ignoreTransparentParts)
{
setProperty("ignoretransparentparts", ignoreTransparentParts);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool PictureRenderer::getIgnoreTransparentParts() const
{
auto it = m_data->propertyValuePairs.find("ignoretransparentparts");
if (it != m_data->propertyValuePairs.end())
return it->second.getBool();
else
return {};
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -34,14 +34,19 @@ namespace tgui
Picture::Picture() Picture::Picture()
{ {
m_type = "Picture"; m_type = "Picture";
m_renderer = aurora::makeCopied<PictureRenderer>();
setRenderer(RendererData::create({}));
} }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Picture::Picture(const Texture& texture, bool fullyClickable) : Picture::Picture(const Texture& texture, bool ignoreTransparentParts) :
Picture{} Picture{}
{ {
setTexture(texture, fullyClickable); getRenderer()->setTexture(texture);
if (ignoreTransparentParts)
getRenderer()->setIgnoreTransparentParts(ignoreTransparentParts);
} }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -63,32 +68,6 @@ namespace tgui
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Picture::setTexture(const Texture& texture, bool fullyClickable)
{
if (!m_sprite.isSet() && (texture.getImageSize() != sf::Vector2f{0,0}))
setSize(texture.getImageSize());
m_fullyClickable = fullyClickable;
m_sprite.setTexture(texture);
m_sprite.setOpacity(m_opacityCached);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
const Texture& Picture::getTexture() const
{
return m_sprite.getTexture();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Texture& Picture::getTexture()
{
return m_sprite.getTexture();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Picture::setSize(const Layout2d& size) void Picture::setSize(const Layout2d& size)
{ {
Widget::setSize(size); Widget::setSize(size);
@ -106,7 +85,7 @@ namespace tgui
if (sf::FloatRect{0, 0, getSize().x, getSize().y}.contains(pos)) if (sf::FloatRect{0, 0, getSize().x, getSize().y}.contains(pos))
{ {
// We sometimes want clicks to go through transparent parts of the picture // We sometimes want clicks to go through transparent parts of the picture
if (!m_fullyClickable && m_sprite.isTransparentPixel(pos)) if (!m_ignoreTransparentParts && m_sprite.isTransparentPixel(pos))
return false; return false;
else else
return true; return true;
@ -153,10 +132,26 @@ namespace tgui
void Picture::rendererChanged(const std::string& property) void Picture::rendererChanged(const std::string& property)
{ {
Widget::rendererChanged(property); if (property == "texture")
{
const auto& texture = getRenderer()->getTexture();
if (property == "opacity") if (!m_sprite.isSet() && (getSize() == sf::Vector2f{0,0}))
setSize(texture.getImageSize());
m_sprite.setTexture(texture);
}
else if (property == "ignoretransparentparts")
{
m_ignoreTransparentParts = getRenderer()->getIgnoreTransparentParts();
}
else if (property == "opacity")
{
Widget::rendererChanged(property);
m_sprite.setOpacity(m_opacityCached); m_sprite.setOpacity(m_opacityCached);
}
else
Widget::rendererChanged(property);
} }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -51,13 +51,13 @@ TEST_CASE("[Picture]")
SECTION("from tgui::Texture") SECTION("from tgui::Texture")
{ {
REQUIRE_NOTHROW(picture = tgui::Picture::create("resources/image.png")); REQUIRE_NOTHROW(picture = tgui::Picture::create("resources/image.png"));
REQUIRE(picture->getTexture().getId() == "resources/image.png"); REQUIRE(picture->getRenderer()->getTexture().getId() == "resources/image.png");
} }
SECTION("from sf::Texture") SECTION("from sf::Texture")
{ {
REQUIRE_NOTHROW(picture = tgui::Picture::create(texture)); REQUIRE_NOTHROW(picture = tgui::Picture::create(texture));
REQUIRE(picture->getTexture().getId() == ""); REQUIRE(picture->getRenderer()->getTexture().getId() == "");
} }
REQUIRE(picture->getSize() == sf::Vector2f(texture.getSize())); REQUIRE(picture->getSize() == sf::Vector2f(texture.getSize()));
@ -74,36 +74,6 @@ TEST_CASE("[Picture]")
REQUIRE(picture->getWidgetOffset() == sf::Vector2f(0, 0)); REQUIRE(picture->getWidgetOffset() == sf::Vector2f(0, 0));
} }
SECTION("setTexture")
{
picture->setSize(50, 50);
SECTION("from tgui::Texture")
{
REQUIRE_NOTHROW(picture->setTexture("resources/image.png"));
REQUIRE(picture->getTexture().getId() == "resources/image.png");
REQUIRE(picture->getSize() == sf::Vector2f(50, 50));
picture->setSize(100, 100);
REQUIRE_NOTHROW(picture->setTexture("resources/image.png"));
REQUIRE(picture->getSize() == sf::Vector2f(100, 100));
}
SECTION("from sf::Texture")
{
sf::Texture texture;
texture.loadFromFile("resources/image.png");
REQUIRE_NOTHROW(picture->setTexture(texture));
REQUIRE(picture->getTexture().getId() == "");
REQUIRE(picture->getSize() == sf::Vector2f(50, 50));
picture->setSize(100, 100);
REQUIRE_NOTHROW(picture->setTexture(texture));
REQUIRE(picture->getSize() == sf::Vector2f(100, 100));
}
}
SECTION("Events / Signals") SECTION("Events / Signals")
{ {
SECTION("ClickableWidget") SECTION("ClickableWidget")
@ -113,7 +83,7 @@ TEST_CASE("[Picture]")
SECTION("double click") SECTION("double click")
{ {
picture->setTexture("resources/image.png"); picture->getRenderer()->setTexture("resources/image.png");
picture->setPosition(40, 30); picture->setPosition(40, 30);
picture->setSize(150, 100); picture->setSize(150, 100);
@ -143,21 +113,31 @@ TEST_CASE("[Picture]")
{ {
auto renderer = picture->getRenderer(); auto renderer = picture->getRenderer();
tgui::Texture texture("resources/Texture1.png");
SECTION("set serialized property") SECTION("set serialized property")
{ {
REQUIRE_NOTHROW(renderer->setProperty("Texture", tgui::Serializer::serialize(texture)));
REQUIRE_NOTHROW(renderer->setProperty("IgnoreTransparentParts", "true"));
REQUIRE_NOTHROW(renderer->setProperty("Opacity", "0.8")); REQUIRE_NOTHROW(renderer->setProperty("Opacity", "0.8"));
} }
SECTION("set object property") SECTION("set object property")
{ {
REQUIRE_NOTHROW(renderer->setProperty("Texture", texture));
REQUIRE_NOTHROW(renderer->setProperty("IgnoreTransparentParts", true));
REQUIRE_NOTHROW(renderer->setProperty("Opacity", 0.8f)); REQUIRE_NOTHROW(renderer->setProperty("Opacity", 0.8f));
} }
SECTION("functions") SECTION("functions")
{ {
renderer->setTexture(texture);
renderer->setIgnoreTransparentParts(true);
renderer->setOpacity(0.8f); renderer->setOpacity(0.8f);
} }
REQUIRE(renderer->getTexture().getData() == texture.getData());
REQUIRE(renderer->getProperty("IgnoreTransparentParts").getBool());
REQUIRE(renderer->getProperty("Opacity").getNumber() == 0.8f); REQUIRE(renderer->getProperty("Opacity").getNumber() == 0.8f);
REQUIRE(renderer->getOpacity() == 0.8f); REQUIRE(renderer->getOpacity() == 0.8f);
@ -166,7 +146,7 @@ TEST_CASE("[Picture]")
SECTION("Saving and loading from file") SECTION("Saving and loading from file")
{ {
picture->setTexture("resources/image.png"); picture->getRenderer()->setTexture("resources/image.png");
picture->setSize(80, 60); picture->setSize(80, 60);
testSavingWidget("Picture", picture, false); testSavingWidget("Picture", picture, false);
@ -176,7 +156,9 @@ TEST_CASE("[Picture]")
{ {
TEST_DRAW_INIT(60, 40, picture) TEST_DRAW_INIT(60, 40, picture)
picture->setTexture("resources/image.png"); picture->getRenderer()->setTexture("resources/image.png");
picture->getRenderer()->setIgnoreTransparentParts(true);
picture->setPosition(10, 5); picture->setPosition(10, 5);
picture->setSize(40, 30); picture->setSize(40, 30);