Files
project_misth/include/window/window.h
T

403 lines
7.9 KiB
C++

#ifndef WINDOW_H
#define WINDOW_H
#include "pch.h"
#include "utils.h"
struct Image {
SDL_Texture *texture;
Vec2<float> size;
~Image() {
SDL_DestroyTexture(texture);
}
};
struct Font {
TTF_Font *font;
bool pixel_art;
~Font() {
TTF_CloseFont(font);
}
};
struct Text {
SDL_Texture *texture;
Vec2<float> size;
~Text() {
SDL_DestroyTexture(texture);
}
};
// Image pool
inline Pool<Image> image_pool;
// Font pool
inline Pool<Font> font_pool;
// Text pool
inline Pool<Text> text_pool;
enum Key : uint16_t {
Unknown = SDL_SCANCODE_UNKNOWN,
A = SDL_SCANCODE_A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z,
Num0 = SDL_SCANCODE_0,
Num1,
Num2,
Num3,
Num4,
Num5,
Num6,
Num7,
Num8,
Num9,
Space = SDL_SCANCODE_SPACE,
Enter = SDL_SCANCODE_RETURN,
Escape = SDL_SCANCODE_ESCAPE,
Tab = SDL_SCANCODE_TAB,
Backspace = SDL_SCANCODE_BACKSPACE,
LeftShift = SDL_SCANCODE_LSHIFT,
RightShift = SDL_SCANCODE_RSHIFT,
LeftCtrl = SDL_SCANCODE_LCTRL,
RightCtrl = SDL_SCANCODE_RCTRL,
LeftAlt = SDL_SCANCODE_LALT,
RightAlt = SDL_SCANCODE_RALT,
CapsLock = SDL_SCANCODE_CAPSLOCK,
Up = SDL_SCANCODE_UP,
Down = SDL_SCANCODE_DOWN,
Left = SDL_SCANCODE_LEFT,
Right = SDL_SCANCODE_RIGHT,
Home = SDL_SCANCODE_HOME,
End = SDL_SCANCODE_END,
PageUp = SDL_SCANCODE_PAGEUP,
PageDown = SDL_SCANCODE_PAGEDOWN,
Delete = SDL_SCANCODE_DELETE,
Insert = SDL_SCANCODE_INSERT,
Minus = SDL_SCANCODE_MINUS,
Equals = SDL_SCANCODE_EQUALS,
LeftBracket = SDL_SCANCODE_LEFTBRACKET,
RightBracket = SDL_SCANCODE_RIGHTBRACKET,
Semicolon = SDL_SCANCODE_SEMICOLON,
Apostrophe = SDL_SCANCODE_APOSTROPHE,
Grave = SDL_SCANCODE_GRAVE,
Comma = SDL_SCANCODE_COMMA,
Period = SDL_SCANCODE_PERIOD,
Slash = SDL_SCANCODE_SLASH,
Backslash = SDL_SCANCODE_NONUSBACKSLASH,
F1 = SDL_SCANCODE_F1,
F2,
F3,
F4,
F5,
F6,
F7,
F8,
F9,
F10,
F11,
F12,
MouseLeft = 513,
MouseMiddle,
MouseRight
};
constexpr std::pair<std::string, Key> KEY_NAMES[] = {
{"a", Key::A},
{"b", Key::B},
{"c", Key::C},
{"d", Key::D},
{"e", Key::E},
{"f", Key::F},
{"g", Key::G},
{"h", Key::H},
{"i", Key::I},
{"j", Key::J},
{"k", Key::K},
{"l", Key::L},
{"m", Key::M},
{"n", Key::N},
{"o", Key::O},
{"p", Key::P},
{"q", Key::Q},
{"r", Key::R},
{"s", Key::S},
{"t", Key::T},
{"u", Key::U},
{"v", Key::V},
{"w", Key::W},
{"x", Key::X},
{"y", Key::Y},
{"z", Key::Z},
{"num0", Key::Num0},
{"num1", Key::Num1},
{"num2", Key::Num2},
{"num3", Key::Num3},
{"num4", Key::Num4},
{"num5", Key::Num5},
{"num6", Key::Num6},
{"num7", Key::Num7},
{"num8", Key::Num8},
{"num9", Key::Num9},
{"space", Key::Space},
{"enter", Key::Enter},
{"escape", Key::Escape},
{"tab", Key::Tab},
{"backspace", Key::Backspace},
{"left_shift", Key::LeftShift},
{"right_shift", Key::RightShift},
{"left_ctrl", Key::LeftCtrl},
{"right_ctrl", Key::RightCtrl},
{"left_alt", Key::LeftAlt},
{"right_alt", Key::RightAlt},
{"capslock", Key::CapsLock},
{"up", Key::Up},
{"down", Key::Down},
{"left", Key::Left},
{"right", Key::Right},
{"home", Key::Home},
{"end", Key::End},
{"page_up", Key::PageUp},
{"page_down", Key::PageDown},
{"delete", Key::Delete},
{"insert", Key::Insert},
{"minus", Key::Minus},
{"equals", Key::Equals},
{"left_bracket", Key::LeftBracket},
{"right_bracket", Key::RightBracket},
{"semicolon", Key::Semicolon},
{"apostrophe", Key::Apostrophe},
{"grave", Key::Grave},
{"comma", Key::Comma},
{"period", Key::Period},
{"slash", Key::Slash},
{"backslash", Key::Backslash},
{"f1", Key::F1},
{"f2", Key::F2},
{"f3", Key::F3},
{"f4", Key::F4},
{"f5", Key::F5},
{"f6", Key::F6},
{"f7", Key::F7},
{"f8", Key::F8},
{"f9", Key::F9},
{"f10", Key::F10},
{"f11", Key::F11},
{"f12", Key::F12},
{"mouse_left", Key::MouseLeft},
{"mouse_middle", Key::MouseMiddle},
{"mouse_right", Key::MouseRight}
};
inline Key get_key_from_name(std::string_view name) {
for (const auto &[key_name, key] : KEY_NAMES)
if (key_name == name)
return key;
return Key::Unknown;
}
inline std::unordered_map<std::string, Key> action_key_map;
inline void set_action_mapping(const std::string &action_name, const std::string &key_name) {
Key key = get_key_from_name(key_name);
if (key != Key::Unknown)
action_key_map[action_name] = key;
}
inline Key get_key(std::string &name) {
auto it = action_key_map.find(name);
if (it != action_key_map.end())
return it->second;
return get_key_from_name(name);
}
struct Event {
enum Type {
NONE,
QUIT,
KEY_UP,
KEY_DOWN,
TEXT_INPUT,
SCROLL,
MOUSE_LEAVE,
MOUSE_BUTTON_UP,
MOUSE_BUTTON_DOWN,
MOUSE_MOVE
} type;
union {
struct {
Key key;
} key;
std::string *text_input;
Vec2<float> scroll;
struct {
Key button;
Vec2<float> position;
} mouse_button;
struct {
Vec2<float> position;
Vec2<float> delta;
} mouse_move;
};
};
struct Animation {
std::vector<uint64_t> frames;
float frame_rate;
~Animation() {
for (uint64_t frame_id : frames)
image_pool.release(frame_id);
}
};
inline Pool<Animation> animation_pool;
struct Window {
public:
// title can be free'd by the caller after the window is created, as it's copied internally.
Window(Vec2<float> size, const char *title);
void update(Vec2<float> new_size, const char *new_title);
~Window();
// Rendering functions
uint64_t load_image(const char *path, bool pixel_art);
Vec2<float> get_image_size(uint64_t image_id);
uint64_t load_font(const char *path, int font_size, bool bold, bool italic, bool underline, bool pixel_art);
// text is copied internally, so it can be free'd by the caller after the text is created.
uint64_t create_text(uint64_t font_id, const char *text, uint32_t length, Color color);
Vec2<float> get_text_size(uint64_t text_id);
bool write(uint64_t text_id, Vec2<float> position, float z, float angle, Vec2<float> pivot, Vec2<float> scale, float alpha);
bool draw(uint64_t image_id, Vec2<float> position, float z, float angle, Vec2<float> pivot, Vec2<float> scale, float alpha);
bool draw_rect(Rect rect, Color color, float z, float angle, Vec2<float> pivot, Vec2<float> scale, float alpha);
void render(); // the rest of the calls only build the instruction list, this actually renders everything added to the screen (following z order)
void clear(); // clears the instruction list
// Event handling
bool poll(Event &event); // returns true if an event was polled, false otherwise
// Clipboard get
// To be free'd by the caller after use.
const char *paste();
// Time
uint64_t get_time(); // returns the time in nanoseconds since the window was created
uint64_t delta_time(); // returns the time in nanoseconds since the last render call
private:
// internal data and functions
SDL_Window *window;
SDL_Renderer *renderer;
Vec2<float> real_size;
Vec2<float> virtual_size;
Vec2<float> offset;
float scale;
// White pixel texture for drawing colored rectangles
SDL_Texture *white_tex;
struct RenderInstruction {
enum Type {
DRAW_IMAGE,
DRAW_TEXT,
DRAW_RECT
} type;
float z;
float angle;
Vec2<float> pivot;
Vec2<float> scale;
float alpha;
union {
struct {
uint64_t image_id;
Vec2<float> position;
} draw_image;
struct {
uint64_t text_id;
Vec2<float> position;
} draw_text;
struct {
Rect rect;
Color color;
} draw_rect;
};
};
std::vector<struct RenderInstruction> render_instructions;
void compute_transform();
bool mouse_in_window(const Vec2<float> real_position, Vec2<float> &virtual_position);
void draw_letterbox();
};
inline Window window({720, 480}, "Mysth Engine");
#endif