#ifndef extension_h_ #define extension_h_ #include #include #include #include #include #include #include #include #include #include #include #include "SDL.h" #include "SDL_image.h" #include "SDL_pixels.h" #define GLM_ENABLE_EXPERIMENTAL #include "glm/trigonometric.hpp" #include "glm/vec2.hpp" #include "glm/gtx/vector_angle.hpp" #include "json/json.hpp" #include "sdl2-gfx/SDL2_gfxPrimitives.h" #include "Box.hpp" #include "Segment.hpp" #include "Color.hpp" #include "filesystem.hpp" struct Pixels; namespace sfw { enum scaler {scale2x, xbr}; void set_magnitude(glm::vec2&, float); glm::vec2 point_on_circle(const glm::vec2&, float, float); glm::vec2 point_on_circle(float, float = 1.0f); void points_on_circle(std::vector&, int, float = 1.0f, const glm::vec2& = {0, 0}, float = 0.0f); std::vector points_on_circle(int, float = 1.0f, const glm::vec2& = {0, 0}, float = 0.0f); Box get_texture_box(SDL_Texture*); glm::vec2 fit_and_preserve_aspect(const glm::vec2&, const glm::vec2&); std::vector> get_blinds_boxes(glm::vec2, float = 0.05f, int = 4); void populate_pixel_2d_array(SDL_Renderer*, SDL_Texture*, std::vector>&); void populate_pixel_2d_array(SDL_Renderer*, SDL_Texture*, std::vector>&, const Box&); void apply_array_to_texture(SDL_Renderer*, SDL_Texture*, std::vector>&); void apply_array_to_texture(SDL_Renderer*, SDL_Texture*, std::vector>&, const Box&); std::vector get_halo_frames( SDL_Renderer*, float, int, const std::vector& = {Color(0, 0, 0), Color(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*, 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_pixel_scaled_texture(SDL_Renderer*, SDL_Texture*, int = 1, int = scaler::scale2x); SDL_Surface* get_surface_from_pixels(Pixels&); std::vector glob(fs::path); fs::path get_next_file_name(fs::path, int = 0, std::string = "", std::string = ""); std::string file_to_string(const fs::path&); void print_error(const std::string&); void print_sdl_error(const std::string&); /* Returns an unsorted vector of keys from the passed map */ template class Map> std::vector get_keys(const Map& map) { std::vector keys; keys.reserve(map.size()); for (auto& member : map) { keys.push_back(member.first); } return keys; } /* Returns true if member is found in container, false otherwise */ template bool is_in_container(T1& container, T2& member) { return std::find(container.begin(), container.end(), member) != container.end(); } /* Modulus that handles negative and float arguments */ template inline float mod(N a, N b) { return (b + (a % b)) % b; } /* Front pad passed end string with fill character until it is width characters long and return a new string */ template std::string pad(T end, int width, char fill = '0') { std::stringstream padded; padded.fill(fill); padded.width(width); padded << end; return padded.str(); } /* Return a vector of values in order from start to stop with step between each value, not including the stop value. * Returns a vector of the same type as step. */ template std::vector range(N start, N stop, N2 step = N(1)) { if (step == N2(0)) { throw std::invalid_argument("step for range must be non-zero"); } std::vector result; while ((step > 0) ? (start < stop) : (start > stop)) { result.push_back(start); start += step; } return result; } /* If only one argument is provided, treat it as the stop value, and use 0 for start and 1 for step */ template std::vector range(N stop) { return range(N(0), stop, N(1)); } /* Return a vector of exactly count values from start to end, inclusive, with an even amount between each value */ template std::vector range_count(N start, N end, int count) { /* negative or zero count is invalid */ if (count < 1) { throw std::invalid_argument("count argument must be greater than zero"); } 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; } /* Return a map where the keys are the percent way through the range from start to end each value is, * with step between each value. End is not included in the range. */ 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; } /* Return a map where the keys are the percent way through the range from start to end (inclusive) each value is, * with exactly count values in the range, spaced evenly. */ template std::map range_percent_count(N start, N end, int count) { /* negative or zero count is invalid */ if (count < 1) { throw std::invalid_argument("count argument must be greater than zero"); } 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; } } int SDL_SetRenderDrawColor(SDL_Renderer*, const Color&); int SDL_RenderFillRect(SDL_Renderer*, const Box&); int lineColor(SDL_Renderer*, const Segment&, const Color&, std::uint8_t = 1); template std::ostream& operator<<(std::ostream& out, const std::vector& members) { out << "{ "; for (const T& member : members) { out << member << " "; } out << "}"; return out; } std::ostream& operator<<(std::ostream&, const glm::vec2&); std::ostream& operator<<(std::ostream&, const glm::vec3&); std::ostream& operator<<(std::ostream&, const SDL_Color&); #endif