neoGFX
Cross-platform C++ app/game engine
Loading...
Searching...
No Matches
i_gradient.hpp
Go to the documentation of this file.
1// i_gradient.hpp
2/*
3 neogfx C++ App/Game Engine
4 Copyright (c) 2020 Leigh Johnston. All Rights Reserved.
5
6 This program is free software: you can redistribute it and / or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18*/
19
20#pragma once
21
22#include <neogfx/neogfx.hpp>
23#include <tuple>
25#include <neogfx/gfx/color.hpp>
27#include <neogfx/game/i_ecs.hpp>
28
29namespace neogfx
30{
32
34
35 enum class gradient_direction : uint32_t
36 {
41 Radial
42 };
43
45 {
47 bool aligned;
48 auto operator<=>(const gradient_tile&) const = default;
49 };
50
51 enum class gradient_shape : uint32_t
52 {
53 Ellipse,
54 Circle
55 };
56
57 enum class gradient_size : uint32_t
58 {
63 };
64}
65
73
78
85
86namespace neogfx
87{
88 class i_gradient_sampler
89 {
90 friend class gradient_manager;
91 public:
92 virtual ~i_gradient_sampler() = default;
93 public:
94 virtual i_shader_array<avec4u8> const& sampler() const = 0;
95 virtual uint32_t sampler_row() const = 0;
96 virtual bool used_by(gradient_id aGradient) const = 0;
97 virtual void add_ref(gradient_id aGradient) const = 0;
98 virtual void release(gradient_id aGradient) const = 0;
99 virtual void release_all() const = 0;
100 };
101
102 class i_gradient_filter
103 {
104 friend class gradient_manager;
105 public:
106 virtual ~i_gradient_filter() = default;
107 public:
108 virtual i_shader_array<float> const& sampler() const = 0;
109 private:
110 virtual i_shader_array<float>& sampler() = 0;
111 };
112
113 enum class gradient_sharing
114 {
115 Shared,
116 Unique
117 };
118
119 class i_gradient : public i_reference_counted
120 {
121 template <gradient_sharing>
122 friend class basic_gradient;
123 // exceptions
124 public:
125 struct bad_position : std::logic_error { bad_position() : std::logic_error("neogfx::i_gradient::bad_position") {} };
126 // constants
127 public:
128 static const std::uint32_t MaxStops = 256;
129 // types
130 public:
131 typedef i_gradient abstract_type;
134 typedef neolib::i_vector<color_stop> color_stop_list;
135 typedef neolib::i_vector<alpha_stop> alpha_stop_list;
136 // construction
137 public:
138 virtual ~i_gradient() = default;
139 virtual void clone(neolib::i_ref_ptr<i_gradient>& aResult) const = 0;
140 // assignment
141 public:
142 virtual i_gradient& operator=(const i_gradient& aOther) = 0;
143 // meta
144 public:
145 virtual gradient_id id() const = 0;
146 virtual bool is_singular() const = 0;
147 // operations
148 public:
149 virtual color_stop_list const& color_stops() const = 0;
150 virtual color_stop_list& color_stops() = 0;
151 virtual alpha_stop_list const& alpha_stops() const = 0;
152 virtual alpha_stop_list& alpha_stops() = 0;
153 virtual color_stop_list::const_iterator find_color_stop(scalar aPos, bool aToInsert = false) const = 0;
154 virtual color_stop_list::const_iterator find_color_stop(scalar aPos, scalar aStart, scalar aEnd, bool aToInsert = false) const = 0;
155 virtual alpha_stop_list::const_iterator find_alpha_stop(scalar aPos, bool aToInsert = false) const = 0;
156 virtual alpha_stop_list::const_iterator find_alpha_stop(scalar aPos, scalar aStart, scalar aEnd, bool aToInsert = false) const = 0;
157 virtual color_stop_list::iterator find_color_stop(scalar aPos, bool aToInsert = false) = 0;
158 virtual color_stop_list::iterator find_color_stop(scalar aPos, scalar aStart, scalar aEnd, bool aToInsert = false) = 0;
159 virtual alpha_stop_list::iterator find_alpha_stop(scalar aPos, bool aToInsert = false) = 0;
160 virtual alpha_stop_list::iterator find_alpha_stop(scalar aPos, scalar aStart, scalar aEnd, bool aToInsert = false) = 0;
161 virtual color_stop_list::iterator insert_color_stop(scalar aPos) = 0;
162 virtual color_stop_list::iterator insert_color_stop(scalar aPos, scalar aStart, scalar aEnd) = 0;
163 virtual alpha_stop_list::iterator insert_alpha_stop(scalar aPos) = 0;
164 virtual alpha_stop_list::iterator insert_alpha_stop(scalar aPos, scalar aStart, scalar aEnd) = 0;
165 virtual sRGB_color at(scalar aPos) const = 0;
166 virtual sRGB_color at(scalar aPos, scalar aStart, scalar aEnd) const = 0;
167 virtual sRGB_color color_at(scalar aPos) const = 0;
168 virtual sRGB_color color_at(scalar aPos, scalar aStart, scalar aEnd) const = 0;
169 virtual sRGB_color::view_component alpha_at(scalar aPos) const = 0;
170 virtual sRGB_color::view_component alpha_at(scalar aPos, scalar aStart, scalar aEnd) const = 0;
171 virtual i_gradient& reverse() = 0;
172 virtual i_gradient& set_alpha(sRGB_color::view_component aAlpha) = 0;
173 virtual i_gradient& set_combined_alpha(sRGB_color::view_component aAlpha) = 0;
174 virtual gradient_direction direction() const = 0;
175 virtual i_gradient& set_direction(gradient_direction aDirection) = 0;
176 virtual gradient_orientation orientation() const = 0;
177 virtual i_gradient& set_orientation(gradient_orientation aOrientation) = 0;
178 virtual gradient_shape shape() const = 0;
179 virtual i_gradient& set_shape(gradient_shape aShape) = 0;
180 virtual gradient_size size() const = 0;
181 virtual i_gradient& set_size(gradient_size aSize) = 0;
182 virtual const optional_vec2& exponents() const = 0;
183 virtual i_gradient& set_exponents(const optional_vec2& aExponents) = 0;
184 virtual const optional_point& center() const = 0;
185 virtual i_gradient& set_center(const optional_point& aCenter) = 0;
186 virtual const std::optional<gradient_tile>& tile() const = 0;
187 virtual i_gradient& set_tile(const std::optional<gradient_tile>& aTile) = 0;
188 virtual scalar smoothness() const = 0;
189 virtual i_gradient& set_smoothness(scalar aSmoothness) = 0;
190 virtual const optional_rect& bounding_box() const = 0;
191 virtual i_gradient& set_bounding_box(const optional_rect& aBoundingBox) = 0;
192 virtual i_gradient& set_bounding_box_if_none(const optional_rect& aBoundingBox) = 0;
193 // shader
194 public:
195 virtual const i_gradient_sampler& colors() const = 0;
196 virtual const i_gradient_filter& filter() const = 0;
197 // object
198 private:
199 virtual void share_object(i_ref_ptr<i_gradient>& aRef) const = 0;
200 // helpers
201 public:
202 neolib::ref_ptr<i_gradient> clone() const
203 {
205 clone(result);
206 return result;
207 }
208 neolib::ref_ptr<i_gradient> reversed() const
209 {
210 auto result = clone();
211 result->reverse();
212 return result;
213 }
214 neolib::ref_ptr<i_gradient> with_alpha(sRGB_color::view_component aAlpha) const
215 {
216 auto result = clone();
217 result->set_alpha(aAlpha);
218 return result;
219 }
220 template <typename T>
221 neolib::ref_ptr<i_gradient> with_alpha(T aAlpha, std::enable_if_t<!std::is_same_v<T, sRGB_color::view_component>, sfinae> = {})
222 {
223 return with_alpha(sRGB_color::convert<sRGB_color::view_component>(aAlpha));
224 }
225 neolib::ref_ptr<i_gradient> with_combined_alpha(sRGB_color::view_component aAlpha) const
226 {
227 auto result = clone();
228 result->set_combined_alpha(aAlpha);
229 return result;
230 }
231 template <typename T>
232 neolib::ref_ptr<i_gradient> with_combined_alpha(T aAlpha, std::enable_if_t<!std::is_same_v<T, sRGB_color::view_component>, sfinae> = {}) const
233 {
234 return with_combined_alpha(sRGB_color::convert<sRGB_color::view_component>(aAlpha));
235 }
236 neolib::ref_ptr<i_gradient> with_direction(gradient_direction aDirection) const
237 {
238 auto result = clone();
239 result->set_direction(aDirection);
240 return result;
241 }
242 neolib::ref_ptr<i_gradient> with_orientation(gradient_orientation aOrientation) const
243 {
244 auto result = clone();
245 result->set_orientation(aOrientation);
246 return result;
247 }
248 neolib::ref_ptr<i_gradient> with_shape(gradient_shape aShape) const
249 {
250 auto result = clone();
251 result->set_shape(aShape);
252 return result;
253 }
254 neolib::ref_ptr<i_gradient> with_size(gradient_size aSize) const
255 {
256 auto result = clone();
257 result->set_size(aSize);
258 return result;
259 }
260 neolib::ref_ptr<i_gradient> with_exponents(const optional_vec2& aExponents) const
261 {
262 auto result = clone();
263 result->set_exponents(aExponents);
264 return result;
265 }
266 neolib::ref_ptr<i_gradient> with_center(const optional_point& aCenter) const
267 {
268 auto result = clone();
269 result->set_center(aCenter);
270 return result;
271 }
272 neolib::ref_ptr<i_gradient> with_tile(const std::optional<gradient_tile>& aTile) const
273 {
274 auto result = clone();
275 result->set_tile(aTile);
276 return result;
277 }
278 neolib::ref_ptr<i_gradient> with_smoothness(scalar aSmoothness) const
279 {
280 auto result = clone();
281 result->set_smoothness(aSmoothness);
282 return result;
283 }
284 public:
285 static scalar normalized_position(scalar aPos, scalar aStart, scalar aEnd)
286 {
287 if (aStart != aEnd)
288 return std::max(0.0, std::min(1.0, (aPos - aStart) / (aEnd - aStart)));
289 else
290 return 0.0;
291 }
292 };
293
294 inline bool operator==(const i_gradient& aLhs, const i_gradient& aRhs)
295 {
296 if (aLhs.is_singular() != aRhs.is_singular())
297 return false;
298 else if (aLhs.is_singular())
299 return false;
300 else if (aLhs.id() == aRhs.id())
301 return true;
302 else
303 return std::forward_as_tuple(aLhs.color_stops(), aLhs.alpha_stops(), aLhs.direction(), aLhs.orientation(), aLhs.shape(), aLhs.size(), aLhs.exponents(), aLhs.center(), aLhs.tile(), aLhs.smoothness()) ==
304 std::forward_as_tuple(aRhs.color_stops(), aRhs.alpha_stops(), aRhs.direction(), aRhs.orientation(), aRhs.shape(), aRhs.size(), aRhs.exponents(), aRhs.center(), aRhs.tile(), aRhs.smoothness());
305 }
306
307 inline std::partial_ordering operator<=>(const i_gradient& aLhs, const i_gradient& aRhs)
308 {
309 if (aLhs.is_singular() || aRhs.is_singular())
310 {
311 if (aLhs.is_singular() == aRhs.is_singular())
312 return std::partial_ordering::unordered;
313 if (aLhs.is_singular() < aRhs.is_singular())
314 return std::partial_ordering::less;
315 else
316 return std::partial_ordering::greater;
317 }
318 else if (aLhs.id() == aRhs.id())
319 return std::partial_ordering::equivalent;
320 else
321 return std::forward_as_tuple(aLhs.color_stops(), aLhs.alpha_stops(), aLhs.direction(), aLhs.orientation(), aLhs.shape(), aLhs.size(), aLhs.exponents(), aLhs.center(), aLhs.tile(), aLhs.smoothness()) <=>
322 std::forward_as_tuple(aRhs.color_stops(), aRhs.alpha_stops(), aRhs.direction(), aRhs.orientation(), aRhs.shape(), aRhs.size(), aRhs.exponents(), aRhs.center(), aRhs.tile(), aRhs.smoothness());
323 }
324}
#define end_declare_enum(enumName)
Definition i_enum.hpp:62
#define declare_enum_string(enumName, enumEnumerator)
Definition i_enum.hpp:59
#define begin_declare_enum(enumName)
Definition i_enum.hpp:52
optional< rect > optional_rect
uint32_t id
game::id_t gradient_id
optional< point > optional_point
text_direction direction(glyph_char const &g)
neolib::variant< corner, scalar > gradient_orientation
bool operator==(const basic_rect< CoordinateType, CoordinateSystem > &left, const basic_rect< CoordinateType, CoordinateSystem > &right)
gradient_direction
std::partial_ordering operator<=>(const gradient &aLhs, const gradient &aRhs)
Definition gradient.hpp:189
basic_size< coordinate > size
neolib::cookie id_t
Definition ecs_ids.hpp:48
double scalar
Definition numerical.hpp:63
optional< vec2 > optional_vec2
Definition plf_hive.h:79
auto operator<=>(const gradient_tile &) const =default