[Add] Beginning of login UI and db persistance.
This commit is contained in:
		
							parent
							
								
									1cbf8ff0d8
								
							
						
					
					
						commit
						564512225f
					
				@ -1,11 +1,12 @@
 | 
				
			|||||||
cmake_minimum_required(VERSION 3.16)
 | 
					cmake_minimum_required(VERSION 3.16)
 | 
				
			||||||
project(bettola CXX)
 | 
					project(bettola CXX C)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
 | 
					set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set(CMAKE_CXX_STANDARD 17)
 | 
					set(CMAKE_CXX_STANDARD 17)
 | 
				
			||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
 | 
					set(CMAKE_CXX_STANDARD_REQUIRED ON)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# === Sol2 ===
 | 
				
			||||||
include(FetchContent)
 | 
					include(FetchContent)
 | 
				
			||||||
FetchContent_Declare(
 | 
					FetchContent_Declare(
 | 
				
			||||||
  sol2
 | 
					  sol2
 | 
				
			||||||
@ -14,6 +15,7 @@ FetchContent_Declare(
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
FetchContent_MakeAvailable(sol2)
 | 
					FetchContent_MakeAvailable(sol2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# === Asio ===
 | 
				
			||||||
FetchContent_Declare(
 | 
					FetchContent_Declare(
 | 
				
			||||||
  asio
 | 
					  asio
 | 
				
			||||||
  GIT_REPOSITORY https://github.com/chriskohlhoff/asio
 | 
					  GIT_REPOSITORY https://github.com/chriskohlhoff/asio
 | 
				
			||||||
@ -21,6 +23,33 @@ FetchContent_Declare(
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
FetchContent_MakeAvailable(asio)
 | 
					FetchContent_MakeAvailable(asio)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# === SQLite ===
 | 
				
			||||||
 | 
					# Supress the developer warning for using Populate with declared content.
 | 
				
			||||||
 | 
					# We need it because sqlite zip isn't a CMAKE project.
 | 
				
			||||||
 | 
					cmake_policy(SET CMP0169 OLD)
 | 
				
			||||||
 | 
					FetchContent_Declare(
 | 
				
			||||||
 | 
					  sqlite_source
 | 
				
			||||||
 | 
					  URL https://sqlite.org/2025/sqlite-amalgamation-3500400.zip
 | 
				
			||||||
 | 
					  URL_HASH SHA256=1d3049dd0f830a025a53105fc79fd2ab9431aea99e137809d064d8ee8356b032
 | 
				
			||||||
 | 
					  DOWNLOAD_EXTRACT_TIMESTAMP true
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					FetchContent_GetProperties(sqlite_source)
 | 
				
			||||||
 | 
					if(NOT sqlite_source_POPULATED)
 | 
				
			||||||
 | 
					  FetchContent_Populate(sqlite_source)
 | 
				
			||||||
 | 
					  add_library(sqlite STATIC "${sqlite_source_SOURCE_DIR}/sqlite3.c")
 | 
				
			||||||
 | 
					  target_include_directories(sqlite PUBLIC "${sqlite_source_SOURCE_DIR}")
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					# Revert policy to default.
 | 
				
			||||||
 | 
					cmake_policy(SET CMP0169 NEW)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# === sqlite_modern_cpp (SQLite wrapper) ===
 | 
				
			||||||
 | 
					FetchContent_Declare(
 | 
				
			||||||
 | 
					  sqlite_modern_cpp
 | 
				
			||||||
 | 
					  GIT_REPOSITORY https://github.com/SqliteModernCpp/sqlite_modern_cpp.git
 | 
				
			||||||
 | 
					  GIT_TAG v3.2
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					FetchContent_MakeAvailable(sqlite_modern_cpp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
add_subdirectory(common)
 | 
					add_subdirectory(common)
 | 
				
			||||||
add_subdirectory(client)
 | 
					add_subdirectory(client)
 | 
				
			||||||
add_subdirectory(server)
 | 
					add_subdirectory(server)
 | 
				
			||||||
 | 
				
			|||||||
@ -13,6 +13,7 @@
 | 
				
			|||||||
#include "ui/i_window_content.h"
 | 
					#include "ui/i_window_content.h"
 | 
				
			||||||
#include "ui/ui_window.h"
 | 
					#include "ui/ui_window.h"
 | 
				
			||||||
#include "ui/editor.h"
 | 
					#include "ui/editor.h"
 | 
				
			||||||
 | 
					#include "ui/login_screen.h"
 | 
				
			||||||
#include <SDL3/SDL_events.h>
 | 
					#include <SDL3/SDL_events.h>
 | 
				
			||||||
#include <ui/main_menu.h>
 | 
					#include <ui/main_menu.h>
 | 
				
			||||||
#include <ui/boot_sequence.h>
 | 
					#include <ui/boot_sequence.h>
 | 
				
			||||||
@ -91,6 +92,11 @@ void GameState::handle_event(SDL_Event* event, int screen_width, int screen_heig
 | 
				
			|||||||
      _main_menu->handle_event(event);
 | 
					      _main_menu->handle_event(event);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    break;
 | 
					    break;
 | 
				
			||||||
 | 
					  case Screen::LOGIN:
 | 
				
			||||||
 | 
					    if(_login_screen) {
 | 
				
			||||||
 | 
					      _login_screen->handle_event(event);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    break;
 | 
				
			||||||
  case Screen::BOOTING:
 | 
					  case Screen::BOOTING:
 | 
				
			||||||
    /* TODO: */
 | 
					    /* TODO: */
 | 
				
			||||||
    break;
 | 
					    break;
 | 
				
			||||||
@ -116,12 +122,25 @@ void GameState::update(float dt, int draw_calls, int shape_verts, int text_verts
 | 
				
			|||||||
      _current_screen = next_screen;
 | 
					      _current_screen = next_screen;
 | 
				
			||||||
      _main_menu.reset(); /* Free mem. */
 | 
					      _main_menu.reset(); /* Free mem. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if(_current_screen == Screen::BOOTING) {
 | 
					      if(_current_screen == Screen::LOGIN) {
 | 
				
			||||||
        _boot_sequence = std::make_unique<BootSequence>();
 | 
					        _login_screen = std::make_unique<LoginScreen>(_screen_width, _screen_height);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    break;
 | 
					    break;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  case Screen::LOGIN:
 | 
				
			||||||
 | 
					    if(_login_screen && _login_screen->is_login_attempted()) {
 | 
				
			||||||
 | 
					      /* TODO: Send credentials to server for verification. */
 | 
				
			||||||
 | 
					      printf("Login attempt: user=%s, pass=%s, host=%s\n",
 | 
				
			||||||
 | 
					            _login_screen->get_username().c_str(),
 | 
				
			||||||
 | 
					            _login_screen->get_password().c_str(),
 | 
				
			||||||
 | 
					            _login_screen->get_hostname().c_str());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      _current_screen = Screen::BOOTING;
 | 
				
			||||||
 | 
					      _login_screen.reset(); /* Free mem. */
 | 
				
			||||||
 | 
					      _boot_sequence = std::make_unique<BootSequence>();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    break;
 | 
				
			||||||
  case Screen::BOOTING: {
 | 
					  case Screen::BOOTING: {
 | 
				
			||||||
    if(!_boot_sequence) break; /* Shouldn't happen. */
 | 
					    if(!_boot_sequence) break; /* Shouldn't happen. */
 | 
				
			||||||
    if(_boot_sequence->is_finished()) {
 | 
					    if(_boot_sequence->is_finished()) {
 | 
				
			||||||
@ -219,6 +238,11 @@ void GameState::render(const RenderContext& context) {
 | 
				
			|||||||
      _main_menu->render(context.ui_renderer);
 | 
					      _main_menu->render(context.ui_renderer);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    break;
 | 
					    break;
 | 
				
			||||||
 | 
					  case Screen::LOGIN:
 | 
				
			||||||
 | 
					    if(_login_screen) {
 | 
				
			||||||
 | 
					      _login_screen->render(context);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    break;
 | 
				
			||||||
  case Screen::BOOTING:
 | 
					  case Screen::BOOTING:
 | 
				
			||||||
    if(_boot_sequence) {
 | 
					    if(_boot_sequence) {
 | 
				
			||||||
      _boot_sequence->render(context.ui_renderer);
 | 
					      _boot_sequence->render(context.ui_renderer);
 | 
				
			||||||
 | 
				
			|||||||
@ -7,6 +7,7 @@
 | 
				
			|||||||
class DebugOverlay;
 | 
					class DebugOverlay;
 | 
				
			||||||
class ClientNetwork;
 | 
					class ClientNetwork;
 | 
				
			||||||
class Desktop;
 | 
					class Desktop;
 | 
				
			||||||
 | 
					class LoginScreen;
 | 
				
			||||||
class BootSequence;
 | 
					class BootSequence;
 | 
				
			||||||
class MainMenu;
 | 
					class MainMenu;
 | 
				
			||||||
class ShapeRenderer;
 | 
					class ShapeRenderer;
 | 
				
			||||||
@ -14,6 +15,7 @@ class TextRenderer;
 | 
				
			|||||||
union SDL_Event;
 | 
					union SDL_Event;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum class Screen {
 | 
					enum class Screen {
 | 
				
			||||||
 | 
					  LOGIN,
 | 
				
			||||||
  MAIN_MENU,
 | 
					  MAIN_MENU,
 | 
				
			||||||
  BOOTING,
 | 
					  BOOTING,
 | 
				
			||||||
  DESKTOP
 | 
					  DESKTOP
 | 
				
			||||||
@ -34,6 +36,7 @@ private:
 | 
				
			|||||||
  std::unique_ptr<ClientNetwork>  _network;
 | 
					  std::unique_ptr<ClientNetwork>  _network;
 | 
				
			||||||
  std::unique_ptr<Desktop>        _desktop;
 | 
					  std::unique_ptr<Desktop>        _desktop;
 | 
				
			||||||
  std::unique_ptr<BootSequence>   _boot_sequence;
 | 
					  std::unique_ptr<BootSequence>   _boot_sequence;
 | 
				
			||||||
 | 
					  std::unique_ptr<LoginScreen>    _login_screen;
 | 
				
			||||||
  std::unique_ptr<MainMenu>       _main_menu;
 | 
					  std::unique_ptr<MainMenu>       _main_menu;
 | 
				
			||||||
  std::unique_ptr<DebugOverlay>   _debug_overlay;
 | 
					  std::unique_ptr<DebugOverlay>   _debug_overlay;
 | 
				
			||||||
  bool                            _show_debug_overlay;
 | 
					  bool                            _show_debug_overlay;
 | 
				
			||||||
 | 
				
			|||||||
@ -6,6 +6,8 @@
 | 
				
			|||||||
#include <SDL3/SDL_keyboard.h>
 | 
					#include <SDL3/SDL_keyboard.h>
 | 
				
			||||||
#include <SDL3/SDL_timer.h>
 | 
					#include <SDL3/SDL_timer.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "db/db.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#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"
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										149
									
								
								client/src/ui/login_screen.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								client/src/ui/login_screen.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,149 @@
 | 
				
			|||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "gfx/types.h"
 | 
				
			||||||
 | 
					#include "ui/ui_renderer.h"
 | 
				
			||||||
 | 
					#include "ui/login_screen.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					LoginScreen::LoginScreen(int screen_width, int screen_height) 
 | 
				
			||||||
 | 
					    : _screen_width(screen_width), _screen_height(screen_height) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					LoginScreen::~LoginScreen(void) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void LoginScreen::update(float dt) {
 | 
				
			||||||
 | 
					  /* TODO: */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void LoginScreen::render(const RenderContext& context) const {
 | 
				
			||||||
 | 
					  UIRenderer* ui_renderer = context.ui_renderer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Colours. */
 | 
				
			||||||
 | 
					  const Color text_color          = { 0.8f,   0.8f,   0.8f  };
 | 
				
			||||||
 | 
					  const Color inactive_box_color  = { 0.1f,   0.1f,   0.15f };
 | 
				
			||||||
 | 
					  const Color active_box_color    = { 0.15f,  0.15f,  0.2f  };
 | 
				
			||||||
 | 
					  const Color warning_color       = { 0.7f,   0.3f,   0.3f  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Layout. */
 | 
				
			||||||
 | 
					  const int box_width   = 300;
 | 
				
			||||||
 | 
					  const int box_height  = 30;
 | 
				
			||||||
 | 
					  const int center_x    = (_screen_width - box_width) / 2;
 | 
				
			||||||
 | 
					  const int start_y     = _screen_height / 2 - 100;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const Rect username_rect = { center_x, start_y+40,  box_width, box_height };
 | 
				
			||||||
 | 
					  const Rect password_rect = { center_x, start_y+100, box_width, box_height };
 | 
				
			||||||
 | 
					  const Rect hostname_rect = { center_x, start_y+160, box_width, box_height };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ui_renderer->begin_shapes();
 | 
				
			||||||
 | 
					  ui_renderer->begin_text();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Draw title. */
 | 
				
			||||||
 | 
					  const char* title = _is_new_account ? "Create Account" : "Login";
 | 
				
			||||||
 | 
					  float title_width = ui_renderer->get_text_renderer()->get_text_width(title, 1.0f);
 | 
				
			||||||
 | 
					  ui_renderer->render_text(title, (_screen_width-title_width)/2, start_y, text_color);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Draw input boxes and labels. */
 | 
				
			||||||
 | 
					  /* Username */
 | 
				
			||||||
 | 
					  ui_renderer->render_text("Username", username_rect.x, username_rect.y-5, text_color);
 | 
				
			||||||
 | 
					  ui_renderer->draw_rect(username_rect.x, username_rect.y, username_rect.w, username_rect.h,
 | 
				
			||||||
 | 
					                         _active_field == 0 ? active_box_color : inactive_box_color);
 | 
				
			||||||
 | 
					  ui_renderer->render_text(_username_input.c_str(), username_rect.x+10, username_rect.y+20, text_color);
 | 
				
			||||||
 | 
					  if(_active_field == 0 && context.show_cursor) {
 | 
				
			||||||
 | 
					    float cursor_x = username_rect.x + 10 +
 | 
				
			||||||
 | 
					      ui_renderer->get_text_renderer()->get_text_width(_username_input.c_str(), 1.0f);
 | 
				
			||||||
 | 
					    ui_renderer->draw_rect((int)cursor_x, username_rect.y+5, 2, 20, text_color);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Password. */
 | 
				
			||||||
 | 
					  ui_renderer->render_text("Password", password_rect.x, password_rect.y-5, text_color);
 | 
				
			||||||
 | 
					  ui_renderer->draw_rect(password_rect.x, password_rect.y, password_rect.w, password_rect.h,
 | 
				
			||||||
 | 
					                         _active_field == 1 ? active_box_color : inactive_box_color);
 | 
				
			||||||
 | 
					  ui_renderer->render_text(_password_input.c_str(), password_rect.x+10, password_rect.y+20, text_color);
 | 
				
			||||||
 | 
					  if(_active_field == 1 && context.show_cursor) {
 | 
				
			||||||
 | 
					    float cursor_x = password_rect.x + 10 +
 | 
				
			||||||
 | 
					      ui_renderer->get_text_renderer()->get_text_width(_password_input.c_str(), 1.0f);
 | 
				
			||||||
 | 
					    ui_renderer->draw_rect((int)cursor_x, password_rect.y+5, 2, 20, text_color);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Hostname (only for new account). */
 | 
				
			||||||
 | 
					  if(_is_new_account) {
 | 
				
			||||||
 | 
					    ui_renderer->render_text("Hostname", hostname_rect.x, hostname_rect.y-5, text_color);
 | 
				
			||||||
 | 
					    ui_renderer->draw_rect(hostname_rect.x, hostname_rect.y, hostname_rect.w, hostname_rect.h,
 | 
				
			||||||
 | 
					                           _active_field == 2 ? active_box_color : inactive_box_color);
 | 
				
			||||||
 | 
					    ui_renderer->render_text(_hostname_input.c_str(), hostname_rect.x+10, hostname_rect.y+20, text_color);
 | 
				
			||||||
 | 
					    if(_active_field == 2 && context.show_cursor) {
 | 
				
			||||||
 | 
					      float cursor_x = hostname_rect.x + 10 +
 | 
				
			||||||
 | 
					        ui_renderer->get_text_renderer()->get_text_width(_hostname_input.c_str(), 1.0f);
 | 
				
			||||||
 | 
					      ui_renderer->draw_rect((int)cursor_x, hostname_rect.y+5, 2, 20, text_color);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Draw the security warning. */
 | 
				
			||||||
 | 
					  const char* warning_title = "Security Warning";
 | 
				
			||||||
 | 
					  float warning_title_width = ui_renderer->get_text_renderer()->get_text_width(warning_title, 1.0f);
 | 
				
			||||||
 | 
					  ui_renderer->render_text(warning_title, (_screen_width-warning_title_width)/2,
 | 
				
			||||||
 | 
					                           _screen_height-120, warning_color);
 | 
				
			||||||
 | 
					  const std::vector<std::string> warning_lines = {
 | 
				
			||||||
 | 
					    "Passwords in Bettola are stored in plain text by design.",
 | 
				
			||||||
 | 
					    "Players, can, and will attempt to obtain your password.",
 | 
				
			||||||
 | 
					    "DO NOT use a password you have used for any other game or service.",
 | 
				
			||||||
 | 
					    "Use a unique, throwaway password for this game only!"
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  for(size_t i = 0; i < warning_lines.size(); ++i) {
 | 
				
			||||||
 | 
					    const std::string& line = warning_lines[i];
 | 
				
			||||||
 | 
					    float line_width = ui_renderer->get_text_renderer()->get_text_width(line.c_str(), 1.0f);
 | 
				
			||||||
 | 
					    ui_renderer->render_text(line.c_str(), (_screen_width-line_width)/2, 
 | 
				
			||||||
 | 
					                             _screen_height-100+(i*20), warning_color);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ui_renderer->flush_shapes();
 | 
				
			||||||
 | 
					  ui_renderer->flush_text();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void LoginScreen::handle_event(const SDL_Event* event) {
 | 
				
			||||||
 | 
					  if(event->type == SDL_EVENT_TEXT_INPUT) {
 | 
				
			||||||
 | 
					    /* Append character to active input string. */
 | 
				
			||||||
 | 
					    switch(_active_field) {
 | 
				
			||||||
 | 
					      case 0: _username_input += event->text.text; break;
 | 
				
			||||||
 | 
					      case 1: _password_input += event->text.text; break;
 | 
				
			||||||
 | 
					      case 2: if(_is_new_account) { _hostname_input += event->text.text; } break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  } else if(event->type == SDL_EVENT_KEY_DOWN) {
 | 
				
			||||||
 | 
					    if(event->key.key == SDLK_BACKSPACE) {
 | 
				
			||||||
 | 
					      /* Handle backspace. */
 | 
				
			||||||
 | 
					      switch(_active_field) {
 | 
				
			||||||
 | 
					        case 0: if(!_username_input.empty()) { _username_input.pop_back(); } break;
 | 
				
			||||||
 | 
					        case 1: if(!_password_input.empty()) { _password_input.pop_back(); } break;
 | 
				
			||||||
 | 
					        case 2: if(_is_new_account && !_hostname_input.empty()) {
 | 
				
			||||||
 | 
					          _hostname_input.pop_back();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    } else if(event->key.key == SDLK_TAB) {
 | 
				
			||||||
 | 
					      /* Tab to switch fields. */
 | 
				
			||||||
 | 
					      int num_fields = _is_new_account ? 3 : 2;
 | 
				
			||||||
 | 
					      _active_field = (_active_field+1) % num_fields;
 | 
				
			||||||
 | 
					    } else if(event->key.key == SDLK_RETURN) {
 | 
				
			||||||
 | 
					      _login_attempted = true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  } else if(event->type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
 | 
				
			||||||
 | 
					    /* Handle mouse clicks. */
 | 
				
			||||||
 | 
					    int mouse_x = event->button.x;
 | 
				
			||||||
 | 
					    int mouse_y = event->button.y;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Recalculate rects to check for clicks. */
 | 
				
			||||||
 | 
					    const int box_width = 300;
 | 
				
			||||||
 | 
					    const int start_y = _screen_height / 2 - 100;
 | 
				
			||||||
 | 
					    const int center_x = (_screen_width - box_width) / 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const Rect username_rect = { center_x, start_y+40,  box_width, 30 };
 | 
				
			||||||
 | 
					    const Rect password_rect = { center_x, start_y+100, box_width, 30 };
 | 
				
			||||||
 | 
					    const Rect hostname_rect = { center_x, start_y+160, box_width, 30 };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(mouse_y >= username_rect.y && mouse_y <= username_rect.y + username_rect.h)
 | 
				
			||||||
 | 
					      _active_field = 0;
 | 
				
			||||||
 | 
					    else if(mouse_y >= password_rect.y && mouse_y <= password_rect.y + password_rect.h)
 | 
				
			||||||
 | 
					      _active_field = 1;
 | 
				
			||||||
 | 
					    else if(_is_new_account && (mouse_y >= hostname_rect.y && mouse_y <= hostname_rect.y + hostname_rect.h))
 | 
				
			||||||
 | 
					      _active_field = 2;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										35
									
								
								client/src/ui/login_screen.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								client/src/ui/login_screen.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <SDL3/SDL.h>
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "gfx/types.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class LoginScreen {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  LoginScreen(int screen_width, int screen_height);
 | 
				
			||||||
 | 
					  ~LoginScreen(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void update(float dt);
 | 
				
			||||||
 | 
					  void render(const RenderContext& context) const;
 | 
				
			||||||
 | 
					  void handle_event(const SDL_Event* event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool is_login_attempted(void)  const { return _login_attempted; }
 | 
				
			||||||
 | 
					  std::string get_username(void) const { return _username_input; }
 | 
				
			||||||
 | 
					  std::string get_password(void) const { return _password_input; }
 | 
				
			||||||
 | 
					  std::string get_hostname(void) const { return _hostname_input; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					  /* UI State. */
 | 
				
			||||||
 | 
					  std::string _username_input;
 | 
				
			||||||
 | 
					  std::string _password_input;
 | 
				
			||||||
 | 
					  std::string _hostname_input;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool _login_attempted   = false;
 | 
				
			||||||
 | 
					  bool _is_new_account    = true;
 | 
				
			||||||
 | 
					  int _active_field       = 0; /* 0: username, 1: password, 2: hostname. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Screen dimensions. */
 | 
				
			||||||
 | 
					  int _screen_width;
 | 
				
			||||||
 | 
					  int _screen_height;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@ -42,14 +42,14 @@ MainMenu::MainMenu(int screen_width, int screen_height) :
 | 
				
			|||||||
  _buttons.push_back({
 | 
					  _buttons.push_back({
 | 
				
			||||||
    "Single-Player",
 | 
					    "Single-Player",
 | 
				
			||||||
    { center_x, center_y + 30, button_width, button_height },
 | 
					    { center_x, center_y + 30, button_width, button_height },
 | 
				
			||||||
    Screen::BOOTING, /* This will trigger the booting screen. */
 | 
					    Screen::LOGIN, /* This will trigger the login screen. */
 | 
				
			||||||
    true,
 | 
					    true,
 | 
				
			||||||
    false
 | 
					    false
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
  _buttons.push_back({
 | 
					  _buttons.push_back({
 | 
				
			||||||
    "Online",
 | 
					    "Online",
 | 
				
			||||||
    { center_x, center_y - 30, button_width, button_height },
 | 
					    { center_x, center_y - 30, button_width, button_height },
 | 
				
			||||||
    Screen::BOOTING,
 | 
					    Screen::LOGIN,
 | 
				
			||||||
    false,
 | 
					    false,
 | 
				
			||||||
    false
 | 
					    false
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
				
			|||||||
@ -6,9 +6,11 @@ add_library(bettola
 | 
				
			|||||||
  ${BETTOLA_SOURCES}
 | 
					  ${BETTOLA_SOURCES}
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(bettola PUBLIC ${LUA_LIBRARIES} sol2)
 | 
					target_link_libraries(bettola PUBLIC ${LUA_LIBRARIES} sol2 sqlite)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_include_directories(bettola PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src
 | 
					target_include_directories(bettola PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src
 | 
				
			||||||
  ${LUA_INCLUDE_DIR}
 | 
					  ${LUA_INCLUDE_DIR}
 | 
				
			||||||
  ${asio_SOURCE_DIR}/asio/include)
 | 
					  ${asio_SOURCE_DIR}/asio/include
 | 
				
			||||||
 | 
					  ${sqlite_modern_cpp_SOURCE_DIR}/hdr
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										3
									
								
								common/src/db/db.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								common/src/db/db.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <sqlite_modern_cpp.h>
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user