added Image class to wrap SDL_Surface; changed Window to use Images

This commit is contained in:
Bob Polis 2020-10-24 15:13:13 +02:00
parent 0c4f5456a4
commit 7382120a0b
4 changed files with 88 additions and 19 deletions

37
Image.cpp Normal file
View File

@ -0,0 +1,37 @@
//
// Image.cpp
// libscgui
//
// Created by Bob Polis at 2020-10-23
// Copyright (c) 2020 SwiftCoder. All rights reserved.
//
#include "Image.hpp"
#include <SDL2/SDL_image.h>
#include <stdexcept>
using namespace sc::gui;
Image::Image(int w, int h) {
Uint32 rmask, gmask, bmask, amask;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
rmask = 0xff000000;
gmask = 0x00ff0000;
bmask = 0x0000ff00;
amask = 0x000000ff;
#else
rmask = 0x000000ff;
gmask = 0x0000ff00;
bmask = 0x00ff0000;
amask = 0xff000000;
#endif
SDL_Surface* s {SDL_CreateRGBSurface(0, w, h, 32, rmask, gmask, bmask, amask)};
_s.reset(s);
}
Image::Image(const std::string& path) {
// load image from file into surface
SDL_Surface* loaded = IMG_Load(path.c_str());
if (!loaded) throw std::runtime_error(IMG_GetError());
_s.reset(loaded);
}

33
Image.hpp Normal file
View File

@ -0,0 +1,33 @@
//
// Image.hpp
// libscgui
//
// Created by Bob Polis at 2020-10-23
// Copyright (c) 2020 SwiftCoder. All rights reserved.
//
#ifndef _Image_H_
#define _Image_H_
#include <string>
#include <memory>
#include <SDL2/SDL.h>
namespace sc {
namespace gui {
class Image {
public:
Image(int w, int h);
Image(const std::string& path);
SDL_Surface* surface() const { return _s.get(); }
int width() const { return _s.get()->w; }
int height() const { return _s.get()->h; }
private:
std::unique_ptr<SDL_Surface, void(*)(SDL_Surface*)> _s {nullptr, SDL_FreeSurface};
};
}
}
#endif // _Image_H_

View File

@ -10,12 +10,18 @@
#include <cmath> #include <cmath>
#include <algorithm> #include <algorithm>
#include "Window.hpp" #include "Window.hpp"
#include "Image.hpp"
using namespace sc::gui; using namespace sc::gui;
std::vector<Window> Window::_windows; std::vector<Window> Window::_windows;
std::map<SDL_WindowEventID, std::vector<WindowEventHandler>> Window::_global_event_handlers; std::map<SDL_WindowEventID, std::vector<WindowEventHandler>> Window::_global_event_handlers;
Window& Window::new_window(const std::string& title) {
_windows.emplace_back(title);
return _windows.back();
}
Window* Window::from_sdl(Uint32 window_id) { Window* Window::from_sdl(Uint32 window_id) {
SDL_Window* w {SDL_GetWindowFromID(window_id)}; SDL_Window* w {SDL_GetWindowFromID(window_id)};
if (w) { if (w) {
@ -75,10 +81,10 @@ void Window::add_global_event_handler(WindowEventHandler handler, SDL_WindowEven
} }
} }
Window::Window(const char* title) : _title {title} { Window::Window(const std::string& title) : _title {title} {
SDL_Window* win = SDL_CreateWindow(title, SDL_Window* win = SDL_CreateWindow(title.c_str(),
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
900, 540, 800, 450,
SDL_WINDOW_RESIZABLE); SDL_WINDOW_RESIZABLE);
_w.reset(win); _w.reset(win);
_r.reset(SDL_CreateRenderer(win, -1, 0)); _r.reset(SDL_CreateRenderer(win, -1, 0));
@ -94,23 +100,13 @@ void Window::update() const {
SDL_RenderPresent(_r.get()); SDL_RenderPresent(_r.get());
} }
void Window::load_image() { void Window::show_image(const Image& image) {
// load image from file into surface
SDL_Surface* loaded = IMG_Load(_title.c_str());
if (!loaded) throw std::runtime_error(IMG_GetError());
std::unique_ptr<SDL_Surface, void(*)(SDL_Surface*)> loaded_ {loaded, SDL_FreeSurface};
// create texture from surface // create texture from surface
_t.reset(SDL_CreateTextureFromSurface(_r.get(), loaded)); _t.reset(SDL_CreateTextureFromSurface(_r.get(), image.surface()));
// query texture for properties, like image size
Uint32 format;
int access;
int w, h;
int result = SDL_QueryTexture(_t.get(), &format, &access, &w, &h);
if (result != 0) throw std::runtime_error(SDL_GetError());
// get screen size, to scale down if image is too big // get screen size, to scale down if image is too big
int w {image.width()};
int h {image.height()};
SDL_DisplayMode dm; SDL_DisplayMode dm;
SDL_GetCurrentDisplayMode(0, &dm); SDL_GetCurrentDisplayMode(0, &dm);
if (dm.w < w || dm.h < h) { if (dm.w < w || dm.h < h) {

View File

@ -19,6 +19,7 @@
namespace sc { namespace sc {
namespace gui { namespace gui {
using WindowEventHandler = bool(*)(const SDL_Event&, bool quit); using WindowEventHandler = bool(*)(const SDL_Event&, bool quit);
class Image;
class Window { class Window {
public: public:
@ -27,17 +28,19 @@ namespace sc {
static bool handle_global_event(const SDL_Event& event); static bool handle_global_event(const SDL_Event& event);
static void add_global_event_handler(WindowEventHandler handler, SDL_WindowEventID type); static void add_global_event_handler(WindowEventHandler handler, SDL_WindowEventID type);
static Window* from_sdl(Uint32 window_id); static Window* from_sdl(Uint32 window_id);
static Window& new_window(const std::string& title);
Window(const char* title); Window(const std::string& title);
void add_event_handler(WindowEventHandler handler, SDL_WindowEventID type); void add_event_handler(WindowEventHandler handler, SDL_WindowEventID type);
bool handle_event(const SDL_Event& event, bool quit); bool handle_event(const SDL_Event& event, bool quit);
SDL_Window* get_window() const { return _w.get(); } SDL_Window* get_window() const { return _w.get(); }
SDL_Renderer* renderer() const { return _r.get(); }
void set_size(int w, int h); void set_size(int w, int h);
void update() const; void update() const;
void load_image(); void show_image(const Image& image);
private: private:
static std::vector<Window> _windows; static std::vector<Window> _windows;