diff --git a/include/SAL/README.txt b/include/SAL/README.txt index d780046..5c818b0 100644 --- a/include/SAL/README.txt +++ b/include/SAL/README.txt @@ -1,27 +1,27 @@ -Service Adapter Library (or "Software Abstraction Layer", on every other day) +Service Adapter Library (or "Software Abstraction Layer", every other day...) Like a HAL, but rather than standardizing an imaginary _underlying_ platform, the goal of this middleware layer is to facilitate replacing certain external -components -- not just those belonging to a backend, but any libraries. +components -- not just those belonging to a backend (but any libraries). -The contents of this layer is diven by the needs of the application -- so each -app should have its own optimal, tailored set of adapters. The app is free to -decide to use SAL adapters, or integrate (or interface with) external services -directly. +The contents of this layer is diven by the needs of the application -- so, in +theory, each app should have its own optimally tailored set of adapters in a +layer like this. -(So, it's neither "standardizing", nor hierarchically layered. That's why it -hasn't become a "platform abstraction layer" (or PAL) either: not all services -used are low-level, platform-like; the only common theme connecting them is -just that they are meant to be easily replaceable without app rewrites.) +So, it's neither an attempt at "standardizing", nor is it hierarchically layered. +(That's why it's not a "platform abstraction layer" (or "PAL") either: not all +services used are low-level, platform-like; the only common theme connecting them +is just that they are meant to be easily replaceable without app rewrites.) --------------------- Actually... It could also be called even more generally a "Software Compatibility Layer", and then it could naturally also have a bunch of selected "utility" headers -(and even modules, later -> overlapping a personal foundation lib!...) the -app can still freely use, without any explicit "adaptering"!... +(and even modules, later -> overlapping with a personal foundation lib!...) +which apps can use directly, without any explicit "adaptering"!... (Which +_does_ mean a kind of implicit standardization then...) -And then all the truly generic crap buried under sfw/util (etc.) could finally +And then all the legacy generic crap buried under sfw/util (etc.) could finally find a better home! diff --git a/include/SAL/geometry/Rectangle.hpp b/include/SAL/geometry/Rectangle.hpp index e5a13f7..7436595 100644 --- a/include/SAL/geometry/Rectangle.hpp +++ b/include/SAL/geometry/Rectangle.hpp @@ -200,7 +200,7 @@ namespace SAL::geometry //---------------------------------------------------------------------------- template - using Rect = Rectangle_Interface>; + using Rect = Rectangle_Interface>; using fRect = Rectangle_Interface>; using iRect = Rectangle_Interface>; diff --git a/include/SAL/geometry/SFML/Rectangle_Impl.hpp b/include/SAL/geometry/SFML/Rectangle_Impl.hpp index e380c10..044a727 100644 --- a/include/SAL/geometry/SFML/Rectangle_Impl.hpp +++ b/include/SAL/geometry/SFML/Rectangle_Impl.hpp @@ -60,12 +60,16 @@ namespace SFML } // namespace SFML -// Save the specific adapter type to a backend-agnostic symbol... -//namespace active_backend -//{ + // Save the specific adapter type to a backend-agnostic symbol... + //!! + //!! This looks totally useless, as this entire header is dispached by the selected backend, + //!! so things defined here could just live directly in adapter::, no need for SFML:: too + //!! -- but... The build system can't also dispatch the translation units yet, so it would + //!! just compile -- and link -- everything together, causing name clashes across backends! + //!! template using Rectangle_Impl = SFML::Rectangle_Impl; -//} + } // namespace SAL::adapter diff --git a/include/SAL/gfx/Color.hpp b/include/SAL/gfx/Color.hpp new file mode 100644 index 0000000..87d5fca --- /dev/null +++ b/include/SAL/gfx/Color.hpp @@ -0,0 +1,388 @@ +//!! +//!! Don't just move this to a gfx/Color class -- at least definitely not +//!! directly into that class (which shouldn't have all these deps)!... +//!! + +#ifndef _DFGM9W3804QWM89E70DFRNYGUYMCHW9D85MYHUV_ +#define _DFGM9W3804QWM89E70DFRNYGUYMCHW9D85MYHUV_ + + +#include "SAL.hpp" +#include SAL_ADAPTER(gfx/Color) + +#include "SAL/util/diagnostics.hpp" + +#include // uint32_t, uint8_t +#include // strtoul +#include +#include // For a temorary inside the hex -> color converter... :-/ + + +namespace SAL::gfx +{ + template + class RGBAColor : public Impl + { + protected: + constexpr auto adapter() { return static_cast< Impl*>(this); } + constexpr const auto adapter() const { return static_cast(this); } + + public: + enum : std::uint8_t { + Transparent = 0, + Translucent = 127, + Opaque = 255, + }; + + using Impl::Impl; + + constexpr std::uint8_t& r() { return adapter()->_r(); } + constexpr std::uint8_t& g() { return adapter()->_g(); } + constexpr std::uint8_t& b() { return adapter()->_b(); } + constexpr std::uint8_t& a() { return adapter()->_a(); } + + constexpr std::uint8_t r() const { return adapter()->_r(); } + constexpr std::uint8_t g() const { return adapter()->_g(); } + constexpr std::uint8_t b() const { return adapter()->_b(); } + constexpr std::uint8_t a() const { return adapter()->_a(); } + + constexpr void r(std::uint8_t red) { adapter()->_r(red); } + constexpr void g(std::uint8_t green) { adapter()->_g(green); } + constexpr void b(std::uint8_t blue) { adapter()->_b(blue); } + constexpr void a(std::uint8_t alpha) { adapter()->_a(alpha); } + + constexpr RGBAColor() = default; // uninitialized + + constexpr RGBAColor(std::uint8_t r, std::uint8_t g, std::uint8_t b, std::uint8_t a = Opaque) + : Impl(r, g, b, a) {} + + constexpr RGBAColor(std::uint32_t rgba) + : Impl(rgba) {} + /* + : r(uint8_t((rgba & 0xff000000) >> 24)), + g(uint8_t((rgba & 0x00ff0000) >> 16)), + b(uint8_t((rgba & 0x0000ff00) >> 8)), + a(uint8_t( rgba & 0x000000ff)) {} + */ + constexpr RGBAColor(std::uint32_t rgb, std::uint8_t alpha) + : Impl(rgb << 8 | alpha) {} + /* + : r(uint8_t((rgb & 0xff000000) >> 16)), + g(uint8_t((rgb & 0x00ff0000) >> 8)), + b(uint8_t( rgb & 0x0000ff00)), + a(alpha) {} + */ +/*!! + explicit constexpr RGBAColor(std::string_view csshexcolor) + { + auto len = csshexcolor.size(); + + SAL_ASSERT(len == 7 || len == 9 || len == 4 || len == 5); + SAL_ASSERT(csshexcolor[0] == '#'); + + // Note: strtoul will just return 0 for garbage. + + if (len >= 7) // #rrggbb[aa] + { + r( (uint8_t)strtoul(csshexcolor.substr(1, 2).c_str(), nullptr, 16) ); + g( (uint8_t)strtoul(csshexcolor.substr(3, 2).c_str(), nullptr, 16) ); + b( (uint8_t)strtoul(csshexcolor.substr(5, 2).c_str(), nullptr, 16) ); + a( (len == 9) ? (uint8_t)strtoul(csshexcolor.substr(7, 2).c_str(), nullptr, 16) : Opaque ); + } + else if (len >= 4) // #rgb[a] + { + r( (uint8_t)strtoul(csshexcolor.substr(1, 1).c_str(), nullptr, 16) * 17 ); + g( (uint8_t)strtoul(csshexcolor.substr(2, 1).c_str(), nullptr, 16) * 17 ); + b( (uint8_t)strtoul(csshexcolor.substr(3, 1).c_str(), nullptr, 16) * 17 ); + a( (len == 5) ? (uint8_t)strtoul(csshexcolor.substr(4, 1).c_str(), nullptr, 16) * 17 : Opaque ); + } + else + { + // Give a chance to catch it in DEBUG mode (but leave + // it uninitialized, as in the default ctor): + SAL_ASSERT(0); // Malformed color specifier! + } + } +!!*/ + + explicit constexpr RGBAColor(std::string_view hexcolor_strview) + { + //!! strtoul() can't deal with string_views! :-/ + auto hexcolor = std::string(hexcolor_strview); + + SAL_ASSERT(hexcolor.size() == 7 || hexcolor.size() == 4 || hexcolor.size() == 9 || hexcolor.size() == 5); + SAL_ASSERT(hexcolor[0] == '#'); + +# define CCOMP(str, pos, width) (std::uint8_t)std::strtoul(hexcolor.substr(1 + (pos)*(width), width).c_str(), nullptr, 16) + + //!! No checking though!... But strtoul might even throw!... :-o + switch (hexcolor.size()) + { + case 7: // #rrggbb + r( CCOMP(hexcolor, 0, 2) ); + g( CCOMP(hexcolor, 1, 2) ); + b( CCOMP(hexcolor, 2, 2) ); + a( 255 ); + break; + case 4: // #rgb + r( CCOMP(hexcolor, 0, 1) * 17 ); + g( CCOMP(hexcolor, 1, 1) * 17 ); + b( CCOMP(hexcolor, 2, 1) * 17 ); + a( 255 ); + break; + case 9: // #rrggbbaa + r( CCOMP(hexcolor, 0, 2) ); + g( CCOMP(hexcolor, 1, 2) ); + b( CCOMP(hexcolor, 2, 2) ); + a( CCOMP(hexcolor, 3, 2) ); + break; + case 5: // #rgba + r( CCOMP(hexcolor, 0, 1) * 17 ); + g( CCOMP(hexcolor, 1, 1) * 17 ); + b( CCOMP(hexcolor, 2, 1) * 17 ); + a( CCOMP(hexcolor, 3, 1) * 17 ); + break; + default:; + } +# undef CCOMP + + } + + //!! std::string get_hex() const (uint32_t rgb, uint8_t alpha = 255) { ... } + + // Generic (implicit) "get RGBA": + constexpr operator std::uint32_t() const { return adapter()->_get_rgba(); } //!! OLD: return getRGBA(); + + // Generic (implicit) "set RGBA": + constexpr RGBAColor& operator = (std::uint32_t c) { rgba(c); return *this; } + + // The default op=(RGBAColor) is fine! + + constexpr std::uint32_t rgba() const { return adapter()->_get_rgba(); } + constexpr std::uint32_t rgb() const { return r() << 16 | g() << 8 | b(); } + + constexpr void rgba(std::uint32_t c_rgba) { adapter()->_set_rgba(c_rgba); } + + // Leave the alpha unmodified: + constexpr void rgb(std::uint32_t c_rgb) { rgba(c_rgb << 8 | a()); } + constexpr void rgb(uint8_t red, uint8_t green, uint8_t blue) { rgba((red << 24) | (green << 16) | (blue << 8) | a()); } + + // Set both the colors & alpha: + constexpr void set(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha = Opaque) { rgba((red << 24) | (green << 16) | (blue << 8) | alpha); } + constexpr void set(uint32_t c_rgb, uint8_t alpha = Opaque) { rgba((c_rgb << 8) | alpha); } + + + constexpr bool operator == (std::uint32_t c) const { return rgba() == c; } + // Other param. types are accepted via implicit conv. to uint32! + + + // Some predefined colors, for convenience: + static constinit const RGBAColor None; // Tansparent! + static constinit const RGBAColor Black; + static constinit const RGBAColor White; + static constinit const RGBAColor Green; + static constinit const RGBAColor Red; + static constinit const RGBAColor Blue; + static constinit const RGBAColor Yellow; + static constinit const RGBAColor Magenta; + static constinit const RGBAColor Cyan; + + }; // class RGBAColor + +///*!! I don't even know how to set these with a template, but +// I do know it will be a fucking nightmare, yet again: + template constinit const RGBAColor RGBAColor::None = 0x00000000; + template constinit const RGBAColor RGBAColor::Black = 0x000000ff; + template constinit const RGBAColor RGBAColor::White = 0xffffffff; + template constinit const RGBAColor RGBAColor::Green = 0x00ff00ff; + template constinit const RGBAColor RGBAColor::Red = 0xff0000ff; + template constinit const RGBAColor RGBAColor::Blue = 0x0000ffff; + template constinit const RGBAColor RGBAColor::Yellow = 0xffff00ff; + template constinit const RGBAColor RGBAColor::Magenta = 0xff00ffff; + template constinit const RGBAColor RGBAColor::Cyan = 0x00ffffff; +//!!*/ + +/*!! + class Color //!!?? or: RGBAColor : Color + { + enum : unsigned { + Transparent = 0, + Opaque = 255, + }; + + uint8_t r; + uint8_t g; + uint8_t b; + uint8_t a; + + Color() = default; // uninitialized + + constexpr Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a = Opaque) + : r(r), g(g), b(b), a(a) {} + + constexpr Color(uint32_t rgba) + : r(uint8_t((rgba & 0xff000000) >> 24)), + g(uint8_t((rgba & 0x00ff0000) >> 16)), + b(uint8_t((rgba & 0x0000ff00) >> 8)), + a(uint8_t((rgba & 0x000000ff)) {} + + constexpr Color(uint32_t rgb, uint_8 alpha) + : r(uint8_t((rgb & 0xff000000) >> 16)), + g(uint8_t((rgb & 0x00ff0000) >> 8)), + b(uint8_t( rgb & 0x0000ff00), + a(alpha) {} + + explicit constexpr Color(const std::string& csshexcolor) + { + auto len = hexcolor.size(); + + assert(len == 7 || len == 9 || len == 4 || len == 5); + assert(csshexcolor[0] == '#'); + + // Note: strtoul will just return 0 for garbage. + + if (len >= 7) // #rrggbb[aa] + { + color.r = (uint8_t)strtoul(csshexcolor.substr(1, 2).c_str(), nullptr, 16); + color.g = (uint8_t)strtoul(csshexcolor.substr(3, 2).c_str(), nullptr, 16); + color.b = (uint8_t)strtoul(csshexcolor.substr(5, 2).c_str(), nullptr, 16); + color.a = (len == 9) ? (uint8_t)strtoul(csshexcolor.substr(7, 2).c_str(), nullptr, 16) : Opaque; + { + else if (len >= 4) // #rgb[a] + { + color.r = (uint8_t)strtoul(csshexcolor.substr(1, 1).c_str(), nullptr, 16) * 17; + color.g = (uint8_t)strtoul(csshexcolor.substr(2, 1).c_str(), nullptr, 16) * 17; + color.b = (uint8_t)strtoul(csshexcolor.substr(3, 1).c_str(), nullptr, 16) * 17; + color.a = (len == 5) ? (uint8_t)strtoul(csshexcolor.substr(4, 1).c_str(), nullptr, 16) * 17 : Opaque; + } + else + { + // Give a chance to catch it in DEBUG mode (but leave + // it uninitialized, as in the default ctor): + assert(csshexcolor == "well-formed"); + } + } + + operator uint32_t() const { return getRGBA(); } + + void set(uint32_t rgb, uint8_t alpha) { setRGBA((rgb << 8) | alpha); } + //!! void setRGBA(uint32_t rgba), uint8_t alpha = 255) { ... } + //!! // Leave alpha unmodified: + //!! void setRGB( uint32_t rgb) uint8_t alpha = 255) { ... } + + uint32_t getRGBA() const { return (getRGB() << 8) | a; } + uint32_t getRGB() const { return (r << 24) | (g << 16) | (b << 8) | a; } + + //!! std::string getCSShex() const (uint32_t rgb, uint8_t alpha = 255) { return (rgb << 8) | alpha; } + + //!!Move to some derived Color_SFML class: + //!! oprator sf::Color() { return sf::Color(getRGBA()); } + }; // class Color +!!*/ + +/*!! +inline sf::Color Color(const std::string& hexcolor) +{ + assert(hexcolor.size() == 7 || hexcolor.size() == 4 || hexcolor.size() == 9 || hexcolor.size() == 5); + assert(hexcolor[0] == '#'); + + sf::Color color = sf::Color::Black; + +#define CCOMP(str, pos, width) (uint8_t)std::strtoul(hexcolor.substr(1 + (pos)*(width), width).c_str(), nullptr, 16) + switch (hexcolor.size()) + { + case 7: // #rrggbb + color.r = CCOMP(hexcolor, 0, 2); + color.g = CCOMP(hexcolor, 1, 2); + color.b = CCOMP(hexcolor, 2, 2); + color.a = 255; + break; + case 4: // #rgb + color.r = CCOMP(hexcolor, 0, 1) * 17; + color.g = CCOMP(hexcolor, 1, 1) * 17; + color.b = CCOMP(hexcolor, 2, 1) * 17; + color.a = 255; + break; + case 9: // #rrggbbaa + color.r = CCOMP(hexcolor, 0, 2); + color.g = CCOMP(hexcolor, 1, 2); + color.b = CCOMP(hexcolor, 2, 2); + color.a = CCOMP(hexcolor, 3, 2); + break; + case 5: // #rgba + color.r = CCOMP(hexcolor, 0, 1) * 17; + color.g = CCOMP(hexcolor, 1, 1) * 17; + color.b = CCOMP(hexcolor, 2, 1) * 17; + color.a = CCOMP(hexcolor, 3, 1) * 17; + break; + default:; + } +#undef CCOMP + return color; + +} // Color() +!!*/ + + + //-------------------------------------------------------------------- + // The actual API ("dictionary") type: + using Color = RGBAColor; + + + //////////////////////////////////////////////////////////// + //!! Componentwise ops. ripped from SFML!... + //////////////////////////////////////////////////////////// + + constexpr Color operator+(Color left, Color right) + { + const auto clampedAdd = [](std::uint8_t lhs, std::uint8_t rhs) -> std::uint8_t + { + int result = int(lhs) + int(rhs); + return std::uint8_t(result < 255 ? result : 255); + }; + + return {clampedAdd(left.r(), right.r()), + clampedAdd(left.b(), right.b()), + clampedAdd(left.g(), right.g()), + clampedAdd(left.a(), right.a())}; + } + + constexpr Color operator-(Color left, Color right) + { + const auto clampedSub = [](std::uint8_t lhs, std::uint8_t rhs) -> std::uint8_t + { + int result = int(lhs) - int(rhs); + return std::uint8_t(result > 0 ? result : 0); + }; + + return {clampedSub(left.r(), right.r()), + clampedSub(left.g(), right.g()), + clampedSub(left.b(), right.b()), + clampedSub(left.a(), right.a())}; + } + + constexpr Color operator*(Color left, Color right) + { + const auto scaledMul = [](std::uint8_t lhs, std::uint8_t rhs) -> std::uint8_t + { + auto result_u16 = std::uint16_t(std::uint16_t(lhs) * std::uint16_t(rhs)); + return std::uint8_t(result_u16 / 255u); + }; + + return {scaledMul(left.r(), right.r()), + scaledMul(left.g(), right.g()), + scaledMul(left.b(), right.b()), + scaledMul(left.a(), right.a())}; + } + + //////////////////////////////////////////////////////////// + + constexpr Color& operator+=(Color& left, Color right) { return left = left + right; } + constexpr Color& operator-=(Color& left, Color right) { return left = left - right; } + constexpr Color& operator*=(Color& left, Color right) { return left = left * right; } + + +} // namespace SAL::gfx + + +#endif // _DFGM9W3804QWM89E70DFRNYGUYMCHW9D85MYHUV_ diff --git a/include/SAL/gfx/Color/SFML/Impl.hpp b/include/SAL/gfx/Color/SFML/Impl.hpp new file mode 100644 index 0000000..0466865 --- /dev/null +++ b/include/SAL/gfx/Color/SFML/Impl.hpp @@ -0,0 +1,71 @@ +#ifndef _CDFVOMEBINRD87FYMH39THMY89546YM856H89I6RH_ +#define _CDFVOMEBINRD87FYMH39THMY89546YM856H89I6RH_ + + +#include // uint32_t, uint8_t +#include // forward + +//#include "SAL/util/diagnostics.hpp" + +#include + + +namespace SAL::gfx::adapter +{ + class RGBAColor_Impl + { + protected: + using native_type = sf::Color; + + native_type _d; + + constexpr const native_type& native() const { return _d; } + constexpr native_type& native() { return _d; } + + public: +//!! This all-in implicit forwarding leaks backend API dependencies through the interface layer! +//!! // Forward to the backend ctor: +//!! template +//!! constexpr RGBAColor_Impl(T&&... args) : _d(std::forward(args)...) {} + + constexpr RGBAColor_Impl() {} // No init! + + constexpr RGBAColor_Impl(std::uint32_t c) + : _d(c) {} + + constexpr RGBAColor_Impl(std::uint8_t r, std::uint8_t g, std::uint8_t b, std::uint8_t a) + : _d(r, g, b, a) {} + + // Convert from the backend type: + constexpr RGBAColor_Impl(native_type n) : _d(n) {} + + // Convert to the backend type: + constexpr operator const native_type& () const { return native(); } + constexpr operator native_type& () { return native(); } + +// constexpr RGBAColor_Impl& operator = (const RGBAColor_Impl&) = default; + constexpr RGBAColor_Impl& operator = (std::uint32_t rgba) { _set_rgba(rgba); return *this; } + + constexpr std::uint8_t& _r() { return _d.r; } + constexpr std::uint8_t& _g() { return _d.g; } + constexpr std::uint8_t& _b() { return _d.b; } + constexpr std::uint8_t& _a() { return _d.a; } + constexpr std::uint8_t _r() const { return _d.r; } + constexpr std::uint8_t _g() const { return _d.g; } + constexpr std::uint8_t _b() const { return _d.b; } + constexpr std::uint8_t _a() const { return _d.a; } + + constexpr void _r(std::uint8_t red) { _d.r = red; } + constexpr void _g(std::uint8_t green) { _d.g = green; } + constexpr void _b(std::uint8_t blue) { _d.b = blue; } + constexpr void _a(std::uint8_t alpha) { _d.a = alpha; } + + constexpr void _set_rgba(std::uint32_t rgba) { _d = native_type(rgba); } + constexpr std::uint32_t _get_rgba() const { return _d.toInteger(); } + + }; // class RGBAColor_Impl + +} // namespace SAL::gfx::adapter + + +#endif // _CDFVOMEBINRD87FYMH39THMY89546YM856H89I6RH_ diff --git a/include/SAL/gfx/Render.hpp b/include/SAL/gfx/Render.hpp index 98fc7b1..62cb524 100644 --- a/include/SAL/gfx/Render.hpp +++ b/include/SAL/gfx/Render.hpp @@ -1,6 +1,16 @@ +/***************************************************************************** +!!REQUIREMENTS: + +- Like the other SAL adapters, it should interoperate seamlessly with the real + backend "renderer" (if there even is one...), "as much as possible" (TBD!). + -> Entirely different rendering pipelines may make this infeasible though! + + *****************************************************************************/ + #ifndef _DMNE98475Y687D348057NHY6378945HY6B0V45978Y9TG898_ #define _DMNE98475Y687D348057NHY6378945HY6B0V45978Y9TG898_ + namespace SAL::gfx { diff --git a/include/SAL/gfx/element/ColorVertex2.hpp b/include/SAL/gfx/element/ColorVertex2.hpp index 19b9a01..a0a580d 100644 --- a/include/SAL/gfx/element/ColorVertex2.hpp +++ b/include/SAL/gfx/element/ColorVertex2.hpp @@ -7,7 +7,7 @@ #include "SAL/math/Vector.hpp" -#include //!! DIRECT SFML! +#include "SAL/gfx/Color.hpp" #include "SAL/gfx/Render.hpp" #include "SAL.hpp" @@ -36,11 +36,14 @@ namespace SAL::gfx using Impl::Impl; // Accessors... - constexpr fVec2 position() const { return adapter()->_position(); } - constexpr sf::Color color() const { return adapter()->_color(); } - - constexpr void position(fVec2 pos) { adapter()->_position(pos); } - constexpr void color(sf::Color c) { adapter()->_color(c); } + constexpr fVec2 position() const { return adapter()->_position(); } + constexpr Color color() const { return adapter()->_color(); } +//!! Doesn't work, but also confusing syntax: .prop() = x...: +//!! constexpr fVec2& position() { return adapter()->_position(); } +//!! constexpr Color& color() { return adapter()->_color(); } + + constexpr void position(fVec2 pos) { adapter()->_position(pos); } + constexpr void color(Color c) { adapter()->_color(c); } //!! Be a bit more sophisticated than this embarrassment! :) diff --git a/include/SAL/gfx/element/ColorVertex2/SFML/Impl.hpp b/include/SAL/gfx/element/ColorVertex2/SFML/Impl.hpp index e780cfc..04aec56 100644 --- a/include/SAL/gfx/element/ColorVertex2/SFML/Impl.hpp +++ b/include/SAL/gfx/element/ColorVertex2/SFML/Impl.hpp @@ -21,9 +21,8 @@ #include "SAL/math/Vector.hpp" #include "SAL/gfx/Render.hpp" -//!!#include "SAL/gfx/Color.hpp" //!!Also include this, for the class interface (signatures)! +#include "SAL/gfx/Color.hpp" -#include #include @@ -37,10 +36,10 @@ namespace SFML using native_type = sf::Vertex; public: - ColorVertex2_Impl() : _d({0,0}, sf::Color::White) {} //!!SFML: not just sf::Color, but the init list ("ctor call")! + ColorVertex2_Impl() : _d({0,0}, Color::White) {} //!! SFML init list! - ColorVertex2_Impl(fVec2 pos, sf::Color color) : _d(pos, color) {} // fVec2 auto-converts to sf::Vector -//!!??OR: ColorVertex2_Impl(const fVec2& pos, sf::Color color) : _d(pos, color) {} // fVec2 auto-converts to sf::Vector + ColorVertex2_Impl(fVec2 pos, Color color) : _d(pos, color) {} // fVec2 auto-converts to sf::Vector +//!!??OR: ColorVertex2_Impl(const fVec2& pos, Color color) : _d(pos, color) {} // fVec2 auto-converts to sf::Vector // Copy ColorVertex2_Impl(const ColorVertex2_Impl&) = default; @@ -56,10 +55,13 @@ namespace SFML // Accessors for the position, color, texture pos... constexpr fVec2 _position() const { return native().position; } // fVec2 auto-converts from sf::Vector2f - constexpr sf::Color _color() const { return native().color; } + constexpr Color _color() const { return native().color; } +//!! Type mismatch (SAL vs. native), but also confusing syntax: .prop() = x...: +//!! constexpr fVec2& _position() { return native().position; } // fVec2 auto-converts from sf::Vector2f +//!! constexpr Color& _color() { return native().color; } constexpr void _position(fVec2 pos) { native().position = pos; } - constexpr void _color(sf::Color c) { native().color = c; } + constexpr void _color(Color c) { native().color = c; } //!! Be a bit more sophisticated than this embarrassment! :) diff --git a/include/SAL/gfx/element/FilledRect/SFML/Impl.hpp b/include/SAL/gfx/element/FilledRect/SFML/Impl.hpp index b455c59..13aea35 100644 --- a/include/SAL/gfx/element/FilledRect/SFML/Impl.hpp +++ b/include/SAL/gfx/element/FilledRect/SFML/Impl.hpp @@ -2,10 +2,11 @@ #define _OIU345YTNDC84675TOB678WTBN5MC94285N7_ +#include "SAL/math/Vector.hpp" +#include "SAL/gfx/Color.hpp" #include "SAL/gfx/Render.hpp" #include -#include namespace SAL::gfx::adapter @@ -22,23 +23,23 @@ namespace SFML //!!template class Self struct FilledRect_Impl : public SAL::gfx::Drawable { - sf::Vector2f size{}; - sf::Vector2f position{}; - sf::Color colorFill{}; - sf::Color colorBorder{}; + fVec2 size{}; + fVec2 position{}; + Color colorFill{}; + Color colorBorder{}; //!!?? It's a trade-off between size (the rather fat SFML Rect. (Shape) object here) //!!?? and speed (reinitializing the rect. from scratch in each frame, in draw())... //!!?? sf::RectangleShape m_rect; Self() = default; - Self(const sf::Vector2f& s, sf::Color fill_color, sf::Color border_color): + Self(const fVec2& s, Color fill_color, Color border_color): size(s), //! size(size) makes GCC freak out... colorFill(fill_color), colorBorder(border_color) {} - Self(const sf::Vector2f& s, sf::Color fill_color): + Self(const fVec2& s, Color fill_color): Self(s, fill_color, fill_color) {} diff --git a/include/SAL/gfx/element/SFML/CheckMark.hpp b/include/SAL/gfx/element/SFML/CheckMark.hpp index 38ef6e3..9b30d12 100644 --- a/include/SAL/gfx/element/SFML/CheckMark.hpp +++ b/include/SAL/gfx/element/SFML/CheckMark.hpp @@ -2,15 +2,13 @@ #define _YGM78SY487Y3G45YNV87M475D70YRT7YHVM579H_ +#include "sfw/math/Vector.hpp" +#include "sfw/gfx/Color.hpp" +#include "sfw/gfx/element/TexturedVertex2.hpp" #include "sfw/gfx/Render.hpp" -#include "sfw/math/Vector.hpp" //!!?? SAL/... -#include -#include - - -namespace sfw +namespace sfw//!!::parts { class CheckMark: public gfx::Drawable @@ -23,7 +21,7 @@ class CheckMark: public gfx::Drawable void setSize(float size); fVec2 getSize() const; - void setColor(const sf::Color& color); + void setColor(Color color); public: //! <- NOT private, because draw() may be accessed directly (statically), //! rather than just polymorphically (dynamically) via a pointer! @@ -32,11 +30,11 @@ class CheckMark: public gfx::Drawable private: void updateGeometry(float x, float y); - sf::Vertex m_vertices[4]; + gfx::TexturedVertex2 m_vertices[4]; }; // class CheckMark -} // namespace sfw +} // namespace sfw//!!::parts #endif // _YGM78SY487Y3G45YNV87M475D70YRT7YHVM579H_ diff --git a/include/SAL/gfx/element/SFML/Color.hpp b/include/SAL/gfx/element/SFML/Color.hpp deleted file mode 100644 index 2b42597..0000000 --- a/include/SAL/gfx/element/SFML/Color.hpp +++ /dev/null @@ -1,138 +0,0 @@ -#ifndef _SFW_COLOR_HPP_ -#define _SFW_COLOR_HPP_ - -#include -#include - -#include "SAL/util/diagnostics.hpp" - -//!! Auto-dispatch for the current backend instead (-> gfx/backend.hpp): -//!! Also, don't just move this to gfx/Color -- at lesat definitely not -//!! directly into that class (which shouldn't have all these deps)!... -#include - -namespace sfw { - -inline sf::Color Color(const std::string& hexcolor) -{ - assert(hexcolor.size() == 7 || hexcolor.size() == 4 || hexcolor.size() == 9 || hexcolor.size() == 5); - assert(hexcolor[0] == '#'); - - sf::Color color = sf::Color::Black; - -#define CCOMP(str, pos, width) (uint8_t)std::strtoul(hexcolor.substr(1 + (pos)*(width), width).c_str(), nullptr, 16) - switch (hexcolor.size()) - { - case 7: // #rrggbb - color.r = CCOMP(hexcolor, 0, 2); - color.g = CCOMP(hexcolor, 1, 2); - color.b = CCOMP(hexcolor, 2, 2); - color.a = 255; - break; - case 4: // #rgb - color.r = CCOMP(hexcolor, 0, 1) * 17; - color.g = CCOMP(hexcolor, 1, 1) * 17; - color.b = CCOMP(hexcolor, 2, 1) * 17; - color.a = 255; - break; - case 9: // #rrggbbaa - color.r = CCOMP(hexcolor, 0, 2); - color.g = CCOMP(hexcolor, 1, 2); - color.b = CCOMP(hexcolor, 2, 2); - color.a = CCOMP(hexcolor, 3, 2); - break; - case 5: // #rgba - color.r = CCOMP(hexcolor, 0, 1) * 17; - color.g = CCOMP(hexcolor, 1, 1) * 17; - color.b = CCOMP(hexcolor, 2, 1) * 17; - color.a = CCOMP(hexcolor, 3, 1) * 17; - break; - default:; - } -#undef CCOMP - - return color; -} - -/*!! Generalize, make it versatile etc.! - -struct Color //!!?? or: RGBAColor : Color -{ - enum : unsigned { - Transparent = 0, - Opaque = 255, - }; - - uint8_t r; - uint8_t g; - uint8_t b; - uint8_t a; - - Color() = default; // uninitialized - - constexpr Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a = Opaque) - : r(r), g(g), b(b), a(a) {} - - constexpr Color(uint32_t rgba) - : r(uint8_t((rgba & 0xff000000) >> 24)), - g(uint8_t((rgba & 0x00ff0000) >> 16)), - b(uint8_t((rgba & 0x0000ff00) >> 8)), - a(uint8_t((rgba & 0x000000ff)) {} - - constexpr Color(uint32_t rgb, uint_8 alpha) - : r(uint8_t((rgb & 0xff000000) >> 16)), - g(uint8_t((rgb & 0x00ff0000) >> 8)), - b(uint8_t( rgb & 0x0000ff00), - a(alpha) {} - - explicit constexpr Color(const std::string& csshexcolor) - { - auto len = hexcolor.size(); - - assert(len == 7 || len == 9 || len == 4 || len == 5); - assert(csshexcolor[0] == '#'); - - // Note: strtoul will just return 0 for garbage. - - if (len >= 7) // #rrggbb[aa] - { - color.r = (uint8_t)strtoul(csshexcolor.substr(1, 2).c_str(), nullptr, 16); - color.g = (uint8_t)strtoul(csshexcolor.substr(3, 2).c_str(), nullptr, 16); - color.b = (uint8_t)strtoul(csshexcolor.substr(5, 2).c_str(), nullptr, 16); - color.a = (len == 9) ? (uint8_t)strtoul(csshexcolor.substr(7, 2).c_str(), nullptr, 16) : Opaque; - { - else if (len >= 4) // #rgb[a] - { - color.r = (uint8_t)strtoul(csshexcolor.substr(1, 1).c_str(), nullptr, 16) * 17; - color.g = (uint8_t)strtoul(csshexcolor.substr(2, 1).c_str(), nullptr, 16) * 17; - color.b = (uint8_t)strtoul(csshexcolor.substr(3, 1).c_str(), nullptr, 16) * 17; - color.a = (len == 5) ? (uint8_t)strtoul(csshexcolor.substr(4, 1).c_str(), nullptr, 16) * 17 : Opaque; - } - else - { - // Give a chance to catch it in DEBUG mode (but leave - // it uninitialized, as in the default ctor): - assert(csshexcolor == "well-formed"); - } - } - - operator uint32_t() const { return getRGBA(); } - - void set(uint32_t rgb, uint8_t alpha) { setRGBA((rgb << 8) | alpha); } -//!! void setRGBA(uint32_t rgba), uint8_t alpha = 255) { ... } -//!! // Leave alpha unmodified: -//!! void setRGB( uint32_t rgb) uint8_t alpha = 255) { ... } - - uint32_t getRGBA() const { return (getRGB() << 8) | a; } - uint32_t getRGB() const { return (r << 24) | (g << 16) | (b << 8) | a; } - -//!! std::string getCSShex() const (uint32_t rgb, uint8_t alpha = 255) { return (rgb << 8) | alpha; } - -//!!Move to some derived Color_SFML class: -//!! oprator sf::Color() { return sf::Color(getRGBA()); } -}; -!!*/ - -} // namespace - -#endif // _SFW_COLOR_HPP_ diff --git a/include/SAL/gfx/element/SFML/ItemBox.hpp b/include/SAL/gfx/element/SFML/ItemBox.hpp index 91297e9..d19d0d1 100644 --- a/include/SAL/gfx/element/SFML/ItemBox.hpp +++ b/include/SAL/gfx/element/SFML/ItemBox.hpp @@ -7,9 +7,9 @@ #include "sfw/gfx/element/Box.hpp" #include "sfw/gfx/element/Text.hpp" #include "sfw/math/Vector.hpp" -#include "SAL/util/cpp/macros.hpp" // MIXIN() +#include "sfw/gfx/Color.hpp" -#include +#include "SAL/util/cpp/macros.hpp" // SAL_MIXIN() //!!?? Remove this and just use a comment... Or use it everywhere consistently! #include // E.g. for optional coloring #include // is_convertible_v @@ -42,11 +42,11 @@ class ItemBox : SAL_MIXIN(Box) ItemBox(Box::Type type = Box::Click); ItemBox(const T& item, Box::Type type = Box::Click); - void setFillColor(sf::Color color); - void setItemColor(sf::Color color); + void setFillColor(Color color); + void setItemColor(Color color); // This would draw a filled rect *over* the "item" of ItemBox, so `color` // would usually need an alpha value set accordingly to be practical: - void setTintColor(sf::Color color); + void setTintColor(Color color); void applyState(ActivationState state); @@ -68,8 +68,8 @@ class ItemBox : SAL_MIXIN(Box) void onRelease() override; T m_item; - std::optional m_itemColor; - std::optional m_tintColor; + std::optional m_itemColor; + std::optional m_tintColor; }; } // namespace sfw diff --git a/include/SAL/gfx/element/SFML/ItemBox.inl b/include/SAL/gfx/element/SFML/ItemBox.inl index 1e5c04c..99967cc 100644 --- a/include/SAL/gfx/element/SFML/ItemBox.inl +++ b/include/SAL/gfx/element/SFML/ItemBox.inl @@ -1,7 +1,6 @@ #include "sfw/Theme.hpp" -#include -#include +#include //!! DIRECT SFML! namespace sfw { @@ -23,20 +22,20 @@ ItemBox::ItemBox(const T& item, Box::Type type): template -void ItemBox::setItemColor(sf::Color color) +void ItemBox::setItemColor(Color color) { m_itemColor = color; m_item.setFillColor(m_itemColor.value()); } template -void ItemBox::setFillColor(sf::Color color) +void ItemBox::setFillColor(Color color) { Box::setFillColor(color); } template -void ItemBox::setTintColor(sf::Color color) +void ItemBox::setTintColor(Color color) { m_tintColor = color; } diff --git a/include/SAL/gfx/element/Text/SFML/Impl.hpp b/include/SAL/gfx/element/Text/SFML/Impl.hpp index 16be802..ddbad65 100644 --- a/include/SAL/gfx/element/Text/SFML/Impl.hpp +++ b/include/SAL/gfx/element/Text/SFML/Impl.hpp @@ -10,6 +10,7 @@ #include "SAL/gfx/element/Font.hpp" #include "SAL/geometry/Rectangle.hpp" +#include "SAL/gfx/Color.hpp" #include "SAL/gfx/Render.hpp" #include "SAL/sfml.hpp" //!! Should be "interfaced" away!... @@ -57,6 +58,10 @@ class Text : public sf::Text, public SAL::gfx::Drawable //!!void setFont(const Font&) { ...; _recalc(); } const Font& getFont() const { return _font_ref; } + // Proxies for some already used SFML features: + void setFillColor(Color c) { ((native_type*)this)->setFillColor(c); } + Color getFillColor() const { return ((native_type*)this)->getFillColor(); } + void draw(const gfx::RenderContext& ctx) const override; diff --git a/include/SAL/gfx/element/TextureFrame.hpp b/include/SAL/gfx/element/TextureFrame.hpp index b7b47b7..22137fc 100644 --- a/include/SAL/gfx/element/TextureFrame.hpp +++ b/include/SAL/gfx/element/TextureFrame.hpp @@ -17,6 +17,7 @@ #include "SAL/geometry/Rectangle.hpp" #include "SAL/gfx/element/Texture.hpp" +#include "SAL/gfx/Color.hpp" #include "SAL/gfx/Render.hpp" @@ -36,7 +37,8 @@ namespace SAL::gfx void place(fVec2 pos, Direction dir) { _place(pos.x(), pos.y(), dir); } - void setFillColor(const sf::Color& color); //!!?? NOOP for now +// void setFillColor(Color color); +// Color getFillColor() const; void move(fVec2 delta) { for (unsigned i = 0; i < _vertex_count; ++i) diff --git a/include/SAL/gfx/element/TextureFrame/SFML/Impl.hpp b/include/SAL/gfx/element/TextureFrame/SFML/Impl.hpp index 79e044e..13626a8 100644 --- a/include/SAL/gfx/element/TextureFrame/SFML/Impl.hpp +++ b/include/SAL/gfx/element/TextureFrame/SFML/Impl.hpp @@ -5,15 +5,16 @@ #define _CNJERHKDNGF6C98O423576TGB87RT9NM23745T6Y807RE5T_ -#include "sfw/gfx/Render.hpp" //!! SALIFY!... +#include "SAL.hpp" + +#include "SAL/gfx/element/TexturedVertex2.hpp" //!! Adapt the code itself; it's still using sf::Vertex! +//!!??#include SAL_ADAPTER(gfx/element/TexturedVertex2) // Only the backend-facing part! +#include SAL_ADAPTER(gfx/element/Texture) // Only the backend-facing part! #include "SAL/math/Vector.hpp" //!!#include "SAL/geometry/Rectangle.hpp" +#include "SAL/gfx/Color.hpp" +#include "SAL/gfx/Render.hpp" -#include "SAL.hpp" -// Use the SFLM-level part of the texture only! -#include SAL_ADAPTER(gfx/element/Texture) - -#include //!! SALIFY! #include #include @@ -28,9 +29,6 @@ namespace SAL::gfx::adapter { namespace SFML { -//!! TEMP. HACKS UNTIL THE NAMESPACES GET RECONCILED: -using sfw::gfx::RenderContext; - class TextureFrame_Impl { diff --git a/include/SAL/gfx/element/TexturedVertex2.hpp b/include/SAL/gfx/element/TexturedVertex2.hpp index 494a7e3..4d14d39 100644 --- a/include/SAL/gfx/element/TexturedVertex2.hpp +++ b/include/SAL/gfx/element/TexturedVertex2.hpp @@ -26,6 +26,9 @@ namespace SAL::gfx // Accessors for texture pos... constexpr iVec2 texture_position() const { return Impl::_texture_position(); } +//!! Doesn't work, but also confusing syntax: .prop() = x...: +//!! constexpr iVec2& texture_position() { return Impl::_texture_position(); } + constexpr void texture_position(iVec2 txpos) { Impl::_texture_position(txpos); } //!! Be a bit more sophisticated than this embarrassment! :) diff --git a/include/SAL/gfx/element/TexturedVertex2/SFML/Impl.hpp b/include/SAL/gfx/element/TexturedVertex2/SFML/Impl.hpp index 5b899bc..efd9e6e 100644 --- a/include/SAL/gfx/element/TexturedVertex2/SFML/Impl.hpp +++ b/include/SAL/gfx/element/TexturedVertex2/SFML/Impl.hpp @@ -12,7 +12,9 @@ #include SAL_ADAPTER(gfx/element/ColorVertex2) #include "SAL/gfx/element/Texture.hpp" -#include //!! DIRECT SFML! +#include "SAL/gfx/Color.hpp" + +#include // is_same namespace SAL::gfx::adapter @@ -21,15 +23,19 @@ namespace SFML { class TexturedVertex2_Impl : public ColorVertex2_Impl { using Base = ColorVertex2_Impl; + protected: + using native_type = Base::native_type; //! Same here!... + static_assert(std::is_same_v); + public: // Inherited ctors... // Note: The missing texture coords will be initialized to zero by iVec2 itself! using Base::Base; //!! constexpr TexturedVertex2_Impl() -//!! : _d({0,0}, sf::Color::White, {0,0}) {} +//!! : _d({0,0}, Color::White, {0,0}) {} - constexpr TexturedVertex2_Impl(fVec2 pos, sf::Color color, iVec2 txpos) -//!!??OR: constexpr TexturedVertex2_Impl(const fVec2& pos, sf::Color color, const iVec2& txpos) + constexpr TexturedVertex2_Impl(fVec2 pos, Color color, iVec2 txpos) +//!!??OR: constexpr TexturedVertex2_Impl(const fVec2& pos, Color color, const iVec2& txpos) : Base(pos, color) // fVec2 auto-converts to sf::Vector { _d.texCoords = {(float)txpos.x(), (float)txpos.y()}; } //!! Alas, double init: overriding the default {0,0}!... :-/ //! This is actually a float vector in SFML; quoting from Vertex.hpp: @@ -55,6 +61,9 @@ namespace SFML // Accessors for texture pos... constexpr iVec2 _texture_position() const { return iVec2((int)native().texCoords.x, (int)native().texCoords.y); } //! See the int<->float comment at the ctors! +//!! Type mismatch (SAL vs. native), but also confusing syntax: .prop() = x...: +//!! constexpr iVec2& _texture_position() { return iVec2((int)native().texCoords.x, (int)native().texCoords.y); } //! See the int<->float comment at the ctors! + constexpr void _texture_position(iVec2 txpos) { native().texCoords = {(float)txpos.x(), (float)txpos.y()}; } //! See the int<->float comment at the ctors! @@ -70,8 +79,8 @@ namespace SFML } private: - const native_type& native() const { return _d; } - native_type& native() { return _d; } + constexpr const native_type& native() const { return _d; } + constexpr native_type& native() { return _d; } }; } // namespace SFML diff --git a/include/SAL/math/Vector.hpp b/include/SAL/math/Vector.hpp index 13ab301..f16dbee 100644 --- a/include/SAL/math/Vector.hpp +++ b/include/SAL/math/Vector.hpp @@ -80,8 +80,8 @@ namespace SAL//!!::math protected: - constexpr auto adapter() { return static_cast< Impl*>(this); } constexpr auto adapter() const { return static_cast(this); } + constexpr auto adapter() { return static_cast< Impl*>(this); } }; // class Vector_Interface diff --git a/include/SAL/math/Vector/SFML/Impl.hpp b/include/SAL/math/Vector/SFML/Impl.hpp index b95aa3b..34b5e08 100644 --- a/include/SAL/math/Vector/SFML/Impl.hpp +++ b/include/SAL/math/Vector/SFML/Impl.hpp @@ -10,9 +10,9 @@ #include // forward -namespace SAL//!!::math +namespace SAL/*!!::math!!*/::adapter { -namespace adapter::SFML +namespace SFML { template //!! Dim is totally unused; just a reminder! class Vector2_Impl @@ -55,18 +55,22 @@ namespace adapter::SFML template Vector2_Impl(NumT x, NumT y) -> Vector2_Impl; -} // namespace adapter::SFML +} // namespace SFML -// Save the specific adapter type to a backend-agnostic symbol... -namespace adapter//::active_backend -{ + + // Save the specific adapter type to a backend-agnostic symbol... + //!! + //!! This looks totally useless, as this entire header is dispached by the selected backend, + //!! so things defined here could just live directly in adapter::, no need for SFML:: too + //!! -- but... The build system can't also dispatch the translation units yet, so it would + //!! just compile -- and link -- everything together, causing name clashes across backends! + //!! template using Vector2_Impl = SFML::Vector2_Impl; //!! Use a "standard" SAL macro for the indirectly name the current backend! -} -} // namespace SAL//!!::math +} // namespace SAL/*!!::math!!*/::adapter #endif // _RVSRTYNFDGYSVEC336AB64N7W568VW47W57RT7_ diff --git a/include/sfw/GUI-main.hpp b/include/sfw/GUI-main.hpp index 997dbac..80a84f1 100644 --- a/include/sfw/GUI-main.hpp +++ b/include/sfw/GUI-main.hpp @@ -2,12 +2,12 @@ #define _KUNYWET5GX94358T645N345TF678RWE5TG67F4B57_ #include "sfw/Theme.hpp" -#include "sfw/gfx/Render.hpp" #include "sfw/Widget.hpp" #include "sfw/WidgetPtr.hpp" #include "sfw/layout/VBox.hpp" #include "sfw/gfx/element/Wallpaper.hpp" - +#include "sfw/gfx/Color.hpp" +#include "sfw/gfx/Render.hpp" #include "sfw/math/Vector.hpp" #include @@ -116,19 +116,20 @@ class GUI: public VBox /** * Set/manage wallpaper image * If `filename` is omitted, the wallpaper configured for the current theme - * (if any) will be reset. + * (if any) will be used. */ void setWallpaper(const Wallpaper::Cfg& cfg); void setWallpaper(std::string filename = "", Wallpaper::Placement placement = sfw::Wallpaper::Placement::Center, - sf::Color tintColor = sf::Color::White); + Color tintColor = Color::White); const Wallpaper& getWallpaper() const { return m_wallpaper; } void disableWallpaper(); bool hasWallpaper(); /** - * Tint the wallpaper and/or set its transparency (alpha) level + * Wallpaper color "tint" and/or transparency (alpha) level */ - void setWallpaperColor(sf::Color tint); + void setWallpaperColor(Color tint); + Color getWallpaperColor() const; // Accumulated session time (minus while !active()), in seconds float sessionTime() const; diff --git a/include/sfw/GUI.hpp b/include/sfw/GUI.hpp index d12c99b..f14c9c9 100644 --- a/include/sfw/GUI.hpp +++ b/include/sfw/GUI.hpp @@ -1,11 +1,10 @@ -#ifndef _GUI_ALL_HPP_ -#define _GUI_ALL_HPP_ +#ifndef _MCDF0V874GYE8F90RUHY75UMYB78U56MHUN98BUMVU67_ +#define _MCDF0V874GYE8F90RUHY75UMYB78U56MHUN98BUMVU67_ + #include "sfw/GUI-main.hpp" #include "sfw/Theme.hpp" -//!!#include "sfw/geometry/Orientation.hpp" //!!LEGACY: Shouldn't be (pre-)included here! - // Widgets #include "sfw/widget/Button.hpp" #include "sfw/widget/CheckBox.hpp" @@ -24,7 +23,5 @@ #include "sfw/layout/HBox.hpp" #include "sfw/layout/Form.hpp" -// Misc -//!!#include "sfw/gfx/Color.hpp" //!! Likely included by the others, though... -#endif // _GUI_ALL_HPP_ +#endif // _MCDF0V874GYE8F90RUHY75UMYB78U56MHUN98BUMVU67_ diff --git a/include/sfw/Layout.hpp b/include/sfw/Layout.hpp index b65b951..032c5bb 100644 --- a/include/sfw/Layout.hpp +++ b/include/sfw/Layout.hpp @@ -1,10 +1,12 @@ -#ifndef _SFW_LAYOUT_HPP_ -#define _SFW_LAYOUT_HPP_ +#ifndef _DOIFUU98DTHUMU985M85Y987NW4579631BRT65Z1286GYMC438Y_ +#define _DOIFUU98DTHUMU985M85Y987NW4579631BRT65Z1286GYMC438Y_ + #include "sfw/WidgetContainer.hpp" #include + namespace sfw { @@ -53,8 +55,10 @@ class Layout: public WidgetContainer private: Widget* m_hoveredWidget; Widget* m_focusedWidget; -}; -} // namespace +}; // class Layout + +} // namespace sfw + -#endif // _SFW_LAYOUT_HPP_ +#endif // _DOIFUU98DTHUMU985M85Y987NW4579631BRT65Z1286GYMC438Y_ diff --git a/include/sfw/Theme.hpp b/include/sfw/Theme.hpp index 03b7bba..35770fb 100644 --- a/include/sfw/Theme.hpp +++ b/include/sfw/Theme.hpp @@ -10,10 +10,10 @@ //!!#include "sfw/widget/Tooltip/Style.hpp" //#include "SAL/geometry/Rectangle.hpp" // Definitely done already by the rectangular things above. ;) +//#include "sfw/gfx/Color.hpp" // Also this, by those colorful things above. :) #include #include -#include #include #include @@ -41,7 +41,8 @@ class Theme const char* name = nullptr; const char* basePath = nullptr; const char* textureFile = nullptr; - sf::Color bgColor = sf::Color::White; // no "unset" color, so must use a sensible default here + Color bgColor = Color::None; // "transparent black" +//!!?? Color bgColor = Color::White; // Color::None could be the "unset" color, but white may still be more practical for debugging here Wallpaper::Cfg wallpaper = {}; size_t textSize = 0; //!!?? uint16_t: a) fixed (-> ABI compat.!), b) smaller, c) but may need annoying extra casts, d) uint_least16_t is the guaranteed type actually... const char* fontFile = nullptr; @@ -84,19 +85,19 @@ class Theme //!!CLEANUP! -> #308, #11... Should be more refined & flexible! struct Style { - sf::Color textColor; - sf::Color textColorHover; - sf::Color textColorFocus; - sf::Color textColorDisabled; - sf::Color textSelectionColor; - sf::Color textPlaceholderColor; + Color textColor; + Color textColorHover; + Color textColorFocus; + Color textColorDisabled; + Color textSelectionColor; + Color textPlaceholderColor; }; static Style click; static Style input; static size_t textSize; - static sf::Color bgColor; + static Color bgColor; static Wallpaper::Cfg wallpaper; static bool clearBackground; diff --git a/include/sfw/Widget.hpp b/include/sfw/Widget.hpp index c0b6fff..697a6f7 100644 --- a/include/sfw/Widget.hpp +++ b/include/sfw/Widget.hpp @@ -26,7 +26,7 @@ #ifdef DEBUG # -# include // for draw_outline() +# include "sfw/gfx/Color.hpp" // for draw_outline() # #endif @@ -197,8 +197,8 @@ friend class Tooltip; // just to access getMain() via Tooltip::m_owner->! #ifdef DEBUG public: - void draw_outline(const gfx::RenderContext& ctx, sf::Color outlinecolor = sf::Color::Red, - sf::Color fillcolor = sf::Color::Transparent) const; // Well, with fillColor, now it can also do interior, not just "outline" + void draw_outline(const gfx::RenderContext& ctx, Color outlinecolor = Color::Red, + Color fillcolor = Color::None) const; // Well, with fillColor, now it can also do interior, not just "outline" #endif // ---- Misc. hackery... ----------------------------------------------------- diff --git a/include/sfw/gfx/Color.hpp b/include/sfw/gfx/Color.hpp index 2b42597..3928c0b 100644 --- a/include/sfw/gfx/Color.hpp +++ b/include/sfw/gfx/Color.hpp @@ -1,138 +1,22 @@ -#ifndef _SFW_COLOR_HPP_ -#define _SFW_COLOR_HPP_ +#ifndef _GVNH234BVOFDE9R869IUEMRTMHMU89E5BHN98MHBIT7_ +#define _GVNH234BVOFDE9R869IUEMRTMHMU89E5BHN98MHBIT7_ -#include -#include -#include "SAL/util/diagnostics.hpp" +#include "SAL/gfx/Color.hpp" -//!! Auto-dispatch for the current backend instead (-> gfx/backend.hpp): -//!! Also, don't just move this to gfx/Color -- at lesat definitely not -//!! directly into that class (which shouldn't have all these deps)!... -#include - -namespace sfw { - -inline sf::Color Color(const std::string& hexcolor) +//---------------------------------------------------------------------------- +//!! Temporary kludge for the current unfinished C++ namespacing... +//---------------------------------------------------------------------------- +namespace sfw::gfx { - assert(hexcolor.size() == 7 || hexcolor.size() == 4 || hexcolor.size() == 9 || hexcolor.size() == 5); - assert(hexcolor[0] == '#'); - - sf::Color color = sf::Color::Black; - -#define CCOMP(str, pos, width) (uint8_t)std::strtoul(hexcolor.substr(1 + (pos)*(width), width).c_str(), nullptr, 16) - switch (hexcolor.size()) - { - case 7: // #rrggbb - color.r = CCOMP(hexcolor, 0, 2); - color.g = CCOMP(hexcolor, 1, 2); - color.b = CCOMP(hexcolor, 2, 2); - color.a = 255; - break; - case 4: // #rgb - color.r = CCOMP(hexcolor, 0, 1) * 17; - color.g = CCOMP(hexcolor, 1, 1) * 17; - color.b = CCOMP(hexcolor, 2, 1) * 17; - color.a = 255; - break; - case 9: // #rrggbbaa - color.r = CCOMP(hexcolor, 0, 2); - color.g = CCOMP(hexcolor, 1, 2); - color.b = CCOMP(hexcolor, 2, 2); - color.a = CCOMP(hexcolor, 3, 2); - break; - case 5: // #rgba - color.r = CCOMP(hexcolor, 0, 1) * 17; - color.g = CCOMP(hexcolor, 1, 1) * 17; - color.b = CCOMP(hexcolor, 2, 1) * 17; - color.a = CCOMP(hexcolor, 3, 1) * 17; - break; - default:; - } -#undef CCOMP - - return color; + using SAL::gfx::Color; } -/*!! Generalize, make it versatile etc.! - -struct Color //!!?? or: RGBAColor : Color +// Put it out here, too, for the time being: +namespace sfw { - enum : unsigned { - Transparent = 0, - Opaque = 255, - }; - - uint8_t r; - uint8_t g; - uint8_t b; - uint8_t a; - - Color() = default; // uninitialized - - constexpr Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a = Opaque) - : r(r), g(g), b(b), a(a) {} - - constexpr Color(uint32_t rgba) - : r(uint8_t((rgba & 0xff000000) >> 24)), - g(uint8_t((rgba & 0x00ff0000) >> 16)), - b(uint8_t((rgba & 0x0000ff00) >> 8)), - a(uint8_t((rgba & 0x000000ff)) {} - - constexpr Color(uint32_t rgb, uint_8 alpha) - : r(uint8_t((rgb & 0xff000000) >> 16)), - g(uint8_t((rgb & 0x00ff0000) >> 8)), - b(uint8_t( rgb & 0x0000ff00), - a(alpha) {} - - explicit constexpr Color(const std::string& csshexcolor) - { - auto len = hexcolor.size(); - - assert(len == 7 || len == 9 || len == 4 || len == 5); - assert(csshexcolor[0] == '#'); - - // Note: strtoul will just return 0 for garbage. - - if (len >= 7) // #rrggbb[aa] - { - color.r = (uint8_t)strtoul(csshexcolor.substr(1, 2).c_str(), nullptr, 16); - color.g = (uint8_t)strtoul(csshexcolor.substr(3, 2).c_str(), nullptr, 16); - color.b = (uint8_t)strtoul(csshexcolor.substr(5, 2).c_str(), nullptr, 16); - color.a = (len == 9) ? (uint8_t)strtoul(csshexcolor.substr(7, 2).c_str(), nullptr, 16) : Opaque; - { - else if (len >= 4) // #rgb[a] - { - color.r = (uint8_t)strtoul(csshexcolor.substr(1, 1).c_str(), nullptr, 16) * 17; - color.g = (uint8_t)strtoul(csshexcolor.substr(2, 1).c_str(), nullptr, 16) * 17; - color.b = (uint8_t)strtoul(csshexcolor.substr(3, 1).c_str(), nullptr, 16) * 17; - color.a = (len == 5) ? (uint8_t)strtoul(csshexcolor.substr(4, 1).c_str(), nullptr, 16) * 17 : Opaque; - } - else - { - // Give a chance to catch it in DEBUG mode (but leave - // it uninitialized, as in the default ctor): - assert(csshexcolor == "well-formed"); - } - } - - operator uint32_t() const { return getRGBA(); } - - void set(uint32_t rgb, uint8_t alpha) { setRGBA((rgb << 8) | alpha); } -//!! void setRGBA(uint32_t rgba), uint8_t alpha = 255) { ... } -//!! // Leave alpha unmodified: -//!! void setRGB( uint32_t rgb) uint8_t alpha = 255) { ... } - - uint32_t getRGBA() const { return (getRGB() << 8) | a; } - uint32_t getRGB() const { return (r << 24) | (g << 16) | (b << 8) | a; } - -//!! std::string getCSShex() const (uint32_t rgb, uint8_t alpha = 255) { return (rgb << 8) | alpha; } - -//!!Move to some derived Color_SFML class: -//!! oprator sf::Color() { return sf::Color(getRGBA()); } -}; -!!*/ + using SAL::gfx::Color; +} -} // namespace -#endif // _SFW_COLOR_HPP_ +#endif // _GVNH234BVOFDE9R869IUEMRTMHMU89E5BHN98MHBIT7_ diff --git a/include/sfw/gfx/element/Arrow.hpp b/include/sfw/gfx/element/Arrow.hpp index 6f35742..4980cd4 100644 --- a/include/sfw/gfx/element/Arrow.hpp +++ b/include/sfw/gfx/element/Arrow.hpp @@ -6,21 +6,22 @@ #define _ODIU4WE5OYHNUDHSRGUIFYHB87ERHO78GD4N87RGT_ -#include "SAL/gfx/element/TextureFrame.hpp" -#include "SAL/gfx/Render.hpp" +#include "sfw/gfx/element/TextureFrame.hpp" #include "sfw/math/Vector.hpp" +#include "sfw/gfx/Color.hpp" +#include "sfw/gfx/Render.hpp" namespace sfw//!!::parts { - class Arrow : public SAL::gfx::Drawable + class Arrow : public gfx::Drawable { public: - using Direction = SAL::gfx::TextureFrame::Direction; + using Direction = gfx::TextureFrame::Direction; Arrow(Direction); - void setFillColor(const sf::Color& color); //!! SALIFY sf::Color! + void setFillColor(Color color); void move(fVec2 delta); @@ -30,13 +31,13 @@ namespace sfw//!!::parts public: //! <- NOT private, because draw() may be called via the direct subclass //! statically, rather than always polymorphically (dynamically)! - void draw(const SAL::gfx::RenderContext& ctx) const override; + void draw(const gfx::RenderContext& ctx) const override; protected: void updateGeometry(fVec2 pos, Direction direction); Direction m_direction; - SAL::gfx::TextureFrame m_frame; + gfx::TextureFrame m_frame; }; } // namespace sfw//!!::parts diff --git a/include/sfw/gfx/element/Box.hpp b/include/sfw/gfx/element/Box.hpp index 6376d62..a7d4a00 100644 --- a/include/sfw/gfx/element/Box.hpp +++ b/include/sfw/gfx/element/Box.hpp @@ -4,19 +4,18 @@ #include "sfw/ActivationState.hpp" +//!!?? Should we use the SAL headers explicitly instead, here in the sfw::parts layer?! #include "sfw/math/Vector.hpp" -//!!??#include "SAL/math/Vector.hpp" #include "sfw/geometry/Rectangle.hpp" -//!!??#include "SAL/geometry/Rectangle.hpp" -#include "SAL/gfx/element/TexturedVertex2.hpp" -#include "SAL/gfx/element/Text.hpp" -#include "SAL/gfx/Render.hpp" - -#include //!! Use our own adapter class! +#include "sfw/gfx/element/TexturedVertex2.hpp" +#include "sfw/gfx/element/Text.hpp" +#include "sfw/gfx/Render.hpp" +#include "sfw/gfx/Color.hpp" #include #include + namespace sfw//!!::parts { @@ -48,7 +47,7 @@ class Box: public SAL::gfx::Drawable // Fill the interior of the box with a color, overriding its texture // The edges will NOT be affected! - void setFillColor(sf::Color color); + void setFillColor(Color color); void press(); void release(); @@ -124,7 +123,7 @@ class Box: public SAL::gfx::Drawable ActivationState m_activationState; SAL::gfx::TexturedVertex2 m_vertices[VERTEX_COUNT]; - std::optional m_fillColor; + std::optional m_fillColor; }; diff --git a/include/sfw/gfx/element/ColorVertex2.hpp b/include/sfw/gfx/element/ColorVertex2.hpp new file mode 100644 index 0000000..d817e4a --- /dev/null +++ b/include/sfw/gfx/element/ColorVertex2.hpp @@ -0,0 +1,15 @@ +#ifndef _CDFOYD9W07834E8YD5FP98EY5N73D859FYGEW985YU_ +#define _CDFOYD9W07834E8YD5FP98EY5N73D859FYGEW985YU_ + +#include "SAL/gfx/element/ColorVertex2.hpp" + +//---------------------------------------------------------------------------- +//!! Temporary kludge for the current unfinished C++ namespacing... +//---------------------------------------------------------------------------- +namespace sfw::gfx +{ + using ColorVertex2 = SAL::gfx::ColorVertex2; +} + + +#endif // _CDFOYD9W07834E8YD5FP98EY5N73D859FYGEW985YU_ diff --git a/include/sfw/gfx/element/TextureFrame.hpp b/include/sfw/gfx/element/TextureFrame.hpp new file mode 100644 index 0000000..e80e35d --- /dev/null +++ b/include/sfw/gfx/element/TextureFrame.hpp @@ -0,0 +1,16 @@ +#ifndef _TDSFMRIU6HUF6HUIM039UMHY8M73R7YHN87VX2F3_ +#define _TDSFMRIU6HUF6HUIM039UMHY8M73R7YHN87VX2F3_ + + +#include "SAL/gfx/element/TextureFrame.hpp" + +//---------------------------------------------------------------------------- +//!! Temporary kludge for the current unfinished C++ namespacing... +//---------------------------------------------------------------------------- +namespace sfw::gfx +{ + using TextureFrame = SAL::gfx::TextureFrame; +} + + +#endif // _TDSFMRIU6HUF6HUIM039UMHY8M73R7YHN87VX2F3_ diff --git a/include/sfw/gfx/element/TexturedVertex2.hpp b/include/sfw/gfx/element/TexturedVertex2.hpp new file mode 100644 index 0000000..51240b0 --- /dev/null +++ b/include/sfw/gfx/element/TexturedVertex2.hpp @@ -0,0 +1,15 @@ +#ifndef _XD098F4598GUJ689I056GI6HUMPOIYYH569UV3BM5N6_ +#define _XD098F4598GUJ689I056GI6HUMPOIYYH569UV3BM5N6_ + +#include "SAL/gfx/element/TexturedVertex2.hpp" + +//---------------------------------------------------------------------------- +//!! Temporary kludge for the current unfinished C++ namespacing... +//---------------------------------------------------------------------------- +namespace sfw::gfx +{ + using TexturedVertex2 = SAL::gfx::TexturedVertex2; +} + + +#endif // _XD098F4598GUJ689I056GI6HUMPOIYYH569UV3BM5N6_ diff --git a/include/sfw/gfx/element/Wallpaper.hpp b/include/sfw/gfx/element/Wallpaper.hpp index d8ce8fc..1ae78be 100644 --- a/include/sfw/gfx/element/Wallpaper.hpp +++ b/include/sfw/gfx/element/Wallpaper.hpp @@ -3,18 +3,17 @@ #include "sfw/gfx/element/GenericWallpaper.hpp" //!! Pretty stupid experimental design... -#include "SAL/gfx/element/Texture.hpp" -#include "SAL/gfx/element/TexturedVertex2.hpp" -#include "SAL/math/Vector.hpp" -//!!#include "SAL/math/Vector.hpp" -#include "sfw/math/Vector.hpp" //!! -//!!#include "SAL/geometry/Rectangle.hpp" -#include "sfw/geometry/Rectangle.hpp" //!! -#include "SAL/gfx/Render.hpp" - -#include -#include +#include "sfw/gfx/element/Texture.hpp" +#include "sfw/gfx/element/TexturedVertex2.hpp" +#include "sfw/math/Vector.hpp" +#include "sfw/geometry/Rectangle.hpp" +#include "sfw/gfx/Render.hpp" +#include "sfw/gfx/Color.hpp" +#include //!! DIRECT USE of sf::Image! +#include //!! Wallpaper is defined as an sf::Transformable! + +#include #include @@ -24,7 +23,7 @@ namespace sfw /** * Draw an image, possibly stretched, onto a rectangle */ -class Wallpaper: public GenericWallpaper, public SAL::gfx::Drawable, public sf::Transformable +class Wallpaper: public GenericWallpaper, public gfx::Drawable, public sf::Transformable { static constexpr geometry::iRect NullRect{}; @@ -32,10 +31,10 @@ class Wallpaper: public GenericWallpaper, public SAL::gfx::Drawable, public sf:: struct Cfg { std::string filename; - Placement placement; - sf::Color tint; + Placement placement; + Color tint; - Cfg(const std::string& f = "", Wallpaper::Placement p = Center, sf::Color c = sf::Color::White) + Cfg(std::string_view f = "", Wallpaper::Placement p = Center, Color c = Color::White) : filename(f), placement(p), @@ -47,13 +46,13 @@ class Wallpaper: public GenericWallpaper, public SAL::gfx::Drawable, public sf:: Wallpaper(); Wallpaper(std::string_view filename, const geometry::iRect& r = NullRect); Wallpaper(const sf::Image& image, const geometry::iRect& r = NullRect); - Wallpaper(const SAL::gfx::Texture& texture, const geometry::iRect& r = NullRect); + Wallpaper(const gfx::Texture& texture, const geometry::iRect& r = NullRect); Wallpaper* setImage(std::string_view filename, const geometry::iRect& r = NullRect); Wallpaper* setImage(const sf::Image& image, const geometry::iRect& r = NullRect); - Wallpaper* setImage(const SAL::gfx::Texture& texture, const geometry::iRect& r = NullRect); + Wallpaper* setImage(const gfx::Texture& texture, const geometry::iRect& r = NullRect); - const SAL::gfx::Texture& texture() const { return m_texture; } + const gfx::Texture& texture() const { return m_texture; } Wallpaper* setSize(iVec2 size); iVec2 getSize() const; @@ -68,18 +67,18 @@ class Wallpaper: public GenericWallpaper, public SAL::gfx::Drawable, public sf:: // Relative scaling based on the current size Wallpaper* rescale(float factor); - Wallpaper* setColor(const sf::Color& color); - sf::Color getColor() const; + Wallpaper* setColor(const Color& color); + Color getColor() const; public: //! <- NOT private, because draw() may be accessed directly (statically), //! rather than just polymorphically (dynamically) via a pointer! - void draw(const SAL::gfx::RenderContext& ctx) const override; + void draw(const gfx::RenderContext& ctx) const override; private: - SAL::gfx::Texture m_texture; - iVec2 m_baseSize; - float m_scalingFactor = 1.f; - SAL::gfx::TexturedVertex2 m_vertices[4]; + gfx::Texture m_texture; + iVec2 m_baseSize; + float m_scalingFactor = 1.f; + gfx::TexturedVertex2 m_vertices[4]; }; diff --git a/include/sfw/widget/Button.hpp b/include/sfw/widget/Button.hpp index 394e80a..7e16bce 100644 --- a/include/sfw/widget/Button.hpp +++ b/include/sfw/widget/Button.hpp @@ -30,8 +30,8 @@ class Button: public InputWidget