Started modeling an interface. Early MicroUI backend.
This commit is contained in:
248
imgui.odin
248
imgui.odin
@@ -1,3 +1,249 @@
|
||||
package imgui
|
||||
|
||||
// Hello, world!
|
||||
import "core:container/queue"
|
||||
import "core:log"
|
||||
|
||||
import "microui"
|
||||
|
||||
MAX_DRAW_COMMANDS :: #config(IMGUI_MAX_DRAW_COMMANDS, 512 * 1024)
|
||||
|
||||
// TODO: SS - Consider not having 'microui' as a seperate package and instead have it (and other backends) in the 'imgui' package directly.
|
||||
|
||||
IMGUI_BACKEND_MICROUI :: #config(IMGUI_BACKEND_MICROUI, false)
|
||||
|
||||
when IMGUI_BACKEND_MICROUI {
|
||||
Context_Backend :: microui.Context
|
||||
}
|
||||
|
||||
Context :: struct {
|
||||
backend: ^Context_Backend,
|
||||
|
||||
draw_commands: queue.Queue(Draw_Command),
|
||||
input: Input,
|
||||
}
|
||||
|
||||
Input :: struct {
|
||||
mouse_state: Mouse_State,
|
||||
}
|
||||
|
||||
Mouse_Button_State :: enum {
|
||||
Up,
|
||||
Pressed,
|
||||
Down,
|
||||
Released,
|
||||
}
|
||||
|
||||
Mouse_State :: struct {
|
||||
pos_x, pos_y: u16,
|
||||
left, middle, right: Mouse_Button_State,
|
||||
}
|
||||
|
||||
Draw_Command :: struct {
|
||||
color: [4]u8,
|
||||
type: Draw_Command_Type,
|
||||
}
|
||||
|
||||
Draw_Command_Type :: union {
|
||||
Draw_Command_Rect,
|
||||
}
|
||||
|
||||
Draw_Command_Rect :: struct {
|
||||
x, y, width, height: u16,
|
||||
}
|
||||
|
||||
Rect :: struct {
|
||||
x, y, width, height: u16,
|
||||
}
|
||||
|
||||
init :: proc(ctx: ^Context) -> bool {
|
||||
assert(ctx != nil)
|
||||
assert(ctx.backend == nil)
|
||||
|
||||
backend, err := new(Context_Backend)
|
||||
if err != .None {
|
||||
log.errorf("Failed to allocate space for the backend. Error: %v", err)
|
||||
return false
|
||||
}
|
||||
ctx.backend = backend
|
||||
|
||||
ok := false
|
||||
|
||||
when IMGUI_BACKEND_MICROUI {
|
||||
ok = microui.init(ctx.backend)
|
||||
}
|
||||
|
||||
if !ok {
|
||||
free(backend)
|
||||
return false
|
||||
}
|
||||
|
||||
queue_err := queue.init(&ctx.draw_commands, MAX_DRAW_COMMANDS)
|
||||
if queue_err != .None {
|
||||
free(backend)
|
||||
log.errorf("Failed to allocate space for the queue of imgui draw-commands. Error: %v", queue_err)
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
set_input :: proc(ctx: ^Context, input: Input) {
|
||||
ctx.input = input
|
||||
}
|
||||
|
||||
begin :: proc(ctx: ^Context) {
|
||||
assert(ctx != nil)
|
||||
assert(ctx.backend != nil)
|
||||
|
||||
when IMGUI_BACKEND_MICROUI {
|
||||
input: microui.Input
|
||||
input.mouse_x = ctx.input.mouse_state.pos_x
|
||||
input.mouse_y = ctx.input.mouse_state.pos_y
|
||||
|
||||
if ctx.input.mouse_state.left == .Pressed {
|
||||
input.mouse_buttons_pressed += { .LEFT }
|
||||
}
|
||||
else if ctx.input.mouse_state.left == .Released {
|
||||
input.mouse_buttons_released += { .LEFT }
|
||||
}
|
||||
|
||||
if ctx.input.mouse_state.middle == .Pressed {
|
||||
input.mouse_buttons_pressed += { .MIDDLE }
|
||||
}
|
||||
else if ctx.input.mouse_state.middle == .Released {
|
||||
input.mouse_buttons_released += { .MIDDLE }
|
||||
}
|
||||
|
||||
if ctx.input.mouse_state.right == .Pressed {
|
||||
input.mouse_buttons_pressed += { .RIGHT }
|
||||
}
|
||||
else if ctx.input.mouse_state.right == .Released {
|
||||
input.mouse_buttons_released += { .RIGHT }
|
||||
}
|
||||
|
||||
microui.begin(ctx.backend, input)
|
||||
}
|
||||
}
|
||||
|
||||
end :: proc(ctx: ^Context) {
|
||||
assert(ctx != nil)
|
||||
assert(ctx.backend != nil)
|
||||
|
||||
when IMGUI_BACKEND_MICROUI {
|
||||
microui.end(ctx.backend)
|
||||
}
|
||||
}
|
||||
|
||||
begin_window :: proc(ctx: ^Context, title: string, rect: Rect) -> bool {
|
||||
assert(ctx != nil)
|
||||
|
||||
when IMGUI_BACKEND_MICROUI {
|
||||
return microui.begin_window(ctx.backend, title, microui.Rect {
|
||||
x = i32(rect.x),
|
||||
y = i32(rect.y),
|
||||
w = i32(rect.width),
|
||||
h = i32(rect.height),
|
||||
})
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
end_window :: proc(ctx: ^Context) {
|
||||
assert(ctx != nil)
|
||||
|
||||
when IMGUI_BACKEND_MICROUI {
|
||||
microui.end_window(ctx.backend)
|
||||
}
|
||||
}
|
||||
|
||||
button :: proc(ctx: ^Context, title: string) -> bool {
|
||||
when IMGUI_BACKEND_MICROUI {
|
||||
return microui.button(ctx.backend, title)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
collect :: proc(ctx: ^Context) { // TODO: SS - Come up with a better name. Adds commands from backend to queue in ctx.
|
||||
assert(ctx != nil)
|
||||
|
||||
// TODO: SS - Reduce code-repetition if possible. MicroUI asks to be "popped"/iterated like this, apparently.
|
||||
|
||||
when IMGUI_BACKEND_MICROUI {
|
||||
last_cmd: ^microui.Command = nil
|
||||
for {
|
||||
dc: Draw_Command
|
||||
dc.type = nil
|
||||
|
||||
cmd := microui.pop_draw_command(ctx.backend, last_cmd)
|
||||
if cmd == nil {
|
||||
break
|
||||
}
|
||||
|
||||
last_cmd = cmd
|
||||
|
||||
#partial switch &v in &cmd.variant {
|
||||
// case ^microui.Command_Jump: {} // Internal.
|
||||
// case ^microui.Command_Clip: {
|
||||
// }
|
||||
// case ^microui.Command_Icon: {
|
||||
// }
|
||||
case ^microui.Command_Rect: {
|
||||
assert(v.rect.x >= 0)
|
||||
assert(v.rect.y >= 0)
|
||||
assert(v.rect.w >= 0)
|
||||
assert(v.rect.h >= 0)
|
||||
|
||||
dc.color = {
|
||||
v.color.r,
|
||||
v.color.g,
|
||||
v.color.b,
|
||||
v.color.a,
|
||||
}
|
||||
dc.type = Draw_Command_Rect {
|
||||
x = u16(v.rect.x),
|
||||
y = u16(v.rect.y),
|
||||
width = u16(v.rect.w),
|
||||
height = u16(v.rect.h),
|
||||
}
|
||||
}
|
||||
// case ^microui.Command_Text: {
|
||||
// }
|
||||
}
|
||||
|
||||
if dc.type != nil {
|
||||
queue.push_back(&ctx.draw_commands, dc)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pop_draw_command :: proc(ctx: ^Context, out_draw_command: ^Draw_Command) -> bool {
|
||||
assert(ctx != nil)
|
||||
assert(out_draw_command != nil)
|
||||
|
||||
out_draw_command^ = {}
|
||||
|
||||
elem, ok := queue.pop_front_safe(&ctx.draw_commands)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
out_draw_command^ = elem
|
||||
return true
|
||||
}
|
||||
|
||||
shutdown :: proc(ctx: ^Context) {
|
||||
assert(ctx != nil)
|
||||
assert(ctx.backend != nil)
|
||||
|
||||
when IMGUI_BACKEND_MICROUI {
|
||||
microui.shutdown(ctx.backend)
|
||||
}
|
||||
|
||||
free(ctx.backend)
|
||||
ctx.backend = nil
|
||||
|
||||
queue.destroy(&ctx.draw_commands)
|
||||
}
|
||||
Reference in New Issue
Block a user