// Raylib renderer for microui package ui import "core:log" import "core:math" import "core:strings" import rl "libs:raylib" import "libs:raylib/rlgl" import gl "vendor:OpenGL" _ :: log default_atlas_texture: rl.Texture2D rl_init :: proc() { rl.UnloadTexture(default_atlas_texture) default_atlas_texture = {} image := rl.Image { data = &default_atlas_alpha, width = DEFAULT_ATLAS_WIDTH, height = DEFAULT_ATLAS_HEIGHT, mipmaps = 1, format = .UNCOMPRESSED_GRAYSCALE, } default_atlas_texture = rl.LoadTextureFromImage(image) rl.SetTextureFilter(default_atlas_texture, .POINT) gl.BindTexture(gl.TEXTURE_2D, default_atlas_texture.id) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_SWIZZLE_A, gl.RED) gl.BindTexture(gl.TEXTURE_2D, 0) } to_rl_color :: proc(c: Color) -> rl.Color { return rl.Color{c.r, c.g, c.b, c.a} } to_rl_rect :: proc(r: Rect) -> rl.Rectangle { return rl.Rectangle{x = f32(r.x), y = f32(r.y), width = f32(r.w), height = f32(r.h)} } rl_measure_text_2d :: #force_inline proc(font: Font, font_size: i32, text: string) -> [2]i32 { font := (cast(^rl.Font)font) size := rl.MeasureTextEx( font^ if font != nil else rl.GetFontDefault(), strings.clone_to_cstring(text, context.temp_allocator), f32(font_size), f32(font_size / (font.baseSize if font != nil else 10)), ) return {i32(math.ceil(size.x)), i32(math.ceil(size.y))} } rl_draw :: proc(ctx: ^Context) { tmp_cmd: ^Command for cmd in next_command_iterator(ctx, &tmp_cmd) { switch c in cmd { case ^Command_Clip: if c.rect == unclipped_rect { rl.EndScissorMode() } else { rl.BeginScissorMode(c.rect.x, c.rect.y, c.rect.w, c.rect.h) } case ^Command_Text: font := cast(^rl.Font)c.font rl.DrawTextEx( font^ if font != nil else rl.GetFontDefault(), strings.clone_to_cstring(c.str, context.temp_allocator), rl.Vector2{f32(c.pos.x), f32(c.pos.y)}, f32(c.font_size), f32(c.font_size / (font.baseSize if font != nil else 10)), to_rl_color(c.color), ) case ^Command_Rect: rl.DrawRectangle(c.rect.x, c.rect.y, c.rect.w, c.rect.h, to_rl_color(c.color)) case ^Command_Line: segments := get_line_segments(ctx, c.first_segment, c.num_segments) rl.DrawLineStrip(&segments[0], i32(len(segments)), to_rl_color(c.color)) case ^Command_Jump: case ^Command_Icon: src_rect := default_atlas[int(c.id)] x := f32(c.rect.x + (c.rect.w - src_rect.w) / 2) y := f32(c.rect.y + (c.rect.h - src_rect.h) / 2) rl.DrawTextureRec( default_atlas_texture, to_rl_rect(src_rect), {x, y}, to_rl_color(c.color), ) } } rlgl.DrawRenderBatchActive() rlgl.DisableScissorTest() } RL_MOUSE_BUTTON_MAPPING :: [Mouse]rl.MouseButton { .LEFT = .LEFT, .RIGHT = .RIGHT, .MIDDLE = .MIDDLE, } RL_KEY_MAPPING :: [Key]rl.KeyboardKey { .SHIFT = .LEFT_SHIFT, .CTRL = .LEFT_CONTROL, .ALT = .LEFT_ALT, .BACKSPACE = .BACKSPACE, .DELETE = .DELETE, .RETURN = .ENTER, .LEFT = .LEFT, .RIGHT = .RIGHT, .HOME = .HOME, .END = .END, .A = .A, .X = .X, .C = .C, .V = .V, } rl_update_inputs :: proc(ctx: ^Context) { ctx.mouse_pos.x = rl.GetMouseX() ctx.mouse_pos.y = rl.GetMouseY() for rl_btn, ui_btn in RL_MOUSE_BUTTON_MAPPING { if rl.IsMouseButtonPressed(rl_btn) { input_mouse_down(ctx, ctx.mouse_pos.x, ctx.mouse_pos.y, ui_btn) } if rl.IsMouseButtonReleased(rl_btn) { input_mouse_up(ctx, ctx.mouse_pos.x, ctx.mouse_pos.y, ui_btn) } } wheel_move := rl.GetMouseWheelMoveV() * -50 input_scroll(ctx, i32(wheel_move.x), i32(wheel_move.y)) for rl_key, ui_key in RL_KEY_MAPPING { if rl.IsKeyPressed(rl_key) { input_key_down(ctx, ui_key) } if rl.IsKeyReleased(rl_key) { input_key_up(ctx, ui_key) } } for char := rl.GetCharPressed(); char != 0; char = rl.GetCharPressed() { strings.write_rune(&ctx.text_input, char) } }