- add a text plane class
- load default font as a static class variable, make it a shared pointer - add filter option to texture storage - move Color into sb namespace - move Delegate object into protected
This commit is contained in:
parent
e5aef6ffb8
commit
9ed0e9ea71
|
@ -1,30 +1,40 @@
|
|||
/* +------------------------------------------------------+
|
||||
____/ \____ /| - Open source game framework licensed to freely use, |
|
||||
\ / / | copy, modify and sell without restriction |
|
||||
+--\ ^__^ /--+ | |
|
||||
| ~/ \~ | | - created for <https://foam.shampoo.ooo> |
|
||||
| ~~~~~~~~~~~~ | +------------------------------------------------------+
|
||||
| SPACE ~~~~~ | /
|
||||
| ~~~~~~~ BOX |/
|
||||
+-------------*/
|
||||
|
||||
#include "Color.hpp"
|
||||
|
||||
Color::Color() : Color(0, 0, 0, 255) {}
|
||||
sb::Color::Color() : sb::Color(0, 0, 0, 255) {}
|
||||
|
||||
Color::Color(const SDL_Color& color) : Color(color.r, color.g, color.b, color.a) {};
|
||||
sb::Color::Color(const SDL_Color& color) : sb::Color(color.r, color.g, color.b, color.a) {};
|
||||
|
||||
void Color::set_percent(const float& red, const float& green, const float& blue)
|
||||
void sb::Color::percent(float red, float green, float blue)
|
||||
{
|
||||
r = std::round(255.0f * red);
|
||||
g = std::round(255.0f * green);
|
||||
b = std::round(255.0f * blue);
|
||||
}
|
||||
|
||||
void Color::set_percent(const float& red, const float& green, const float& blue, const float& alpha)
|
||||
void sb::Color::percent(float red, float green, float blue, float alpha)
|
||||
{
|
||||
a = std::round(255.0f * alpha);
|
||||
set_percent(red, green, blue);
|
||||
sb::Color::percent(red, green, blue);
|
||||
}
|
||||
|
||||
void Color::set_hsv(const float& hue, const float& saturation, const float& value)
|
||||
void sb::Color::hsv(float hue, float saturation, float value)
|
||||
{
|
||||
float red_percent, green_percent, blue_percent;
|
||||
HSVtoRGB(red_percent, green_percent, blue_percent, hue, saturation, value);
|
||||
set_percent(red_percent, green_percent, blue_percent);
|
||||
sb::Color::percent(red_percent, green_percent, blue_percent);
|
||||
}
|
||||
|
||||
float Color::get_hue() const
|
||||
float sb::Color::hue() const
|
||||
{
|
||||
float hue, saturation, value;
|
||||
float red_percent = r / 255.0f, green_percent = g / 255.0f, blue_percent = b / 255.0f;
|
||||
|
@ -32,17 +42,17 @@ float Color::get_hue() const
|
|||
return hue;
|
||||
}
|
||||
|
||||
void Color::shift_hue(float offset)
|
||||
void sb::Color::shift_hue(float offset)
|
||||
{
|
||||
float hue, saturation, value;
|
||||
float red_percent = r / 255.0f, green_percent = g / 255.0f, blue_percent = b / 255.0f;
|
||||
RGBtoHSV(red_percent, green_percent, blue_percent, hue, saturation, value);
|
||||
hue = std::fmod(hue + offset, 360.0f);
|
||||
HSVtoRGB(red_percent, green_percent, blue_percent, hue, saturation, value);
|
||||
set_percent(red_percent, green_percent, blue_percent);
|
||||
percent(red_percent, green_percent, blue_percent);
|
||||
}
|
||||
|
||||
Color::operator std::uint32_t() const
|
||||
sb::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);
|
||||
|
@ -50,7 +60,7 @@ Color::operator std::uint32_t() const
|
|||
return pixel;
|
||||
}
|
||||
|
||||
Color::operator std::uint16_t() const
|
||||
sb::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);
|
||||
|
@ -58,7 +68,7 @@ Color::operator std::uint16_t() const
|
|||
return pixel;
|
||||
}
|
||||
|
||||
Color::operator std::uint8_t() const
|
||||
sb::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);
|
||||
|
@ -66,22 +76,22 @@ Color::operator std::uint8_t() const
|
|||
return pixel;
|
||||
}
|
||||
|
||||
bool Color::operator==(const Color& color) const
|
||||
bool sb::Color::operator==(const sb::Color& color) const
|
||||
{
|
||||
return r == color.r && g == color.g && b == color.b && a == color.a;
|
||||
}
|
||||
|
||||
bool Color::operator!=(const Color& color) const
|
||||
bool sb::Color::operator!=(const sb::Color& color) const
|
||||
{
|
||||
return !(*this == color);
|
||||
}
|
||||
|
||||
bool Color::operator<(const Color& color) const
|
||||
bool sb::Color::operator<(const sb::Color& color) const
|
||||
{
|
||||
return r < color.r || g < color.g || b < color.b || a < color.a;
|
||||
}
|
||||
|
||||
std::ostream& std::operator<<(std::ostream& out, const Color& color)
|
||||
std::ostream& std::operator<<(std::ostream& out, const sb::Color& color)
|
||||
{
|
||||
float h, s, v;
|
||||
RGBtoHSV(color.r / 255.0f, color.g / 255.0f, color.b / 255.0f, h, s, v);
|
||||
|
|
|
@ -1,3 +1,13 @@
|
|||
/* +------------------------------------------------------+
|
||||
____/ \____ /| - Open source game framework licensed to freely use, |
|
||||
\ / / | copy, modify and sell without restriction |
|
||||
+--\ ^__^ /--+ | |
|
||||
| ~/ \~ | | - created for <https://foam.shampoo.ooo> |
|
||||
| ~~~~~~~~~~~~ | +------------------------------------------------------+
|
||||
| SPACE ~~~~~ | /
|
||||
| ~~~~~~~ BOX |/
|
||||
+-------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
@ -10,12 +20,14 @@
|
|||
struct Color : SDL_Color
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
Color();
|
||||
Color(const SDL_Color&);
|
||||
void set_percent(const float&, const float&, const float&);
|
||||
void set_percent(const float&, const float&, const float&, const float&);
|
||||
void set_hsv(const float&, const float& = 1.0f, const float& = 1.0f);
|
||||
float get_hue() const;
|
||||
void percent(float, float, float);
|
||||
void percent(float, float, float, float);
|
||||
void hsv(float, float = 1.0f, float = 1.0f);
|
||||
float hue() const;
|
||||
void shift_hue(float);
|
||||
operator std::uint32_t() const;
|
||||
operator std::uint16_t() const;
|
||||
|
@ -24,10 +36,10 @@ struct Color : SDL_Color
|
|||
bool operator!=(const Color&) const;
|
||||
bool operator<(const Color&) const;
|
||||
|
||||
template <typename T>
|
||||
Color(T red, T green, T blue, T alpha = 255)
|
||||
template <typename Type>
|
||||
Color(Type red, Type green, Type blue, Type alpha = 255)
|
||||
{
|
||||
if (std::is_floating_point<T>())
|
||||
if (std::is_floating_point<Type>())
|
||||
{
|
||||
red = std::round(red);
|
||||
green = std::round(green);
|
||||
|
@ -49,3 +61,11 @@ namespace std
|
|||
{
|
||||
std::ostream& operator<<(std::ostream&, const Color&);
|
||||
}
|
||||
|
||||
/* Add Color class to the sb namespace. This should be the default location, but Color is left in the global namespace
|
||||
* for backward compatibility.
|
||||
*/
|
||||
namespace sb
|
||||
{
|
||||
using ::Color;
|
||||
}
|
||||
|
|
|
@ -28,12 +28,11 @@ void Configuration::set_defaults()
|
|||
{"left", "left"},
|
||||
{"pause", "enter"},
|
||||
{"fullscreen", {"ALT", "enter"}},
|
||||
{"toggle-framerate", {"CTRL", "f"}},
|
||||
{"reset", {"CTRL", "r"}}
|
||||
};
|
||||
config["input"] = {
|
||||
{"suppress-any-key-on-mods", true},
|
||||
{"system-any-key-ignore-commands", {"fullscreen", "screenshot", "toggle-framerate", "record", "quit"}},
|
||||
{"system-any-key-ignore-commands", {"fullscreen", "screenshot", "record", "quit"}},
|
||||
{"any-key-ignore-commands", nlohmann::json::array()},
|
||||
{"default-unsuppress-delay", 700},
|
||||
{"ignore-repeat-keypress", true}
|
||||
|
@ -46,7 +45,9 @@ void Configuration::set_defaults()
|
|||
{"show-cursor", false},
|
||||
{"render-test-spacing", 2},
|
||||
{"render driver", "opengl"},
|
||||
{"fluid resize", false}
|
||||
{"fluid resize", false},
|
||||
{"default font path", "BPmono.ttf"},
|
||||
{"default font size", 16}
|
||||
};
|
||||
config["audio"] = {
|
||||
{"default-sfx-root", "resource/sfx"},
|
||||
|
@ -77,12 +78,6 @@ void Configuration::set_defaults()
|
|||
{"max-video-memory", 1000},
|
||||
{"mp4-pixel-format", "yuv444p"}
|
||||
};
|
||||
config["fps-indicator"] = {
|
||||
{"width", .05},
|
||||
{"height", .04},
|
||||
{"background", {255, 255, 255}},
|
||||
{"foreground", {0, 0, 0}}
|
||||
};
|
||||
config["animation"] = {
|
||||
{"all-frames-frameset-name", "all"}
|
||||
};
|
||||
|
|
79
src/Game.cpp
79
src/Game.cpp
|
@ -41,6 +41,9 @@ Game::Game()
|
|||
log_message << "Current path as seen by std::filesystem is " << std::filesystem::current_path();
|
||||
sb::Log::log(log_message);
|
||||
|
||||
/* Load the key mappings into the input manager object */
|
||||
input.load_key_map();
|
||||
|
||||
/* Log Android storage paths as determined by SDL */
|
||||
#if defined(__ANDROID__) || defined(ANDROID)
|
||||
log_message = std::ostringstream();
|
||||
|
@ -158,10 +161,20 @@ Game::Game()
|
|||
{
|
||||
SDL_Log("initialized SDL ttf %d.%d.%d", SDL_TTF_MAJOR_VERSION, SDL_TTF_MINOR_VERSION, SDL_TTF_PATCHLEVEL);
|
||||
}
|
||||
if ((bp_mono_font = TTF_OpenFont("BPmono.ttf", 14)) == nullptr)
|
||||
|
||||
/* Try to load the default font path. The font will be freed when the Game object is destroyed. */
|
||||
bp_mono_font = std::shared_ptr<TTF_Font>(
|
||||
TTF_OpenFont(configuration()["display"]["default font path"].get<std::string>().c_str(),
|
||||
configuration()["display"]["default font size"]), TTF_CloseFont);
|
||||
if (bp_mono_font.get() == nullptr)
|
||||
{
|
||||
sb::Log::log("Could not load BPmono.ttf", sb::Log::ERROR);
|
||||
}
|
||||
else
|
||||
{
|
||||
sb::Log::log("Loaded BPmono.ttf");
|
||||
}
|
||||
|
||||
if (Mix_Init(MIX_INIT_OGG) == 0)
|
||||
{
|
||||
sb::Log::sdl_error("Could not initialize SDL mixer");
|
||||
|
@ -479,6 +492,16 @@ Configuration& Game::configuration()
|
|||
return _configuration;
|
||||
}
|
||||
|
||||
const sb::Delegate& sb::Game::delegate() const
|
||||
{
|
||||
return _delegate;
|
||||
}
|
||||
|
||||
sb::Delegate& sb::Game::delegate()
|
||||
{
|
||||
return _delegate;
|
||||
}
|
||||
|
||||
const SDL_Window* Game::window() const
|
||||
{
|
||||
return _window;
|
||||
|
@ -514,6 +537,11 @@ Audio& Game::get_audio()
|
|||
return audio;
|
||||
}
|
||||
|
||||
const std::shared_ptr<TTF_Font>& sb::Game::font()
|
||||
{
|
||||
return sb::Game::bp_mono_font;
|
||||
}
|
||||
|
||||
void Game::run()
|
||||
{
|
||||
SDL_FlushEvents(SDL_FIRSTEVENT, SDL_LASTEVENT);
|
||||
|
@ -550,7 +578,6 @@ void Game::frame(float ticks)
|
|||
audio.update();
|
||||
input.unsuppress_animation.update();
|
||||
update();
|
||||
framerate_indicator.update();
|
||||
_configuration.update();
|
||||
if (!is_gl_context)
|
||||
{
|
||||
|
@ -566,12 +593,12 @@ void Game::frame(float ticks)
|
|||
frame_count_this_second++;
|
||||
if (ticks - last_frame_count_timestamp >= 1000)
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Counted " << frame_count_this_second << " frames last second";
|
||||
sb::Log::log(message, sb::Log::DEBUG);
|
||||
framerate_indicator.refresh();
|
||||
current_frames_per_second = frame_count_this_second;
|
||||
last_frame_count_timestamp = ticks;
|
||||
frame_count_this_second = 0;
|
||||
std::ostringstream message;
|
||||
message << "Counted " << current_frames_per_second << " frames last second";
|
||||
sb::Log::log(message, sb::Log::DEBUG);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -636,7 +663,6 @@ void Game::quit()
|
|||
}
|
||||
if (TTF_WasInit())
|
||||
{
|
||||
TTF_CloseFont(bp_mono_font);
|
||||
TTF_Quit();
|
||||
}
|
||||
Mix_CloseAudio();
|
||||
|
@ -648,42 +674,3 @@ Game::~Game()
|
|||
{
|
||||
_delegate.unsubscribe(this);
|
||||
}
|
||||
|
||||
FramerateIndicator::FramerateIndicator(Node* parent) : Sprite(parent)
|
||||
{
|
||||
delegate().subscribe(&FramerateIndicator::respond, this);
|
||||
hide();
|
||||
}
|
||||
|
||||
void FramerateIndicator::respond(SDL_Event& event)
|
||||
{
|
||||
if (delegate().compare(event, "toggle-framerate"))
|
||||
{
|
||||
toggle_hidden();
|
||||
}
|
||||
}
|
||||
|
||||
SDL_Surface* FramerateIndicator::get_surface()
|
||||
{
|
||||
std::string padded = sb::pad(get_root()->frame_count_this_second, 2);
|
||||
SDL_Surface* shaded = TTF_RenderText_Shaded(
|
||||
get_root()->bp_mono_font, padded.c_str(), {0, 0, 0, 255}, {255, 255, 255, 255});
|
||||
if (!shaded)
|
||||
{
|
||||
sb::Log::sdl_error("Could not create text");
|
||||
}
|
||||
return shaded;
|
||||
}
|
||||
|
||||
void FramerateIndicator::refresh()
|
||||
{
|
||||
if (!is_hidden() && get_root()->bp_mono_font != nullptr)
|
||||
{
|
||||
unload();
|
||||
SDL_Surface* surface = get_surface();
|
||||
SDL_Texture* texture = SDL_CreateTextureFromSurface(get_root()->get_renderer(), surface);
|
||||
add_frames(texture);
|
||||
SDL_FreeSurface(surface);
|
||||
set_ne(get_display().window_box().ne());
|
||||
}
|
||||
}
|
||||
|
|
36
src/Game.hpp
36
src/Game.hpp
|
@ -52,18 +52,6 @@
|
|||
#include "filesystem.hpp"
|
||||
#include "extension.hpp"
|
||||
|
||||
class FramerateIndicator : public Sprite
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
FramerateIndicator(Node*);
|
||||
void respond(SDL_Event&);
|
||||
SDL_Surface* get_surface();
|
||||
void refresh();
|
||||
|
||||
};
|
||||
|
||||
class Game : public Node
|
||||
{
|
||||
|
||||
|
@ -73,6 +61,8 @@ private:
|
|||
float frame_length = 1000.0 / 60.0;
|
||||
SDL_Window* _window;
|
||||
|
||||
inline static std::shared_ptr<TTF_Font> bp_mono_font;
|
||||
|
||||
inline static const std::string USER_CONFIG_PATH = "config.json";
|
||||
inline static const std::string ANDROID_CONFIG_PATH = "config_android.json";
|
||||
inline static const std::string WASM_CONFIG_PATH = "config_wasm.json";
|
||||
|
@ -92,6 +82,11 @@ private:
|
|||
*/
|
||||
static void sdl_log_override(void* userdata, int category, SDL_LogPriority priority, const char* message);
|
||||
|
||||
protected:
|
||||
|
||||
Configuration _configuration {this};
|
||||
sb::Delegate _delegate {this};
|
||||
|
||||
public:
|
||||
|
||||
/* two-state enum equivalent to a boolean that can improve readability depending on the context */
|
||||
|
@ -108,18 +103,14 @@ public:
|
|||
|
||||
SDL_Renderer* renderer = nullptr;
|
||||
SDL_GLContext glcontext = nullptr;
|
||||
int frame_count_this_second = 0, last_frame_length;
|
||||
int frame_count_this_second = 0, last_frame_length, current_frames_per_second = 0;
|
||||
float frame_time_overflow = 0, last_frame_timestamp, last_frame_count_timestamp;
|
||||
bool done = false, show_framerate = true, is_gl_context = true;
|
||||
Configuration _configuration {this};
|
||||
sb::Delegate _delegate {this};
|
||||
sb::Display display {this};
|
||||
Recorder recorder {this};
|
||||
Input input {this};
|
||||
Audio audio {this};
|
||||
std::vector<float> frame_length_history;
|
||||
TTF_Font* bp_mono_font = nullptr;
|
||||
FramerateIndicator framerate_indicator {this};
|
||||
|
||||
Game();
|
||||
virtual void reset() { activate(); }
|
||||
|
@ -144,6 +135,8 @@ public:
|
|||
void log_surface_format(SDL_Surface*, std::string = "surface");
|
||||
const Configuration& configuration() const;
|
||||
Configuration& configuration();
|
||||
const sb::Delegate& delegate() const;
|
||||
sb::Delegate& delegate();
|
||||
const SDL_Window* window() const;
|
||||
SDL_Window* window();
|
||||
const SDL_Renderer* get_renderer() const;
|
||||
|
@ -151,6 +144,7 @@ public:
|
|||
const Input& get_input() const;
|
||||
Input& get_input();
|
||||
Audio& get_audio();
|
||||
static const std::shared_ptr<TTF_Font>& font();
|
||||
void run();
|
||||
void frame(float);
|
||||
void flag_to_end();
|
||||
|
@ -178,6 +172,14 @@ public:
|
|||
|
||||
};
|
||||
|
||||
/* Add Game class to the sb namespace. This should be the default location, but Game is left in the global namespace
|
||||
* for backward compatibility.
|
||||
*/
|
||||
namespace sb
|
||||
{
|
||||
using ::Game;
|
||||
}
|
||||
|
||||
#if defined(__EMSCRIPTEN__)
|
||||
|
||||
void loop(void*);
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
Input::Input(Node *parent) : Node(parent)
|
||||
{
|
||||
load_key_map();
|
||||
get_delegate().subscribe(&Input::respond, this, SDL_KEYDOWN);
|
||||
get_delegate().subscribe(&Input::respond, this, SDL_KEYUP);
|
||||
for (KeyCombination& combination : key_map)
|
||||
|
|
|
@ -122,7 +122,7 @@ sb::Texture& sb::Model::texture(const std::string& name)
|
|||
else if (textures().find(name) == textures().end())
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "No texture named " << name << " found attached to this model.";
|
||||
message << "No texture named " << name << " attached to this model.";
|
||||
throw std::out_of_range(message.str());
|
||||
}
|
||||
else
|
||||
|
|
|
@ -48,9 +48,14 @@ Configuration& Node::configuration()
|
|||
return get_root()->configuration();
|
||||
}
|
||||
|
||||
const sb::Delegate& Node::delegate() const
|
||||
{
|
||||
return get_root()->delegate();
|
||||
}
|
||||
|
||||
sb::Delegate& Node::delegate()
|
||||
{
|
||||
return get_root()->_delegate;
|
||||
return get_root()->delegate();
|
||||
}
|
||||
|
||||
sb::Delegate& Node::get_delegate()
|
||||
|
|
|
@ -52,6 +52,11 @@ public:
|
|||
const Configuration& configuration() const;
|
||||
Configuration& configuration();
|
||||
|
||||
/*!
|
||||
* @return const reference to the Delegate object
|
||||
*/
|
||||
const sb::Delegate& delegate() const;
|
||||
|
||||
/*!
|
||||
* @return the Delegate object
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
#include "Text.hpp"
|
||||
|
||||
using namespace sb;
|
||||
|
||||
/*!
|
||||
* @param content text to be displayed
|
||||
*/
|
||||
void Text::content(const std::string& content)
|
||||
{
|
||||
_content = content;
|
||||
refresh();
|
||||
}
|
||||
|
||||
/*!
|
||||
* @param foreground text color
|
||||
*/
|
||||
void Text::foreground(const sb::Color& foreground)
|
||||
{
|
||||
_foreground = foreground;
|
||||
refresh();
|
||||
}
|
||||
|
||||
/*!
|
||||
* @param background text background color which fills the Plane
|
||||
*/
|
||||
void Text::background(const sb::Color& background)
|
||||
{
|
||||
_background = background;
|
||||
refresh();
|
||||
}
|
||||
|
||||
/*!
|
||||
* @param font shared pointer to a TTF_Font
|
||||
*/
|
||||
void Text::font(std::shared_ptr<TTF_Font> font)
|
||||
{
|
||||
_font = font;
|
||||
refresh();
|
||||
}
|
||||
|
||||
void Text::refresh()
|
||||
{
|
||||
/* Try getting the font pointer from this class. If that hasn't been set, try getting the default font from the Game class.
|
||||
* If neither has been set, print an error without generating a texture. */
|
||||
TTF_Font* font = nullptr;
|
||||
if (_font.get() != nullptr)
|
||||
{
|
||||
font = _font.get();
|
||||
}
|
||||
else if (sb::Game::font().get() != nullptr)
|
||||
{
|
||||
font = sb::Game::font().get();
|
||||
}
|
||||
|
||||
/* Create pixel data using the SDL image library. The pixel data surface is converted from paletted format to ARGB and flipped. */
|
||||
if (font != nullptr)
|
||||
{
|
||||
SDL_Surface* shaded = TTF_RenderText_Shaded(font, _content.c_str(), _foreground, _background);
|
||||
if (!shaded)
|
||||
{
|
||||
sb::Log::sdl_error("Could not create text");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(shaded = SDL_ConvertSurfaceFormat(shaded, SDL_PIXELFORMAT_ARGB8888, 0)))
|
||||
{
|
||||
sb::Log::sdl_error("Could not convert pixel format");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(shaded = rotozoomSurfaceXY(shaded, 0, 1, -1, 0)))
|
||||
{
|
||||
sb::Log::sdl_error("Could not flip surface");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Generate texture and create storage. Load the pixels from the text rendering surface into the default texture. The texture object will handle
|
||||
* destroying the previous texture. Then destroy the pixels surface. */
|
||||
texture().generate({shaded->w, shaded->h}, GL_RGBA8, GL_LINEAR);
|
||||
texture().load(shaded);
|
||||
}
|
||||
}
|
||||
SDL_FreeSurface(shaded);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sb::Log::log("No font set and no default font found", sb::Log::ERROR);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
#include "SDL.h"
|
||||
#include "SDL_ttf.h"
|
||||
#include "SDL2_rotozoom.h"
|
||||
|
||||
#include "Model.hpp"
|
||||
#include "Color.hpp"
|
||||
|
||||
namespace sb
|
||||
{
|
||||
class Text : public sb::Plane
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
inline static const sb::Color DEFAULT_FG {0.0f, 0.0f, 0.0f, 255.0f};
|
||||
inline static const sb::Color DEFAULT_BG {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
|
||||
std::string _content;
|
||||
sb::Color _foreground, _background;
|
||||
std::shared_ptr<TTF_Font> _font;
|
||||
|
||||
/*!
|
||||
* Set the texture to the appropriate SDL_Surface created by the SDL TTF library.
|
||||
*/
|
||||
void refresh();
|
||||
|
||||
public:
|
||||
|
||||
Text(const std::string& content = "", const sb::Color& foreground = DEFAULT_FG, const sb::Color& background = DEFAULT_BG) :
|
||||
_content(content), _foreground(foreground), _background(background)
|
||||
{
|
||||
/* Assign a default constructed Texture object to be the default texture */
|
||||
texture(sb::Texture());
|
||||
}
|
||||
|
||||
Text(std::shared_ptr<TTF_Font> font, const std::string& content = "", const sb::Color& foreground = DEFAULT_FG,
|
||||
const sb::Color& background = DEFAULT_BG) : Text(content, foreground, background)
|
||||
{
|
||||
_font = font;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @param content text to be displayed
|
||||
*/
|
||||
void content(const std::string& content);
|
||||
|
||||
/*!
|
||||
* @param foreground text color
|
||||
*/
|
||||
void foreground(const sb::Color& foreground);
|
||||
|
||||
/*!
|
||||
* @param background text background color which fills the Plane
|
||||
*/
|
||||
void background(const sb::Color& background);
|
||||
|
||||
/*!
|
||||
* @param font shared pointer to a TTF_Font
|
||||
*/
|
||||
void font(std::shared_ptr<TTF_Font> font);
|
||||
};
|
||||
}
|
||||
|
||||
#include "Game.hpp"
|
|
@ -20,8 +20,6 @@ Texture::Texture(fs::path path) : Texture()
|
|||
associate(path);
|
||||
}
|
||||
|
||||
/* Store an image path as a member variable for loading later. Each texture should have one image
|
||||
* path (support for multiple mipmap levels may be added later) */
|
||||
void Texture::associate(fs::path path)
|
||||
{
|
||||
this->path = path;
|
||||
|
@ -32,13 +30,13 @@ void Texture::generate()
|
|||
GLObject::generate(glGenTextures);
|
||||
}
|
||||
|
||||
void Texture::generate(glm::vec2 size, GLenum format)
|
||||
void Texture::generate(glm::vec2 size, GLenum format, GLint filter)
|
||||
{
|
||||
generate();
|
||||
bind();
|
||||
glTexStorage2D(GL_TEXTURE_2D, 1, format, size.x, size.y);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
|
||||
sb::Log::gl_errors();
|
||||
}
|
||||
|
||||
|
@ -90,19 +88,17 @@ void Texture::load(SDL_RWops* rw)
|
|||
void Texture::load(SDL_Surface* surface)
|
||||
{
|
||||
std::ostringstream message;
|
||||
sb::Log::Level message_level;
|
||||
if (surface->w > 0 && surface->h > 0)
|
||||
{
|
||||
message << "Loading image from SDL surface (" << surface->w << "×" << surface->h << ", " << SDL_GetPixelFormatName(surface->format->format) << ")";
|
||||
sb::Log::log(message, sb::Log::DEBUG);
|
||||
load(surface->pixels, {surface->w, surface->h}, GL_RGBA, GL_UNSIGNED_BYTE);
|
||||
message_level = sb::Log::DEBUG;
|
||||
}
|
||||
else
|
||||
{
|
||||
message << "Cannot load into texture, invalid image data without dimensions found";
|
||||
message_level = sb::Log::WARN;
|
||||
sb::Log::log(message, sb::Log::WARN);
|
||||
}
|
||||
sb::Log::log(message, message_level);
|
||||
}
|
||||
|
||||
void Texture::load(void* pixels, glm::vec2 size, GLenum format, GLenum type)
|
||||
|
|
|
@ -48,7 +48,14 @@ namespace sb
|
|||
|
||||
Texture();
|
||||
Texture(fs::path);
|
||||
void associate(fs::path);
|
||||
|
||||
/*!
|
||||
* Store an image path as a member variable for loading later. Each texture should have one image
|
||||
* path (support for multiple mipmap levels may be added later).
|
||||
*
|
||||
* @param path path to an image that can be loaded by the SDL image library
|
||||
*/
|
||||
void associate(fs::path path);
|
||||
|
||||
/*!
|
||||
* Forward the GL texture generate function to the base class
|
||||
|
@ -60,8 +67,9 @@ namespace sb
|
|||
*
|
||||
* @param size Width and height of the texture in texels
|
||||
* @param format Sized internal format to be used to store texture data (for example, GL_RGBA8, GL_RGB8)
|
||||
* @param filter Resize function to use (see glTexParameter)
|
||||
*/
|
||||
void generate(glm::vec2 size, GLenum format = GL_RGBA8);
|
||||
void generate(glm::vec2 size, GLenum format = GL_RGBA8, GLint filter = GL_NEAREST);
|
||||
|
||||
/*!
|
||||
* @overload load(fs::path path)
|
||||
|
|
|
@ -209,7 +209,7 @@ std::vector<SDL_Texture*> sb::get_portal_frames(
|
|||
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)]);
|
||||
color.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);
|
||||
|
|
Loading…
Reference in New Issue