package main import ( "github.com/gen2brain/raylib-go/raylib" ) type ClientAuth struct { } type LoginState int const ( LOGIN_STATE_CREDENTIALS LoginState = iota LOGIN_STATE_ATTEMPTING LOGIN_STATE_ERROR ) type ButtonState int const ( BUTTON_STATE_IDLE ButtonState = iota BUTTON_STATE_HOVER BUTTON_STATE_PRESSED ) type ClientState struct { auth *ClientAuth login LoginState login_button ButtonState ui_scale uint window_scale rl.Vector2 } const ( WIDTH uint = 1600 HEIGHT uint = 1000 ) func scale(original rl.Rectangle, ui_scale uint, window_scale rl.Vector2) rl.Rectangle { return rl.Rectangle{ X: original.X/window_scale.X, Y: original.Y/window_scale.Y, Width: original.Width*float32(ui_scale)/window_scale.X, Height: original.Height*float32(ui_scale)/window_scale.Y, } } func center(original rl.Rectangle, off_x, off_y int, window_scale rl.Vector2, width, height uint) rl.Rectangle { return rl.Rectangle{ X: (float32(width) /window_scale.X - original.Width )/2 + float32(off_x)/window_scale.X, Y: (float32(height)/window_scale.Y - original.Height)/2 + float32(off_y)/window_scale.Y, Width: original.Width, Height: original.Height, } } func button(rectangle rl.Rectangle, idle, hover, pressed rl.Color, text string, font_size int32, text_color rl.Color, last_state ButtonState) (action bool, next_state ButtonState) { over := rl.CheckCollisionPointRec(rl.GetMousePosition(), rectangle) action = false next_state = last_state if(rl.IsMouseButtonPressed(rl.MouseButtonLeft) && over) { next_state = BUTTON_STATE_PRESSED } else if(rl.IsMouseButtonReleased(rl.MouseButtonLeft) && last_state == BUTTON_STATE_PRESSED) { next_state = BUTTON_STATE_IDLE if(over) { action = true } } else if(rl.IsMouseButtonUp(rl.MouseButtonLeft)) { if(last_state == BUTTON_STATE_IDLE && over) { next_state = BUTTON_STATE_HOVER } else if (last_state == BUTTON_STATE_HOVER && !over) { next_state = BUTTON_STATE_IDLE } } var color rl.Color switch(next_state) { case BUTTON_STATE_HOVER: color = hover case BUTTON_STATE_PRESSED: color = pressed default: color = idle } rl.DrawRectangleRec(rectangle, color) text_size := rl.MeasureTextEx(rl.GetFontDefault(), text, float32(font_size), 1.0) rl.DrawText(text, int32(rectangle.X + rectangle.Width/2 - text_size.X/2), int32(rectangle.Y + rectangle.Height/2 - text_size.Y/2), font_size, text_color) return action, next_state } func main() { state := ClientState{ auth: nil, login: LOGIN_STATE_CREDENTIALS, login_button: BUTTON_STATE_IDLE, ui_scale: 1, } rl.SetConfigFlags(rl.FlagWindowHighdpi) rl.InitWindow(0, 0, "roleplay") rl.SetExitKey(0) rl.SetTargetFPS(60) state.window_scale = rl.GetWindowScaleDPI() rl.SetWindowSize(int(float32(WIDTH)/state.window_scale.X), int(float32(HEIGHT)/state.window_scale.Y)) for(rl.WindowShouldClose() == false) { if(state.auth == nil) { // Draw login rl.BeginDrawing() rl.ClearBackground(rl.White) logo_rect := scale(rl.Rectangle{Width: 1200, Height: 300}, state.ui_scale, state.window_scale) logo_rect = center(logo_rect, 0, -300, state.window_scale, WIDTH, HEIGHT) rl.DrawRectangleRec(logo_rect, rl.Gray) form_rect := scale(rl.Rectangle{Width: 600, Height: 400}, state.ui_scale, state.window_scale) form_rect = center(form_rect, 0, 150, state.window_scale, WIDTH, HEIGHT) rl.DrawRectangleRec(form_rect, rl.Gray) switch(state.login) { case LOGIN_STATE_CREDENTIALS: submit_rect := scale(rl.Rectangle{Width: 100, Height: 50}, state.ui_scale, state.window_scale) submit_rect = center(submit_rect, 0, 300, state.window_scale, WIDTH, HEIGHT) var submit_action bool submit_action, state.login_button = button(submit_rect, rl.Black, rl.Brown, rl.Red, "Submit", 12, rl.White, state.login_button) if submit_action { state.login = LOGIN_STATE_ATTEMPTING } case LOGIN_STATE_ATTEMPTING: text := "Logging in..." text_size := rl.MeasureTextEx(rl.GetFontDefault(), text, 20, 1.0) text_rect := center(rl.Rectangle{Width: text_size.X, Height: text_size.Y}, 0, 0, state.window_scale, WIDTH, HEIGHT) rl.DrawText(text, int32(text_rect.X), int32(text_rect.Y), 20, rl.Black) case LOGIN_STATE_ERROR: text := "Error: {TODO}" text_size := rl.MeasureTextEx(rl.GetFontDefault(), text, 20, 1.0) text_rect := center(rl.Rectangle{Width: text_size.X, Height: text_size.Y}, 0, 0, state.window_scale, WIDTH, HEIGHT) rl.DrawText(text, int32(text_rect.X), int32(text_rect.Y), 20, rl.Black) } rl.EndDrawing() } else { // Draw game } } }