color class, sprite hue shift, generate halo and portal effect
animation frames, ignore repeat keys, hue shifted texture
This commit is contained in:
parent
ae644b7138
commit
bab8c778ca
|
@ -11,7 +11,8 @@
|
|||
dict with metadata, move added sprite locations by offset when location is
|
||||
changed, gradients, level select code input, logging, variable screen
|
||||
resolution, debug display, loading wheel animation, shadowed sprite, separate
|
||||
update and draw, sprite movement cage, multiple windows, multiple renderers
|
||||
update and draw, sprite movement cage, multiple windows, multiple renderers,
|
||||
node children list, node animations list
|
||||
|
||||
:) SWEATY HANDS :) OILY SNACKS :) AND BAD HYGIENE :)
|
||||
|
||||
|
|
|
@ -44,6 +44,11 @@ void Animation::reset()
|
|||
timer.reset();
|
||||
}
|
||||
|
||||
bool Animation::is_playing()
|
||||
{
|
||||
return playing && !paused;
|
||||
}
|
||||
|
||||
void Animation::update()
|
||||
{
|
||||
timer.update();
|
||||
|
|
|
@ -5,11 +5,12 @@
|
|||
#include <functional>
|
||||
#include <algorithm>
|
||||
|
||||
#include "Node.hpp"
|
||||
#include "Timer.hpp"
|
||||
|
||||
typedef std::function<void()> callback;
|
||||
|
||||
struct Node;
|
||||
|
||||
struct Animation
|
||||
{
|
||||
|
||||
|
@ -34,8 +35,11 @@ struct Animation
|
|||
void pause();
|
||||
void unpause();
|
||||
void reset();
|
||||
bool is_playing();
|
||||
void update();
|
||||
|
||||
};
|
||||
|
||||
#include "Node.hpp"
|
||||
|
||||
#endif
|
||||
|
|
|
@ -14,7 +14,7 @@ struct Segment;
|
|||
|
||||
struct Box
|
||||
{
|
||||
SDL_FRect rect;
|
||||
SDL_FRect rect = {0, 0, 0, 0};
|
||||
|
||||
Box(const glm::vec2& = {0, 0}, const glm::vec2& = {0, 0});
|
||||
float get_x() const;
|
||||
|
|
|
@ -0,0 +1,181 @@
|
|||
#include "Color.hpp"
|
||||
|
||||
Color::Color() : Color(0, 0, 0, 255) {}
|
||||
|
||||
Color::Color(std::uint8_t r, std::uint8_t g, std::uint8_t b, std::uint8_t a) : r(r), g(g), b(b), a(a) {};
|
||||
|
||||
Color::Color(const SDL_Color& color) : Color(color.r, color.g, color.b, color.a) {};
|
||||
|
||||
void Color::set_rgb_float(const float& rf, const float& gf, const float& bf)
|
||||
{
|
||||
r = std::round(255.0f * rf);
|
||||
g = std::round(255.0f * gf);
|
||||
b = std::round(255.0f * bf);
|
||||
}
|
||||
|
||||
void Color::set_hsv(const float& h, const float& s, const float& v)
|
||||
{
|
||||
float rf, gf, bf;
|
||||
HSVtoRGB(rf, gf, bf, h, s, v);
|
||||
set_rgb_float(rf, gf, bf);
|
||||
}
|
||||
|
||||
void Color::shift_hue(float offset)
|
||||
{
|
||||
float h, s, v;
|
||||
float rf = r / 255.0f, gf = g / 255.0f, bf = b / 255.0f;
|
||||
RGBtoHSV(rf, gf, bf, h, s, v);
|
||||
h = std::fmod(h + offset, 360.0);
|
||||
HSVtoRGB(rf, gf, bf, h, s, v);
|
||||
set_rgb_float(rf, gf, bf);
|
||||
}
|
||||
|
||||
SDL_Color Color::get_sdl_color()
|
||||
{
|
||||
return {r, g, b, a};
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const Color& color)
|
||||
{
|
||||
float h, s, v;
|
||||
RGBtoHSV(color.r / 255.0f, color.g / 255.0f, color.b / 255.0f, h, s, v);
|
||||
out << "{r=" << static_cast<int>(color.r) << ", g=" << static_cast<int>(color.g) << ", b=" <<
|
||||
static_cast<int>(color.b) << ", a= " << static_cast<int>(color.a) << ", h=" << h <<
|
||||
", s=" << s << ", v=" << v << "}";
|
||||
return out;
|
||||
}
|
||||
|
||||
/*
|
||||
The following copyright applies to RGBtoHSV and HSVtoRGB:
|
||||
*/
|
||||
|
||||
//
|
||||
// Copyright (c) 2014, Jan Winkler <winkler@cs.uni-bremen.de>
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Universität Bremen nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/*! \brief Convert RGB to HSV color space
|
||||
|
||||
Converts a given set of RGB values `r', `g', `b' into HSV
|
||||
coordinates. The input RGB values are in the range [0, 1], and the
|
||||
output HSV values are in the ranges h = [0, 360], and s, v = [0,
|
||||
1], respectively.
|
||||
|
||||
\param fR Red component, used as input, range: [0, 1]
|
||||
\param fG Green component, used as input, range: [0, 1]
|
||||
\param fB Blue component, used as input, range: [0, 1]
|
||||
\param fH Hue component, used as output, range: [0, 360]
|
||||
\param fS Hue component, used as output, range: [0, 1]
|
||||
\param fV Hue component, used as output, range: [0, 1]
|
||||
|
||||
*/
|
||||
void RGBtoHSV(const float& fR, const float& fG, const float& fB, float& fH, float& fS, float& fV) {
|
||||
float fCMax = std::max(std::max(fR, fG), fB);
|
||||
float fCMin = std::min(std::min(fR, fG), fB);
|
||||
float fDelta = fCMax - fCMin;
|
||||
|
||||
if(fDelta > 0) {
|
||||
if(fCMax == fR) {
|
||||
fH = 60 * (std::fmod(((fG - fB) / fDelta), 6));
|
||||
} else if(fCMax == fG) {
|
||||
fH = 60 * (((fB - fR) / fDelta) + 2);
|
||||
} else if(fCMax == fB) {
|
||||
fH = 60 * (((fR - fG) / fDelta) + 4);
|
||||
}
|
||||
|
||||
if(fCMax > 0) {
|
||||
fS = fDelta / fCMax;
|
||||
} else {
|
||||
fS = 0;
|
||||
}
|
||||
|
||||
fV = fCMax;
|
||||
} else {
|
||||
fH = 0;
|
||||
fS = 0;
|
||||
fV = fCMax;
|
||||
}
|
||||
|
||||
if(fH < 0) {
|
||||
fH = 360 + fH;
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief Convert HSV to RGB color space
|
||||
|
||||
Converts a given set of HSV values `h', `s', `v' into RGB
|
||||
coordinates. The output RGB values are in the range [0, 1], and
|
||||
the input HSV values are in the ranges h = [0, 360], and s, v =
|
||||
[0, 1], respectively.
|
||||
|
||||
\param fR Red component, used as output, range: [0, 1]
|
||||
\param fG Green component, used as output, range: [0, 1]
|
||||
\param fB Blue component, used as output, range: [0, 1]
|
||||
\param fH Hue component, used as input, range: [0, 360]
|
||||
\param fS Hue component, used as input, range: [0, 1]
|
||||
\param fV Hue component, used as input, range: [0, 1]
|
||||
|
||||
*/
|
||||
void HSVtoRGB(float& fR, float& fG, float& fB, const float& fH, const float& fS, const float& fV) {
|
||||
float fC = fV * fS; // Chroma
|
||||
float fHPrime = std::fmod(fH / 60.0, 6);
|
||||
float fX = fC * (1 - std::fabs(std::fmod(fHPrime, 2) - 1));
|
||||
float fM = fV - fC;
|
||||
|
||||
if(0 <= fHPrime && fHPrime < 1) {
|
||||
fR = fC;
|
||||
fG = fX;
|
||||
fB = 0;
|
||||
} else if(1 <= fHPrime && fHPrime < 2) {
|
||||
fR = fX;
|
||||
fG = fC;
|
||||
fB = 0;
|
||||
} else if(2 <= fHPrime && fHPrime < 3) {
|
||||
fR = 0;
|
||||
fG = fC;
|
||||
fB = fX;
|
||||
} else if(3 <= fHPrime && fHPrime < 4) {
|
||||
fR = 0;
|
||||
fG = fX;
|
||||
fB = fC;
|
||||
} else if(4 <= fHPrime && fHPrime < 5) {
|
||||
fR = fX;
|
||||
fG = 0;
|
||||
fB = fC;
|
||||
} else if(5 <= fHPrime && fHPrime < 6) {
|
||||
fR = fC;
|
||||
fG = 0;
|
||||
fB = fX;
|
||||
} else {
|
||||
fR = 0;
|
||||
fG = 0;
|
||||
fB = 0;
|
||||
}
|
||||
|
||||
fR += fM;
|
||||
fG += fM;
|
||||
fB += fM;
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
#ifndef Color_h_
|
||||
#define Color_h_
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cmath>
|
||||
#include <ostream>
|
||||
|
||||
#include "SDL_pixels.h"
|
||||
|
||||
struct Color
|
||||
{
|
||||
|
||||
std::uint8_t r, g, b, a;
|
||||
|
||||
Color();
|
||||
Color(std::uint8_t, std::uint8_t, std::uint8_t, std::uint8_t);
|
||||
Color(const SDL_Color&);
|
||||
void set_rgb_float(const float&, const float&, const float&);
|
||||
void set_hsv(const float&, const float& = 1.0f, const float& = 1.0f);
|
||||
void shift_hue(float);
|
||||
SDL_Color get_sdl_color();
|
||||
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream&, const Color&);
|
||||
void RGBtoHSV(const float&, const float&, const float&, float&, float&, float&);
|
||||
void HSVtoRGB(float&, float&, float&, const float&, const float&, const float&);
|
||||
|
||||
#endif
|
|
@ -31,7 +31,8 @@ void Configuration::set_defaults()
|
|||
{"system-any-key-ignore-commands",
|
||||
{"fullscreen", "screenshot", "toggle-framerate", "record", "quit"}},
|
||||
{"any-key-ignore-commands", {}},
|
||||
{"default-unsuppress-delay", 700}
|
||||
{"default-unsuppress-delay", 700},
|
||||
{"ignore-repeat-keypress", true}
|
||||
};
|
||||
sys_config["path"] = {
|
||||
{"screenshots", "."},
|
||||
|
|
|
@ -6,19 +6,33 @@ Display::Display(Node* parent) : Node(parent)
|
|||
get_delegate().subscribe(&Display::respond, this);
|
||||
}
|
||||
|
||||
glm::ivec2 Display::get_window_size()
|
||||
glm::ivec2 Display::get_window_size() const
|
||||
{
|
||||
glm::ivec2 size;
|
||||
SDL_GetWindowSize(get_root()->get_window(), &size.x, &size.y);
|
||||
SDL_GetWindowSize(const_cast<SDL_Window*>(get_window()), &size.x, &size.y);
|
||||
return size;
|
||||
}
|
||||
|
||||
Box Display::get_window_box()
|
||||
Box Display::get_window_box() const
|
||||
{
|
||||
return Box(glm::vec2(0, 0), get_window_size());
|
||||
}
|
||||
|
||||
void Display::get_screen_pixels(unsigned char* pixels, int w, int h, int x, int y)
|
||||
Uint32 Display::get_pixel_format(int display_index) const
|
||||
{
|
||||
SDL_DisplayMode display_mode;
|
||||
if (SDL_GetCurrentDisplayMode(display_index, &display_mode) != 0)
|
||||
{
|
||||
SDL_Log("could not get display mode for index %i: %s", display_index, SDL_GetError());
|
||||
return SDL_PIXELFORMAT_UNKNOWN;
|
||||
}
|
||||
else
|
||||
{
|
||||
return display_mode.format;
|
||||
}
|
||||
}
|
||||
|
||||
void Display::get_screen_pixels(unsigned char* pixels, int w, int h, int x, int y) const
|
||||
{
|
||||
if (get_root()->is_gl_context)
|
||||
{
|
||||
|
@ -38,20 +52,14 @@ void Display::get_screen_pixels(unsigned char* pixels, int w, int h, int x, int
|
|||
}
|
||||
else
|
||||
{
|
||||
// Uint32 format;
|
||||
// #if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||
// format = SDL_PIXELFORMAT_ARGB8888;
|
||||
// #else
|
||||
// format = SDL_PIXELFORMAT_ABGR8888;
|
||||
// #endif
|
||||
SDL_SetRenderTarget(get_root()->renderer, NULL);
|
||||
SDL_RenderPresent(get_root()->renderer);
|
||||
SDL_RenderReadPixels(
|
||||
get_root()->renderer, NULL, SDL_PIXELFORMAT_RGBA32, pixels, bpp / 8 * w);
|
||||
SDL_Renderer* renderer = const_cast<SDL_Renderer*>(get_renderer());
|
||||
SDL_SetRenderTarget(renderer, NULL);
|
||||
SDL_RenderPresent(renderer);
|
||||
SDL_RenderReadPixels(renderer, NULL, SDL_PIXELFORMAT_RGBA32, pixels, bpp / 8 * w);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_Surface* Display::get_screen_surface()
|
||||
SDL_Surface* Display::get_screen_surface() const
|
||||
{
|
||||
glm::ivec2 size = get_window_size();
|
||||
unsigned char* pixels = new unsigned char[bpp / 8 * size.x * size.y];
|
||||
|
@ -62,8 +70,7 @@ SDL_Surface* Display::get_screen_surface()
|
|||
return surface;
|
||||
}
|
||||
|
||||
SDL_Surface* Display::get_screen_surface_from_pixels(
|
||||
unsigned char* pixels, bool flip)
|
||||
SDL_Surface* Display::get_screen_surface_from_pixels(unsigned char* pixels, bool flip) const
|
||||
{
|
||||
glm::ivec2 size = get_window_size();
|
||||
SDL_Surface* surface;
|
||||
|
@ -102,16 +109,17 @@ void Display::respond(SDL_Event& event)
|
|||
}
|
||||
}
|
||||
|
||||
void Display::toggle_fullscreen()
|
||||
void Display::toggle_fullscreen() const
|
||||
{
|
||||
if (SDL_GetWindowFlags(get_root()->get_window()) & SDL_WINDOW_FULLSCREEN)
|
||||
SDL_Window* window = const_cast<SDL_Window*>(get_window());
|
||||
if (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN)
|
||||
{
|
||||
SDL_Log("fullscreen requested");
|
||||
SDL_SetWindowFullscreen(get_root()->window, 0);
|
||||
SDL_SetWindowFullscreen(window, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_Log("exit fullscreen requested");
|
||||
SDL_SetWindowFullscreen(get_root()->get_window(), SDL_WINDOW_FULLSCREEN);
|
||||
SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,13 +23,14 @@ struct Display : Node
|
|||
const static int bpp = 32;
|
||||
|
||||
Display(Node*);
|
||||
glm::ivec2 get_window_size();
|
||||
Box get_window_box();
|
||||
void get_screen_pixels(unsigned char*, int, int, int = 0, int = 0);
|
||||
SDL_Surface* get_screen_surface();
|
||||
SDL_Surface* get_screen_surface_from_pixels(unsigned char*, bool);
|
||||
glm::ivec2 get_window_size() const;
|
||||
Uint32 get_pixel_format(int = 0) const;
|
||||
Box get_window_box() const;
|
||||
void get_screen_pixels(unsigned char*, int, int, int = 0, int = 0) const;
|
||||
SDL_Surface* get_screen_surface() const;
|
||||
SDL_Surface* get_screen_surface_from_pixels(unsigned char*, bool) const;
|
||||
void respond(SDL_Event&);
|
||||
void toggle_fullscreen();
|
||||
void toggle_fullscreen() const;
|
||||
|
||||
};
|
||||
|
||||
|
|
17
src/Game.cpp
17
src/Game.cpp
|
@ -38,7 +38,7 @@ void FramerateIndicator::refresh()
|
|||
unload();
|
||||
SDL_Surface* surface = get_surface();
|
||||
SDL_Texture* texture = SDL_CreateTextureFromSurface(get_root()->get_renderer(), surface);
|
||||
add_frame(texture);
|
||||
add_frames(texture);
|
||||
SDL_FreeSurface(surface);
|
||||
set_ne(get_display().get_window_box().get_ne());
|
||||
}
|
||||
|
@ -445,6 +445,11 @@ std::string Game::get_pixel_format_string(Uint32 format)
|
|||
return pixel_format;
|
||||
}
|
||||
|
||||
const SDL_Window* Game::get_window() const
|
||||
{
|
||||
return window;
|
||||
}
|
||||
|
||||
SDL_Window* Game::get_window()
|
||||
{
|
||||
return window;
|
||||
|
@ -460,6 +465,16 @@ SDL_Renderer* Game::get_renderer()
|
|||
return renderer;
|
||||
}
|
||||
|
||||
const Input& Game::get_input() const
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
Input& Game::get_input()
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
glm::vec2 Game::weight(glm::vec2 motion)
|
||||
{
|
||||
return {weight(motion.x), weight(motion.y)};
|
||||
|
|
|
@ -67,6 +67,7 @@ struct Game : Node
|
|||
|
||||
Game();
|
||||
~Game();
|
||||
virtual void reset() { activate(); }
|
||||
void print_error(const std::string&);
|
||||
void print_sdl_error(const std::string&);
|
||||
void print_gl_attributes();
|
||||
|
@ -77,9 +78,12 @@ struct Game : Node
|
|||
void log_display_mode();
|
||||
void log_surface_format(SDL_Surface*, std::string = "surface");
|
||||
std::string get_pixel_format_string(Uint32);
|
||||
const SDL_Window* get_window() const;
|
||||
SDL_Window* get_window();
|
||||
const SDL_Renderer* get_renderer() const;
|
||||
SDL_Renderer* get_renderer();
|
||||
const Input& get_input() const;
|
||||
Input& get_input();
|
||||
glm::vec2 weight(glm::vec2);
|
||||
void run();
|
||||
void frame(float);
|
||||
|
|
|
@ -86,23 +86,27 @@ void Input::respond(SDL_Event &event)
|
|||
suppress_any_key = get_configuration()["input"]["suppress-any-key-on-mods"] && (ctrl || alt);
|
||||
const std::vector<std::string>& system_any_key_ignore = get_configuration()["input"]["system-any-key-ignore-commands"];
|
||||
const std::vector<std::string>& any_key_ignore = get_configuration()["input"]["any-key-ignore-commands"];
|
||||
for (KeyCombination& combination : key_map)
|
||||
bool ignore_repeat = get_configuration()["input"]["ignore-repeat-keypress"];
|
||||
if (event.key.repeat == 0 || !ignore_repeat)
|
||||
{
|
||||
if (sym == combination.key && (!combination.ctrl || ctrl) && (!combination.shift || shift) &&
|
||||
(!combination.alt || alt))
|
||||
for (KeyCombination& combination : key_map)
|
||||
{
|
||||
post_command(combination.command, cancel);
|
||||
if (!sfw::is_in_container(system_any_key_ignore, combination.command) && !found_command &&
|
||||
!sfw::is_in_container(any_key_ignore, combination.command) && !suppress_any_key)
|
||||
if (sym == combination.key && (!combination.ctrl || ctrl) && (!combination.shift || shift) &&
|
||||
(!combination.alt || alt))
|
||||
{
|
||||
post_command(any, cancel);
|
||||
post_command(combination.command, cancel);
|
||||
if (!sfw::is_in_container(system_any_key_ignore, combination.command) && !found_command &&
|
||||
!sfw::is_in_container(any_key_ignore, combination.command) && !suppress_any_key)
|
||||
{
|
||||
post_command(any, cancel);
|
||||
}
|
||||
found_command = true;
|
||||
}
|
||||
found_command = true;
|
||||
}
|
||||
}
|
||||
if (!found_command && !suppress_any_key)
|
||||
{
|
||||
post_command(any, cancel);
|
||||
if (!found_command && !suppress_any_key)
|
||||
{
|
||||
post_command(any, cancel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
41
src/Node.cpp
41
src/Node.cpp
|
@ -14,16 +14,6 @@ void Node::set_parent(Node* other)
|
|||
parent = other;
|
||||
}
|
||||
|
||||
void Node::activate()
|
||||
{
|
||||
active = true;
|
||||
}
|
||||
|
||||
void Node::deactivate()
|
||||
{
|
||||
active = false;
|
||||
}
|
||||
|
||||
bool Node::is_active() const
|
||||
{
|
||||
return active;
|
||||
|
@ -39,7 +29,7 @@ Delegate& Node::get_delegate()
|
|||
return get_root()->delegate;
|
||||
}
|
||||
|
||||
Display& Node::get_display()
|
||||
const Display& Node::get_display() const
|
||||
{
|
||||
return get_root()->display;
|
||||
}
|
||||
|
@ -54,11 +44,21 @@ SDL_Renderer* Node::get_renderer()
|
|||
return get_root()->get_renderer();
|
||||
}
|
||||
|
||||
const SDL_Window* Node::get_window() const
|
||||
{
|
||||
return get_root()->get_window();
|
||||
}
|
||||
|
||||
SDL_Window* Node::get_window()
|
||||
{
|
||||
return get_root()->get_window();
|
||||
}
|
||||
|
||||
const Input& Node::get_input() const
|
||||
{
|
||||
return get_root()->get_input();
|
||||
}
|
||||
|
||||
const Game* Node::get_root() const
|
||||
{
|
||||
const Node* root = this;
|
||||
|
@ -69,14 +69,29 @@ const Game* Node::get_root() const
|
|||
return dynamic_cast<const Game*>(root);
|
||||
}
|
||||
|
||||
Box Node::get_window_box()
|
||||
{
|
||||
return get_display().get_window_box();
|
||||
}
|
||||
|
||||
void Node::suppress_input()
|
||||
{
|
||||
get_root()->get_input().suppress();
|
||||
}
|
||||
|
||||
void Node::suppress_input_temporarily(int length)
|
||||
{
|
||||
get_root()->input.suppress();
|
||||
suppress_input();
|
||||
if (length == 0)
|
||||
{
|
||||
length = get_configuration()["input"]["default-unsuppress-delay"];
|
||||
}
|
||||
get_root()->input.unsuppress_animation.play_once(length);
|
||||
get_root()->get_input().unsuppress_animation.play_once(length);
|
||||
}
|
||||
|
||||
void Node::unsuppress_input()
|
||||
{
|
||||
get_root()->get_input().unsuppress();
|
||||
}
|
||||
|
||||
void Node::print_branch()
|
||||
|
|
17
src/Node.hpp
17
src/Node.hpp
|
@ -7,11 +7,13 @@
|
|||
#include "json/json.hpp"
|
||||
#include "SDL.h"
|
||||
|
||||
#include "Box.hpp"
|
||||
#include "filesystem.hpp"
|
||||
|
||||
struct Game;
|
||||
struct Delegate;
|
||||
struct Display;
|
||||
struct Input;
|
||||
|
||||
struct Node
|
||||
{
|
||||
|
@ -22,18 +24,24 @@ struct Node
|
|||
Node();
|
||||
Node(Node*);
|
||||
void set_parent(Node*);
|
||||
void activate();
|
||||
void deactivate();
|
||||
virtual void reset() { deactivate(); };
|
||||
virtual void reset() { deactivate(); }
|
||||
virtual void activate() { active = true; }
|
||||
virtual void deactivate() { active = false; }
|
||||
bool is_active() const;
|
||||
nlohmann::json& get_configuration();
|
||||
Delegate& get_delegate();
|
||||
Display& get_display();
|
||||
const Display& get_display() const;
|
||||
const SDL_Renderer* get_renderer() const;
|
||||
SDL_Renderer* get_renderer();
|
||||
const SDL_Window* get_window() const;
|
||||
SDL_Window* get_window();
|
||||
const Input& get_input() const;
|
||||
Input& get_input();
|
||||
const Game* get_root() const;
|
||||
Box get_window_box();
|
||||
void suppress_input();
|
||||
void suppress_input_temporarily(int = 0);
|
||||
void unsuppress_input();
|
||||
void print_branch();
|
||||
virtual std::string get_class_name() { return "Node"; };
|
||||
virtual ~Node();
|
||||
|
@ -56,5 +64,6 @@ struct Node
|
|||
#include "Configuration.hpp"
|
||||
#include "Delegate.hpp"
|
||||
#include "Display.hpp"
|
||||
#include "Input.hpp"
|
||||
|
||||
#endif
|
||||
|
|
|
@ -275,7 +275,7 @@ void Recorder::keep_stash()
|
|||
{
|
||||
in_game_stashes.push_back(current_stash);
|
||||
current_stash = Stash();
|
||||
int max_stashes = get_configuration()["recording"]["max-in-game-stashes"];
|
||||
auto max_stashes = get_configuration()["recording"]["max-in-game-stashes"];
|
||||
if (in_game_stashes.size() > max_stashes)
|
||||
{
|
||||
Stash& stash = in_game_stashes.front();
|
||||
|
|
|
@ -15,6 +15,12 @@ Sprite::Sprite(Node* parent, std::string path) : Sprite(parent)
|
|||
associate(path);
|
||||
}
|
||||
|
||||
void Sprite::reset()
|
||||
{
|
||||
Node::reset();
|
||||
activate();
|
||||
}
|
||||
|
||||
void Sprite::associate(std::string path)
|
||||
{
|
||||
if (fs::is_regular_file(path))
|
||||
|
@ -70,17 +76,17 @@ void Sprite::load_file(fs::path path)
|
|||
}
|
||||
else
|
||||
{
|
||||
add_frame(texture);
|
||||
add_frames(texture);
|
||||
}
|
||||
}
|
||||
|
||||
void Sprite::add_frame(SDL_Texture* texture)
|
||||
void Sprite::add_frames(SDL_Texture* frame)
|
||||
{
|
||||
bool preserve_center = frames.size() > 0;
|
||||
frames.push_back(texture);
|
||||
frames.push_back(frame);
|
||||
Frameset& all_frames_frameset = get_all_frames_frameset();
|
||||
all_frames_frameset.clear();
|
||||
for (int ii = 0; ii < frames.size(); ii++)
|
||||
for (std::size_t ii = 0; ii < frames.size(); ii++)
|
||||
{
|
||||
all_frames_frameset.add_frame_index(ii);
|
||||
}
|
||||
|
@ -91,6 +97,14 @@ void Sprite::add_frame(SDL_Texture* texture)
|
|||
update_size(preserve_center);
|
||||
}
|
||||
|
||||
void Sprite::add_frames(const std::vector<SDL_Texture*>& frames)
|
||||
{
|
||||
for (SDL_Texture* frame : frames)
|
||||
{
|
||||
add_frames(frame);
|
||||
}
|
||||
}
|
||||
|
||||
Frameset& Sprite::get_all_frames_frameset()
|
||||
{
|
||||
return framesets[get_configuration()["animation"]["all-frames-frameset-name"]];
|
||||
|
@ -126,6 +140,11 @@ const Frameset& Sprite::get_current_frameset() const
|
|||
return framesets.at(current_frameset_name);
|
||||
}
|
||||
|
||||
void Sprite::set_frame_length(float length)
|
||||
{
|
||||
get_current_frameset().set_frame_length(length);
|
||||
}
|
||||
|
||||
SDL_Texture* Sprite::get_current_frame() const
|
||||
{
|
||||
return frames[get_current_frameset().get_current_frame_index()];
|
||||
|
@ -152,7 +171,7 @@ void Sprite::add_box(glm::vec2 position, bool absolute)
|
|||
|
||||
void Sprite::update_size(bool preserve_center)
|
||||
{
|
||||
for (int ii = 0; ii < boxes.size(); ii++)
|
||||
for (std::size_t ii = 0; ii < boxes.size(); ii++)
|
||||
{
|
||||
boxes[ii].set_size(get_current_frameset().get_size(), preserve_center);
|
||||
if (scale != 1)
|
||||
|
@ -367,6 +386,16 @@ void Sprite::set_center_y(float y)
|
|||
move({0, y - get_center_y()}, false);
|
||||
}
|
||||
|
||||
void Sprite::set_nw(const glm::vec2& nw)
|
||||
{
|
||||
move(nw - get_nw(), false);
|
||||
}
|
||||
|
||||
void Sprite::set_ne(const glm::vec2& ne)
|
||||
{
|
||||
move(ne - get_ne(), false);
|
||||
}
|
||||
|
||||
void Sprite::set_se(const glm::vec2& se)
|
||||
{
|
||||
move(se - get_se(), false);
|
||||
|
@ -382,14 +411,9 @@ void Sprite::set_sw(const glm::vec2& sw)
|
|||
move(sw - get_sw(), false);
|
||||
}
|
||||
|
||||
void Sprite::set_nw(const glm::vec2& nw)
|
||||
void Sprite::set_west(const glm::vec2& west)
|
||||
{
|
||||
move(nw - get_nw(), false);
|
||||
}
|
||||
|
||||
void Sprite::set_ne(const glm::vec2& ne)
|
||||
{
|
||||
move(ne - get_ne(), false);
|
||||
move(west - get_west(), false);
|
||||
}
|
||||
|
||||
void Sprite::set_center(const glm::vec2& center)
|
||||
|
@ -424,6 +448,16 @@ void Sprite::add_wrap(bool x, bool y, Box frame)
|
|||
wrap_frame = frame;
|
||||
}
|
||||
|
||||
void Sprite::add_hue_shift_frames(int count)
|
||||
{
|
||||
float step = 360 / (count + 1);
|
||||
SDL_Texture* base = get_current_frame();
|
||||
for (float offset = step; offset <= 359.9; offset += step)
|
||||
{
|
||||
add_frames(sfw::get_hue_shifted_texture(get_renderer(), base, offset));
|
||||
}
|
||||
}
|
||||
|
||||
glm::vec2 Sprite::move(glm::vec2 delta, bool weighted)
|
||||
{
|
||||
if (weighted)
|
||||
|
@ -530,7 +564,7 @@ bool Sprite::collide(const Box& box, bool precise, Box* overlap, bool all, SDL_T
|
|||
overlap = &o;
|
||||
}
|
||||
}
|
||||
for (int ii = 0; ii < get_boxes().size(); ii++)
|
||||
for (auto ii = 0; ii < static_cast<int>(get_boxes().size()); ii++)
|
||||
{
|
||||
if (get_box(ii).collide(box, overlap))
|
||||
{
|
||||
|
@ -643,7 +677,7 @@ void Sprite::update()
|
|||
SDL_Rect wrap_frame_rect = wrap_frame.get_int_rect();
|
||||
SDL_RenderSetClipRect(renderer, &wrap_frame_rect);
|
||||
}
|
||||
for (int ii = 0; ii < boxes.size(); ii++)
|
||||
for (auto ii = 0; ii < static_cast<int>(boxes.size()); ii++)
|
||||
{
|
||||
SDL_RenderCopyF(renderer, texture, NULL, boxes[ii].get_rect());
|
||||
}
|
||||
|
@ -709,7 +743,7 @@ glm::vec2 Frameset::measure() const
|
|||
{
|
||||
glm::vec2 s(0, 0);
|
||||
int w, h;
|
||||
for (int index : order)
|
||||
for (std::size_t index : order)
|
||||
{
|
||||
if (index < sprite->frames.size())
|
||||
{
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "Node.hpp"
|
||||
#include "Box.hpp"
|
||||
#include "Animation.hpp"
|
||||
#include "Color.hpp"
|
||||
#include "extension.hpp"
|
||||
|
||||
struct Game;
|
||||
|
@ -42,14 +43,17 @@ struct Sprite : Node
|
|||
Sprite();
|
||||
Sprite(Node*);
|
||||
Sprite(Node*, std::string);
|
||||
void reset();
|
||||
void associate(std::string);
|
||||
void load();
|
||||
void load_file(fs::path);
|
||||
void add_frame(SDL_Texture*);
|
||||
void add_frames(SDL_Texture*);
|
||||
void add_frames(const std::vector<SDL_Texture*>&);
|
||||
Frameset& get_all_frames_frameset();
|
||||
Frameset& add_frameset(std::string);
|
||||
Frameset& set_frameset(std::string);
|
||||
Frameset& get_current_frameset();
|
||||
void set_frame_length(float);
|
||||
const Frameset& get_current_frameset() const;
|
||||
SDL_Texture* get_current_frame() const;
|
||||
const Box& get_box(int = 0) const;
|
||||
|
@ -100,9 +104,11 @@ struct Sprite : Node
|
|||
void set_se(const glm::vec2&);
|
||||
void set_south(const glm::vec2&);
|
||||
void set_sw(const glm::vec2&);
|
||||
void set_west(const glm::vec2&);
|
||||
void set_center(const glm::vec2&);
|
||||
void add_wrap(bool, bool);
|
||||
void add_wrap(bool, bool, Box);
|
||||
void add_hue_shift_frames(int);
|
||||
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;
|
||||
|
@ -125,7 +131,7 @@ struct Frameset
|
|||
int order_index = 0;
|
||||
float frame_length = 0;
|
||||
bool reversed = false;
|
||||
glm::vec2 size;
|
||||
glm::vec2 size = {0, 0};
|
||||
|
||||
Frameset();
|
||||
Frameset(Sprite*);
|
||||
|
|
|
@ -96,6 +96,69 @@ void sfw::populate_pixel_2d_array(
|
|||
}
|
||||
}
|
||||
|
||||
std::vector<SDL_Texture*> sfw::get_halo_frames(
|
||||
Node& node, float radius, int segment_count, const std::vector<SDL_Color>& colors, float min_radius, bool fade)
|
||||
{
|
||||
std::vector<SDL_Texture*> frames;
|
||||
frames.reserve(segment_count);
|
||||
SDL_Renderer* renderer = node.get_renderer();
|
||||
SDL_Texture* frame;
|
||||
float alpha = 255, alpha_step = 255.0f / segment_count, segment_radius;
|
||||
int color_count = colors.size();
|
||||
SDL_Color color;
|
||||
for (int color_offset = 0; color_offset < color_count; color_offset++)
|
||||
{
|
||||
if (fade)
|
||||
{
|
||||
alpha = alpha_step;
|
||||
}
|
||||
frame = sfw::get_filled_texture(renderer, {2 * radius, 2 * radius}, {255, 255, 255, 0});
|
||||
SDL_SetTextureBlendMode(frame, SDL_BLENDMODE_BLEND);
|
||||
SDL_SetRenderTarget(renderer, frame);
|
||||
for (int segment_ii = 0; segment_ii < segment_count; segment_ii++)
|
||||
{
|
||||
color = colors[(color_offset + segment_ii) % color_count];
|
||||
color.a = std::round(alpha);
|
||||
segment_radius = min_radius + (segment_count - 1.0f - segment_ii) / (segment_count - 1.0f) * (radius - min_radius);
|
||||
aaFilledEllipseRGBA(
|
||||
renderer, radius, radius, segment_radius, segment_radius, color.r, color.g, color.b, color.a);
|
||||
if (fade)
|
||||
{
|
||||
alpha += alpha_step;
|
||||
}
|
||||
}
|
||||
frames.push_back(frame);
|
||||
}
|
||||
return frames;
|
||||
}
|
||||
|
||||
std::vector<SDL_Texture*> sfw::get_portal_frames(
|
||||
SDL_Renderer* renderer, glm::vec2 size, float hue_start, float hue_end, int dy, int count)
|
||||
{
|
||||
std::vector<SDL_Texture*> frames;
|
||||
frames.reserve(count);
|
||||
float y_margin = 10;
|
||||
float max_y = size.y - y_margin;
|
||||
std::vector<float> hues = range_step(hue_start, hue_end, count);
|
||||
std::cout << hues << std::endl;
|
||||
SDL_Texture* frame;
|
||||
Color color;
|
||||
for (int frame_ii = 0; frame_ii < count; frame_ii++)
|
||||
{
|
||||
frame = sfw::get_filled_texture(renderer, size, {255, 255, 255, 0});
|
||||
SDL_SetRenderTarget(renderer, frame);
|
||||
SDL_SetTextureBlendMode(frame, SDL_BLENDMODE_BLEND);
|
||||
for (int ellipse_ii = 0, y = max_y; y > y_margin - 3; ellipse_ii++, y -= dy)
|
||||
{
|
||||
color.a = y / max_y * 255.0f;
|
||||
color.set_hsv(hues[mod(ellipse_ii - frame_ii, count)]);
|
||||
aaFilledEllipseRGBA(renderer, size.x / 2, y, size.x / 2, y_margin - 3, color.r, color.g, color.b, color.a);
|
||||
}
|
||||
frames.push_back(frame);
|
||||
}
|
||||
return frames;
|
||||
}
|
||||
|
||||
void sfw::fill_texture(SDL_Renderer* renderer, SDL_Texture* texture, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
|
||||
{
|
||||
SDL_SetRenderTarget(renderer, texture);
|
||||
|
@ -133,6 +196,43 @@ SDL_Texture* sfw::get_filled_texture(SDL_Renderer* renderer, glm::vec2 size, SDL
|
|||
return texture;
|
||||
}
|
||||
|
||||
SDL_Texture* sfw::get_hue_shifted_texture(SDL_Renderer* renderer, SDL_Texture* base, float offset)
|
||||
{
|
||||
SDL_Texture* hue_shifted_texture = sfw::duplicate_texture(renderer, base);
|
||||
Uint32 pixel_format;
|
||||
int w, h;
|
||||
SDL_QueryTexture(hue_shifted_texture, &pixel_format, NULL, &w, &h);
|
||||
SDL_PixelFormat* pixel_format_struct = SDL_AllocFormat(pixel_format);
|
||||
SDL_SetRenderTarget(renderer, hue_shifted_texture);
|
||||
int bytes_per_pixel = SDL_BYTESPERPIXEL(pixel_format);
|
||||
int bytes_per_row = bytes_per_pixel * w;
|
||||
int bytes_total = bytes_per_row * h;
|
||||
int length = bytes_total / 4 + (bytes_total % 4 ? 1 : 0);
|
||||
Uint32* pixels = new Uint32[length];
|
||||
if (SDL_RenderReadPixels(renderer, NULL, pixel_format, pixels, bytes_per_row) < 0)
|
||||
{
|
||||
print_sdl_error("Could not read pixels");
|
||||
}
|
||||
else
|
||||
{
|
||||
Color rgba;
|
||||
for (int ii = 0; ii < length; ii++)
|
||||
{
|
||||
SDL_GetRGBA(pixels[ii], const_cast<const SDL_PixelFormat*>(pixel_format_struct),
|
||||
&rgba.r, &rgba.g, &rgba.b, &rgba.a);
|
||||
rgba.shift_hue(offset);
|
||||
pixels[ii] = SDL_MapRGBA(const_cast<const SDL_PixelFormat*>(pixel_format_struct), rgba.r, rgba.g, rgba.b, rgba.a);
|
||||
}
|
||||
if (SDL_UpdateTexture(hue_shifted_texture, NULL, pixels, bytes_per_row) < 0)
|
||||
{
|
||||
print_sdl_error("Could not apply hue shifted pixels update to texture");
|
||||
}
|
||||
}
|
||||
delete[] pixels;
|
||||
SDL_FreeFormat(pixel_format_struct);
|
||||
return hue_shifted_texture;
|
||||
}
|
||||
|
||||
SDL_Texture* sfw::duplicate_texture(SDL_Renderer* renderer, SDL_Texture* base, Uint32 format)
|
||||
{
|
||||
Box box = get_texture_box(base);
|
||||
|
@ -141,7 +241,8 @@ SDL_Texture* sfw::duplicate_texture(SDL_Renderer* renderer, SDL_Texture* base, U
|
|||
|
||||
SDL_Texture* sfw::duplicate_texture(SDL_Renderer* renderer, SDL_Texture* base, const glm::vec2& size, Uint32 format)
|
||||
{
|
||||
Box box = get_texture_box(base);
|
||||
SDL_BlendMode original_blend_mode;
|
||||
SDL_GetTextureBlendMode(base, &original_blend_mode);
|
||||
SDL_Texture* duplicate = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_TARGET, size.x, size.y);
|
||||
if (duplicate == NULL)
|
||||
{
|
||||
|
@ -160,6 +261,8 @@ SDL_Texture* sfw::duplicate_texture(SDL_Renderer* renderer, SDL_Texture* base, c
|
|||
print_sdl_error("could not render base onto duplicate");
|
||||
return NULL;
|
||||
}
|
||||
SDL_SetTextureBlendMode(base, original_blend_mode);
|
||||
SDL_SetTextureBlendMode(duplicate, original_blend_mode);
|
||||
return duplicate;
|
||||
}
|
||||
|
||||
|
@ -239,9 +342,8 @@ SDL_Texture* sfw::get_remapped_texture(
|
|||
#include "superxbr.cpp"
|
||||
|
||||
/*
|
||||
Base texture must be set to SDL_TEXTUREACCESS_TARGET
|
||||
|
||||
Scale2x implementation based on the explanation at http://www.scale2x.it/algorithm.html
|
||||
- Base texture must be set to SDL_TEXTUREACCESS_TARGET
|
||||
- Scale2x implementation based on http://www.scale2x.it/algorithm.html
|
||||
*/
|
||||
SDL_Texture* sfw::get_pixel_scaled_texture(SDL_Renderer* renderer, SDL_Texture* base, int count, int version)
|
||||
{
|
||||
|
@ -434,14 +536,3 @@ std::ostream& operator<<(std::ostream& out, const SDL_Color& color)
|
|||
static_cast<int>(color.b) << ", " << static_cast<int>(color.a) << "}";
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const std::vector<int> ints)
|
||||
{
|
||||
out << "{ ";
|
||||
for (int ii : ints)
|
||||
{
|
||||
out << ii << " ";
|
||||
}
|
||||
out << "}";
|
||||
return out;
|
||||
}
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#include "SDL.h"
|
||||
#include "SDL_image.h"
|
||||
#include "SDL_pixels.h"
|
||||
|
||||
#define GLM_ENABLE_EXPERIMENTAL
|
||||
#include "glm/trigonometric.hpp"
|
||||
#include "glm/vec2.hpp"
|
||||
|
@ -22,8 +21,11 @@
|
|||
|
||||
#include "Box.hpp"
|
||||
#include "Segment.hpp"
|
||||
#include "Color.hpp"
|
||||
#include "filesystem.hpp"
|
||||
|
||||
struct Node;
|
||||
|
||||
namespace sfw
|
||||
{
|
||||
|
||||
|
@ -36,10 +38,14 @@ namespace sfw
|
|||
Box get_texture_box(SDL_Texture*);
|
||||
void populate_pixel_2d_array(SDL_Renderer*, SDL_Texture*, std::vector<std::vector<SDL_Color>>&);
|
||||
void populate_pixel_2d_array(SDL_Renderer*, SDL_Texture*, std::vector<std::vector<SDL_Color>>&, const Box&);
|
||||
std::vector<SDL_Texture*> get_halo_frames(
|
||||
Node&, float, int, const std::vector<SDL_Color>& = {{0, 0, 0, 255}, {255, 255, 255, 255}}, float = 4.0f, bool = true);
|
||||
std::vector<SDL_Texture*> 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*, 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*, Uint32 = SDL_PIXELFORMAT_RGBA32);
|
||||
SDL_Texture* duplicate_texture(SDL_Renderer*, SDL_Texture*, const glm::vec2&, Uint32 = SDL_PIXELFORMAT_RGBA32);
|
||||
SDL_Texture* get_remapped_texture(
|
||||
|
@ -72,6 +78,12 @@ namespace sfw
|
|||
return std::find(container.begin(), container.end(), member) != container.end();
|
||||
}
|
||||
|
||||
template<typename N>
|
||||
float mod(N a, N b)
|
||||
{
|
||||
return (b + (a % b)) % b;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::string pad(T end, int width, char fill = '0')
|
||||
{
|
||||
|
@ -82,6 +94,19 @@ namespace sfw
|
|||
return padded.str();
|
||||
}
|
||||
|
||||
template <typename N>
|
||||
std::vector<N> range_step(N start, N end, int count)
|
||||
{
|
||||
float step = (end - start) / (count - 1);
|
||||
std::vector<N> 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 <typename IntType>
|
||||
std::vector<IntType> range(IntType start, IntType stop, IntType step)
|
||||
|
@ -113,12 +138,26 @@ namespace sfw
|
|||
{
|
||||
return range(IntType(0), stop, IntType(1));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::ostream& operator<<(std::ostream& out, const std::vector<T>& members)
|
||||
{
|
||||
out << "{ ";
|
||||
for (const T& member : members)
|
||||
{
|
||||
out << member << " ";
|
||||
}
|
||||
out << "}";
|
||||
return out;
|
||||
}
|
||||
|
||||
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&);
|
||||
std::ostream& operator<<(std::ostream&, const std::vector<int>);
|
||||
|
||||
#include "Node.hpp"
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue