From 5e48605e32ff66dd36c570df75afe6a5a1ce71c6 Mon Sep 17 00:00:00 2001 From: Bruno Van de Velde Date: Thu, 7 Sep 2017 15:38:35 +0200 Subject: [PATCH] Support android again (tested with NDK 12b) --- CMakeLists.txt | 34 +++--- examples/android/jni/Application.mk | 2 +- include/TGUI/Config.hpp | 22 ++++ include/TGUI/Global.hpp | 16 +++ include/TGUI/Signal.hpp | 162 ++++++++++++++++++++++++++- src/TGUI/Layout.cpp | 46 ++++---- src/TGUI/Loading/DataIO.cpp | 6 +- src/TGUI/Loading/Serializer.cpp | 4 +- src/TGUI/Loading/WidgetSaver.cpp | 32 +++--- src/TGUI/Signal.cpp | 163 +++++++++++++++++++++++++--- src/TGUI/Sprite.cpp | 2 +- src/TGUI/Texture.cpp | 2 +- src/TGUI/Widgets/Label.cpp | 2 +- src/TGUI/Widgets/Tabs.cpp | 2 +- 14 files changed, 404 insertions(+), 91 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 541e4dbc..b8f610b7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,17 @@ macro(tgui_add_cxx_flag flag) endif() endmacro() +macro(tgui_remove_cxx_flag flagToRemove) + string(REPLACE " " ";" TGUI_CXX_FLAGS_LIST ${CMAKE_CXX_FLAGS}) + set(TGUI_TEMP_CXX_FLAGS "") + foreach (flag ${TGUI_CXX_FLAGS_LIST}) + if (NOT (${flag} STREQUAL "${flagToRemove}")) + set(TGUI_TEMP_CXX_FLAGS "${TGUI_TEMP_CXX_FLAGS} ${flag}") + endif() + endforeach(flag) + set(CMAKE_CXX_FLAGS "${TGUI_TEMP_CXX_FLAGS}") +endmacro() + # Set a default build type and module path if none was provided tgui_set_option(CMAKE_BUILD_TYPE Release STRING "Choose the type of build (Debug or Release)") tgui_set_option(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules" STRING "The path to the cmake modules. This path must contain the FindSFML.cmake file.") @@ -76,27 +87,12 @@ tgui_set_option(TGUI_OPENGL_ES ${OPENGL_ES} BOOL "TRUE to use an OpenGL ES imple # Set compile flags for gcc and clang if (SFML_OS_ANDROID) - # Remove "-fno-exceptions" from the CMAKE_CXX_FLAGS - string(REPLACE " " ";" TGUI_CXX_FLAGS_LIST ${CMAKE_CXX_FLAGS}) - set(TGUI_TEMP_CXX_FLAGS "") - foreach (flag ${TGUI_CXX_FLAGS_LIST}) - if (NOT (${flag} STREQUAL "-fno-exceptions")) - set(TGUI_TEMP_CXX_FLAGS "${TGUI_TEMP_CXX_FLAGS} ${flag}") - endif() - endforeach(flag) + tgui_remove_cxx_flag(-fno-exceptions) + tgui_remove_cxx_flag(-fno-rtti) - # Remove "-fno-rtti" from the CMAKE_CXX_FLAGS - string(REPLACE " " ";" TGUI_CXX_FLAGS_LIST ${TGUI_TEMP_CXX_FLAGS}) - set(TGUI_TEMP_CXX_FLAGS "") - foreach (flag ${TGUI_CXX_FLAGS_LIST}) - if (NOT (${flag} STREQUAL "-fno-rtti")) - set(TGUI_TEMP_CXX_FLAGS "${TGUI_TEMP_CXX_FLAGS} ${flag}") - endif() - endforeach(flag) + # TGUI was only successfully tested on Android with NDK 12b, which did not work when -std=c++1y (or -std=c++14) is defined + tgui_add_cxx_flag(-std=c++11) - set(CMAKE_CXX_FLAGS "${TGUI_TEMP_CXX_FLAGS}") - - tgui_add_cxx_flag(-std=c++1y) tgui_add_cxx_flag(-fexceptions) tgui_add_cxx_flag(-frtti) diff --git a/examples/android/jni/Application.mk b/examples/android/jni/Application.mk index 8d795df7..ce664a9e 100644 --- a/examples/android/jni/Application.mk +++ b/examples/android/jni/Application.mk @@ -1,4 +1,4 @@ -NDK_TOOLCHAIN_VERSION := 4.8 +NDK_TOOLCHAIN_VERSION := 4.9 APP_PLATFORM := android-9 APP_STL := c++_shared APP_ABI := armeabi-v7a diff --git a/include/TGUI/Config.hpp b/include/TGUI/Config.hpp index de58e110..cb9fd7c6 100644 --- a/include/TGUI/Config.hpp +++ b/include/TGUI/Config.hpp @@ -70,6 +70,28 @@ #define TGUI_VERSION_MINOR 8 #define TGUI_VERSION_PATCH 0 +// Disable c++14 code when using -std=c++11, which is needed for android when using NDK 12b. +// This technically results in undefined behavior because the std::function ambiguity was only fixed in c++14 (http://cplusplus.github.io/LWG/lwg-defects.html#2132). +// TGUI relies on a fix for LWG 2132 to be implemented, even when compiling with -std=c++11 (which is the case in supported gcc and clang compilers). +// The TGUI_NO_CPP14 macro thus does not provide support for all compilers with c++11 support, it just allows some compilers to work even with -std=c++11. +#ifndef _MSC_VER + #if __cplusplus <= 201103L + #define TGUI_NO_CPP14 + #endif +#endif + +// The signal system detects whether it can provide unbound parameters by checking the arguments of the function at runtime. +// This comparion is made by checking the typeid of the parameters with the typeid of the value which the widget can transmit. +// Although typeid returns a unique value and the operator== is guarenteed to only be true for the same type, it may not always work correctly. +// Dynamically linked libraries may have a different type_info internally than in the code using the library. In such case the comparison will always be false. +// This behavior has so far only been seen on android (using NDK 12b), so the alternative is currently only used when compiling on android. +// The alternative that is used on android is to compare the strings returned by type_info.name(). This is however considered undefined behavior since the compiler +// is not guarenteed to have unique names for different types. The names will however be the same inside and outside the library so this method solves the issue. +// I am also not aware of any supported compiler that does not create unique names. +#ifdef __ANDROID__ + #define TGUI_UNSAFE_TYPE_INFO_COMPARISON +#endif + // Enable constexpr when using Clang or at least GCC 5 or MSVC++ 14.1 (VS2017) #if _MSC_VER #if _MSC_VER >= 1910 diff --git a/include/TGUI/Global.hpp b/include/TGUI/Global.hpp index 52543614..c8fc46d2 100644 --- a/include/TGUI/Global.hpp +++ b/include/TGUI/Global.hpp @@ -31,6 +31,22 @@ #include #include #include +#include + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef TGUI_NO_CPP14 + namespace tgui + { + template + std::unique_ptr make_unique(Args&&... args) + { + return std::unique_ptr(new T(std::forward(args)...)); + } + } +#else + using std::make_unique; +#endif ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/include/TGUI/Signal.hpp b/include/TGUI/Signal.hpp index ca5be74d..7df1d282 100644 --- a/include/TGUI/Signal.hpp +++ b/include/TGUI/Signal.hpp @@ -569,6 +569,111 @@ namespace tgui namespace internal_signal { + // make_integer_sequence implementation taken from https://gist.github.com/jappa/62f30b6da5adea60bad3 + #ifdef TGUI_NO_CPP14 + template + struct integer_sequence + { + typedef Type value_type; + static std::size_t size() + { + return sizeof...(Indices); + } + }; + + template + using index_sequence = integer_sequence; + + namespace integer_sequence_detail + { + template + struct repeat; + + template + struct repeat, _Extra...> + { + typedef integer_sequence type; + }; + + template struct parity; + template struct make:parity::template pmake {}; + + template <> struct make<0> { typedef integer_sequence type; }; + template <> struct make<1> { typedef integer_sequence type; }; + template <> struct make<2> { typedef integer_sequence type; }; + template <> struct make<3> { typedef integer_sequence type; }; + template <> struct make<4> { typedef integer_sequence type; }; + template <> struct make<5> { typedef integer_sequence type; }; + template <> struct make<6> { typedef integer_sequence type; }; + template <> struct make<7> { typedef integer_sequence type; }; + + template <> struct parity<0> { template struct pmake:repeat::type> {}; }; + template <> struct parity<1> { template struct pmake:repeat::type, N - 1> {}; }; + template <> struct parity<2> { template struct pmake:repeat::type, N - 2, N - 1> {}; }; + template <> struct parity<3> { template struct pmake:repeat::type, N - 3, N - 2, N - 1> {}; }; + template <> struct parity<4> { template struct pmake:repeat::type, N - 4, N - 3, N - 2, N - 1> {}; }; + template <> struct parity<5> { template struct pmake:repeat::type, N - 5, N - 4, N - 3, N - 2, N - 1> {}; }; + template <> struct parity<6> { template struct pmake:repeat::type, N - 6, N - 5, N - 4, N - 3, N - 2, N - 1> {}; }; + template <> struct parity<7> { template struct pmake:repeat::type, N - 7, N - 6, N - 5, N - 4, N - 3, N - 2, N - 1> {}; }; + + template + struct convert + { + template + struct result; + + template + struct result > + { + typedef integer_sequence type; + }; + }; + + template + struct convert + { + template + struct result + { + typedef U type; + }; + }; + + template + using make_integer_sequence_unchecked = typename convert::template result::type>::type; + + template + struct make_integer_sequence + { + static_assert(std::is_integral::value, + "std::make_integer_sequence can only be instantiated with an integral type"); + static_assert(0 <= N,"std::make_integer_sequence input shall not be negative"); + + typedef make_integer_sequence_unchecked type; + }; + } + + template + using make_integer_sequence = typename integer_sequence_detail::make_integer_sequence::type; + + template + using make_index_sequence = make_integer_sequence; + + template + using index_sequence_for = make_index_sequence; + #else + using std::index_sequence; + using std::index_sequence_for; + #endif + // void_t only exists in c++17 so we use our own implementation to support c++14 compilers template using void_t = void; @@ -583,16 +688,24 @@ namespace tgui // The dereference function turns the void* elements in the parameters list back into its original type right before calling the signal handler template ::value>::type* = nullptr> + #ifdef TGUI_NO_CPP14 + std::string dereference(const void* obj) + #else decltype(auto) dereference(const void* obj) + #endif { // Signal handlers are allowed to have std::string parameters while the signal sends sf::String return static_cast(*static_cast(obj)); } template ::value>::type* = nullptr> + #ifdef TGUI_NO_CPP14 + const Type& dereference(const void* obj) + #else decltype(auto) dereference(const void* obj) + #endif { - return *static_cast(obj); + return *static_cast::type*>(obj); } // std::invoke only exists in c++17 so we use our own implementation to support c++14 compilers @@ -623,18 +736,31 @@ namespace tgui struct binder, std::string, UnboundArgs...>, TypeSet<>> { template + #ifdef TGUI_NO_CPP14 + static std::function& widget, const std::string& signalName)> bind(Signal& signal, Func&& func, BoundArgs&&... args) + #else static decltype(auto) bind(Signal& signal, Func&& func, BoundArgs&&... args) + #endif { - return bindImpl(std::index_sequence_for{}, signal, std::forward(func), std::forward(args)...); + return bindImpl(index_sequence_for{}, signal, std::forward(func), std::forward(args)...); } private: template - static decltype(auto) bindImpl(std::index_sequence, Signal& signal, Func&& func, BoundArgs&&... args) + #ifdef TGUI_NO_CPP14 + static std::function& widget, const std::string& signalName)> bindImpl(index_sequence, Signal& signal, Func&& func, BoundArgs&&... args) + #else + static decltype(auto) bindImpl(index_sequence, Signal& signal, Func&& func, BoundArgs&&... args) + #endif { const std::size_t offset = (sizeof...(UnboundArgs) > 0) ? signal.validateTypes({typeid(UnboundArgs)...}) : 0; + #ifdef TGUI_NO_CPP14 + return [=](const std::shared_ptr& widget, const std::string& signalName) { + auto f = func; + #else return [=, f=func](const std::shared_ptr& widget, const std::string& signalName) { // f=func is needed to decay free functions + #endif invokeFunc(f, args..., widget, @@ -648,18 +774,31 @@ namespace tgui struct binder, TypeSet<>> { template + #ifdef TGUI_NO_CPP14 + static std::function bind(Signal& signal, Func&& func, BoundArgs&&... args) + #else static decltype(auto) bind(Signal& signal, Func&& func, BoundArgs&&... args) + #endif { - return bindImpl(std::index_sequence_for{}, signal, std::forward(func), std::forward(args)...); + return bindImpl(index_sequence_for{}, signal, std::forward(func), std::forward(args)...); } private: template - static decltype(auto) bindImpl(std::index_sequence, Signal& signal, Func&& func, BoundArgs&&... args) + #ifdef TGUI_NO_CPP14 + static std::function bindImpl(index_sequence, Signal& signal, Func&& func, BoundArgs&&... args) + #else + static decltype(auto) bindImpl(index_sequence, Signal& signal, Func&& func, BoundArgs&&... args) + #endif { const std::size_t offset = (sizeof...(UnboundArgs) > 0) ? signal.validateTypes({typeid(UnboundArgs)...}) : 0; + #ifdef TGUI_NO_CPP14 + return [=]() { + auto f = func; + #else return [=, f=func]() { // f=func is needed to decay free functions + #endif invokeFunc(f, args..., internal_signal::dereference(internal_signal::parameters[offset + Indices])...); @@ -721,7 +860,11 @@ namespace tgui template >::value>::type* = nullptr> unsigned int connect(std::string signalName, Func&& handler, const Args&... args) { + #ifdef TGUI_NO_CPP14 + const unsigned int id = getSignal(toLower(signalName)).connect([=](){ (std::function(handler))(args...); }); + #else const unsigned int id = getSignal(toLower(signalName)).connect([f=std::function(handler),args...](){ f(args...); }); + #endif m_connectedSignals[id] = toLower(signalName); return id; } @@ -740,11 +883,20 @@ namespace tgui template , const std::string&)>>::value>::type* = nullptr> unsigned int connect(std::string signalName, Func&& handler, BoundArgs&&... args) { + #ifdef TGUI_NO_CPP14 + const unsigned int id = getSignal(toLower(signalName)).connect( + [=](const std::shared_ptr& w, const std::string& s) { + (std::function&, const std::string&)>(handler))(args..., w, s); + } + ); + #else const unsigned int id = getSignal(toLower(signalName)).connect( [f=std::function&, const std::string&)>(handler), args...] (const std::shared_ptr& w, const std::string& s) { f(args..., w, s); } ); + #endif + m_connectedSignals[id] = toLower(signalName); return id; } diff --git a/src/TGUI/Layout.cpp b/src/TGUI/Layout.cpp index 0ed0a99e..7a19fe90 100644 --- a/src/TGUI/Layout.cpp +++ b/src/TGUI/Layout.cpp @@ -53,8 +53,8 @@ namespace tgui { // We don't know if we have to bind the width or height, so bind "size" and let the connectWidget function figure it out later *this = Layout{Layout::Operation::Multiplies, - std::make_unique(tgui::stof(expression.substr(0, expression.length()-1)) / 100.f), - std::make_unique("&.size")}; + make_unique(tgui::stof(expression.substr(0, expression.length()-1)) / 100.f), + make_unique("&.size")}; } else { @@ -79,14 +79,14 @@ namespace tgui else if (expression.size() >= 5 && expression.substr(expression.size()-5) == "right") { *this = Layout{Operation::Plus, - std::make_unique(expression.substr(0, expression.size()-5) + "left"), - std::make_unique(expression.substr(0, expression.size()-5) + "width")}; + make_unique(expression.substr(0, expression.size()-5) + "left"), + make_unique(expression.substr(0, expression.size()-5) + "width")}; } else if (expression.size() >= 6 && expression.substr(expression.size()-6) == "bottom") { *this = Layout{Operation::Plus, - std::make_unique(expression.substr(0, expression.size()-6) + "top"), - std::make_unique(expression.substr(0, expression.size()-6) + "height")}; + make_unique(expression.substr(0, expression.size()-6) + "top"), + make_unique(expression.substr(0, expression.size()-6) + "height")}; } else // Constant value m_value = tgui::stof(expression); @@ -180,8 +180,8 @@ namespace tgui std::advance(nextOperandIt, 1); (*operandIt) = Layout{operators[i], - std::make_unique(*operandIt), - std::make_unique(*nextOperandIt)}; + make_unique(*operandIt), + make_unique(*nextOperandIt)}; operands.erase(nextOperandIt); } @@ -203,8 +203,8 @@ namespace tgui assert(nextOperandIt != operands.end()); (*operandIt) = Layout{operators[i], - std::make_unique(*operandIt), - std::make_unique(*nextOperandIt)}; + make_unique(*operandIt), + make_unique(*nextOperandIt)}; operands.erase(nextOperandIt); } @@ -255,8 +255,8 @@ namespace tgui m_value {other.m_value}, m_parent {other.m_parent}, m_operation {other.m_operation}, - m_leftOperand {other.m_leftOperand ? std::make_unique(*other.m_leftOperand) : nullptr}, - m_rightOperand {other.m_rightOperand ? std::make_unique(*other.m_rightOperand) : nullptr}, + m_leftOperand {other.m_leftOperand ? make_unique(*other.m_leftOperand) : nullptr}, + m_rightOperand {other.m_rightOperand ? make_unique(*other.m_rightOperand) : nullptr}, m_boundWidget {other.m_boundWidget}, m_boundString {other.m_boundString}, m_connectedWidget{nullptr} @@ -292,8 +292,8 @@ namespace tgui m_value = other.m_value; m_parent = other.m_parent; m_operation = other.m_operation; - m_leftOperand = other.m_leftOperand ? std::make_unique(*other.m_leftOperand) : nullptr; - m_rightOperand = other.m_rightOperand ? std::make_unique(*other.m_rightOperand) : nullptr; + m_leftOperand = other.m_leftOperand ? make_unique(*other.m_leftOperand) : nullptr; + m_rightOperand = other.m_rightOperand ? make_unique(*other.m_rightOperand) : nullptr; m_boundWidget = other.m_boundWidget; m_boundString = other.m_boundString; m_connectedWidget = nullptr; @@ -583,35 +583,35 @@ namespace tgui Layout operator-(Layout right) { - return Layout{Layout::Operation::Minus, std::make_unique(), std::make_unique(std::move(right))}; + return Layout{Layout::Operation::Minus, make_unique(), make_unique(std::move(right))}; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Layout operator+(Layout left, Layout right) { - return Layout{Layout::Operation::Plus, std::make_unique(std::move(left)), std::make_unique(std::move(right))}; + return Layout{Layout::Operation::Plus, make_unique(std::move(left)), make_unique(std::move(right))}; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Layout operator-(Layout left, Layout right) { - return Layout{Layout::Operation::Minus, std::make_unique(std::move(left)), std::make_unique(std::move(right))}; + return Layout{Layout::Operation::Minus, make_unique(std::move(left)), make_unique(std::move(right))}; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Layout operator*(Layout left, Layout right) { - return Layout{Layout::Operation::Multiplies, std::make_unique(std::move(left)), std::make_unique(std::move(right))}; + return Layout{Layout::Operation::Multiplies, make_unique(std::move(left)), make_unique(std::move(right))}; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Layout operator/(Layout left, Layout right) { - return Layout{Layout::Operation::Divides, std::make_unique(std::move(left)), std::make_unique(std::move(right))}; + return Layout{Layout::Operation::Divides, make_unique(std::move(left)), make_unique(std::move(right))}; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -694,8 +694,8 @@ namespace tgui Layout bindRight(Widget::Ptr widget) { return Layout{Layout::Operation::Plus, - std::make_unique(Layout::Operation::BindingLeft, widget.get()), - std::make_unique(Layout::Operation::BindingWidth, widget.get())}; + make_unique(Layout::Operation::BindingLeft, widget.get()), + make_unique(Layout::Operation::BindingWidth, widget.get())}; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -703,8 +703,8 @@ namespace tgui Layout bindBottom(Widget::Ptr widget) { return Layout{Layout::Operation::Plus, - std::make_unique(Layout::Operation::BindingTop, widget.get()), - std::make_unique(Layout::Operation::BindingHeight, widget.get())}; + make_unique(Layout::Operation::BindingTop, widget.get()), + make_unique(Layout::Operation::BindingHeight, widget.get())}; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/TGUI/Loading/DataIO.cpp b/src/TGUI/Loading/DataIO.cpp index 909b4b47..43ce5961 100644 --- a/src/TGUI/Loading/DataIO.cpp +++ b/src/TGUI/Loading/DataIO.cpp @@ -287,7 +287,7 @@ namespace tgui stream.read(&chr, 1); // Create a value node to store the value - auto valueNode = std::make_unique(); + auto valueNode = make_unique(); valueNode->value = line; // It might be a list node @@ -367,7 +367,7 @@ namespace tgui std::string parseSection(std::stringstream& stream, const std::unique_ptr& node, const std::string& sectionName) { // Create a new node for this section - auto sectionNode = std::make_unique(); + auto sectionNode = make_unique(); sectionNode->parent = node.get(); sectionNode->name = sectionName; @@ -487,7 +487,7 @@ namespace tgui std::unique_ptr DataIO::parse(std::stringstream& stream) { - auto root = std::make_unique(); + auto root = make_unique(); std::string error; while (stream.peek() != EOF) diff --git a/src/TGUI/Loading/Serializer.cpp b/src/TGUI/Loading/Serializer.cpp index f441f477..4e06da05 100644 --- a/src/TGUI/Loading/Serializer.cpp +++ b/src/TGUI/Loading/Serializer.cpp @@ -220,7 +220,7 @@ namespace tgui std::string serializeRendererData(ObjectConverter&& value) { - auto node = std::make_unique(); + auto node = make_unique(); for (const auto& pair : value.getRenderer()->propertyValuePairs) { sf::String strValue; @@ -233,7 +233,7 @@ namespace tgui else { strValue = ObjectConverter{pair.second}.getString(); - node->propertyValuePairs[pair.first] = std::make_unique(strValue); + node->propertyValuePairs[pair.first] = make_unique(strValue); } } diff --git a/src/TGUI/Loading/WidgetSaver.cpp b/src/TGUI/Loading/WidgetSaver.cpp index 77b341ab..c39632b4 100644 --- a/src/TGUI/Loading/WidgetSaver.cpp +++ b/src/TGUI/Loading/WidgetSaver.cpp @@ -57,7 +57,7 @@ namespace tgui namespace { - #define SET_PROPERTY(property, value) node->propertyValuePairs[property] = std::make_unique(value) + #define SET_PROPERTY(property, value) node->propertyValuePairs[property] = make_unique(value) ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -67,7 +67,7 @@ namespace tgui if (widget->getParent()) widgetName = widget->getParent()->getWidgetName(widget); - auto node = std::make_unique(); + auto node = make_unique(); if (widgetName.isEmpty()) node->name = widget->getWidgetType(); else @@ -86,12 +86,12 @@ namespace tgui { auto toolTipWidgetNode = WidgetSaver::getSaveFunction("widget")(widget->getToolTip()); - auto toolTipNode = std::make_unique(); + auto toolTipNode = make_unique(); toolTipNode->name = "ToolTip"; toolTipNode->children.emplace_back(std::move(toolTipWidgetNode)); - toolTipNode->propertyValuePairs["TimeToDisplay"] = std::make_unique(to_string(ToolTip::getTimeToDisplay().asSeconds())); - toolTipNode->propertyValuePairs["DistanceToMouse"] = std::make_unique("(" + to_string(ToolTip::getDistanceToMouse().x) + "," + to_string(ToolTip::getDistanceToMouse().y) + ")"); + toolTipNode->propertyValuePairs["TimeToDisplay"] = make_unique(to_string(ToolTip::getTimeToDisplay().asSeconds())); + toolTipNode->propertyValuePairs["DistanceToMouse"] = make_unique("(" + to_string(ToolTip::getDistanceToMouse().x) + "," + to_string(ToolTip::getDistanceToMouse().y) + ")"); node->children.emplace_back(std::move(toolTipNode)); } @@ -99,7 +99,7 @@ namespace tgui /// TODO: Separate renderer section? if (!widget->getRenderer()->getPropertyValuePairs().empty()) { - node->children.emplace_back(std::make_unique()); + node->children.emplace_back(make_unique()); node->children.back()->name = "Renderer"; for (const auto& pair : widget->getRenderer()->getPropertyValuePairs()) { @@ -120,7 +120,7 @@ namespace tgui node->children.back()->children.back()->name = pair.first; } else - node->children.back()->propertyValuePairs[pair.first] = std::make_unique(value); + node->children.back()->propertyValuePairs[pair.first] = make_unique(value); } } @@ -188,15 +188,15 @@ namespace tgui unsigned int lineTextSize = chatBox->getLineTextSize(i); sf::Color lineTextColor = chatBox->getLineColor(i); - auto lineNode = std::make_unique(); + auto lineNode = make_unique(); lineNode->parent = node.get(); lineNode->name = "Line"; - lineNode->propertyValuePairs["Text"] = std::make_unique(Serializer::serialize(chatBox->getLine(i))); + lineNode->propertyValuePairs["Text"] = make_unique(Serializer::serialize(chatBox->getLine(i))); if (lineTextSize != chatBox->getTextSize()) - lineNode->propertyValuePairs["TextSize"] = std::make_unique(to_string(lineTextSize)); + lineNode->propertyValuePairs["TextSize"] = make_unique(to_string(lineTextSize)); if (lineTextColor != chatBox->getTextColor()) - lineNode->propertyValuePairs["Color"] = std::make_unique(Serializer::serialize(lineTextColor)); + lineNode->propertyValuePairs["Color"] = make_unique(Serializer::serialize(lineTextColor)); node->children.push_back(std::move(lineNode)); } @@ -362,7 +362,7 @@ namespace tgui } }; - auto getWidgetsInGridString = [&](const auto& w) -> std::string { + auto getWidgetsInGridString = [&](const tgui::Widget::Ptr& w) -> std::string { auto it = widgetsMap.find(w); if (it != widgetsMap.end()) { @@ -491,11 +491,11 @@ namespace tgui std::map> menus = menuBar->getMenus(); for (const auto& menu : menus) { - auto menuNode = std::make_unique(); + auto menuNode = make_unique(); menuNode->parent = node.get(); menuNode->name = "Menu"; - menuNode->propertyValuePairs["Name"] = std::make_unique(Serializer::serialize(menu.first)); + menuNode->propertyValuePairs["Name"] = make_unique(Serializer::serialize(menu.first)); const auto& items = menu.second; if (!items.empty()) @@ -505,7 +505,7 @@ namespace tgui itemList += ", " + Serializer::serialize(items[i]); itemList += "]"; - menuNode->propertyValuePairs["Items"] = std::make_unique(itemList); + menuNode->propertyValuePairs["Items"] = make_unique(itemList); } node->children.push_back(std::move(menuNode)); @@ -762,7 +762,7 @@ namespace tgui void WidgetSaver::save(Container::ConstPtr widget, std::stringstream& stream) { - auto node = std::make_unique(); + auto node = make_unique(); for (const auto& child : widget->getWidgets()) { auto& saveFunction = WidgetSaver::getSaveFunction(toLower(child->getWidgetType())); diff --git a/src/TGUI/Signal.cpp b/src/TGUI/Signal.cpp index 144d5a14..4d042989 100644 --- a/src/TGUI/Signal.cpp +++ b/src/TGUI/Signal.cpp @@ -84,7 +84,12 @@ namespace tgui unsigned int Signal::connect(const DelegateEx& handler) { const auto id = generateUniqueId(); + #ifdef TGUI_NO_CPP14 + std::string name = m_name; + m_handlers[id] = [handler, name](){ handler(getWidget(), name); }; + #else m_handlers[id] = [handler, name=m_name](){ handler(getWidget(), name); }; + #endif return id; } @@ -121,6 +126,23 @@ namespace tgui ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#ifdef TGUI_NO_CPP14 + #define TGUI_SIGNAL_VALUE_CONNECT_DEFINITION(TypeName, Type) \ + unsigned int Signal##TypeName::connect(const Delegate##TypeName& handler) \ + { \ + const auto id = generateUniqueId(); \ + m_handlers[id] = [handler](){ handler(internal_signal::dereference(internal_signal::parameters[1])); }; \ + return id; \ + } \ + \ + unsigned int Signal##TypeName::connect(const Delegate##TypeName##Ex& handler) \ + { \ + const auto id = generateUniqueId(); \ + std::string name = m_name; \ + m_handlers[id] = [handler, name](){ handler(getWidget(), name, internal_signal::dereference(internal_signal::parameters[1])); }; \ + return id; \ + } +#else #define TGUI_SIGNAL_VALUE_CONNECT_DEFINITION(TypeName, Type) \ unsigned int Signal##TypeName::connect(const Delegate##TypeName& handler) \ { \ @@ -134,45 +156,95 @@ namespace tgui const auto id = generateUniqueId(); \ m_handlers[id] = [handler, name=m_name](){ handler(getWidget(), name, internal_signal::dereference(internal_signal::parameters[1])); }; \ return id; \ - } \ - \ - unsigned int Signal##TypeName::validateTypes(std::initializer_list unboundParameters) \ - { \ - if ((unboundParameters.size() == 1) && (*unboundParameters.begin() == typeid(Type))) \ - return 1; \ - else \ - return Signal::validateTypes(unboundParameters); \ } +#endif TGUI_SIGNAL_VALUE_CONNECT_DEFINITION(Int, int) TGUI_SIGNAL_VALUE_CONNECT_DEFINITION(UInt, unsigned int) TGUI_SIGNAL_VALUE_CONNECT_DEFINITION(Bool, bool) TGUI_SIGNAL_VALUE_CONNECT_DEFINITION(Float, float) + TGUI_SIGNAL_VALUE_CONNECT_DEFINITION(String, const sf::String&) TGUI_SIGNAL_VALUE_CONNECT_DEFINITION(Vector2f, sf::Vector2f) - ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - unsigned int SignalString::connect(const DelegateString& handler) + unsigned int SignalInt::validateTypes(std::initializer_list unboundParameters) { - const auto id = generateUniqueId(); - m_handlers[id] = [handler](){ handler(internal_signal::dereference(internal_signal::parameters[1])); }; - return id; + #ifdef TGUI_UNSAFE_TYPE_INFO_COMPARISON + if ((unboundParameters.size() == 1) && (strcmp(unboundParameters.begin()->name(), typeid(int).name()) == 0)) + #else + if ((unboundParameters.size() == 1) && (*unboundParameters.begin() == typeid(int))) + #endif + return 1; + else + return Signal::validateTypes(unboundParameters); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - unsigned int SignalString::connect(const DelegateStringEx& handler) + unsigned int SignalUInt::validateTypes(std::initializer_list unboundParameters) { - const auto id = generateUniqueId(); - m_handlers[id] = [handler, name=m_name](){ handler(getWidget(), name, internal_signal::dereference(internal_signal::parameters[1])); }; - return id; + #ifdef TGUI_UNSAFE_TYPE_INFO_COMPARISON + if ((unboundParameters.size() == 1) && (strcmp(unboundParameters.begin()->name(), typeid(unsigned int).name()) == 0)) + #else + if ((unboundParameters.size() == 1) && (*unboundParameters.begin() == typeid(unsigned int))) + #endif + return 1; + else + return Signal::validateTypes(unboundParameters); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + unsigned int SignalBool::validateTypes(std::initializer_list unboundParameters) + { + #ifdef TGUI_UNSAFE_TYPE_INFO_COMPARISON + if ((unboundParameters.size() == 1) && (strcmp(unboundParameters.begin()->name(), typeid(bool).name()) == 0)) + #else + if ((unboundParameters.size() == 1) && (*unboundParameters.begin() == typeid(bool))) + #endif + return 1; + else + return Signal::validateTypes(unboundParameters); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + unsigned int SignalFloat::validateTypes(std::initializer_list unboundParameters) + { + #ifdef TGUI_UNSAFE_TYPE_INFO_COMPARISON + if ((unboundParameters.size() == 1) && (strcmp(unboundParameters.begin()->name(), typeid(float).name()) == 0)) + #else + if ((unboundParameters.size() == 1) && (*unboundParameters.begin() == typeid(float))) + #endif + return 1; + else + return Signal::validateTypes(unboundParameters); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// unsigned int SignalString::validateTypes(std::initializer_list unboundParameters) { + #ifdef TGUI_UNSAFE_TYPE_INFO_COMPARISON + if ((unboundParameters.size() == 1) && ((strcmp(unboundParameters.begin()->name(), typeid(std::string).name()) == 0) || (strcmp(unboundParameters.begin()->name(), typeid(sf::String).name()) == 0))) + #else if ((unboundParameters.size() == 1) && ((*unboundParameters.begin() == typeid(std::string)) || (*unboundParameters.begin() == typeid(sf::String)))) + #endif + return 1; + else + return Signal::validateTypes(unboundParameters); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + unsigned int SignalVector2f::validateTypes(std::initializer_list unboundParameters) + { + #ifdef TGUI_UNSAFE_TYPE_INFO_COMPARISON + if ((unboundParameters.size() == 1) && (strcmp(unboundParameters.begin()->name(), typeid(sf::Vector2f).name()) == 0)) + #else + if ((unboundParameters.size() == 1) && (*unboundParameters.begin() == typeid(sf::Vector2f))) + #endif return 1; else return Signal::validateTypes(unboundParameters); @@ -192,7 +264,12 @@ namespace tgui unsigned int SignalRange::connect(const DelegateRangeEx& handler) { const auto id = generateUniqueId(); + #ifdef TGUI_NO_CPP14 + std::string name = m_name; + m_handlers[id] = [handler, name](){ handler(getWidget(), name, internal_signal::dereference(internal_signal::parameters[1]), internal_signal::dereference(internal_signal::parameters[2])); }; + #else m_handlers[id] = [handler, name=m_name](){ handler(getWidget(), name, internal_signal::dereference(internal_signal::parameters[1]), internal_signal::dereference(internal_signal::parameters[2])); }; + #endif return id; } @@ -212,7 +289,11 @@ namespace tgui unsigned int SignalRange::validateTypes(std::initializer_list unboundParameters) { + #ifdef TGUI_UNSAFE_TYPE_INFO_COMPARISON + if ((unboundParameters.size() == 2) && (strcmp(unboundParameters.begin()->name(), typeid(int).name()) == 0) && (strcmp((unboundParameters.begin()+1)->name(), typeid(int).name()) == 0)) + #else if ((unboundParameters.size() == 2) && (*unboundParameters.begin() == typeid(int)) && (*(unboundParameters.begin()+1) == typeid(int))) + #endif return 1; else return Signal::validateTypes(unboundParameters); @@ -232,7 +313,12 @@ namespace tgui unsigned int SignalChildWindow::connect(const DelegateChildWindowEx& handler) { const auto id = generateUniqueId(); + #ifdef TGUI_NO_CPP14 + std::string name = m_name; + m_handlers[id] = [handler, name](){ handler(getWidget(), name, std::static_pointer_cast(internal_signal::dereference(internal_signal::parameters[1])->shared_from_this())); }; + #else m_handlers[id] = [handler, name=m_name](){ handler(getWidget(), name, std::static_pointer_cast(internal_signal::dereference(internal_signal::parameters[1])->shared_from_this())); }; + #endif return id; } @@ -251,7 +337,11 @@ namespace tgui unsigned int SignalChildWindow::validateTypes(std::initializer_list unboundParameters) { - if ((unboundParameters.size() == 1) && (*unboundParameters.begin() == typeid(tgui::ChildWindow::Ptr))) + #ifdef TGUI_UNSAFE_TYPE_INFO_COMPARISON + if ((unboundParameters.size() == 1) && (strcmp(unboundParameters.begin()->name(), typeid(ChildWindow::Ptr).name()) == 0)) + #else + if ((unboundParameters.size() == 1) && (*unboundParameters.begin() == typeid(ChildWindow::Ptr))) + #endif return 1; else return Signal::validateTypes(unboundParameters); @@ -271,7 +361,12 @@ namespace tgui unsigned int SignalItem::connect(const DelegateItemEx& handler) { const auto id = generateUniqueId(); + #ifdef TGUI_NO_CPP14 + std::string name = m_name; + m_handlers[id] = [handler, name](){ handler(getWidget(), name, internal_signal::dereference(internal_signal::parameters[1])); }; + #else m_handlers[id] = [handler, name=m_name](){ handler(getWidget(), name, internal_signal::dereference(internal_signal::parameters[1])); }; + #endif return id; } @@ -289,7 +384,12 @@ namespace tgui unsigned int SignalItem::connect(const DelegateItemAndIdEx& handler) { const auto id = generateUniqueId(); + #ifdef TGUI_NO_CPP14 + std::string name = m_name; + m_handlers[id] = [handler, name](){ handler(getWidget(), name, internal_signal::dereference(internal_signal::parameters[1]), internal_signal::dereference(internal_signal::parameters[2])); }; + #else m_handlers[id] = [handler, name=m_name](){ handler(getWidget(), name, internal_signal::dereference(internal_signal::parameters[1]), internal_signal::dereference(internal_signal::parameters[2])); }; + #endif return id; } @@ -297,11 +397,20 @@ namespace tgui unsigned int SignalItem::validateTypes(std::initializer_list unboundParameters) { + #ifdef TGUI_UNSAFE_TYPE_INFO_COMPARISON + if ((unboundParameters.size() == 1) && ((strcmp(unboundParameters.begin()->name(), typeid(std::string).name()) == 0) || (strcmp(unboundParameters.begin()->name(), typeid(sf::String).name()) == 0))) + #else if ((unboundParameters.size() == 1) && ((*unboundParameters.begin() == typeid(std::string)) || (*unboundParameters.begin() == typeid(sf::String)))) + #endif return 1; else if ((unboundParameters.size() == 2) + #ifdef TGUI_UNSAFE_TYPE_INFO_COMPARISON + && ((strcmp(unboundParameters.begin()->name(), typeid(std::string).name()) == 0) || (strcmp(unboundParameters.begin()->name(), typeid(sf::String).name()) == 0)) + && ((strcmp((unboundParameters.begin()+1)->name(), typeid(std::string).name()) == 0) || (strcmp((unboundParameters.begin()+1)->name(), typeid(sf::String).name()) == 0))) + #else && ((*unboundParameters.begin() == typeid(std::string)) || (*unboundParameters.begin() == typeid(sf::String))) && ((*(unboundParameters.begin()+1) == typeid(std::string)) || (*(unboundParameters.begin()+1) == typeid(sf::String)))) + #endif { return 1; } @@ -323,7 +432,12 @@ namespace tgui unsigned int SignalMenuItem::connect(const DelegateMenuItemEx& handler) { const auto id = generateUniqueId(); + #ifdef TGUI_NO_CPP14 + std::string name = m_name; + m_handlers[id] = [handler, name](){ handler(getWidget(), name, internal_signal::dereference(internal_signal::parameters[1])); }; + #else m_handlers[id] = [handler, name=m_name](){ handler(getWidget(), name, internal_signal::dereference(internal_signal::parameters[1])); }; + #endif return id; } @@ -341,7 +455,12 @@ namespace tgui unsigned int SignalMenuItem::connect(const DelegateMenuItemFullEx& handler) { const auto id = generateUniqueId(); + #ifdef TGUI_NO_CPP14 + std::string name = m_name; + m_handlers[id] = [handler, name](){ handler(getWidget(), name, internal_signal::dereference>(internal_signal::parameters[2])); }; + #else m_handlers[id] = [handler, name=m_name](){ handler(getWidget(), name, internal_signal::dereference>(internal_signal::parameters[2])); }; + #endif return id; } @@ -349,9 +468,17 @@ namespace tgui unsigned int SignalMenuItem::validateTypes(std::initializer_list unboundParameters) { + #ifdef TGUI_UNSAFE_TYPE_INFO_COMPARISON + if ((unboundParameters.size() == 1) && ((strcmp(unboundParameters.begin()->name(), typeid(std::string).name()) == 0) || (strcmp(unboundParameters.begin()->name(), typeid(sf::String).name()) == 0))) + #else if ((unboundParameters.size() == 1) && ((*unboundParameters.begin() == typeid(std::string)) || (*unboundParameters.begin() == typeid(sf::String)))) + #endif return 1; + #ifdef TGUI_UNSAFE_TYPE_INFO_COMPARISON + else if ((unboundParameters.size() == 1) && (strcmp(unboundParameters.begin()->name(), typeid(std::vector).name()) == 0)) + #else else if ((unboundParameters.size() == 1) && (*unboundParameters.begin() == typeid(std::vector))) + #endif return 2; else return Signal::validateTypes(unboundParameters); diff --git a/src/TGUI/Sprite.cpp b/src/TGUI/Sprite.cpp index 8f260f6f..39582a2e 100644 --- a/src/TGUI/Sprite.cpp +++ b/src/TGUI/Sprite.cpp @@ -385,7 +385,7 @@ namespace tgui // Apply clipping when needed std::unique_ptr clipping; if (m_visibleRect != sf::FloatRect{0, 0, 0, 0}) - clipping = std::make_unique(target, states, sf::Vector2f{m_visibleRect.left, m_visibleRect.top}, sf::Vector2f{m_visibleRect.width, m_visibleRect.height}); + clipping = make_unique(target, states, sf::Vector2f{m_visibleRect.left, m_visibleRect.top}, sf::Vector2f{m_visibleRect.width, m_visibleRect.height}); states.texture = &m_texture.getData()->texture; target.draw(m_vertices.data(), m_vertices.size(), sf::PrimitiveType::TrianglesStrip, states); diff --git a/src/TGUI/Texture.cpp b/src/TGUI/Texture.cpp index 0f6928a0..aad45b4a 100644 --- a/src/TGUI/Texture.cpp +++ b/src/TGUI/Texture.cpp @@ -37,7 +37,7 @@ namespace tgui Texture::TextureLoaderFunc Texture::m_textureLoader = &TextureManager::getTexture; Texture::ImageLoaderFunc Texture::m_imageLoader = [](const sf::String& filename) -> std::unique_ptr { - auto image = std::make_unique(); + auto image = make_unique(); if (image->loadFromFile(filename)) return image; else diff --git a/src/TGUI/Widgets/Label.cpp b/src/TGUI/Widgets/Label.cpp index bc4c4387..c18da98c 100644 --- a/src/TGUI/Widgets/Label.cpp +++ b/src/TGUI/Widgets/Label.cpp @@ -453,7 +453,7 @@ namespace tgui innerSize.x -= m_paddingCached.getLeft() + m_paddingCached.getRight(); innerSize.y -= m_paddingCached.getTop() + m_paddingCached.getBottom(); - clipping = std::make_unique(target, states, sf::Vector2f{m_paddingCached.getLeft(), m_paddingCached.getTop()}, innerSize); + clipping = make_unique(target, states, sf::Vector2f{m_paddingCached.getLeft(), m_paddingCached.getTop()}, innerSize); } // Draw the text diff --git a/src/TGUI/Widgets/Tabs.cpp b/src/TGUI/Widgets/Tabs.cpp index 146d4adb..f0d68035 100644 --- a/src/TGUI/Widgets/Tabs.cpp +++ b/src/TGUI/Widgets/Tabs.cpp @@ -643,7 +643,7 @@ namespace tgui std::unique_ptr clipping; const float usableWidth = m_tabWidth[i] - (2 * m_distanceToSideCached); if (m_tabTexts[i].getSize().x > usableWidth) - clipping = std::make_unique(target, textStates, sf::Vector2f{m_distanceToSideCached, 0}, sf::Vector2f{usableWidth, usableHeight}); + clipping = make_unique(target, textStates, sf::Vector2f{m_distanceToSideCached, 0}, sf::Vector2f{usableWidth, usableHeight}); // Draw the text textStates.transform.translate({m_distanceToSideCached + ((usableWidth - m_tabTexts[i].getSize().x) / 2.f), ((usableHeight - m_tabTexts[i].getSize().y) / 2.f)});