diff --git a/client/src/game_state.cpp b/client/src/game_state.cpp index a0d9a2e..576e9d4 100644 --- a/client/src/game_state.cpp +++ b/client/src/game_state.cpp @@ -197,12 +197,12 @@ void GameState::render(const RenderContext& context) { switch(_current_screen) { case Screen::MAIN_MENU: if(_main_menu) { - _main_menu->render(context.shape_renderer, context.txt_renderer); + _main_menu->render(context.ui_renderer); } break; case Screen::BOOTING: if(_boot_sequence) { - _boot_sequence->render(context.txt_renderer, context.screen_height); + _boot_sequence->render(context.ui_renderer); } break; case Screen::DESKTOP: diff --git a/client/src/gfx/types.h b/client/src/gfx/types.h index 1752237..64ffafe 100644 --- a/client/src/gfx/types.h +++ b/client/src/gfx/types.h @@ -1,7 +1,6 @@ #pragma once -class ShapeRenderer; -class TextRenderer; +class UIRenderer; struct Color { float r, g, b; @@ -12,8 +11,7 @@ struct Rect { }; struct RenderContext { - ShapeRenderer* shape_renderer; - TextRenderer* txt_renderer; + UIRenderer* ui_renderer; int screen_height; bool show_cursor; }; diff --git a/client/src/main.cpp b/client/src/main.cpp index 3edece2..a289d5a 100644 --- a/client/src/main.cpp +++ b/client/src/main.cpp @@ -8,6 +8,7 @@ #include "gfx/shape_renderer.h" #include "gfx/txt_renderer.h" #include "game_state.h" +#include "ui/ui_renderer.h" #include "gfx/types.h" #include "ui/cursor_manager.h" @@ -78,6 +79,10 @@ int main(int argc, char** argv) { /* Init shape renderer. */ ShapeRenderer* shape_renderer_instance = new ShapeRenderer(SCREEN_WIDTH, SCREEN_HEIGHT); + /* Init UI renderer. */ + UIRenderer* ui_renderer_instance = new UIRenderer(shape_renderer_instance, + txt_render_instance, SCREEN_HEIGHT); + auto game_state = std::make_unique(); if(argc > 1 && std::string(argv[1]) == "-sp") { game_state->start_single_player_now(SCREEN_WIDTH, SCREEN_HEIGHT); @@ -111,8 +116,7 @@ int main(int argc, char** argv) { glClear(GL_COLOR_BUFFER_BIT); RenderContext context = { - shape_renderer_instance, - txt_render_instance, + ui_renderer_instance, SCREEN_HEIGHT, show_cursor }; @@ -124,6 +128,7 @@ int main(int argc, char** argv) { /* Cleanup. */ game_state.reset(); + delete ui_renderer_instance; delete shape_renderer_instance; delete txt_render_instance; SDL_GL_DestroyContext(context); diff --git a/client/src/terminal.cpp b/client/src/terminal.cpp index 008dee2..ebb922a 100644 --- a/client/src/terminal.cpp +++ b/client/src/terminal.cpp @@ -111,8 +111,8 @@ void Terminal::scroll(int amount, int win_content_height) { } } -void Terminal::render(const RenderContext& context, int x, int y, int width, int height) { - +void Terminal::render(const RenderContext& context, int x, int y_screen, int y_gl, + int width, int height) { const Color white = { 1.0f, 1.0f, 1.0f }; const Color green = { 0.2f, 1.0f, 0.2f }; float line_height = 20.0f; @@ -120,27 +120,28 @@ void Terminal::render(const RenderContext& context, int x, int y, int width, int /* Enable scissor test to clip rendering to the window content area. */ glEnable(GL_SCISSOR_TEST); - glScissor(x, y, width, height); + glScissor(x, y_gl, width, height); /* Draw History. */ for(size_t i = _scroll_offset; i < _history.size(); ++i) { - float y_pos = (y+height) - padding - line_height - ((i - _scroll_offset) * line_height); - context.txt_renderer->render_text(_history[i].c_str(), x+padding, y_pos, 1.0f, white); + float line_y_pos = y_screen + padding + ((i - _scroll_offset) * line_height); + context.ui_renderer->render_text(_history[i].c_str(), x+padding, line_y_pos+18, white); } /* Draw current input line. */ - float prompt_y_pos = (y+height) - padding - line_height - - ((_history.size()-_scroll_offset)*line_height); + float prompt_line_y = (y_screen + padding) + ((_history.size() - _scroll_offset) * line_height); + float prompt_baseline_y = prompt_line_y + 18; /* Render prompt string. */ std::string prompt_str = _prompt + "> "; - context.txt_renderer->render_text(prompt_str.c_str(), x+padding, prompt_y_pos, 1.0f, green); + context.ui_renderer->render_text(prompt_str.c_str(), x+padding, prompt_baseline_y, green); /* Render text view for the input right after prompt. */ float input_x_pos = x + padding + (prompt_str.length() * 8.5f); /* Estimate width */ float input_width = width - (input_x_pos-x); - _input_view->render(context.txt_renderer, input_x_pos, prompt_y_pos, input_width, + _input_view->render(context.ui_renderer, input_x_pos, prompt_line_y, input_width, line_height, context.show_cursor); + /* Disable scissor test. */ glDisable(GL_SCISSOR_TEST); } diff --git a/client/src/terminal.h b/client/src/terminal.h index 04b2d83..735aa49 100644 --- a/client/src/terminal.h +++ b/client/src/terminal.h @@ -18,7 +18,8 @@ public: void update(void) override; void handle_input(SDL_Event* event, int window_x, int window_y, int window_gl_y) override; - void render(const RenderContext& context, int x, int y, int width, int height) override; + void render(const RenderContext& context, int x, int y_screen, int y_gl, + int width, int height) override; void scroll(int amount, int content_height) override; void add_history(const std::string& line); void set_prompt(const std::string& prompt); diff --git a/client/src/ui/boot_sequence.cpp b/client/src/ui/boot_sequence.cpp index 4a1f8bd..e0b458a 100644 --- a/client/src/ui/boot_sequence.cpp +++ b/client/src/ui/boot_sequence.cpp @@ -2,7 +2,7 @@ #include #include #include -#include "gfx/txt_renderer.h" +#include "ui/ui_renderer.h" #include "boot_sequence.h" #include @@ -35,7 +35,7 @@ bool BootSequence::is_finished(void) { return (SDL_GetTicks() - _start_time) >= _total_duration_ms; } -void BootSequence::render(TextRenderer* txt_renderer, int screen_height) { +void BootSequence::render(UIRenderer* ui_renderer) { const Color text_color = { 0.9f, 0.9f, 0.9f }; /* grey/white */ const float line_height = 18.0f; const float padding = 15.0f; @@ -48,7 +48,7 @@ void BootSequence::render(TextRenderer* txt_renderer, int screen_height) { } for(int i = 0; i < lines_to_show; ++i) { - float y_pos = (screen_height - padding) - (i * line_height); - txt_renderer->render_text(_messages[i].c_str(), padding, y_pos, 1.0f, text_color); + float y_pos = padding + (i*line_height); + ui_renderer->render_text(_messages[i].c_str(), padding, y_pos, text_color); } } diff --git a/client/src/ui/boot_sequence.h b/client/src/ui/boot_sequence.h index a8aeeb1..7e73dde 100644 --- a/client/src/ui/boot_sequence.h +++ b/client/src/ui/boot_sequence.h @@ -4,7 +4,7 @@ #include #include -#include "gfx/txt_renderer.h" +#include "ui/ui_renderer.h" class BootSequence { public: @@ -12,7 +12,7 @@ public: ~BootSequence(void); bool is_finished(void); - void render(TextRenderer* txt_renderer, int screen_height); + void render(UIRenderer* ui_renderer); private: std::vector _messages; Uint32 _start_time; diff --git a/client/src/ui/desktop.cpp b/client/src/ui/desktop.cpp index 20bb760..58e9153 100644 --- a/client/src/ui/desktop.cpp +++ b/client/src/ui/desktop.cpp @@ -2,21 +2,19 @@ #include #include #include -#include #include +#include +#include +#include #include "gfx/types.h" #include "ui/editor.h" #include "desktop.h" -#include #include "client_network.h" -#include "gfx/shape_renderer.h" -#include "gfx/txt_renderer.h" #include "terminal.h" #include "ui/i_window_content.h" +#include "ui/launcher.h" #include "ui/taskbar.h" -#include -#include #include "ui/ui_window.h" #include "ui/window_action.h" @@ -33,7 +31,9 @@ Desktop::Desktop(int screen_width, int screen_height, ClientNetwork* network) { _network = network; _focused_window = nullptr; _launcher_is_open = false; - _launcher = std::make_unique(5, 5 + _taskbar->get_height(), 200); + _launcher = std::make_unique(5, 0, 200); /* Tmp y-coord. */ + int launcher_y = screen_height - _taskbar->get_height() - _launcher->get_height(); + _launcher->set_y(launcher_y); /* Load snippets for temp wallpaper. */ std::ifstream snippet_file("assets/menu_background_snippets.txt"); @@ -196,11 +196,11 @@ UIWindow* Desktop::get_focused_window(void) { } void Desktop::render(const RenderContext& context) { - _render_wallpaper(context.txt_renderer); + _render_wallpaper(context.ui_renderer); if(_launcher_is_open) { - _launcher->render(context.shape_renderer, context.txt_renderer, context.screen_height); + _launcher->render(context.ui_renderer); } - _taskbar->render(context.shape_renderer, context.txt_renderer, _windows, _focused_window); + _taskbar->render(context.ui_renderer, _windows, _focused_window); /* Render non-focused windows first. */ for(const auto& win : _windows) { if(win.get() != _focused_window && !win->is_minimized()) { @@ -213,11 +213,11 @@ void Desktop::render(const RenderContext& context) { } } -void Desktop::_render_wallpaper(TextRenderer* txt_renderer) { +void Desktop::_render_wallpaper(UIRenderer* ui_renderer) { const Color wallpaper_color = { 0.0f, 0.15f, 0.08f }; for(auto& line : _background_text) { - txt_renderer->render_text(line.text.c_str(), std::round(line.x), - line.render_y, 1.0f, wallpaper_color); + ui_renderer->render_text(line.text.c_str(), std::round(line.x), + line.render_y, wallpaper_color); } } diff --git a/client/src/ui/desktop.h b/client/src/ui/desktop.h index 2ca2b40..e9e484f 100644 --- a/client/src/ui/desktop.h +++ b/client/src/ui/desktop.h @@ -5,11 +5,11 @@ #include #include "client_network.h" -#include "gfx/txt_renderer.h" #include "gfx/types.h" #include "ui/ui_window.h" #include "ui/taskbar.h" #include "ui/launcher.h" +#include "ui/ui_renderer.h" /* Animated background stuff. */ struct ScrollingText { @@ -34,7 +34,7 @@ public: private: void _set_focused_window(UIWindow* window); - void _render_wallpaper(TextRenderer* txt_renderer); + void _render_wallpaper(UIRenderer* ui_renderer); void _update_wallpaper(int screen_width, int screen_height); std::vector> _windows; diff --git a/client/src/ui/editor.cpp b/client/src/ui/editor.cpp index 6ad1dec..714c3a4 100644 --- a/client/src/ui/editor.cpp +++ b/client/src/ui/editor.cpp @@ -34,7 +34,7 @@ void Editor::update(void) { void Editor::handle_input(SDL_Event* event, int window_x, int window_y, int window_gl_y) { if(!event) return; - _menu_bar->handle_event(event, window_x, window_y, window_gl_y); + _menu_bar->handle_event(event, window_x, window_y); /* We don't care about the return val here. RET is just newline. */ if(event->type == SDL_EVENT_KEY_DOWN && event->key.key == SDLK_S && @@ -46,13 +46,14 @@ void Editor::handle_input(SDL_Event* event, int window_x, int window_y, int wind } } -void Editor::render(const RenderContext& context, int x, int y, int width, int height) { +void Editor::render(const RenderContext& context, int x, int y_screen, int y_gl, + int width, int height) { int menu_bar_height = _menu_bar->get_height(); - int menu_bar_y_gl = y + height - menu_bar_height; + int content_y = y_screen + menu_bar_height; + int content_height = height - menu_bar_height; - _view->render(context.txt_renderer, x, y, width, height - menu_bar_height, - context.show_cursor); - _menu_bar->render(context.shape_renderer, context.txt_renderer, x, menu_bar_y_gl, width); + _view->render(context.ui_renderer, x, content_y, width, content_height, context.show_cursor); + _menu_bar->render(context.ui_renderer, x, y_screen, width); } void Editor::scroll(int amount, int content_height) { diff --git a/client/src/ui/editor.h b/client/src/ui/editor.h index 55247b4..1e32a2b 100644 --- a/client/src/ui/editor.h +++ b/client/src/ui/editor.h @@ -17,7 +17,8 @@ public: void update(void) override; void handle_input(SDL_Event* event, int window_x, int window_y, int window_gl_y) override; - void render(const RenderContext& context, int x, int y, int width, int height) override; + void render(const RenderContext& context, int x, int y_screen, int y_gl, + int width, int height) override; void scroll(int amount, int content_height) override; bool should_close(void) override; void set_buffer_content(const std::string& content); diff --git a/client/src/ui/i_window_content.h b/client/src/ui/i_window_content.h index 4fb02f6..1cb78d1 100644 --- a/client/src/ui/i_window_content.h +++ b/client/src/ui/i_window_content.h @@ -10,7 +10,8 @@ public: virtual ~IWindowContent(void) = default; virtual void update(void) = 0; virtual void handle_input(SDL_Event* event, int window_x, int window_y, int window_gl_y) = 0; - virtual void render(const RenderContext& context, int x, int y, int width, int height) = 0; + virtual void render(const RenderContext& context, int x, int y_screen, int y_gl, + int width, int height) = 0; virtual void scroll(int amount, int content_height) = 0; virtual bool should_close(void) = 0; virtual WindowAction get_pending_action() = 0; diff --git a/client/src/ui/launcher.cpp b/client/src/ui/launcher.cpp index 907dd4f..6b2e62e 100644 --- a/client/src/ui/launcher.cpp +++ b/client/src/ui/launcher.cpp @@ -1,8 +1,6 @@ #include "launcher.h" #include -#include "gfx/shape_renderer.h" -#include "gfx/txt_renderer.h" -#include "gfx/types.h" +#include "ui/ui_renderer.h" Launcher::Launcher(int x, int y, int width) : _x(x), _y(y), _width(width) { /* TODO: Hardcode the launcher apps for now. */ @@ -16,34 +14,31 @@ Launcher::Launcher(int x, int y, int width) : _x(x), _y(y), _width(width) { Launcher::~Launcher(void) {} bool Launcher::is_point_inside(int x, int y, int screen_height) const { - int ui_y = screen_height - y; /* convert mouse y to GL/UI coords. */ - return (x >= _x && x <= _x + _width && ui_y >= _y && ui_y <= _y + _height); + return (x >= _x && x <= _x + _width && y>= _y && y <= _y + _height); } -void Launcher::render(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer, - int screen_height) { +void Launcher::render(UIRenderer* ui_renderer) { const Color bg_color = { 0.15f, 0.17f, 0.19f }; const Color text_color = { 0.9f, 0.9f, 0.9f }; const Color hover_color = { 0.3f, 0.32f, 0.34f }; /* Note: y-coord is TOP of launcher menu. */ - shape_renderer->draw_rect(_x, _y, _width, _height, bg_color); + ui_renderer->draw_rect(_x, _y, _width, _height, bg_color); int item_height = 30; int item_y = _y; float mouse_x, mouse_y; SDL_GetMouseState(&mouse_x, &mouse_y); - int ui_mouse_y = screen_height - mouse_y; for(const auto& app_name : _apps) { /* Check for hover. */ if(mouse_x >= _x && mouse_x <= _x + _width && - ui_mouse_y >= item_y && ui_mouse_y <= item_y + item_height) { - shape_renderer->draw_rect(_x, item_y, _width, item_height, hover_color); + mouse_y >= item_y && mouse_y <= item_y + item_height) { + ui_renderer->draw_rect(_x, item_y, _width, item_height, hover_color); } - txt_renderer->render_text(app_name.c_str(), _x + 10, item_y + 8, 1.0f, text_color); + ui_renderer->render_text(app_name.c_str(), _x+10, item_y+20, text_color); item_y += item_height; } } @@ -51,13 +46,13 @@ void Launcher::render(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer, std::string Launcher::handle_event(SDL_Event* event, int screen_height) { if(event->type == SDL_EVENT_MOUSE_BUTTON_UP) { int mouse_x = event->button.x; - int ui_mouse_y = screen_height - event->button.y; + int mouse_y = event->button.y; int item_height = 30; int item_y = _y; for(const auto& app_name : _apps) { if(mouse_x >= _x && mouse_x <= _x + _width && - ui_mouse_y >= item_y && ui_mouse_y <= item_y + item_height) { + mouse_y >= item_y && mouse_y <= item_y + item_height) { return app_name; /* Return name of clicked app. */ } item_y += item_height; @@ -65,3 +60,11 @@ std::string Launcher::handle_event(SDL_Event* event, int screen_height) { } return ""; /* Nothing clicked. */ } + +void Launcher::set_y(int y) { + _y = y; +} + +int Launcher::get_height(void) const { + return _height; +} diff --git a/client/src/ui/launcher.h b/client/src/ui/launcher.h index 7eb0dcd..289c331 100644 --- a/client/src/ui/launcher.h +++ b/client/src/ui/launcher.h @@ -4,17 +4,18 @@ #include #include -class ShapeRenderer; -class TextRenderer; +class UIRenderer; class Launcher { public: Launcher(int x, int y, int width); ~Launcher(void); - void render(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer, int screen_height); + void render(UIRenderer* ui_renderer); std::string handle_event(SDL_Event* event, int screen_height); bool is_point_inside(int x, int y, int screen_height) const; + void set_y(int y); + int get_height(void) const; private: int _x, _y, _width, _height; diff --git a/client/src/ui/main_menu.cpp b/client/src/ui/main_menu.cpp index a02cae3..416c4bf 100644 --- a/client/src/ui/main_menu.cpp +++ b/client/src/ui/main_menu.cpp @@ -1,9 +1,7 @@ #include #include #include - -#include "gfx/shape_renderer.h" -#include "gfx/txt_renderer.h" +#include "ui/ui_renderer.h" #include "main_menu.h" @@ -73,12 +71,10 @@ void MainMenu::handle_event(SDL_Event* event) { int mouse_x = event->motion.x; int mouse_y = event->motion.y; for(auto& button : _buttons) { - /* Invert mouse_y for UI coordinate system. */ - int inverted_y = _screen_height - mouse_y; button.is_hovered = (mouse_x >= button.rect.x && mouse_x <= button.rect.x + button.rect.w - && inverted_y >= button.rect.y - && inverted_y <= button.rect.y + button.rect.h); + && mouse_y >= button.rect.y + && mouse_y <= button.rect.y + button.rect.h); } } else if(event->type == SDL_EVENT_MOUSE_BUTTON_DOWN) { for(const auto& button : _buttons) { @@ -95,8 +91,8 @@ Screen MainMenu::update(void) { return _next_screen; } -void MainMenu::render(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer) { - _render_background(txt_renderer); +void MainMenu::render(UIRenderer* ui_renderer) { + _render_background(ui_renderer->get_text_renderer()); /* Button colours. */ const Color button_color = { 0.1f, 0.15f, 0.2f }; @@ -106,18 +102,17 @@ void MainMenu::render(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer) for(const auto& button : _buttons) { /* Draw button background. */ if(button.is_hovered) { - shape_renderer->draw_rect(button.rect.x, button.rect.y, button.rect.w, + ui_renderer->draw_rect(button.rect.x, button.rect.y, button.rect.w, button.rect.h, button_hover_color); } else { - shape_renderer->draw_rect(button.rect.x, button.rect.y, button.rect.w, + ui_renderer->draw_rect(button.rect.x, button.rect.y, button.rect.w, button.rect.h, button_color); } /* Draw button text centered. */ - float text_width = txt_renderer->get_text_width(button.label.c_str(), 1.0f); + float text_width = ui_renderer->get_text_renderer()->get_text_width(button.label.c_str(), 1.0f); float text_x = button.rect.x + (button.rect.w - text_width) / 2.0f; - txt_renderer->render_text(button.label.c_str(), text_x, - button.rect.y + 18, 1.0f, text_color); + ui_renderer->render_text(button.label.c_str(), text_x, button.rect.y + 32, text_color); } } diff --git a/client/src/ui/main_menu.h b/client/src/ui/main_menu.h index 014136c..487dd42 100644 --- a/client/src/ui/main_menu.h +++ b/client/src/ui/main_menu.h @@ -3,9 +3,8 @@ #include #include -#include "gfx/txt_renderer.h" -#include "gfx/shape_renderer.h" #include "gfx/types.h" +#include "ui/ui_renderer.h" #include "game_state.h" union SDL_Event; @@ -24,7 +23,7 @@ public: void handle_event(SDL_Event* event); Screen update(void); - void render(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer); + void render(UIRenderer* ui_renderer); private: void _update_background(void); diff --git a/client/src/ui/menu_bar.cpp b/client/src/ui/menu_bar.cpp index 8db5ff6..fca7d64 100644 --- a/client/src/ui/menu_bar.cpp +++ b/client/src/ui/menu_bar.cpp @@ -26,7 +26,7 @@ int MenuBar::get_height(void) const { return _height; } -void MenuBar::handle_event(SDL_Event* event, int window_x, int window_y, int window_gl_y) { +void MenuBar::handle_event(SDL_Event* event, int window_x, int window_y) { if(event->type == SDL_EVENT_MOUSE_BUTTON_DOWN) { int mouse_x = event->button.x; int mouse_y = event->button.y; @@ -72,27 +72,26 @@ void MenuBar::handle_event(SDL_Event* event, int window_x, int window_y, int win } } -void MenuBar::render(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer, - int x, int y_gl, int width) { +void MenuBar::render(UIRenderer* ui_renderer, int x, int y, int width) { const Color bg_color = {0.15f, 0.17f, 0.19f}; const Color text_color = {0.9f, 0.9f, 0.9f}; const Color hover_color = {0.3f, 0.32f, 0.34f}; - shape_renderer->draw_rect(x, y_gl, width, _height, bg_color); + ui_renderer->draw_rect(x, y, width, _height, bg_color); int menu_x = x; for(size_t i = 0; i < _menus.size(); ++i) { int menu_width = 60; - txt_renderer->render_text(_menus[i].label.c_str(), menu_x+10, y_gl+8, 1.0f, text_color); + ui_renderer->render_text(_menus[i].label.c_str(), menu_x+10, y+20, text_color); if(_open_menu_index == (int)i) { - int item_gl_y = y_gl - 30; /* Draw items below the bar. */ + int item_y = y + _height; /* Draw items below the bar. */ int item_height = 30; int dropdown_width = 150; for(const auto& item : _menus[i].items) { - shape_renderer->draw_rect(menu_x, item_gl_y, dropdown_width, item_height, bg_color); - txt_renderer->render_text(item.label.c_str(), menu_x+10, item_gl_y+8, 1.0f, text_color); - item_gl_y -= item_height; + ui_renderer->draw_rect(menu_x, item_y, dropdown_width, item_height, bg_color); + ui_renderer->render_text(item.label.c_str(), menu_x+10, item_y+20, text_color); + item_y += item_height; } } menu_x += menu_width; diff --git a/client/src/ui/menu_bar.h b/client/src/ui/menu_bar.h index 30beaad..4cf24f6 100644 --- a/client/src/ui/menu_bar.h +++ b/client/src/ui/menu_bar.h @@ -5,8 +5,7 @@ #include #include -#include "gfx/shape_renderer.h" -#include "gfx/txt_renderer.h" +#include "ui/ui_renderer.h" struct MenuItem { std::string label; @@ -28,9 +27,8 @@ public: void add_menu_item(const std::string& menu_label, const std::string& item_label, std::function action); - void handle_event(SDL_Event* event, int window_x, int window_y, int window_gl_y); - void render(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer, int x, - int y_gl, int width); + void handle_event(SDL_Event* event, int window_x, int window_y); + void render(UIRenderer* ui_renderer, int x, int y, int width); int get_height(void) const; private: diff --git a/client/src/ui/taskbar.cpp b/client/src/ui/taskbar.cpp index c834029..15b7e8f 100644 --- a/client/src/ui/taskbar.cpp +++ b/client/src/ui/taskbar.cpp @@ -5,21 +5,19 @@ #include #include -#include "gfx/shape_renderer.h" -#include "gfx/txt_renderer.h" -#include "gfx/types.h" +#include "ui/ui_renderer.h" #include "ui/ui_window.h" Taskbar::Taskbar(int screen_width, int screen_height) { _width = screen_width; _height = 32; - _y_pos = 0; /* Taskbar at bottom because boring? */ + _y_pos = screen_height - _height; /* Taskbar at bottom because boring? */ _start_button_width = 60; } Taskbar::~Taskbar(void) {} -void Taskbar::render(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer, +void Taskbar::render(UIRenderer* ui_renderer, const std::vector>& windows, UIWindow* focused_window) { @@ -28,13 +26,12 @@ void Taskbar::render(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer, const Color button_focused_color = { 0.3f, 0.32f, 0.34f }; const Color button_text_color = { 0.9f, 0.9f, 0.9f }; - shape_renderer->draw_rect(0, _y_pos, _width, _height, taskbar_color); + ui_renderer->draw_rect(0, _y_pos, _width, _height, taskbar_color); /* Draw start button. */ - shape_renderer->draw_rect(5, _y_pos + 5, _start_button_width - 10, + ui_renderer->draw_rect(5, _y_pos + 5, _start_button_width - 10, _height - 10, button_color); - txt_renderer->render_text("[B]", 20, _y_pos + 11, 1.0f, - button_text_color); + ui_renderer->render_text("[B]", 20, _y_pos + 20, button_text_color); /* Draw app buttons. */ int button_width = 150; @@ -43,13 +40,13 @@ void Taskbar::render(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer, for(const auto& window : windows) { bool is_focused = (window.get() == focused_window); - shape_renderer->draw_rect(x_offset, _y_pos + padding, button_width, + ui_renderer->draw_rect(x_offset, _y_pos + padding, button_width, _height - (padding * 2), is_focused ? button_focused_color : button_color); /* TODO: Truncate text when too long. */ - txt_renderer->render_text(window->get_title().c_str(), x_offset + 10, - _y_pos + 11, 1.0f, button_text_color); + ui_renderer->render_text(window->get_title().c_str(), x_offset + 10, + _y_pos + 20, button_text_color); x_offset += button_width + padding; } /* Draw clock. */ @@ -59,15 +56,14 @@ void Taskbar::render(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer, ss << std::put_time(std::localtime(&in_time_t), "%H:%M"); std::string time_str = ss.str(); - txt_renderer->render_text(time_str.c_str(), _width-50, _y_pos+11, 1.0f, - button_text_color); + ui_renderer->render_text(time_str.c_str(), _width-50, _y_pos+20, button_text_color); } UIWindow* Taskbar::handle_event(SDL_Event* event, int screen_height, const std::vector>& windows) { if(event->type == SDL_EVENT_MOUSE_BUTTON_UP) { int mouse_x = event->button.x; - int mouse_y = screen_height - event->button.y; /* Convert to UI coords. */ + int mouse_y = event->button.y; int button_width = 150; int padding = 5; @@ -86,7 +82,7 @@ UIWindow* Taskbar::handle_event(SDL_Event* event, int screen_height, bool Taskbar::is_start_button_clicked(SDL_Event* event, int screen_height) { if(event->type == SDL_EVENT_MOUSE_BUTTON_UP) { int mouse_x = event->button.x; - int mouse_y = screen_height - event->button.y; + int mouse_y = event->button.y; return (mouse_x >= 0 && mouse_x <= _start_button_width && mouse_y >= _y_pos && mouse_y <= _y_pos + _height); } diff --git a/client/src/ui/taskbar.h b/client/src/ui/taskbar.h index ac3882d..179cbf3 100644 --- a/client/src/ui/taskbar.h +++ b/client/src/ui/taskbar.h @@ -5,15 +5,14 @@ #include class UIWindow; -class ShapeRenderer; -class TextRenderer; +class UIRenderer; class Taskbar { public: Taskbar(int screen_width, int screen_height); ~Taskbar(void); - void render(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer, + void render(UIRenderer* ui_renderer, const std::vector>& windows, UIWindow* focused_window); diff --git a/client/src/ui/text_view.cpp b/client/src/ui/text_view.cpp index f786347..cf418aa 100644 --- a/client/src/ui/text_view.cpp +++ b/client/src/ui/text_view.cpp @@ -70,7 +70,7 @@ void TextView::scroll(int amount, int content_height) { } } -void TextView::render(TextRenderer* renderer, int x, int y, int width, int height, +void TextView::render(UIRenderer* ui_renderer, int x, int y, int width, int height, bool show_cursor) { if(!_buffer) return; @@ -79,7 +79,7 @@ void TextView::render(TextRenderer* renderer, int x, int y, int width, int heigh float padding = 5.0f; Point cursor_pos = _buffer->get_cursor_pos(); - float current_y = y + height - line_height; /* Start at top. */ + float current_y = y; for(size_t i = _scroll_offset; i < _buffer->get_line_count(); ++i) { std::string line = _buffer->get_line(i); @@ -96,7 +96,8 @@ void TextView::render(TextRenderer* renderer, int x, int y, int width, int heigh line.insert(cursor_pos.col, 1, '_'); } } - renderer->render_text(line.c_str(), x, current_y, 1.0f, text_color); - current_y -= line_height; + /* Add 18 to get baseline from top of the line. */ + ui_renderer->render_text(line.c_str(), x+padding, current_y + 18, text_color); + current_y += line_height; } } diff --git a/client/src/ui/text_view.h b/client/src/ui/text_view.h index b2f2856..a19d498 100644 --- a/client/src/ui/text_view.h +++ b/client/src/ui/text_view.h @@ -3,6 +3,7 @@ #include #include "ui/text_buffer.h" +#include "ui/ui_renderer.h" class TextRenderer; @@ -12,7 +13,7 @@ public: ~TextView(void); bool handle_event(SDL_Event* event); - void render(TextRenderer* renderer, int x, int y, int width, int height, + void render(UIRenderer* ui_renderer, int x, int y, int width, int height, bool show_cursor); void scroll(int amount, int content_height); diff --git a/client/src/ui/ui_renderer.cpp b/client/src/ui/ui_renderer.cpp new file mode 100644 index 0000000..405e872 --- /dev/null +++ b/client/src/ui/ui_renderer.cpp @@ -0,0 +1,33 @@ +#include "ui_renderer.h" +#include "gfx/shape_renderer.h" +#include "gfx/txt_renderer.h" + +UIRenderer::UIRenderer(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer, int screen_height) + : _shape_renderer(shape_renderer), _txt_renderer(txt_renderer), _screen_height(screen_height) {} + +void UIRenderer::draw_rect(int x, int y, int width, int height, const Color& color) { + if(!_shape_renderer) return; + /* Convert top-left screen coord to bottom-left GL coord. */ + int y_gl = _screen_height - y - height; + _shape_renderer->draw_rect(x, y_gl, width, height, color); +} + +void UIRenderer::draw_triangle(int x1, int y1, int x2, int y2, int x3, int y3, const Color& color) { + if(!_shape_renderer) return; + /* Convert top-left screen coord to bottom-left GL coord. */ + int y1_gl = _screen_height - y1; + int y2_gl = _screen_height - y2; + int y3_gl = _screen_height - y3; + _shape_renderer->draw_triangle(x1, y1_gl, x2, y2_gl, x3, y3_gl, color); +} + +void UIRenderer::render_text(const char* text, int x, int y, const Color& color) { + if(!_txt_renderer) return; + /* Convert the screen-space baseline y-coord to GL-space baseline y-coord. */ + int y_gl = _screen_height - y; + _txt_renderer->render_text(text, x, y_gl, 1.0f, color); +} + +TextRenderer* UIRenderer::get_text_renderer(void) { + return _txt_renderer; +} diff --git a/client/src/ui/ui_renderer.h b/client/src/ui/ui_renderer.h new file mode 100644 index 0000000..a638a4a --- /dev/null +++ b/client/src/ui/ui_renderer.h @@ -0,0 +1,27 @@ +#pragma once + +#include "gfx/shape_renderer.h" +#include "gfx/txt_renderer.h" +#include "gfx/types.h" + +/* + * I'm so damn sick of working between two rendering systems! + * Here! Have a wrapper around the low-level renderers to provide a f.cking + * consistant top-left origin for all UI components. + */ +class UIRenderer { +public: + UIRenderer(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer, int screen_height); + + void draw_rect(int x, int y, int width, int height, const Color& color); + void draw_triangle(int x1, int y1, int x2, int y2, int x3, int y3, const Color& color); + void render_text(const char* text, int x, int y, const Color& color); + + /* Expose underlying text renderer for things like width calculation. */ + TextRenderer* get_text_renderer(void); + +private: + ShapeRenderer* _shape_renderer; + TextRenderer* _txt_renderer; + int _screen_height; +}; diff --git a/client/src/ui/ui_window.cpp b/client/src/ui/ui_window.cpp index 3c87eae..311f3ee 100644 --- a/client/src/ui/ui_window.cpp +++ b/client/src/ui/ui_window.cpp @@ -1,10 +1,9 @@ #include "ui_window.h" #include +#include #include -#include "gfx/shape_renderer.h" -#include "gfx/txt_renderer.h" -#include "gfx/types.h" #include "ui/i_window_content.h" +#include "ui_renderer.h" UIWindow::UIWindow(const char* title, int x, int y, int width, int height) : _title(title), @@ -87,45 +86,41 @@ void UIWindow::render(const RenderContext& context) { const Color title_text_color = { 0.9f, 0.9f, 0.9f }; const Color resize_handle_color = { 0.9f, 0.9f, 0.9f }; - /* Convert top-left coords to bottom-left for OpenGL. */ - int y_gl = context.screen_height - _y - _height; - /* Draw main window frame/background. */ - context.shape_renderer->draw_rect(_x, y_gl, _width, _height, frame_color); + context.ui_renderer->draw_rect(_x, _y, _width, _height, frame_color); /* Draw title bar. */ if(_is_focused) { - context.shape_renderer->draw_rect(_x, y_gl+_height-title_bar_height, _width, title_bar_height, - focused_title_bar_color); + context.ui_renderer->draw_rect(_x, _y, _width, title_bar_height, focused_title_bar_color); } else { - context.shape_renderer->draw_rect(_x, y_gl+_height-title_bar_height, _width, title_bar_height, - title_bar_color); + context.ui_renderer->draw_rect(_x, _y, _width, title_bar_height, title_bar_color); } /* Draw title text. */ - context.txt_renderer->render_text(_title.c_str(), _x+5, y_gl+_height-title_bar_height+8, - 1.0f, title_text_color); + context.ui_renderer->render_text(_title.c_str(), _x+5, _y+20, title_text_color); /* Draw title bar buttons. */ int button_size = 20; int button_margin = 5; int x_offset = _x + _width - button_size - button_margin; for(const auto& button : _title_bar_buttons) { - context.shape_renderer->draw_rect(x_offset, y_gl + _height - title_bar_height + button_margin, - button_size, button_size, button.color); + context.ui_renderer->draw_rect(x_offset, _y+button_margin, button_size, + button_size, button.color); x_offset -= (button_size + button_margin); } /* Draw Resize handle. */ int corner_x = _x + _width; - int corner_y = y_gl; - context.shape_renderer->draw_triangle(corner_x, corner_y + 10, corner_x - 10, + int corner_y = _y + _height; + context.ui_renderer->draw_triangle(corner_x, corner_y - 10, corner_x - 10, corner_y, corner_x, corner_y, resize_handle_color); if(_content) { - int content_y_gl = y_gl; - int content_height_gl = _height - title_bar_height; - _content->render(context, _x, content_y_gl, _width, content_height_gl); + int content_screen_y = _y + title_bar_height; + int content_height = _height - title_bar_height; + /* Got to pass GL y-coord for scissor box to work correctly. */ + int content_gl_y = context.screen_height - content_screen_y - content_height; + _content->render(context, _x, content_screen_y, content_gl_y, _width, content_height); } }