From edc836908ddf8a2c015fb6e74198beab14234631 Mon Sep 17 00:00:00 2001 From: Frank DeMarco Date: Wed, 26 Aug 2020 16:43:43 -0400 Subject: [PATCH] box inherits sdl_rect; color comparison operators; pixels operator() returns pointer of void, 8bit, 16bit, or 32bit; remap texture uses pixel class --- demo/Demo.cpp | 2 +- src/Box.cpp | 45 +++++++++-------- src/Box.hpp | 10 ++-- src/Color.cpp | 39 +++++++++++++++ src/Color.hpp | 7 ++- src/Pixels.cpp | 36 ++------------ src/Pixels.hpp | 18 ++++++- src/Sprite.cpp | 17 ++++--- src/Sprite.hpp | 15 +++--- src/extension.cpp | 122 ++++++++++++++++++++++++---------------------- src/extension.hpp | 93 ++++++++++++++++++++++------------- 11 files changed, 232 insertions(+), 172 deletions(-) diff --git a/demo/Demo.cpp b/demo/Demo.cpp index 12f14d4..ae5c702 100644 --- a/demo/Demo.cpp +++ b/demo/Demo.cpp @@ -13,7 +13,7 @@ resolution, debug display, loading wheel animation, shadowed sprite, separate update and draw, sprite movement cage, multiple windows, multiple renderers, node children list, node animations list, copy constructor for node, private - and public class members + and public class members, pixel class iterator :) SWEATY HANDS :) OILY SNACKS :) AND BAD HYGIENE :) diff --git a/src/Box.cpp b/src/Box.cpp index 8cb9ba4..1c35eb3 100644 --- a/src/Box.cpp +++ b/src/Box.cpp @@ -1,45 +1,51 @@ #include "Box.hpp" -Box::Box(const glm::vec2& nw, const glm::vec2& size) : rect({nw.x, nw.y, size.x, size.y}) {} +Box::Box(const glm::vec2& nw, const glm::vec2& size) +{ + x = nw.x; + y = nw.y; + w = size.x; + h = size.y; +} float Box::get_x() const { - return rect.x; + return x; } float Box::get_y() const { - return rect.y; + return y; } float Box::get_w() const { - return rect.w; + return w; } float Box::get_h() const { - return rect.h; + return h; } void Box::set_x(float x) { - rect.x = x; + this->x = x; } void Box::set_y(float y) { - rect.y = y; + this->y = y; } -void Box::set_w(float w) +void Box::set_w(float width) { - rect.w = w; + w = width; } -void Box::set_h(float h) +void Box::set_h(float height) { - rect.h = h; + h = height; } glm::vec2 Box::get_size() const @@ -238,19 +244,12 @@ void Box::set_center(const glm::vec2& center) move(center - get_center()); } -SDL_FRect* Box::get_rect() -{ - return ▭ -} - -SDL_Rect Box::get_int_rect() const -{ - return {static_cast(rect.x), static_cast(rect.y), static_cast(rect.w), static_cast(rect.h)}; -} - Box::operator SDL_Rect() const { - return {static_cast(rect.x), static_cast(rect.y), static_cast(rect.w), static_cast(rect.h)}; + return { + static_cast(get_x()), static_cast(get_y()), + static_cast(get_w()), static_cast(get_h()) + }; } void Box::clear() @@ -327,7 +326,7 @@ bool Box::collide(const Box& box, Box& overlap) const std::ostream& Box::to_string (std::ostream& out) const { - out << "{(" << rect.x << ", " << rect.y << "), (" << rect.w << ", " << rect.h << ")}"; + out << "{(" << get_x() << ", " << get_y() << "), (" << get_w() << ", " << get_h() << ")}"; return out; } diff --git a/src/Box.hpp b/src/Box.hpp index 2a71a59..76669c4 100644 --- a/src/Box.hpp +++ b/src/Box.hpp @@ -12,11 +12,9 @@ struct Segment; -struct Box +struct Box : SDL_FRect { - SDL_FRect rect = {0, 0, 0, 0}; - Box(const glm::vec2& = {0, 0}, const glm::vec2& = {0, 0}); float get_x() const; float get_y() const; @@ -60,16 +58,14 @@ struct Box void set_south(const glm::vec2&); void set_west(const glm::vec2&); void set_center(const glm::vec2&); - SDL_FRect* get_rect(); - SDL_Rect get_int_rect() const; operator SDL_Rect() const; void clear(); void scale(float, bool = false); void move(const glm::vec2&); bool collide(const glm::vec2&) const; - bool collide(const Segment&, glm::vec2* = NULL) const; + bool collide(const Segment&, glm::vec2* = nullptr) const; bool collide(const Segment&, glm::vec2&) const; - bool collide(const Box&, Box* = NULL) const; + bool collide(const Box&, Box* = nullptr) const; bool collide(const Box&, Box&) const; std::string get_class_name() { return "Box"; } std::ostream& to_string (std::ostream&) const; diff --git a/src/Color.cpp b/src/Color.cpp index e206133..dfcd0fc 100644 --- a/src/Color.cpp +++ b/src/Color.cpp @@ -34,6 +34,45 @@ void Color::shift_hue(float offset) set_percent(red_percent, green_percent, blue_percent); } +Color::operator std::uint32_t() const +{ + SDL_PixelFormat* format = SDL_AllocFormat(SDL_PIXELFORMAT_RGBA32); + std::uint32_t pixel = SDL_MapRGBA(format, r, g, b, a); + SDL_FreeFormat(format); + return pixel; +} + +Color::operator std::uint16_t() const +{ + SDL_PixelFormat* format = SDL_AllocFormat(SDL_PIXELFORMAT_RGBA4444); + std::uint16_t pixel = SDL_MapRGBA(format, r, g, b, a); + SDL_FreeFormat(format); + return pixel; +} + +Color::operator std::uint8_t() const +{ + SDL_PixelFormat* format = SDL_AllocFormat(SDL_PIXELFORMAT_RGB332); + std::uint8_t pixel = SDL_MapRGBA(format, r, g, b, a); + SDL_FreeFormat(format); + return pixel; +} + +bool Color::operator==(const Color& color) const +{ + return r == color.r && g == color.g && b == color.b && a == color.a; +} + +bool Color::operator!=(const Color& color) const +{ + return !(*this == color); +} + +bool Color::operator<(const Color& color) const +{ + return r < color.r || g < color.g || b < color.b || a < color.a; +} + std::ostream& operator<<(std::ostream& out, const Color& color) { float h, s, v; diff --git a/src/Color.hpp b/src/Color.hpp index dcce4ef..87dc068 100644 --- a/src/Color.hpp +++ b/src/Color.hpp @@ -8,7 +8,6 @@ #include #include "SDL_pixels.h" -#include "extension.hpp" struct Color : SDL_Color { @@ -19,6 +18,12 @@ struct Color : SDL_Color void set_percent(const float&, const float&, const float&, const float&); void set_hsv(const float&, const float& = 1.0f, const float& = 1.0f); void shift_hue(float); + operator std::uint32_t() const; + operator std::uint16_t() const; + operator std::uint8_t() const; + bool operator==(const Color&) const; + bool operator!=(const Color&) const; + bool operator<(const Color&) const; template Color(T red, T green, T blue, T alpha = 255) diff --git a/src/Pixels.cpp b/src/Pixels.cpp index 04d000a..a8b343a 100644 --- a/src/Pixels.cpp +++ b/src/Pixels.cpp @@ -58,32 +58,9 @@ int Pixels::get_bytes_per_row() const return format->BytesPerPixel * rect.w; } -void* Pixels::operator()(int x, int y) +Color Pixels::get(int x, int y) { - std::uint8_t* access = static_cast(source); - if (x < 0 || x >= rect.w) - { - x = sfw::mod(x, static_cast(rect.w)); - } - if (y < 0 || y >= rect.y) - { - y = sfw::mod(y, static_cast(rect.h)); - } - return access + y * get_bytes_per_row() + x * format->BytesPerPixel; -} - -Color Pixels::operator()(int x, int y) const -{ - std::uint8_t* access = static_cast(source); - if (x < 0 || x >= rect.w) - { - x = sfw::mod(x, static_cast(rect.w)); - } - if (y < 0 || x >= rect.y) - { - y = sfw::mod(y, static_cast(rect.h)); - } - Uint32* pixel = reinterpret_cast(access + y * get_bytes_per_row() + x * format->BytesPerPixel); + std::uint32_t* pixel = operator()(x, y); Color color; SDL_GetRGBA(*pixel, const_cast(format), &color.r, &color.g, &color.b, &color.a); return color; @@ -94,18 +71,15 @@ void Pixels::set(const SDL_Color& color, int x, int y) std::uint32_t pixel = SDL_MapRGBA(const_cast(format), color.r, color.g, color.b, color.a); if (format->BytesPerPixel == 1) { - std::uint8_t* access = reinterpret_cast((*this)(x, y)); - *access = static_cast(pixel); + *operator()(x, y) = pixel; } else if (format->BytesPerPixel == 2) { - std::uint16_t* access = reinterpret_cast((*this)(x, y)); - *access = static_cast(pixel); + *operator()(x, y) = pixel; } else { - std::uint32_t* access = reinterpret_cast((*this)(x, y)); - *access = static_cast(pixel); + *operator()(x, y) = pixel; } } diff --git a/src/Pixels.hpp b/src/Pixels.hpp index d87352d..f01da21 100644 --- a/src/Pixels.hpp +++ b/src/Pixels.hpp @@ -23,12 +23,26 @@ struct Pixels Pixels(Sprite&); Pixels(Sprite&, const SDL_Rect&); int get_bytes_per_row() const; - void* operator()(int x, int y); - Color operator()(int x, int y) const; + Color get(int x, int y); void set(const SDL_Color&, int x, int y); void apply(); ~Pixels(); + template + T operator()(int x, int y) + { + std::uint8_t* access = static_cast(source); + if (x < 0 || x >= rect.w) + { + x = sfw::mod(x, static_cast(rect.w)); + } + if (y < 0 || y >= rect.y) + { + y = sfw::mod(y, static_cast(rect.h)); + } + return reinterpret_cast(access + y * get_bytes_per_row() + x * format->BytesPerPixel); + } + }; #endif diff --git a/src/Sprite.cpp b/src/Sprite.cpp index 6780fa9..d4e9a87 100644 --- a/src/Sprite.cpp +++ b/src/Sprite.cpp @@ -105,6 +105,11 @@ void Sprite::add_frames(const std::vector& frames) } } +const std::vector& Sprite::get_frames() const +{ + return frames; +} + Frameset& Sprite::get_all_frames_frameset() { return framesets[get_configuration()["animation"]["all-frames-frameset-name"]]; @@ -674,12 +679,12 @@ void Sprite::update() SDL_SetRenderTarget(renderer, NULL); if (wrap.x || wrap.y) { - SDL_Rect wrap_frame_rect = wrap_frame.get_int_rect(); + SDL_Rect wrap_frame_rect = wrap_frame; SDL_RenderSetClipRect(renderer, &wrap_frame_rect); } for (auto ii = 0; ii < static_cast(boxes.size()); ii++) { - SDL_RenderCopyF(renderer, texture, NULL, boxes[ii].get_rect()); + SDL_RenderCopyF(renderer, texture, NULL, &boxes[ii]); } if (wrap.x || wrap.y) { @@ -745,11 +750,11 @@ glm::vec2 Frameset::measure() const int w, h; for (std::size_t index : order) { - if (index < sprite->frames.size()) + if (index < sprite->get_frames().size()) { - SDL_QueryTexture(sprite->frames[index], NULL, NULL, &w, &h); - s.x = std::max(static_cast(w * sprite->scale), s.x); - s.y = std::max(static_cast(h * sprite->scale), s.y); + SDL_QueryTexture(sprite->get_frames()[index], nullptr, nullptr, &w, &h); + s.x = std::max(static_cast(w * sprite->get_scale()), s.x); + s.y = std::max(static_cast(h * sprite->get_scale()), s.y); } } return s; diff --git a/src/Sprite.hpp b/src/Sprite.hpp index daae24e..7c07dff 100644 --- a/src/Sprite.hpp +++ b/src/Sprite.hpp @@ -15,7 +15,6 @@ #include "Box.hpp" #include "Animation.hpp" #include "Color.hpp" -#include "extension.hpp" struct Game; struct Frameset; @@ -43,12 +42,13 @@ struct Sprite : Node Sprite(); Sprite(Node*); Sprite(Node*, std::string); - void reset(); - void associate(std::string); - void load(); + virtual void reset(); + virtual void associate(std::string); + virtual void load(); void load_file(fs::path); void add_frames(SDL_Texture*); void add_frames(const std::vector&); + const std::vector& get_frames() const; Frameset& get_all_frames_frameset(); Frameset& add_frameset(std::string); Frameset& set_frameset(std::string); @@ -109,7 +109,7 @@ struct Sprite : Node void add_wrap(bool, bool); void add_wrap(bool, bool, Box); void add_hue_shift_frames(int); - glm::vec2 move(glm::vec2, bool = true); + virtual glm::vec2 move(glm::vec2, bool = true); bool collide(const glm::vec2&, bool = false) const; bool collide(const Segment&, glm::vec2* = NULL, bool = false) const; bool collide(const Segment&, glm::vec2&, bool = false) const; @@ -117,8 +117,8 @@ struct Sprite : Node bool collide(const Box&, Box&, bool = false, bool = false) const; bool collide(const Sprite&, bool = false, Box* = NULL, bool = false, bool = false) const; bool collide(const Sprite&, Box&, bool = false, bool = false, bool = false) const; - void update(); - std::string get_class_name() { return "Sprite"; } + virtual void update(); + virtual std::string get_class_name() { return "Sprite"; } ~Sprite() { unload(); } }; @@ -158,5 +158,6 @@ struct Frameset #include "Pixels.hpp" #include "Game.hpp" +#include "extension.hpp" #endif diff --git a/src/extension.cpp b/src/extension.cpp index c286a25..d3e95d2 100644 --- a/src/extension.cpp +++ b/src/extension.cpp @@ -69,7 +69,7 @@ void sfw::populate_pixel_2d_array( int bytes_per_row = bytes_per_pixel * region.get_w(); int bytes_total = bytes_per_row * region.get_h(); Uint8* source = new Uint8[bytes_total]; - SDL_Rect int_rect = region.get_int_rect(); + SDL_Rect int_rect = region; if (SDL_RenderReadPixels(renderer, &int_rect, format, source, bytes_per_row) < 0) { print_sdl_error("Could not read pixels after setting remapped texture as target"); @@ -139,8 +139,7 @@ std::vector sfw::get_portal_frames( frames.reserve(count); float y_margin = 10; float max_y = size.y - y_margin; - std::vector hues = range_step(hue_start, hue_end, count); - std::cout << hues << std::endl; + std::vector hues = range_count(hue_start, hue_end, count); SDL_Texture* frame; Color color; for (int frame_ii = 0; frame_ii < count; frame_ii++) @@ -159,40 +158,79 @@ std::vector sfw::get_portal_frames( return frames; } -void sfw::fill_texture(SDL_Renderer* renderer, SDL_Texture* texture, Uint8 r, Uint8 g, Uint8 b, Uint8 a) +void sfw::fill_texture(SDL_Renderer* renderer, SDL_Texture* texture, const SDL_Color& color, const Box& box) { SDL_SetRenderTarget(renderer, texture); SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE); - SDL_SetRenderDrawColor(renderer, r, g, b, a); - SDL_RenderFillRect(renderer, NULL); + SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a); + SDL_RenderFillRectF(renderer, &box); } -void sfw::fill_texture(SDL_Renderer* renderer, SDL_Texture* texture, SDL_Texture* tile) +void sfw::fill_texture(SDL_Renderer* renderer, SDL_Texture* texture, const SDL_Color& color) +{ + fill_texture(renderer, texture, color, get_texture_box(texture)); +} + +void sfw::fill_texture(SDL_Renderer* renderer, SDL_Texture* texture, SDL_Texture* tile, const Box& box) { - SDL_SetRenderTarget(renderer, texture); Box texture_box = get_texture_box(texture), tile_box = get_texture_box(tile); SDL_FRect draw_rect; - for (int x = 0; x < texture_box.get_w(); x += tile_box.get_w()) + if (SDL_SetRenderTarget(renderer, texture) < 0) { - for (int y = 0; y < texture_box.get_h(); y += tile_box.get_h()) + print_sdl_error("could not set render target"); + } + else + { + SDL_Rect int_rect = box; + if (SDL_RenderSetClipRect(renderer, &int_rect) < 0) { - draw_rect = {(float) x, (float) y, tile_box.get_w(), tile_box.get_h()}; - SDL_RenderCopyF(renderer, tile, NULL, &draw_rect); + print_sdl_error("could not set clip"); + } + else + { + for (int x = 0; x < texture_box.get_w(); x += tile_box.get_w()) + { + for (int y = 0; y < texture_box.get_h(); y += tile_box.get_h()) + { + draw_rect = {(float) x, (float) y, tile_box.get_w(), tile_box.get_h()}; + SDL_RenderCopyF(renderer, tile, nullptr, &draw_rect); + } + } + SDL_RenderSetClipRect(renderer, nullptr); } } } +void sfw::fill_texture(SDL_Renderer* renderer, SDL_Texture* texture, SDL_Texture* tile) +{ + fill_texture(renderer, texture, tile, get_texture_box(texture)); +} + SDL_Texture* sfw::get_filled_texture(SDL_Renderer* renderer, glm::vec2 size, const SDL_Color& color, Uint32 format) { - SDL_Texture* texture = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_TARGET, size.x, size.y); - sfw::fill_texture(renderer, texture, color.r, color.g, color.b, color.a); + SDL_Texture* texture; + if ((texture = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_TARGET, size.x, size.y)) == nullptr) + { + print_sdl_error("could not create texture to fill"); + } + else + { + sfw::fill_texture(renderer, texture, color); + } return texture; } SDL_Texture* sfw::get_filled_texture(SDL_Renderer* renderer, glm::vec2 size, SDL_Texture* tile, Uint32 format) { - SDL_Texture* texture = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_TARGET, size.x, size.y); - sfw::fill_texture(renderer, texture, tile); + SDL_Texture* texture; + if ((texture = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_TARGET, size.x, size.y)) == nullptr) + { + print_sdl_error("could not create texture to fill"); + } + else + { + sfw::fill_texture(renderer, texture, tile); + } return texture; } @@ -275,7 +313,7 @@ SDL_Texture* sfw::duplicate_texture(SDL_Renderer* renderer, SDL_Texture* base, c } SDL_Texture* sfw::get_remapped_texture( - SDL_Renderer* renderer, SDL_Texture* base, const std::map& map) + SDL_Renderer* renderer, SDL_Texture* base, const std::map& map) { SDL_Texture* remapped = duplicate_texture(renderer, base); if (remapped == nullptr) @@ -288,50 +326,26 @@ SDL_Texture* sfw::get_remapped_texture( print_sdl_error("could not set render target to remapped texture"); return nullptr; } - Box box = get_texture_box(remapped); - std::uint32_t format; - SDL_QueryTexture(remapped, &format, nullptr, nullptr, nullptr); - int bytes_per_pixel = SDL_BYTESPERPIXEL(format); - int bytes_total = bytes_per_pixel * box.get_w() * box.get_h(); - unsigned char* pixels = new unsigned char[bytes_total]; - if ((SDL_RenderReadPixels(renderer, nullptr, format, pixels, bytes_total / box.get_h())) < 0) + Pixels pixels = Pixels(renderer, remapped); + for (int x = 0; x < pixels.rect.w; x++) { - print_sdl_error("could not read pixels after setting remapped texture as target"); - return nullptr; - } - SDL_Color color; - for (int ii = 0; ii < bytes_total; ii += bytes_per_pixel) - { - color = {pixels[ii], pixels[ii + 1], pixels[ii + 2], 255}; - if (bytes_per_pixel == 4) + for (int y = 0; y < pixels.rect.h; y++) { - color.a = pixels[ii + 3]; - } - for (auto& pair : map) - { - if (color.r == pair.first.r && color.g == pair.first.g && color.b == pair.first.b && - (bytes_per_pixel < 4 || color.a == pair.first.a)) + for (auto& [original, replacement] : map) { - pixels[ii] = pair.second.r; - pixels[ii + 1] = pair.second.g; - pixels[ii + 2] = pair.second.b; - if (bytes_per_pixel == 4) + if (pixels.get(x, y) == original) { - pixels[ii + 3] = pair.second.a; + pixels.set(replacement, x, y); } } } } - if (SDL_UpdateTexture(remapped, nullptr, pixels, bytes_total / box.get_h()) < 0) - { - print_sdl_error("could not update remapped texture"); - } - delete[] pixels; + pixels.apply(); return remapped; } SDL_Texture* sfw::get_remapped_texture( - SDL_Renderer* renderer, const std::string& path, const std::map& map) + SDL_Renderer* renderer, const std::string& path, const std::map& map) { SDL_Texture* base = IMG_LoadTexture(renderer, path.c_str()); if (base == nullptr) @@ -530,16 +544,6 @@ std::ostream& operator<<(std::ostream& out, const glm::vec2& vector) return out; } -bool operator<(const SDL_Color& color_1, const SDL_Color& color_2) -{ - return color_1.r < color_2.r || color_1.g < color_2.g || color_1.b < color_2.b || color_1.a < color_2.a; -} - -bool operator==(const SDL_Color& color_1, const SDL_Color& color_2) -{ - return color_1.r == color_2.r && color_1.g == color_2.g && color_1.b == color_2.b && color_1.a == color_2.a; -} - std::ostream& operator<<(std::ostream& out, const SDL_Color& color) { out << "{" << static_cast(color.r) << ", " << static_cast(color.g) << ", " << diff --git a/src/extension.hpp b/src/extension.hpp index 574ea77..2cb6778 100644 --- a/src/extension.hpp +++ b/src/extension.hpp @@ -44,15 +44,17 @@ namespace sfw std::vector get_halo_frames( Node&, float, int, const std::vector& = {{0, 0, 0, 255}, {255, 255, 255, 255}}, float = 4.0f, bool = true); std::vector get_portal_frames(SDL_Renderer*, glm::vec2, float = 60, float = 30, int = 4, int = 6); - void fill_texture(SDL_Renderer*, SDL_Texture*, Uint8, Uint8, Uint8, Uint8 = 0xff); + void fill_texture(SDL_Renderer*, SDL_Texture*, const SDL_Color&, const Box&); + void fill_texture(SDL_Renderer*, SDL_Texture*, const SDL_Color&); + void fill_texture(SDL_Renderer*, SDL_Texture*, SDL_Texture*, const Box&); void fill_texture(SDL_Renderer*, SDL_Texture*, SDL_Texture*); SDL_Texture* get_filled_texture(SDL_Renderer*, glm::vec2, const SDL_Color&, Uint32 = SDL_PIXELFORMAT_RGBA32); SDL_Texture* get_filled_texture(SDL_Renderer*, glm::vec2, SDL_Texture*, Uint32 = SDL_PIXELFORMAT_RGBA32); SDL_Texture* get_hue_shifted_texture(SDL_Renderer*, SDL_Texture*, float); SDL_Texture* duplicate_texture(SDL_Renderer*, SDL_Texture*); SDL_Texture* duplicate_texture(SDL_Renderer*, SDL_Texture*, const glm::vec2&); - SDL_Texture* get_remapped_texture(SDL_Renderer*, SDL_Texture*, const std::map&); - SDL_Texture* get_remapped_texture(SDL_Renderer*, const std::string&, const std::map&); + SDL_Texture* get_remapped_texture(SDL_Renderer*, SDL_Texture*, const std::map&); + SDL_Texture* get_remapped_texture(SDL_Renderer*, const std::string&, const std::map&); SDL_Texture* get_pixel_scaled_texture(SDL_Renderer*, SDL_Texture*, int = 1, int = scaler::scale2x); std::vector glob(fs::path); fs::path get_next_file_name( @@ -94,49 +96,71 @@ namespace sfw return padded.str(); } - template - std::vector range_step(N start, N end, int count) + template + std::vector range(N start, N stop, N2 step) { - float step = (end - start) / (count - 1); - std::vector nums; - nums.reserve(count); - for (int ii = 0; ii < count; ii++) - { - nums.push_back(start + ii * step); - } - return nums; - } - - // from https://stackoverflow.com/a/30312659/1256386 - template - std::vector range(IntType start, IntType stop, IntType step) - { - if (step == IntType(0)) + if (step == N2(0)) { throw std::invalid_argument("step for range must be non-zero"); } - std::vector result; - IntType i = start; - while ((step > 0) ? (i < stop) : (i > stop)) + std::vector result; + while ((step > 0) ? (start < stop) : (start > stop)) { - result.push_back(i); - i += step; + result.push_back(start); + start += step; } return result; } - // from https://stackoverflow.com/a/30312659/1256386 - template - std::vector range(IntType start, IntType stop) + template + std::vector range(N start, N stop) { - return range(start, stop, IntType(1)); + return range(start, stop, N(1)); } - // from https://stackoverflow.com/a/30312659/1256386 - template - std::vector range(IntType stop) + template + std::vector range(N stop) { - return range(IntType(0), stop, IntType(1)); + return range(N(0), stop, N(1)); + } + + template + std::vector range_count(N start, N end, int count) + { + float step = (end - start) / (count - 1); + std::vector all; + all.reserve(count); + for (int ii = 0; ii < count; ii++) + { + all.push_back(start + ii * step); + } + return all; + } + + template + std::map range_percent(N start, N end, N2 step = N(1)) + { + std::map range_percent_map; + std::vector all = range(start, end, step); + int ii = 0; + for (N2& current : all) + { + range_percent_map[ii++ / static_cast(all.size() - 1)] = current; + } + return range_percent_map; + } + + template + std::map range_percent_count(N start, N end, int count) + { + std::map range_percent_map; + std::vector all = range_count(start, end, count); + int ii = 0; + for (float& current : all) + { + range_percent_map[ii++ / static_cast(all.size() - 1)] = current; + } + return range_percent_map; } } @@ -154,8 +178,6 @@ std::ostream& operator<<(std::ostream& out, const std::vector& members) } std::ostream& operator<<(std::ostream&, const glm::vec2&); -bool operator<(const SDL_Color& color_1, const SDL_Color& color_2); -bool operator==(const SDL_Color& color_1, const SDL_Color& color_2); std::ostream& operator<<(std::ostream&, const SDL_Color&); namespace glm @@ -175,5 +197,6 @@ namespace glm } #include "Node.hpp" +#include "Pixels.hpp" #endif