From a02c8c63fdcc8d41ef32494c023ee0a60474222f Mon Sep 17 00:00:00 2001 From: Relintai Date: Sat, 13 Nov 2021 12:26:19 +0100 Subject: [PATCH] Added 2 renderer classes with some notes, thye are not it the build yet, they'll be changed. --- core/renderer/camera.cpp | 24 +++ core/renderer/camera.h | 22 +++ core/renderer/renderer.cpp | 369 +++++++++++++++++++++++++++++++++++++ core/renderer/renderer.h | 101 ++++++++++ 4 files changed, 516 insertions(+) create mode 100644 core/renderer/camera.cpp create mode 100644 core/renderer/camera.h create mode 100644 core/renderer/renderer.cpp create mode 100644 core/renderer/renderer.h diff --git a/core/renderer/camera.cpp b/core/renderer/camera.cpp new file mode 100644 index 0000000..f21407f --- /dev/null +++ b/core/renderer/camera.cpp @@ -0,0 +1,24 @@ +#include "camera.h" + +#include "renderer.h" + +void Camera::bind() { + Renderer::get_singleton()->set_integer_scaling(integer_scaling); + + Renderer::get_singleton()->set_scale(scale_w, scale_h); + + Renderer::get_singleton()->set_viewport(viewport); + Renderer::get_singleton()->set_clip_rect(&clip_rect); +} + +Camera::Camera() { + integer_scaling = false; + + scale_w = 1; + scale_h = 1; + + viewport = Renderer::get_singleton()->get_viewport(); + clip_rect = Renderer::get_singleton()->get_clip_rect(); +} +Camera::~Camera() { +} diff --git a/core/renderer/camera.h b/core/renderer/camera.h new file mode 100644 index 0000000..3ae59bc --- /dev/null +++ b/core/renderer/camera.h @@ -0,0 +1,22 @@ +#ifndef CAMERA_H +#define CAMERA_H + +#include + +#include "core/rect2.h" + +class Camera { +public: + void bind(); + + Camera(); + virtual ~Camera(); + + bool integer_scaling; + float scale_w; + float scale_h; + Rect2 viewport; + Rect2 clip_rect; +}; + +#endif \ No newline at end of file diff --git a/core/renderer/renderer.cpp b/core/renderer/renderer.cpp new file mode 100644 index 0000000..ba3adb9 --- /dev/null +++ b/core/renderer/renderer.cpp @@ -0,0 +1,369 @@ +#include "renderer.h" + +#include + +#include "core/math.h" + +void Renderer::present() { + SDL_RenderPresent(_renderer); +} + +void Renderer::set_draw_color(const Uint8 r, const Uint8 g, const Uint8 b, const Uint8 a) { + SDL_SetRenderDrawColor(_renderer, r, g, b, a); +} + +void Renderer::set_draw_color(const Color &color) { + SDL_SetRenderDrawColor(_renderer, color.r, color.g, color.b, color.a); +} + +void Renderer::clear() { + SDL_RenderClear(_renderer); +} + +SDL_BlendMode Renderer::get_blend_mode() const { + SDL_BlendMode mode; + SDL_GetRenderDrawBlendMode(_renderer, &mode); + + return mode; +} +void Renderer::set_blend_mode(const SDL_BlendMode mode) { + SDL_SetRenderDrawBlendMode(_renderer, mode); +} + +void Renderer::draw_point(const int x, const int y) { + SDL_RenderDrawPoint(_renderer, x, y); +} +void Renderer::draw_point(const float x, const float y) { + SDL_RenderDrawPointF(_renderer, x, y); +} + +void Renderer::draw_line(const int x1, const int x2, const int y1, const int y2) { + SDL_RenderDrawLine(_renderer, x1, x2, y1, y2); +} +void Renderer::draw_line(const float x1, const float x2, const float y1, const float y2) { + SDL_RenderDrawLineF(_renderer, x1, x2, y1, y2); +} + +void Renderer::draw_rect(const Rect2 &rect) { + SDL_Rect r = rect.as_rect(); + + SDL_RenderDrawRect(_renderer, &r); +} + +void Renderer::draw_fill_rect(const Rect2 &rect) { + SDL_Rect r = rect.as_rect(); + + SDL_RenderFillRect(_renderer, &r); +} + +void Renderer::draw_texture(const Texture &texture, const Rect2 &dst_rect) { + SDL_Rect sr; + + sr.x = 0; + sr.y = 0; + sr.w = texture.get_width(); + sr.h = texture.get_height(); + + SDL_Rect dr = dst_rect.as_rect(); + + SDL_RenderCopy(_renderer, texture.get_texture(), &sr, &dr); +} +void Renderer::draw_texture(const Texture &texture, const Rect2 &src_rect, const Rect2 &dst_rect) { + SDL_Rect sr = src_rect.as_rect(); + SDL_Rect dr = dst_rect.as_rect(); + + SDL_RenderCopy(_renderer, texture.get_texture(), &sr, &dr); +} +void Renderer::draw_texture(const Texture &texture, const Rect2 &src_rect, const Rect2 &dst_rect, const double angle, const float cx, const float cy, const SDL_RendererFlip flip) { + SDL_Rect sr = src_rect.as_rect(); + SDL_FRect dr = dst_rect.as_frect(); + + SDL_FPoint p; + + p.x = cx; + p.y = cy; + + SDL_RenderCopyExF(_renderer, texture.get_texture(), &sr, &dr, angle, &p, flip); +} + +void Renderer::draw_sprite(const Sprite &sprite) { + Texture *t = sprite.get_texture(); + + if (!t) { + return; + } + + t->set_color_mod(sprite.get_color_mod()); + + double angle = sprite.get_angle(); + + if (Math::is_zero_approx(angle)) { + SDL_Rect sr = sprite.get_texture_clip_rect().as_rect(); + SDL_Rect dr = sprite.get_transform().as_rect(); + + SDL_RenderCopy(_renderer, t->get_texture(), &sr, &dr); + } else { + SDL_Rect sr = sprite.get_texture_clip_rect().as_rect(); + SDL_FRect dr = sprite.get_transform().as_frect(); + + SDL_FPoint p; + + p.x = sprite.get_anchor_x(); + p.y = sprite.get_anchor_y(); + + SDL_RenderCopyExF(_renderer, t->get_texture(), &sr, &dr, angle, &p, sprite.get_flip()); + } +} + +void Renderer::draw_sprite(const Sprite *sprite) { + if (!sprite) + return; + + Texture *t = sprite->get_texture(); + + if (!t) { + return; + } + + t->set_color_mod(sprite->get_color_mod()); + + double angle = sprite->get_angle(); + + if (Math::is_zero_approx(angle)) { + SDL_Rect sr = sprite->get_texture_clip_rect().as_rect(); + SDL_Rect dr = sprite->get_transform().as_rect(); + + SDL_RenderCopy(_renderer, t->get_texture(), &sr, &dr); + } else { + SDL_Rect sr = sprite->get_texture_clip_rect().as_rect(); + SDL_FRect dr = sprite->get_transform().as_frect(); + + SDL_FPoint p; + + p.x = sprite->get_anchor_x(); + p.y = sprite->get_anchor_y(); + + SDL_RenderCopyExF(_renderer, t->get_texture(), &sr, &dr, angle, &p, sprite->get_flip()); + } +} + +int Renderer::get_dpi() const { + float ddpi; + float hdpi; + float vdpi; + + if (SDL_GetDisplayDPI(_window_display_index, &ddpi, &hdpi, &vdpi)) { + return ddpi; + } + + //fallback + return 1; +} + +int Renderer::get_window_size_w() const { + int w; + int h; + + SDL_GetWindowSize(_window, &w, &h); + + return w; +} + +int Renderer::get_window_size_h() const { + int w; + int h; + + SDL_GetWindowSize(_window, &w, &h); + + return h; +} + +int Renderer::get_size_w() const { + int w; + int h; + + SDL_RenderGetLogicalSize(_renderer, &w, &h); + + return w; +} + +int Renderer::get_size_h() const { + int w; + int h; + + SDL_RenderGetLogicalSize(_renderer, &w, &h); + + return h; +} + +void Renderer::get_size(int *w, int *h) const { + SDL_RenderGetLogicalSize(_renderer, w, h); +} + +void Renderer::set_size(const int w, const int h) const { + SDL_RenderSetLogicalSize(_renderer, w, h); +} + +float Renderer::get_scale_w() const { + float w; + float h; + + SDL_RenderGetScale(_renderer, &w, &h); + + return w; +} +float Renderer::get_scale_h() const { + float w; + float h; + + SDL_RenderGetScale(_renderer, &w, &h); + + return h; +} +void Renderer::set_scale(const float w, const float h) const { + SDL_RenderSetScale(_renderer, w, h); +} +void Renderer::get_scale(float *w, float *h) const { + SDL_RenderGetScale(_renderer, w, h); +} + +bool Renderer::get_integer_scaling() const { + return SDL_RenderGetIntegerScale(_renderer); +} +void Renderer::set_integer_scaling(const bool enable) { + if (enable) + SDL_RenderSetIntegerScale(_renderer, SDL_TRUE); + else + SDL_RenderSetIntegerScale(_renderer, SDL_FALSE); +} + +Rect2 Renderer::get_viewport() const { + SDL_Rect r; + + SDL_RenderGetViewport(_renderer, &r); + + return Rect2(r.x, r.y, r.w, r.h); +} +void Renderer::set_viewport(const Rect2 &rect) const { + SDL_Rect r = rect.as_rect(); + + SDL_RenderSetViewport(_renderer, &r); +} + +Rect2 Renderer::get_clip_rect() const { + SDL_Rect r; + + SDL_RenderGetClipRect(_renderer, &r); + + return Rect2(r.x, r.y, r.w, r.h); +} +void Renderer::set_clip_rect(Rect2 *rect) const { + if (rect) { + SDL_Rect r = rect->as_rect(); + + SDL_RenderSetClipRect(_renderer, &r); + } else { + SDL_RenderSetClipRect(_renderer, nullptr); + } +} +bool Renderer::clip_rect_enabled() const { + return SDL_RenderIsClipEnabled(_renderer); +} + +bool Renderer::render_target_supported() { + return SDL_RenderTargetSupported(_renderer); +} + +SDL_Texture *Renderer::get_render_target() { + return SDL_GetRenderTarget(_renderer); +} +void Renderer::set_render_target(Texture *texture) { + if (texture) { + SDL_SetRenderTarget(_renderer, texture->get_texture()); + } else { + SDL_SetRenderTarget(_renderer, nullptr); + } +} + +void Renderer::initialize() { + if (SDL_Init(_flags) != 0) { + printf("SDL_Init() hiba!\n"); + + return; + } + + if (SDL_CreateWindowAndRenderer(_initial_window_width, _initial_window_height, _window_flags, &_window, &_renderer) != 0) { + printf("SDL_CreateWindowAndRenderer() hiba!\n"); + + return; + } + + _window_display_index = SDL_GetWindowDisplayIndex(_window); +} + +void Renderer::destroy() { + if (_window) + SDL_DestroyWindow(_window); + + if (_renderer) + SDL_DestroyRenderer(_renderer); + + _window = nullptr; + _renderer = nullptr; +} + +SDL_Window *Renderer::get_window() { + return _window; +} + +SDL_Renderer *Renderer::get_renderer() { + return _renderer; +} + +Renderer::Renderer() { + if (_singleton) { + printf("Renderer::Renderer(): _singleton is not null!\n"); + } + + _initial_window_width = 640; + _initial_window_height = 480; + + _singleton = this; + + _flags = SDL_INIT_VIDEO | SDL_INIT_TIMER; + _window_flags = SDL_WINDOW_SHOWN; + + initialize(); +} + +Renderer::Renderer(unsigned int flags, unsigned int window_flags, int initial_window_width, int initial_window_height) { + if (_singleton) { + printf("Renderer::Renderer(flags): _singleton is not null!\n"); + } + + _initial_window_width = initial_window_width; + _initial_window_height = initial_window_height; + + _singleton = this; + + _flags = flags; + _window_flags = window_flags; + + initialize(); +} + +Renderer::~Renderer() { + if (_singleton != this) { + printf("Renderer::~Renderer(): _singleton is not this!\n"); + } + + _singleton = nullptr; + + destroy(); +} + +Renderer *Renderer::get_singleton() { + return _singleton; +} + +Renderer *Renderer::_singleton = nullptr; \ No newline at end of file diff --git a/core/renderer/renderer.h b/core/renderer/renderer.h new file mode 100644 index 0000000..5ad1c32 --- /dev/null +++ b/core/renderer/renderer.h @@ -0,0 +1,101 @@ +#ifndef RENDERER_H +#define RENDERER_H + +#include "core/color.h" +#include "core/rect2.h" +#include "sprite.h" +#include "texture.h" + +#include + +//should not be a singleton +//should be a fully abstract class (even if not technically abstract) +//remove windows management and add it to a new window class (implemented into platforms) +//should work more like Libgdx's spritebatches -> it could veen have html renderer backends -> same ui could work both ways +//Events could work like godot's -> Ref and subclasses -> could even parse http post request into events like this +//httppostevent? +//state could be stored in a different class with http, (and maybe the session) + +class Renderer { +public: + void present(); + void set_draw_color(const Uint8 r, const Uint8 g, const Uint8 b, const Uint8 a); + void set_draw_color(const Color &color); + void clear(); + + SDL_BlendMode get_blend_mode() const; + void set_blend_mode(const SDL_BlendMode mode); + + void draw_point(const int x, const int y); + void draw_point(const float x, const float y); + + void draw_line(const int x1, const int x2, const int y1, const int y2); + void draw_line(const float x1, const float x2, const float y1, const float y2); + + void draw_rect(const Rect2 &rect); + + void draw_fill_rect(const Rect2 &rect); + + void draw_texture(const Texture &texture, const Rect2 &dst_rect); + void draw_texture(const Texture &texture, const Rect2 &src_rect, const Rect2 &dst_rect); + void draw_texture(const Texture &texture, const Rect2 &src_rect, const Rect2 &dst_rect, const double angle, const float cx = 0, const float cy = 0, const SDL_RendererFlip flip = SDL_FLIP_NONE); + + void draw_sprite(const Sprite &sprite); + void draw_sprite(const Sprite *sprite); + + int get_dpi() const; + int get_window_size_w() const; + int get_window_size_h() const; + int get_size_w() const; + int get_size_h() const; + void set_size(const int w, const int h) const; + void get_size(int *w, int *h) const; + + float get_scale_w() const; + float get_scale_h() const; + void set_scale(const float w, const float h) const; + void get_scale(float *w, float *h) const; + + bool get_integer_scaling() const; + void set_integer_scaling(const bool enable); + + Rect2 get_viewport() const; + void set_viewport(const Rect2 &rect) const; + + Rect2 get_clip_rect() const; + void set_clip_rect(Rect2 *rect) const; + bool clip_rect_enabled() const; + + bool render_target_supported(); + + SDL_Texture *get_render_target(); + void set_render_target(Texture *texture); + + void initialize(); + void destroy(); + + SDL_Window *get_window(); + SDL_Renderer *get_renderer(); + + Renderer(); + Renderer(unsigned int flags, unsigned int window_flags, int window_width = 640, int window_height = 480); + virtual ~Renderer(); + + static Renderer *get_singleton(); + +private: + int _initial_window_width; + int _initial_window_height; + + unsigned int _flags; + unsigned int _window_flags; + + SDL_Window *_window; + SDL_Renderer *_renderer; + + int _window_display_index; + + static Renderer *_singleton; +}; + +#endif \ No newline at end of file