[Refactor] Created UIRenderer for consistant coord system.
The UI codebase was suffering with complexity due to the need to manually convert between two different coordinate systems: - Top-down "screen coordinates" used by SDL for input and windowing. - Bottom-up "GL coordinates" used by low-level renderers. This was making layout calculations diffucult and is bug prone. With this commit, I'm introducing a 'UIRenderer' abstraction layer that wraps the low-level 'ShapeRenderer' and 'TextRenderer'. This is responsible for centralising all coordinate system conversations. All UI components has been refactored to use the 'UIRenderer' so the entire UI code opeates exclusively in a single, top-down screen coordinate system as one would expect.
This commit is contained in:
		
							parent
							
								
									601bc86bdc
								
							
						
					
					
						commit
						e7607e3fc0
					
				@ -197,12 +197,12 @@ void GameState::render(const RenderContext& context) {
 | 
				
			|||||||
  switch(_current_screen) {
 | 
					  switch(_current_screen) {
 | 
				
			||||||
  case Screen::MAIN_MENU:
 | 
					  case Screen::MAIN_MENU:
 | 
				
			||||||
    if(_main_menu) {
 | 
					    if(_main_menu) {
 | 
				
			||||||
      _main_menu->render(context.shape_renderer, context.txt_renderer);
 | 
					      _main_menu->render(context.ui_renderer);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    break;
 | 
					    break;
 | 
				
			||||||
  case Screen::BOOTING:
 | 
					  case Screen::BOOTING:
 | 
				
			||||||
    if(_boot_sequence) {
 | 
					    if(_boot_sequence) {
 | 
				
			||||||
      _boot_sequence->render(context.txt_renderer, context.screen_height);
 | 
					      _boot_sequence->render(context.ui_renderer);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    break;
 | 
					    break;
 | 
				
			||||||
  case Screen::DESKTOP:
 | 
					  case Screen::DESKTOP:
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,6 @@
 | 
				
			|||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ShapeRenderer;
 | 
					class UIRenderer;
 | 
				
			||||||
class TextRenderer;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct Color {
 | 
					struct Color {
 | 
				
			||||||
  float r, g, b;
 | 
					  float r, g, b;
 | 
				
			||||||
@ -12,8 +11,7 @@ struct Rect {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct RenderContext {
 | 
					struct RenderContext {
 | 
				
			||||||
  ShapeRenderer* shape_renderer;
 | 
					  UIRenderer* ui_renderer;
 | 
				
			||||||
  TextRenderer* txt_renderer;
 | 
					 | 
				
			||||||
  int screen_height;
 | 
					  int screen_height;
 | 
				
			||||||
  bool show_cursor;
 | 
					  bool show_cursor;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -8,6 +8,7 @@
 | 
				
			|||||||
#include "gfx/shape_renderer.h"
 | 
					#include "gfx/shape_renderer.h"
 | 
				
			||||||
#include "gfx/txt_renderer.h"
 | 
					#include "gfx/txt_renderer.h"
 | 
				
			||||||
#include "game_state.h"
 | 
					#include "game_state.h"
 | 
				
			||||||
 | 
					#include "ui/ui_renderer.h"
 | 
				
			||||||
#include "gfx/types.h"
 | 
					#include "gfx/types.h"
 | 
				
			||||||
#include "ui/cursor_manager.h"
 | 
					#include "ui/cursor_manager.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -78,6 +79,10 @@ int main(int argc, char** argv) {
 | 
				
			|||||||
  /* Init shape renderer. */
 | 
					  /* Init shape renderer. */
 | 
				
			||||||
  ShapeRenderer* shape_renderer_instance = new ShapeRenderer(SCREEN_WIDTH, SCREEN_HEIGHT);
 | 
					  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<GameState>();
 | 
					  auto game_state = std::make_unique<GameState>();
 | 
				
			||||||
  if(argc > 1 && std::string(argv[1]) == "-sp") {
 | 
					  if(argc > 1 && std::string(argv[1]) == "-sp") {
 | 
				
			||||||
    game_state->start_single_player_now(SCREEN_WIDTH, SCREEN_HEIGHT);
 | 
					    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);
 | 
					    glClear(GL_COLOR_BUFFER_BIT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    RenderContext context = {
 | 
					    RenderContext context = {
 | 
				
			||||||
      shape_renderer_instance,
 | 
					      ui_renderer_instance,
 | 
				
			||||||
      txt_render_instance,
 | 
					 | 
				
			||||||
      SCREEN_HEIGHT,
 | 
					      SCREEN_HEIGHT,
 | 
				
			||||||
      show_cursor
 | 
					      show_cursor
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
@ -124,6 +128,7 @@ int main(int argc, char** argv) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  /* Cleanup. */
 | 
					  /* Cleanup. */
 | 
				
			||||||
  game_state.reset();
 | 
					  game_state.reset();
 | 
				
			||||||
 | 
					  delete ui_renderer_instance;
 | 
				
			||||||
  delete shape_renderer_instance;
 | 
					  delete shape_renderer_instance;
 | 
				
			||||||
  delete txt_render_instance;
 | 
					  delete txt_render_instance;
 | 
				
			||||||
  SDL_GL_DestroyContext(context);
 | 
					  SDL_GL_DestroyContext(context);
 | 
				
			||||||
 | 
				
			|||||||
@ -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 white = { 1.0f, 1.0f, 1.0f };
 | 
				
			||||||
  const Color green = { 0.2f, 1.0f, 0.2f };
 | 
					  const Color green = { 0.2f, 1.0f, 0.2f };
 | 
				
			||||||
  float line_height = 20.0f;
 | 
					  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. */
 | 
					  /* Enable scissor test to clip rendering to the window content area. */
 | 
				
			||||||
  glEnable(GL_SCISSOR_TEST);
 | 
					  glEnable(GL_SCISSOR_TEST);
 | 
				
			||||||
  glScissor(x, y, width, height);
 | 
					  glScissor(x, y_gl, width, height);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /* Draw History. */
 | 
					  /* Draw History. */
 | 
				
			||||||
  for(size_t i = _scroll_offset; i < _history.size(); ++i) {
 | 
					  for(size_t i = _scroll_offset; i < _history.size(); ++i) {
 | 
				
			||||||
    float y_pos = (y+height) - padding - line_height - ((i - _scroll_offset) * line_height);
 | 
					    float line_y_pos = y_screen + padding + ((i - _scroll_offset) * line_height);
 | 
				
			||||||
    context.txt_renderer->render_text(_history[i].c_str(), x+padding, y_pos, 1.0f, white);
 | 
					    context.ui_renderer->render_text(_history[i].c_str(), x+padding, line_y_pos+18, white);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /* Draw current input line. */
 | 
					  /* Draw current input line. */
 | 
				
			||||||
  float prompt_y_pos = (y+height) - padding - line_height
 | 
					  float prompt_line_y = (y_screen + padding) + ((_history.size() - _scroll_offset) * line_height);
 | 
				
			||||||
    - ((_history.size()-_scroll_offset)*line_height);
 | 
					  float prompt_baseline_y = prompt_line_y + 18;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /* Render prompt string. */
 | 
					  /* Render prompt string. */
 | 
				
			||||||
  std::string prompt_str = _prompt + "> ";
 | 
					  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. */
 | 
					  /* Render text view for the input right after prompt. */
 | 
				
			||||||
  float input_x_pos = x + padding + (prompt_str.length() * 8.5f); /* Estimate width */
 | 
					  float input_x_pos = x + padding + (prompt_str.length() * 8.5f); /* Estimate width */
 | 
				
			||||||
  float input_width = width - (input_x_pos-x);
 | 
					  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);
 | 
					                      line_height, context.show_cursor);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /* Disable scissor test. */
 | 
					  /* Disable scissor test. */
 | 
				
			||||||
  glDisable(GL_SCISSOR_TEST);
 | 
					  glDisable(GL_SCISSOR_TEST);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -18,7 +18,8 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  void update(void) override;
 | 
					  void update(void) override;
 | 
				
			||||||
  void handle_input(SDL_Event* event, int window_x, int window_y, int window_gl_y) 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 scroll(int amount, int content_height) override;
 | 
				
			||||||
  void add_history(const std::string& line);
 | 
					  void add_history(const std::string& line);
 | 
				
			||||||
  void set_prompt(const std::string& prompt);
 | 
					  void set_prompt(const std::string& prompt);
 | 
				
			||||||
 | 
				
			|||||||
@ -2,7 +2,7 @@
 | 
				
			|||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
#include <vector>
 | 
					#include <vector>
 | 
				
			||||||
#include <cstdio>
 | 
					#include <cstdio>
 | 
				
			||||||
#include "gfx/txt_renderer.h"
 | 
					#include "ui/ui_renderer.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "boot_sequence.h"
 | 
					#include "boot_sequence.h"
 | 
				
			||||||
#include <SDL3/SDL_timer.h>
 | 
					#include <SDL3/SDL_timer.h>
 | 
				
			||||||
@ -35,7 +35,7 @@ bool BootSequence::is_finished(void) {
 | 
				
			|||||||
  return (SDL_GetTicks() - _start_time) >= _total_duration_ms;
 | 
					  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 Color text_color  = { 0.9f, 0.9f, 0.9f }; /* grey/white */
 | 
				
			||||||
  const float line_height = 18.0f;
 | 
					  const float line_height = 18.0f;
 | 
				
			||||||
  const float padding     = 15.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) {
 | 
					  for(int i = 0; i < lines_to_show; ++i) {
 | 
				
			||||||
    float y_pos = (screen_height - padding) - (i * line_height);
 | 
					    float y_pos = padding + (i*line_height);
 | 
				
			||||||
    txt_renderer->render_text(_messages[i].c_str(), padding, y_pos, 1.0f, text_color);
 | 
					    ui_renderer->render_text(_messages[i].c_str(), padding, y_pos, text_color);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -4,7 +4,7 @@
 | 
				
			|||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
#include <SDL3/SDL.h>
 | 
					#include <SDL3/SDL.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "gfx/txt_renderer.h"
 | 
					#include "ui/ui_renderer.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class BootSequence {
 | 
					class BootSequence {
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
@ -12,7 +12,7 @@ public:
 | 
				
			|||||||
  ~BootSequence(void);
 | 
					  ~BootSequence(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bool is_finished(void);
 | 
					  bool is_finished(void);
 | 
				
			||||||
  void render(TextRenderer* txt_renderer, int screen_height);
 | 
					  void render(UIRenderer* ui_renderer);
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
  std::vector<std::string> _messages;
 | 
					  std::vector<std::string> _messages;
 | 
				
			||||||
  Uint32 _start_time;
 | 
					  Uint32 _start_time;
 | 
				
			||||||
 | 
				
			|||||||
@ -2,21 +2,19 @@
 | 
				
			|||||||
#include <ctime>
 | 
					#include <ctime>
 | 
				
			||||||
#include <fstream>
 | 
					#include <fstream>
 | 
				
			||||||
#include <cmath>
 | 
					#include <cmath>
 | 
				
			||||||
#include <functional>
 | 
					 | 
				
			||||||
#include <memory>
 | 
					#include <memory>
 | 
				
			||||||
 | 
					#include <ui/cursor_manager.h>
 | 
				
			||||||
 | 
					#include <SDL3/SDL_events.h>
 | 
				
			||||||
 | 
					#include <SDL3/SDL_video.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "gfx/types.h"
 | 
					#include "gfx/types.h"
 | 
				
			||||||
#include "ui/editor.h"
 | 
					#include "ui/editor.h"
 | 
				
			||||||
#include "desktop.h"
 | 
					#include "desktop.h"
 | 
				
			||||||
#include <SDL3/SDL_events.h>
 | 
					 | 
				
			||||||
#include "client_network.h"
 | 
					#include "client_network.h"
 | 
				
			||||||
#include "gfx/shape_renderer.h"
 | 
					 | 
				
			||||||
#include "gfx/txt_renderer.h"
 | 
					 | 
				
			||||||
#include "terminal.h"
 | 
					#include "terminal.h"
 | 
				
			||||||
#include "ui/i_window_content.h"
 | 
					#include "ui/i_window_content.h"
 | 
				
			||||||
 | 
					#include "ui/launcher.h"
 | 
				
			||||||
#include "ui/taskbar.h"
 | 
					#include "ui/taskbar.h"
 | 
				
			||||||
#include <SDL3/SDL_video.h>
 | 
					 | 
				
			||||||
#include <ui/cursor_manager.h>
 | 
					 | 
				
			||||||
#include "ui/ui_window.h"
 | 
					#include "ui/ui_window.h"
 | 
				
			||||||
#include "ui/window_action.h"
 | 
					#include "ui/window_action.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -33,7 +31,9 @@ Desktop::Desktop(int screen_width, int screen_height, ClientNetwork* network) {
 | 
				
			|||||||
  _network = network;
 | 
					  _network = network;
 | 
				
			||||||
  _focused_window = nullptr;
 | 
					  _focused_window = nullptr;
 | 
				
			||||||
  _launcher_is_open = false;
 | 
					  _launcher_is_open = false;
 | 
				
			||||||
  _launcher = std::make_unique<Launcher>(5, 5 + _taskbar->get_height(), 200);
 | 
					  _launcher = std::make_unique<Launcher>(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. */
 | 
					  /* Load snippets for temp wallpaper. */
 | 
				
			||||||
  std::ifstream snippet_file("assets/menu_background_snippets.txt");
 | 
					  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) {
 | 
					void Desktop::render(const RenderContext& context) {
 | 
				
			||||||
  _render_wallpaper(context.txt_renderer);
 | 
					  _render_wallpaper(context.ui_renderer);
 | 
				
			||||||
  if(_launcher_is_open) {
 | 
					  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. */
 | 
					  /* Render non-focused windows first. */
 | 
				
			||||||
  for(const auto& win : _windows) {
 | 
					  for(const auto& win : _windows) {
 | 
				
			||||||
    if(win.get() != _focused_window && !win->is_minimized()) {
 | 
					    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 };
 | 
					  const Color wallpaper_color = { 0.0f, 0.15f, 0.08f };
 | 
				
			||||||
  for(auto& line : _background_text) {
 | 
					  for(auto& line : _background_text) {
 | 
				
			||||||
    txt_renderer->render_text(line.text.c_str(), std::round(line.x),
 | 
					    ui_renderer->render_text(line.text.c_str(), std::round(line.x),
 | 
				
			||||||
                              line.render_y, 1.0f, wallpaper_color);
 | 
					                              line.render_y, wallpaper_color);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -5,11 +5,11 @@
 | 
				
			|||||||
#include <SDL3/SDL.h>
 | 
					#include <SDL3/SDL.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "client_network.h"
 | 
					#include "client_network.h"
 | 
				
			||||||
#include "gfx/txt_renderer.h"
 | 
					 | 
				
			||||||
#include "gfx/types.h"
 | 
					#include "gfx/types.h"
 | 
				
			||||||
#include "ui/ui_window.h"
 | 
					#include "ui/ui_window.h"
 | 
				
			||||||
#include "ui/taskbar.h"
 | 
					#include "ui/taskbar.h"
 | 
				
			||||||
#include "ui/launcher.h"
 | 
					#include "ui/launcher.h"
 | 
				
			||||||
 | 
					#include "ui/ui_renderer.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Animated background stuff. */
 | 
					/* Animated background stuff. */
 | 
				
			||||||
struct ScrollingText {
 | 
					struct ScrollingText {
 | 
				
			||||||
@ -34,7 +34,7 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
  void _set_focused_window(UIWindow* window);
 | 
					  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);
 | 
					  void _update_wallpaper(int screen_width, int screen_height);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  std::vector<std::unique_ptr<UIWindow>> _windows;
 | 
					  std::vector<std::unique_ptr<UIWindow>> _windows;
 | 
				
			||||||
 | 
				
			|||||||
@ -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) {
 | 
					void Editor::handle_input(SDL_Event* event, int window_x, int window_y, int window_gl_y) {
 | 
				
			||||||
  if(!event) return;
 | 
					  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. */
 | 
					  /* 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 &&
 | 
					  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_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,
 | 
					  _view->render(context.ui_renderer, x, content_y, width, content_height, context.show_cursor);
 | 
				
			||||||
                context.show_cursor);
 | 
					  _menu_bar->render(context.ui_renderer, x, y_screen, width);
 | 
				
			||||||
  _menu_bar->render(context.shape_renderer, context.txt_renderer, x, menu_bar_y_gl, width);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Editor::scroll(int amount, int content_height) {
 | 
					void Editor::scroll(int amount, int content_height) {
 | 
				
			||||||
 | 
				
			|||||||
@ -17,7 +17,8 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  void update(void) override;
 | 
					  void update(void) override;
 | 
				
			||||||
  void handle_input(SDL_Event* event, int window_x, int window_y, int window_gl_y) 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 scroll(int amount, int content_height) override;
 | 
				
			||||||
  bool should_close(void) override;
 | 
					  bool should_close(void) override;
 | 
				
			||||||
  void set_buffer_content(const std::string& content);
 | 
					  void set_buffer_content(const std::string& content);
 | 
				
			||||||
 | 
				
			|||||||
@ -10,7 +10,8 @@ public:
 | 
				
			|||||||
  virtual ~IWindowContent(void) = default;
 | 
					  virtual ~IWindowContent(void) = default;
 | 
				
			||||||
  virtual void update(void) = 0;
 | 
					  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 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 void scroll(int amount, int content_height) = 0;
 | 
				
			||||||
  virtual bool should_close(void) = 0;
 | 
					  virtual bool should_close(void) = 0;
 | 
				
			||||||
  virtual WindowAction get_pending_action() = 0;
 | 
					  virtual WindowAction get_pending_action() = 0;
 | 
				
			||||||
 | 
				
			|||||||
@ -1,8 +1,6 @@
 | 
				
			|||||||
#include "launcher.h"
 | 
					#include "launcher.h"
 | 
				
			||||||
#include <SDL3/SDL_mouse.h>
 | 
					#include <SDL3/SDL_mouse.h>
 | 
				
			||||||
#include "gfx/shape_renderer.h"
 | 
					#include "ui/ui_renderer.h"
 | 
				
			||||||
#include "gfx/txt_renderer.h"
 | 
					 | 
				
			||||||
#include "gfx/types.h"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
Launcher::Launcher(int x, int y, int width) : _x(x), _y(y), _width(width) {
 | 
					Launcher::Launcher(int x, int y, int width) : _x(x), _y(y), _width(width) {
 | 
				
			||||||
  /* TODO: Hardcode the launcher apps for now. */
 | 
					  /* 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) {}
 | 
					Launcher::~Launcher(void) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool Launcher::is_point_inside(int x, int y, int screen_height) const {
 | 
					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 && y>= _y && y <= _y + _height);
 | 
				
			||||||
  return (x >= _x && x <= _x + _width && ui_y >= _y && ui_y <= _y + _height);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Launcher::render(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer,
 | 
					void Launcher::render(UIRenderer* ui_renderer) {
 | 
				
			||||||
                      int screen_height) {
 | 
					 | 
				
			||||||
  const Color bg_color    = { 0.15f, 0.17f, 0.19f };
 | 
					  const Color bg_color    = { 0.15f, 0.17f, 0.19f };
 | 
				
			||||||
  const Color text_color  = { 0.9f,  0.9f,  0.9f  };
 | 
					  const Color text_color  = { 0.9f,  0.9f,  0.9f  };
 | 
				
			||||||
  const Color hover_color = { 0.3f,  0.32f, 0.34f };
 | 
					  const Color hover_color = { 0.3f,  0.32f, 0.34f };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /* Note: y-coord is TOP of launcher menu. */
 | 
					  /* 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_height = 30;
 | 
				
			||||||
  int item_y = _y;
 | 
					  int item_y = _y;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  float mouse_x, mouse_y;
 | 
					  float mouse_x, mouse_y;
 | 
				
			||||||
  SDL_GetMouseState(&mouse_x, &mouse_y);
 | 
					  SDL_GetMouseState(&mouse_x, &mouse_y);
 | 
				
			||||||
  int ui_mouse_y = screen_height - mouse_y;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  for(const auto& app_name : _apps) {
 | 
					  for(const auto& app_name : _apps) {
 | 
				
			||||||
    /* Check for hover. */
 | 
					    /* Check for hover. */
 | 
				
			||||||
    if(mouse_x >= _x && mouse_x <= _x + _width &&
 | 
					    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) {
 | 
				
			||||||
      shape_renderer->draw_rect(_x, item_y, _width, item_height, hover_color);
 | 
					      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;
 | 
					    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) {
 | 
					std::string Launcher::handle_event(SDL_Event* event, int screen_height) {
 | 
				
			||||||
  if(event->type == SDL_EVENT_MOUSE_BUTTON_UP) {
 | 
					  if(event->type == SDL_EVENT_MOUSE_BUTTON_UP) {
 | 
				
			||||||
    int mouse_x = event->button.x;
 | 
					    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_height = 30;
 | 
				
			||||||
    int item_y = _y;
 | 
					    int item_y = _y;
 | 
				
			||||||
    for(const auto& app_name : _apps) {
 | 
					    for(const auto& app_name : _apps) {
 | 
				
			||||||
      if(mouse_x >= _x && mouse_x <= _x + _width &&
 | 
					      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. */
 | 
					        return app_name; /* Return name of clicked app. */
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      item_y += item_height;
 | 
					      item_y += item_height;
 | 
				
			||||||
@ -65,3 +60,11 @@ std::string Launcher::handle_event(SDL_Event* event, int screen_height) {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
  return ""; /* Nothing clicked. */
 | 
					  return ""; /* Nothing clicked. */
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Launcher::set_y(int y) {
 | 
				
			||||||
 | 
					  _y = y;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int Launcher::get_height(void) const {
 | 
				
			||||||
 | 
					  return _height;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -4,17 +4,18 @@
 | 
				
			|||||||
#include <vector>
 | 
					#include <vector>
 | 
				
			||||||
#include <SDL3/SDL_events.h>
 | 
					#include <SDL3/SDL_events.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ShapeRenderer;
 | 
					class UIRenderer;
 | 
				
			||||||
class TextRenderer;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Launcher {
 | 
					class Launcher {
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
  Launcher(int x, int y, int width);
 | 
					  Launcher(int x, int y, int width);
 | 
				
			||||||
  ~Launcher(void);
 | 
					  ~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);
 | 
					  std::string handle_event(SDL_Event* event, int screen_height);
 | 
				
			||||||
  bool is_point_inside(int x, int y, int screen_height) const;
 | 
					  bool is_point_inside(int x, int y, int screen_height) const;
 | 
				
			||||||
 | 
					  void set_y(int y);
 | 
				
			||||||
 | 
					  int get_height(void) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
  int _x, _y, _width, _height;
 | 
					  int _x, _y, _width, _height;
 | 
				
			||||||
 | 
				
			|||||||
@ -1,9 +1,7 @@
 | 
				
			|||||||
#include <SDL3/SDL_events.h>
 | 
					#include <SDL3/SDL_events.h>
 | 
				
			||||||
#include <fstream>
 | 
					#include <fstream>
 | 
				
			||||||
#include <vector>
 | 
					#include <vector>
 | 
				
			||||||
 | 
					#include "ui/ui_renderer.h"
 | 
				
			||||||
#include "gfx/shape_renderer.h"
 | 
					 | 
				
			||||||
#include "gfx/txt_renderer.h"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "main_menu.h"
 | 
					#include "main_menu.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -73,12 +71,10 @@ void MainMenu::handle_event(SDL_Event* event) {
 | 
				
			|||||||
    int mouse_x = event->motion.x;
 | 
					    int mouse_x = event->motion.x;
 | 
				
			||||||
    int mouse_y = event->motion.y;
 | 
					    int mouse_y = event->motion.y;
 | 
				
			||||||
    for(auto& button : _buttons) {
 | 
					    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
 | 
					      button.is_hovered = (mouse_x >= button.rect.x
 | 
				
			||||||
        && mouse_x <= button.rect.x + button.rect.w
 | 
					        && mouse_x <= button.rect.x + button.rect.w
 | 
				
			||||||
        && inverted_y >= button.rect.y
 | 
					        && mouse_y >= button.rect.y
 | 
				
			||||||
        && inverted_y <= button.rect.y + button.rect.h);
 | 
					        && mouse_y <= button.rect.y + button.rect.h);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  } else if(event->type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
 | 
					  } else if(event->type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
 | 
				
			||||||
    for(const auto& button : _buttons) {
 | 
					    for(const auto& button : _buttons) {
 | 
				
			||||||
@ -95,8 +91,8 @@ Screen MainMenu::update(void) {
 | 
				
			|||||||
  return _next_screen;
 | 
					  return _next_screen;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void MainMenu::render(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer) {
 | 
					void MainMenu::render(UIRenderer* ui_renderer) {
 | 
				
			||||||
  _render_background(txt_renderer);
 | 
					  _render_background(ui_renderer->get_text_renderer());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /* Button colours. */
 | 
					  /* Button colours. */
 | 
				
			||||||
  const Color button_color        = { 0.1f, 0.15f, 0.2f };
 | 
					  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) {
 | 
					  for(const auto& button : _buttons) {
 | 
				
			||||||
    /* Draw button background. */
 | 
					    /* Draw button background. */
 | 
				
			||||||
    if(button.is_hovered) {
 | 
					    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);
 | 
					                                button.rect.h, button_hover_color);
 | 
				
			||||||
    } else {
 | 
					    } 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);
 | 
					                                button.rect.h, button_color);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Draw button text centered. */
 | 
					    /* 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;
 | 
					    float text_x = button.rect.x + (button.rect.w - text_width) / 2.0f;
 | 
				
			||||||
    txt_renderer->render_text(button.label.c_str(), text_x,
 | 
					    ui_renderer->render_text(button.label.c_str(), text_x, button.rect.y + 32, text_color);
 | 
				
			||||||
                              button.rect.y + 18, 1.0f, text_color);
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -3,9 +3,8 @@
 | 
				
			|||||||
#include <vector>
 | 
					#include <vector>
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "gfx/txt_renderer.h"
 | 
					 | 
				
			||||||
#include "gfx/shape_renderer.h"
 | 
					 | 
				
			||||||
#include "gfx/types.h"
 | 
					#include "gfx/types.h"
 | 
				
			||||||
 | 
					#include "ui/ui_renderer.h"
 | 
				
			||||||
#include "game_state.h"
 | 
					#include "game_state.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
union SDL_Event;
 | 
					union SDL_Event;
 | 
				
			||||||
@ -24,7 +23,7 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  void handle_event(SDL_Event* event);
 | 
					  void handle_event(SDL_Event* event);
 | 
				
			||||||
  Screen update(void);
 | 
					  Screen update(void);
 | 
				
			||||||
  void render(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer);
 | 
					  void render(UIRenderer* ui_renderer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
  void _update_background(void);
 | 
					  void _update_background(void);
 | 
				
			||||||
 | 
				
			|||||||
@ -26,7 +26,7 @@ int MenuBar::get_height(void) const {
 | 
				
			|||||||
  return _height;
 | 
					  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) {
 | 
					  if(event->type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
 | 
				
			||||||
    int mouse_x = event->button.x;
 | 
					    int mouse_x = event->button.x;
 | 
				
			||||||
    int mouse_y = event->button.y;
 | 
					    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,
 | 
					void MenuBar::render(UIRenderer* ui_renderer, int x, int y, int width) {
 | 
				
			||||||
                     int x, int y_gl, int width) {
 | 
					 | 
				
			||||||
  const Color bg_color    = {0.15f, 0.17f, 0.19f};
 | 
					  const Color bg_color    = {0.15f, 0.17f, 0.19f};
 | 
				
			||||||
  const Color text_color  = {0.9f, 0.9f, 0.9f};
 | 
					  const Color text_color  = {0.9f, 0.9f, 0.9f};
 | 
				
			||||||
  const Color hover_color = {0.3f, 0.32f, 0.34f};
 | 
					  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;
 | 
					  int menu_x = x;
 | 
				
			||||||
  for(size_t i = 0; i < _menus.size(); ++i) {
 | 
					  for(size_t i = 0; i < _menus.size(); ++i) {
 | 
				
			||||||
    int menu_width = 60;
 | 
					    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) {
 | 
					    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 item_height = 30;
 | 
				
			||||||
      int dropdown_width = 150;
 | 
					      int dropdown_width = 150;
 | 
				
			||||||
      for(const auto& item : _menus[i].items) {
 | 
					      for(const auto& item : _menus[i].items) {
 | 
				
			||||||
        shape_renderer->draw_rect(menu_x, item_gl_y, dropdown_width, item_height, bg_color);
 | 
					        ui_renderer->draw_rect(menu_x, item_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);
 | 
					        ui_renderer->render_text(item.label.c_str(), menu_x+10, item_y+20, text_color);
 | 
				
			||||||
        item_gl_y -= item_height;
 | 
					        item_y += item_height;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    menu_x += menu_width;
 | 
					    menu_x += menu_width;
 | 
				
			||||||
 | 
				
			|||||||
@ -5,8 +5,7 @@
 | 
				
			|||||||
#include <functional>
 | 
					#include <functional>
 | 
				
			||||||
#include <SDL3/SDL_events.h>
 | 
					#include <SDL3/SDL_events.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "gfx/shape_renderer.h"
 | 
					#include "ui/ui_renderer.h"
 | 
				
			||||||
#include "gfx/txt_renderer.h"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct MenuItem {
 | 
					struct MenuItem {
 | 
				
			||||||
  std::string label;
 | 
					  std::string label;
 | 
				
			||||||
@ -28,9 +27,8 @@ public:
 | 
				
			|||||||
  void add_menu_item(const std::string& menu_label, const std::string& item_label,
 | 
					  void add_menu_item(const std::string& menu_label, const std::string& item_label,
 | 
				
			||||||
                     std::function<void()> action);
 | 
					                     std::function<void()> action);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void handle_event(SDL_Event* event, int window_x, int window_y, int window_gl_y);
 | 
					  void handle_event(SDL_Event* event, int window_x, int window_y);
 | 
				
			||||||
  void render(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer, int x,
 | 
					  void render(UIRenderer* ui_renderer, int x, int y, int width);
 | 
				
			||||||
              int y_gl, int width);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  int get_height(void) const;
 | 
					  int get_height(void) const;
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
 | 
				
			|||||||
@ -5,21 +5,19 @@
 | 
				
			|||||||
#include <iomanip>
 | 
					#include <iomanip>
 | 
				
			||||||
#include <sstream>
 | 
					#include <sstream>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "gfx/shape_renderer.h"
 | 
					#include "ui/ui_renderer.h"
 | 
				
			||||||
#include "gfx/txt_renderer.h"
 | 
					 | 
				
			||||||
#include "gfx/types.h"
 | 
					 | 
				
			||||||
#include "ui/ui_window.h"
 | 
					#include "ui/ui_window.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Taskbar::Taskbar(int screen_width, int screen_height) {
 | 
					Taskbar::Taskbar(int screen_width, int screen_height) {
 | 
				
			||||||
  _width  = screen_width;
 | 
					  _width  = screen_width;
 | 
				
			||||||
  _height = 32;
 | 
					  _height = 32;
 | 
				
			||||||
  _y_pos  = 0; /* Taskbar at bottom because boring? */
 | 
					  _y_pos  = screen_height - _height; /* Taskbar at bottom because boring? */
 | 
				
			||||||
  _start_button_width = 60;
 | 
					  _start_button_width = 60;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Taskbar::~Taskbar(void) {}
 | 
					Taskbar::~Taskbar(void) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Taskbar::render(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer,
 | 
					void Taskbar::render(UIRenderer* ui_renderer,
 | 
				
			||||||
                     const std::vector<std::unique_ptr<UIWindow>>& windows,
 | 
					                     const std::vector<std::unique_ptr<UIWindow>>& windows,
 | 
				
			||||||
                     UIWindow* focused_window) {
 | 
					                     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_focused_color  = { 0.3f, 0.32f, 0.34f };
 | 
				
			||||||
  const Color button_text_color     = { 0.9f, 0.9f,  0.9f  };
 | 
					  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. */
 | 
					  /* 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);
 | 
					                            _height - 10, button_color);
 | 
				
			||||||
  txt_renderer->render_text("[B]", 20, _y_pos + 11, 1.0f,
 | 
					  ui_renderer->render_text("[B]", 20, _y_pos + 20, button_text_color);
 | 
				
			||||||
                            button_text_color);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /* Draw app buttons. */
 | 
					  /* Draw app buttons. */
 | 
				
			||||||
  int button_width  = 150;
 | 
					  int button_width  = 150;
 | 
				
			||||||
@ -43,13 +40,13 @@ void Taskbar::render(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  for(const auto& window : windows) {
 | 
					  for(const auto& window : windows) {
 | 
				
			||||||
    bool is_focused = (window.get() == focused_window);
 | 
					    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),
 | 
					                              _height - (padding * 2),
 | 
				
			||||||
                              is_focused ? button_focused_color : button_color);
 | 
					                              is_focused ? button_focused_color : button_color);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* TODO: Truncate text when too long. */
 | 
					    /* TODO: Truncate text when too long. */
 | 
				
			||||||
    txt_renderer->render_text(window->get_title().c_str(), x_offset + 10,
 | 
					    ui_renderer->render_text(window->get_title().c_str(), x_offset + 10,
 | 
				
			||||||
                              _y_pos + 11, 1.0f, button_text_color);
 | 
					                              _y_pos + 20, button_text_color);
 | 
				
			||||||
    x_offset += button_width + padding;
 | 
					    x_offset += button_width + padding;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
    /* Draw clock. */
 | 
					    /* 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");
 | 
					    ss << std::put_time(std::localtime(&in_time_t), "%H:%M");
 | 
				
			||||||
    std::string time_str = ss.str();
 | 
					    std::string time_str = ss.str();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    txt_renderer->render_text(time_str.c_str(), _width-50, _y_pos+11, 1.0f,
 | 
					    ui_renderer->render_text(time_str.c_str(), _width-50, _y_pos+20, button_text_color);
 | 
				
			||||||
                              button_text_color);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
UIWindow* Taskbar::handle_event(SDL_Event* event, int screen_height,
 | 
					UIWindow* Taskbar::handle_event(SDL_Event* event, int screen_height,
 | 
				
			||||||
                           const std::vector<std::unique_ptr<UIWindow>>& windows) {
 | 
					                           const std::vector<std::unique_ptr<UIWindow>>& windows) {
 | 
				
			||||||
  if(event->type == SDL_EVENT_MOUSE_BUTTON_UP) {
 | 
					  if(event->type == SDL_EVENT_MOUSE_BUTTON_UP) {
 | 
				
			||||||
    int mouse_x = event->button.x;
 | 
					    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 button_width  = 150;
 | 
				
			||||||
    int padding       = 5;
 | 
					    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) {
 | 
					bool Taskbar::is_start_button_clicked(SDL_Event* event, int screen_height) {
 | 
				
			||||||
  if(event->type == SDL_EVENT_MOUSE_BUTTON_UP) {
 | 
					  if(event->type == SDL_EVENT_MOUSE_BUTTON_UP) {
 | 
				
			||||||
    int mouse_x = event->button.x;
 | 
					    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 &&
 | 
					    return (mouse_x >= 0 && mouse_x <= _start_button_width && mouse_y >= _y_pos &&
 | 
				
			||||||
            mouse_y <= _y_pos + _height);
 | 
					            mouse_y <= _y_pos + _height);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
				
			|||||||
@ -5,15 +5,14 @@
 | 
				
			|||||||
#include <memory>
 | 
					#include <memory>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class UIWindow;
 | 
					class UIWindow;
 | 
				
			||||||
class ShapeRenderer;
 | 
					class UIRenderer;
 | 
				
			||||||
class TextRenderer;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Taskbar {
 | 
					class Taskbar {
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
  Taskbar(int screen_width, int screen_height);
 | 
					  Taskbar(int screen_width, int screen_height);
 | 
				
			||||||
  ~Taskbar(void);
 | 
					  ~Taskbar(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void render(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer,
 | 
					  void render(UIRenderer* ui_renderer,
 | 
				
			||||||
              const std::vector<std::unique_ptr<UIWindow>>& windows,
 | 
					              const std::vector<std::unique_ptr<UIWindow>>& windows,
 | 
				
			||||||
              UIWindow* focused_window);
 | 
					              UIWindow* focused_window);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -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) {
 | 
					                      bool show_cursor) {
 | 
				
			||||||
  if(!_buffer) return;
 | 
					  if(!_buffer) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -79,7 +79,7 @@ void TextView::render(TextRenderer* renderer, int x, int y, int width, int heigh
 | 
				
			|||||||
  float padding = 5.0f;
 | 
					  float padding = 5.0f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Point cursor_pos = _buffer->get_cursor_pos();
 | 
					  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) {
 | 
					  for(size_t i = _scroll_offset; i < _buffer->get_line_count(); ++i) {
 | 
				
			||||||
    std::string line = _buffer->get_line(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, '_');
 | 
					        line.insert(cursor_pos.col, 1, '_');
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    renderer->render_text(line.c_str(), x, current_y, 1.0f, text_color);
 | 
					    /* Add 18 to get baseline from top of the line. */
 | 
				
			||||||
    current_y -= line_height;
 | 
					    ui_renderer->render_text(line.c_str(), x+padding, current_y + 18, text_color);
 | 
				
			||||||
 | 
					    current_y += line_height;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -3,6 +3,7 @@
 | 
				
			|||||||
#include <SDL3/SDL_events.h>
 | 
					#include <SDL3/SDL_events.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "ui/text_buffer.h"
 | 
					#include "ui/text_buffer.h"
 | 
				
			||||||
 | 
					#include "ui/ui_renderer.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TextRenderer;
 | 
					class TextRenderer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -12,7 +13,7 @@ public:
 | 
				
			|||||||
  ~TextView(void);
 | 
					  ~TextView(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bool handle_event(SDL_Event* event);
 | 
					  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);
 | 
					              bool show_cursor);
 | 
				
			||||||
  void scroll(int amount, int content_height);
 | 
					  void scroll(int amount, int content_height);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										33
									
								
								client/src/ui/ui_renderer.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								client/src/ui/ui_renderer.cpp
									
									
									
									
									
										Normal file
									
								
							@ -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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										27
									
								
								client/src/ui/ui_renderer.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								client/src/ui/ui_renderer.h
									
									
									
									
									
										Normal file
									
								
							@ -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;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@ -1,10 +1,9 @@
 | 
				
			|||||||
#include "ui_window.h"
 | 
					#include "ui_window.h"
 | 
				
			||||||
#include <SDL3/SDL_events.h>
 | 
					#include <SDL3/SDL_events.h>
 | 
				
			||||||
 | 
					#include <SDL3/SDL_hidapi.h>
 | 
				
			||||||
#include <memory>
 | 
					#include <memory>
 | 
				
			||||||
#include "gfx/shape_renderer.h"
 | 
					 | 
				
			||||||
#include "gfx/txt_renderer.h"
 | 
					 | 
				
			||||||
#include "gfx/types.h"
 | 
					 | 
				
			||||||
#include "ui/i_window_content.h"
 | 
					#include "ui/i_window_content.h"
 | 
				
			||||||
 | 
					#include "ui_renderer.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
UIWindow::UIWindow(const char* title, int x, int y, int width, int height) :
 | 
					UIWindow::UIWindow(const char* title, int x, int y, int width, int height) :
 | 
				
			||||||
    _title(title),
 | 
					    _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 title_text_color        = { 0.9f,  0.9f,  0.9f  };
 | 
				
			||||||
  const Color resize_handle_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. */
 | 
					  /* 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. */
 | 
					  /* Draw title bar. */
 | 
				
			||||||
  if(_is_focused) {
 | 
					  if(_is_focused) {
 | 
				
			||||||
    context.shape_renderer->draw_rect(_x, y_gl+_height-title_bar_height, _width, title_bar_height,
 | 
					    context.ui_renderer->draw_rect(_x, _y, _width, title_bar_height, focused_title_bar_color);
 | 
				
			||||||
                              focused_title_bar_color);
 | 
					 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    context.shape_renderer->draw_rect(_x, y_gl+_height-title_bar_height, _width, title_bar_height,
 | 
					    context.ui_renderer->draw_rect(_x, _y, _width, title_bar_height, title_bar_color);
 | 
				
			||||||
                              title_bar_color);
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /* Draw title text. */
 | 
					  /* Draw title text. */
 | 
				
			||||||
  context.txt_renderer->render_text(_title.c_str(), _x+5, y_gl+_height-title_bar_height+8,
 | 
					  context.ui_renderer->render_text(_title.c_str(), _x+5, _y+20, title_text_color);
 | 
				
			||||||
                            1.0f, title_text_color);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /* Draw title bar buttons. */
 | 
					  /* Draw title bar buttons. */
 | 
				
			||||||
  int button_size = 20;
 | 
					  int button_size = 20;
 | 
				
			||||||
  int button_margin = 5;
 | 
					  int button_margin = 5;
 | 
				
			||||||
  int x_offset = _x + _width - button_size - button_margin;
 | 
					  int x_offset = _x + _width - button_size - button_margin;
 | 
				
			||||||
  for(const auto& button : _title_bar_buttons) {
 | 
					  for(const auto& button : _title_bar_buttons) {
 | 
				
			||||||
    context.shape_renderer->draw_rect(x_offset, y_gl + _height - title_bar_height + button_margin,
 | 
					    context.ui_renderer->draw_rect(x_offset, _y+button_margin, button_size,
 | 
				
			||||||
                              button_size, button_size, button.color);
 | 
					                                   button_size, button.color);
 | 
				
			||||||
    x_offset -= (button_size + button_margin);
 | 
					    x_offset -= (button_size + button_margin);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /* Draw Resize handle. */
 | 
					  /* Draw Resize handle. */
 | 
				
			||||||
  int corner_x = _x + _width;
 | 
					  int corner_x = _x + _width;
 | 
				
			||||||
  int corner_y = y_gl;
 | 
					  int corner_y = _y + _height;
 | 
				
			||||||
  context.shape_renderer->draw_triangle(corner_x, corner_y + 10, corner_x - 10,
 | 
					  context.ui_renderer->draw_triangle(corner_x, corner_y - 10, corner_x - 10,
 | 
				
			||||||
                                corner_y, corner_x, corner_y, resize_handle_color);
 | 
					                                corner_y, corner_x, corner_y, resize_handle_color);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if(_content) {
 | 
					  if(_content) {
 | 
				
			||||||
    int content_y_gl = y_gl;
 | 
					    int content_screen_y = _y + title_bar_height;
 | 
				
			||||||
    int content_height_gl = _height - title_bar_height;
 | 
					    int content_height = _height - title_bar_height;
 | 
				
			||||||
    _content->render(context, _x, content_y_gl, _width, content_height_gl);
 | 
					    /* 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);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user