#ifndef WINDOW_H #define WINDOW_H #include "pch.h" #include "utils.h" struct Image { SDL_Texture *texture; Vec2 size; ~Image() { SDL_DestroyTexture(texture); } }; struct Font { TTF_Font *font; bool pixel_art; ~Font() { TTF_CloseFont(font); } }; struct Text { SDL_Texture *texture; Vec2 size; ~Text() { SDL_DestroyTexture(texture); } }; // Image pool inline Pool image_pool; // Font pool inline Pool font_pool; // Text pool inline Pool text_pool; 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 { uint32_t key; } key; struct { char *text; uint32_t length; } text_input; struct { float x, y; } scroll; struct { uint8_t button; Vec2 position; } mouse_button; struct { Vec2 position; Vec2 delta; } mouse_move; }; }; struct Animation { std::vector frames; float frame_rate; bool loop; int reference_count = 0; ~Animation() { for (uint64_t frame_id : frames) image_pool.release(frame_id); } }; inline Pool 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 size, const char *title); void update(Vec2 new_size, const char *new_title); ~Window(); // Rendering functions uint64_t load_image(const char *path, float alpha = 1.0f, bool pixel_art = false); Vec2 get_image_size(uint64_t image_id); uint64_t load_font(const char *path, int font_size, bool bold = false, bool italic = false, bool underline = false, bool pixel_art = false); // 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 get_text_size(uint64_t text_id); bool write(uint64_t text_id, Vec2 position, float z, float angle = 0.0f, Vec2 scale = {1.0f, 1.0f}); bool draw(uint64_t image_id, Vec2 position, float z, float angle = 0.0f, Vec2 scale = {1.0f, 1.0f}); bool draw_rect(Rect rect, Color color, float z, float angle = 0.0f); 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 // consumes an event, (mostly for text input, to free the text input buffer) // but also so the user can decide when they're done with the event explicitly. void consume(Event &event); // Text input // Starts accepting Unicode text input events, and stops acceptong normal key down/up events for those keys. void start_text_input(); void stop_text_input(); // Clipboard get // To be free'd by the caller after use. const char *paste(); // Time uint64_t get_time(); // returns the time in milliseconds since the window was created uint64_t delta_time(); // returns the time in milliseconds since the last render call private: // internal data and functions SDL_Window *window; SDL_Renderer *renderer; Vec2 real_size; Vec2 virtual_size; Vec2 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 scale; union { struct { uint64_t image_id; Vec2 position; } draw_image; struct { uint64_t text_id; Vec2 position; } draw_text; struct { Rect rect; Color color; } draw_rect; }; }; std::vector render_instructions; bool text_input_active; void compute_transform(); bool mouse_in_window(const Vec2 real_position, Vec2 &virtual_position); void draw_letterbox(); }; inline Window window({720, 480}, "Mysth Engine"); #endif