Add future dependencies

This commit is contained in:
2026-06-14 01:35:08 -07:00
parent aea63986a2
commit 50882df786
10 changed files with 1079 additions and 0 deletions
+4
View File
@@ -0,0 +1,4 @@
# Local build outputs
game_msan
game
*.bin
+3
View File
@@ -0,0 +1,3 @@
[submodule "odin-imgui"]
path = odin-imgui
url = https://github.com/Capati/odin-imgui.git
+601
View File
@@ -0,0 +1,601 @@
package clay
import "core:c"
when ODIN_OS == .Windows {
foreign import Clay "windows/clay.lib"
} else when ODIN_OS == .Linux {
foreign import Clay "linux/clay.a"
} else when ODIN_OS == .Darwin {
when ODIN_ARCH == .arm64 {
foreign import Clay "macos-arm64/clay.a"
} else {
foreign import Clay "macos/clay.a"
}
} else when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 {
foreign import Clay "wasm/clay.o"
}
String :: struct {
isStaticallyAllocated: c.bool,
length: c.int32_t,
chars: [^]c.char,
}
StringSlice :: struct {
length: c.int32_t,
chars: [^]c.char,
baseChars: [^]c.char,
}
Vector2 :: [2]c.float
Dimensions :: struct {
width: c.float,
height: c.float,
}
Arena :: struct {
nextAllocation: uintptr,
capacity: c.size_t,
memory: [^]c.char,
}
BoundingBox :: struct {
x: c.float,
y: c.float,
width: c.float,
height: c.float,
}
Color :: [4]c.float
CornerRadius :: struct {
topLeft: c.float,
topRight: c.float,
bottomLeft: c.float,
bottomRight: c.float,
}
ElementId :: struct {
id: u32,
offset: u32,
baseId: u32,
stringId: String,
}
ElementIdArray :: struct {
capacity: i32,
length: i32,
internalArray: [^]ElementId,
}
when ODIN_OS == .Windows {
EnumBackingType :: u32
} else {
EnumBackingType :: u8
}
RenderCommandType :: enum EnumBackingType {
None,
Rectangle,
Border,
Text,
Image,
ScissorStart,
ScissorEnd,
OverlayColorStart,
OverlayColorEnd,
Custom,
}
RectangleElementConfig :: struct {
color: Color,
}
TextWrapMode :: enum EnumBackingType {
Words,
Newlines,
None,
}
TextAlignment :: enum EnumBackingType {
Left,
Center,
Right,
}
TextElementConfig :: struct {
userData: rawptr,
textColor: Color,
fontId: u16,
fontSize: u16,
letterSpacing: u16,
lineHeight: u16,
wrapMode: TextWrapMode,
textAlignment: TextAlignment,
}
AspectRatioElementConfig :: struct {
aspectRatio: f32,
}
ImageElementConfig :: struct {
imageData: rawptr,
}
CustomElementConfig :: struct {
customData: rawptr,
}
BorderWidth :: struct {
left: u16,
right: u16,
top: u16,
bottom: u16,
betweenChildren: u16,
}
BorderElementConfig :: struct {
color: Color,
width: BorderWidth,
}
TransitionData :: struct {
boundingBox: BoundingBox,
backgroundColor: Color,
overlayColor: Color,
borderColor: Color,
borderWidth: BorderWidth,
}
TransitionState :: enum c.int {
Idle,
Entering,
Transitioning,
Exiting,
}
TransitionProperty :: enum c.int {
X,
Y,
Width,
Height,
BackgroundColor,
OverlayColor,
CornerRadius,
BorderColor,
BorderWidth,
}
TransitionPropertyFlags :: bit_set[TransitionProperty;c.int]
TransitionPropertyPosition :: TransitionPropertyFlags{.X, .Y}
TransitionPropertyDimensions :: TransitionPropertyFlags{.Width, .Height}
TransitionPropertyBoundingBox :: TransitionPropertyPosition + TransitionPropertyDimensions
TransitionPropertyBorder :: TransitionPropertyFlags{.BorderColor, .BorderWidth}
TransitionCallbackArguments :: struct {
transitionState: TransitionState,
initial: TransitionData,
current: ^TransitionData,
target: TransitionData,
elapsedTime: f32,
duration: f32,
properties: TransitionPropertyFlags,
}
TransitionEnterTriggerType :: enum EnumBackingType {
SkipOnFirstParentFrame,
TriggerOnFirstParentFrame,
}
TransitionExitTriggerType :: enum EnumBackingType {
SkipWhenParentExits,
TriggerWhenParentExits,
}
TransitionInteractionHandlingType :: enum EnumBackingType {
DisableInteractionsWhileTransitioningPosition,
AllowInteractionsWhileTransitioningPosition,
}
ExitTransitionSiblingOrdering :: enum EnumBackingType {
UnderneathSiblings,
NaturalOrder,
AboveSiblings,
}
TransitionElementConfig :: struct {
handler: proc "c" (args: TransitionCallbackArguments) -> bool,
duration: f32,
properties: TransitionPropertyFlags,
interactionHandling: TransitionInteractionHandlingType,
enter: struct {
setInitialState: proc "c" (initialState: TransitionData, properties: TransitionPropertyFlags) -> TransitionData,
trigger: TransitionEnterTriggerType,
},
exit: struct {
setFinalState: proc "c" (finalState: TransitionData, properties: TransitionPropertyFlags) -> TransitionData,
trigger: TransitionExitTriggerType,
siblingOrdering: ExitTransitionSiblingOrdering,
},
}
ClipElementConfig :: struct {
horizontal: bool, // clip overflowing elements on the "X" axis
vertical: bool, // clip overflowing elements on the "Y" axis
childOffset: Vector2, // offsets the [X,Y] positions of all child elements, primarily for scrolling containers
}
FloatingAttachPointType :: enum EnumBackingType {
LeftTop,
LeftCenter,
LeftBottom,
CenterTop,
CenterCenter,
CenterBottom,
RightTop,
RightCenter,
RightBottom,
}
FloatingAttachPoints :: struct {
element: FloatingAttachPointType,
parent: FloatingAttachPointType,
}
PointerCaptureMode :: enum EnumBackingType {
Capture,
Passthrough,
}
FloatingAttachToElement :: enum EnumBackingType {
None,
Parent,
ElementWithId,
Root,
}
FloatingClipToElement :: enum EnumBackingType {
None,
AttachedParent,
}
FloatingElementConfig :: struct {
offset: Vector2,
expand: Dimensions,
parentId: u32,
zIndex: i16,
attachment: FloatingAttachPoints,
pointerCaptureMode: PointerCaptureMode,
attachTo: FloatingAttachToElement,
clipTo: FloatingClipToElement,
}
TextRenderData :: struct {
stringContents: StringSlice,
textColor: Color,
fontId: u16,
fontSize: u16,
letterSpacing: u16,
lineHeight: u16,
}
RectangleRenderData :: struct {
backgroundColor: Color,
cornerRadius: CornerRadius,
}
ImageRenderData :: struct {
backgroundColor: Color,
cornerRadius: CornerRadius,
imageData: rawptr,
}
CustomRenderData :: struct {
backgroundColor: Color,
cornerRadius: CornerRadius,
customData: rawptr,
}
ClipRenderData :: struct {
horizontal: bool,
vertical: bool,
}
OverlayColorRenderData :: struct {
color: Color,
}
BorderRenderData :: struct {
color: Color,
cornerRadius: CornerRadius,
width: BorderWidth,
}
RenderCommandData :: struct #raw_union {
rectangle: RectangleRenderData,
text: TextRenderData,
image: ImageRenderData,
custom: CustomRenderData,
border: BorderRenderData,
clip: ClipRenderData,
overlayColor: OverlayColorRenderData,
}
RenderCommand :: struct {
boundingBox: BoundingBox,
renderData: RenderCommandData,
userData: rawptr,
id: u32,
zIndex: i16,
commandType: RenderCommandType,
}
ScrollContainerData :: struct {
// Note: This is a pointer to the real internal scroll position, mutating it may cause a change in final layout.
// Intended for use with external functionality that modifies scroll position, such as scroll bars or auto scrolling.
scrollPosition: ^Vector2,
scrollContainerDimensions: Dimensions,
contentDimensions: Dimensions,
config: ClipElementConfig,
// Indicates whether an actual scroll container matched the provided ID or if the default struct was returned.
found: bool,
}
ElementData :: struct {
boundingBox: BoundingBox,
found: bool,
}
PointerDataInteractionState :: enum EnumBackingType {
PressedThisFrame,
Pressed,
ReleasedThisFrame,
Released,
}
PointerData :: struct {
position: Vector2,
state: PointerDataInteractionState,
}
SizingType :: enum EnumBackingType {
Fit,
Grow,
Percent,
Fixed,
}
SizingConstraintsMinMax :: struct {
min: c.float,
max: c.float,
}
SizingConstraints :: struct #raw_union {
sizeMinMax: SizingConstraintsMinMax,
sizePercent: c.float,
}
SizingAxis :: struct {
// Note: `min` is used for CLAY_SIZING_PERCENT, slightly different to clay.h due to lack of C anonymous unions
constraints: SizingConstraints,
type: SizingType,
}
Sizing :: struct {
width: SizingAxis,
height: SizingAxis,
}
Padding :: struct {
left: u16,
right: u16,
top: u16,
bottom: u16,
}
LayoutDirection :: enum EnumBackingType {
LeftToRight,
TopToBottom,
}
LayoutAlignmentX :: enum EnumBackingType {
Left,
Right,
Center,
}
LayoutAlignmentY :: enum EnumBackingType {
Top,
Bottom,
Center,
}
ChildAlignment :: struct {
x: LayoutAlignmentX,
y: LayoutAlignmentY,
}
LayoutConfig :: struct {
sizing: Sizing,
padding: Padding,
childGap: u16,
childAlignment: ChildAlignment,
layoutDirection: LayoutDirection,
}
ClayArray :: struct($type: typeid) {
capacity: i32,
length: i32,
internalArray: [^]type,
}
ElementDeclaration :: struct {
layout: LayoutConfig,
backgroundColor: Color,
overlayColor: Color,
cornerRadius: CornerRadius,
aspectRatio: AspectRatioElementConfig,
image: ImageElementConfig,
floating: FloatingElementConfig,
custom: CustomElementConfig,
clip: ClipElementConfig,
border: BorderElementConfig,
transition: TransitionElementConfig,
userData: rawptr,
}
ErrorType :: enum EnumBackingType {
TextMeasurementFunctionNotProvided,
ArenaCapacityExceeded,
ElementsCapacityExceeded,
TextMeasurementCapacityExceeded,
DuplicateId,
FloatingContainerParentNotFound,
PercentageOver1,
InternalError,
UnbalancedOpenClose,
}
ErrorData :: struct {
errorType: ErrorType,
errorText: String,
userData: rawptr,
}
ErrorHandler :: struct {
handler: proc "c" (errorData: ErrorData),
userData: rawptr,
}
Context :: struct {} // opaque structure, only use as a pointer
@(link_prefix = "Clay_", default_calling_convention = "c")
foreign Clay {
_OpenElement :: proc() ---
_OpenElementWithId :: proc(id: ElementId) ---
_CloseElement :: proc() ---
MinMemorySize :: proc() -> u32 ---
CreateArenaWithCapacityAndMemory :: proc(capacity: c.size_t, offset: [^]u8) -> Arena ---
SetPointerState :: proc(position: Vector2, pointerDown: bool) ---
GetPointerState :: proc() -> PointerData ---
Initialize :: proc(arena: Arena, layoutDimensions: Dimensions, errorHandler: ErrorHandler) -> ^Context ---
GetCurrentContext :: proc() -> ^Context ---
SetCurrentContext :: proc(ctx: ^Context) ---
UpdateScrollContainers :: proc(enableDragScrolling: bool, scrollDelta: Vector2, deltaTime: c.float) ---
SetLayoutDimensions :: proc(dimensions: Dimensions) ---
BeginLayout :: proc() ---
EndLayout :: proc(deltaTime: c.float) -> ClayArray(RenderCommand) ---
GetOpenElementId :: proc() -> u32 ---
GetElementId :: proc(id: String) -> ElementId ---
GetElementIdWithIndex :: proc(id: String, index: u32) -> ElementId ---
GetElementData :: proc(id: ElementId) -> ElementData ---
Hovered :: proc() -> bool ---
OnHover :: proc(onHoverFunction: proc "c" (id: ElementId, pointerData: PointerData, userData: rawptr), userData: rawptr) ---
PointerOver :: proc(id: ElementId) -> bool ---
GetPointerOverIds :: proc() -> ElementIdArray ---
GetScrollOffset :: proc() -> Vector2 ---
GetScrollContainerData :: proc(id: ElementId) -> ScrollContainerData ---
SetMeasureTextFunction :: proc(measureTextFunction: proc "c" (text: StringSlice, config: ^TextElementConfig, userData: rawptr) -> Dimensions, userData: rawptr) ---
SetQueryScrollOffsetFunction :: proc(queryScrollOffsetFunction: proc "c" (elementId: u32, userData: rawptr) -> Vector2, userData: rawptr) ---
RenderCommandArray_Get :: proc(array: ^ClayArray(RenderCommand), index: i32) -> ^RenderCommand ---
SetDebugModeEnabled :: proc(enabled: bool) ---
IsDebugModeEnabled :: proc() -> bool ---
SetCullingEnabled :: proc(enabled: bool) ---
GetMaxElementCount :: proc() -> i32 ---
SetMaxElementCount :: proc(maxElementCount: i32) ---
GetMaxMeasureTextCacheWordCount :: proc() -> i32 ---
SetMaxMeasureTextCacheWordCount :: proc(maxMeasureTextCacheWordCount: i32) ---
ResetMeasureTextCache :: proc() ---
EaseOut :: proc(arguments: TransitionCallbackArguments) -> bool ---
}
@(link_prefix = "Clay_", default_calling_convention = "c", private)
foreign Clay {
_ConfigureOpenElement :: proc(config: ElementDeclaration) ---
_HashString :: proc(key: String, seed: u32) -> ElementId ---
_HashStringWithOffset :: proc(key: String, index: u32, seed: u32) -> ElementId ---
_OpenTextElement :: proc(text: String, textConfig: TextElementConfig) ---
}
ConfigureOpenElement :: proc(config: ElementDeclaration) -> bool {
_ConfigureOpenElement(config)
return true
}
@(deferred_none = _CloseElement)
UI_WithId :: proc(id: ElementId) -> proc(config: ElementDeclaration) -> bool {
_OpenElementWithId(id)
return ConfigureOpenElement
}
@(deferred_none = _CloseElement)
UI_AutoId :: proc() -> proc(config: ElementDeclaration) -> bool {
_OpenElement()
return ConfigureOpenElement
}
UI :: proc {
UI_WithId,
UI_AutoId,
}
Text :: proc {
TextStatic,
TextDynamic,
}
TextStatic :: proc($text: string, config: TextElementConfig) {
wrapped := MakeString(text)
wrapped.isStaticallyAllocated = true
_OpenTextElement(wrapped, config)
}
TextDynamic :: proc(text: string, config: TextElementConfig) {
_OpenTextElement(MakeString(text), config)
}
PaddingAll :: proc(allPadding: u16) -> Padding {
return {left = allPadding, right = allPadding, top = allPadding, bottom = allPadding}
}
BorderOutside :: proc(width: u16) -> BorderWidth {
return {width, width, width, width, 0}
}
BorderAll :: proc(width: u16) -> BorderWidth {
return {width, width, width, width, width}
}
CornerRadiusAll :: proc(radius: f32) -> CornerRadius {
return CornerRadius{radius, radius, radius, radius}
}
SizingFit :: proc(sizeMinMax: SizingConstraintsMinMax = {}) -> SizingAxis {
return SizingAxis{type = SizingType.Fit, constraints = {sizeMinMax = sizeMinMax}}
}
SizingGrow :: proc(sizeMinMax: SizingConstraintsMinMax = {}) -> SizingAxis {
return SizingAxis{type = SizingType.Grow, constraints = {sizeMinMax = sizeMinMax}}
}
SizingFixed :: proc(size: c.float) -> SizingAxis {
return SizingAxis{type = SizingType.Fixed, constraints = {sizeMinMax = {size, size}}}
}
SizingPercent :: proc(sizePercent: c.float) -> SizingAxis {
return SizingAxis{type = SizingType.Percent, constraints = {sizePercent = sizePercent}}
}
MakeString :: proc(label: string) -> String {
return String{chars = raw_data(label), length = cast(c.int)len(label)}
}
ID :: proc(label: string, index: u32 = 0) -> ElementId {
return _HashString(MakeString(label), index)
}
ID_LOCAL :: proc(label: string, index: u32 = 0) -> ElementId {
return _HashStringWithOffset(MakeString(label), index, GetOpenElementId())
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+470
View File
@@ -0,0 +1,470 @@
package imgui_impl_raylib
// Based on the raylib extras rlImGui: https://github.com/raylib-extras/rlImGui/blob/main/rlImGui.cpp
/* Usage:
import imgui_rl "imgui_impl_raylib"
import imgui "../../odin-imgui"
main :: proc() {
rl.SetConfigFlags({ rl.ConfigFlag.WINDOW_RESIZABLE })
rl.InitWindow(800, 600, "raylib basic window")
defer rl.CloseWindow()
imgui.CreateContext(nil)
defer imgui.DestroyContext(nil)
imgui_rl.init()
defer imgui_rl.shutdown()
imgui_rl.build_font_atlas()
for !rl.WindowShouldClose() {
imgui_rl.process_events()
imgui_rl.new_frame()
imgui.NewFrame()
rl.BeginDrawing()
rl.ClearBackground(rl.RAYWHITE)
imgui.ShowDemoWindow(nil)
imgui.Render()
imgui_rl.render_draw_data(imgui.GetDrawData())
rl.EndDrawing()
}
}
*/
import "core:c"
import "core:mem"
import "core:math"
// Follow build instruction for imgui bindings in: https://gitlab.com/L-4/odin-imgui
import imgui "../odin-imgui"
import rl "vendor:raylib"
current_mouse_cursor: imgui.MouseCursor = imgui.MouseCursor.COUNT
mouse_cursor_map: [imgui.MouseCursor.COUNT]rl.MouseCursor
last_frame_focused := false
last_control_pressed := false
last_shift_pressed := false
last_alt_pressed := false
last_super_pressed := false
raylib_key_map: map[rl.KeyboardKey]imgui.Key = {}
init :: proc() -> bool {
setup_globals()
setup_keymap()
setup_mouse_cursor()
setup_backend()
return true
}
build_font_atlas :: proc() -> mem.Allocator_Error {
io: ^imgui.IO = imgui.GetIO()
pixels: ^c.uchar
width, height: c.int
imgui.FontAtlas_GetTexDataAsRGBA32(io.Fonts, &pixels, &width, &height, nil)
image: rl.Image = rl.GenImageColor(width, height, rl.BLANK)
mem.copy(image.data, pixels, int(width * height * 4))
font_texture: ^rl.Texture2D = transmute(^rl.Texture)io.Fonts.TexID
if font_texture != nil && font_texture.id != 0 {
rl.UnloadTexture(font_texture^)
mem.free(font_texture)
}
font_texture = cast(^rl.Texture2D)(mem.alloc(size_of(rl.Texture2D), align_of(rl.Texture2D)) or_return)
font_texture^ = rl.LoadTextureFromImage(image)
rl.UnloadImage(image)
io.Fonts.TexID = font_texture
return nil
}
shutdown :: proc() {
io: ^imgui.IO = imgui.GetIO()
font_texture: ^rl.Texture2D = transmute(^rl.Texture)io.Fonts.TexID
if font_texture != nil && font_texture.id != 0 {
rl.UnloadTexture(font_texture^)
mem.free(font_texture)
}
io.Fonts.TexID = nil
}
new_frame :: proc() {
io: ^imgui.IO = imgui.GetIO()
if rl.IsWindowFullscreen() {
monitor := rl.GetCurrentMonitor()
io.DisplaySize.x = f32(rl.GetMonitorWidth(monitor))
io.DisplaySize.y = f32(rl.GetMonitorHeight(monitor))
} else {
io.DisplaySize.x = f32(rl.GetScreenWidth())
io.DisplaySize.y = f32(rl.GetScreenHeight())
}
io.DisplayFramebufferScale = rl.GetWindowScaleDPI()
io.DeltaTime = rl.GetFrameTime()
if io.WantSetMousePos {
rl.SetMousePosition(c.int(io.MousePos.x), c.int(io.MousePos.y))
} else {
mouse_pos := rl.GetMousePosition()
imgui.IO_AddMousePosEvent(io, mouse_pos.x, mouse_pos.y)
}
set_mouse_event :: proc(io: ^imgui.IO, rl_mouse: rl.MouseButton, imgui_mouse: c.int) {
if rl.IsMouseButtonPressed(rl_mouse) {
imgui.IO_AddMouseButtonEvent(io, imgui_mouse, true)
} else if rl.IsMouseButtonReleased(rl_mouse) {
imgui.IO_AddMouseButtonEvent(io, imgui_mouse, false)
}
}
set_mouse_event(io, rl.MouseButton.LEFT, c.int(imgui.MouseButton.Left))
set_mouse_event(io, rl.MouseButton.RIGHT, c.int(imgui.MouseButton.Right))
set_mouse_event(io, rl.MouseButton.MIDDLE, c.int(imgui.MouseButton.Middle))
set_mouse_event(io, rl.MouseButton.FORWARD, c.int(imgui.MouseButton.Middle) + 1)
set_mouse_event(io, rl.MouseButton.BACK, c.int(imgui.MouseButton.Middle) + 2)
mouse_wheel := rl.GetMouseWheelMoveV()
imgui.IO_AddMouseWheelEvent(io, mouse_wheel.x, mouse_wheel.y)
if imgui.ConfigFlag.NoMouseCursorChange not_in io.ConfigFlags {
imgui_cursor: imgui.MouseCursor = imgui.GetMouseCursor()
if imgui_cursor != current_mouse_cursor || io.MouseDrawCursor {
current_mouse_cursor = imgui_cursor
if io.MouseDrawCursor || imgui_cursor == imgui.MouseCursor.None {
rl.HideCursor()
} else {
rl.ShowCursor()
if c.int(imgui_cursor) > -1 && imgui_cursor < imgui.MouseCursor.COUNT {
rl.SetMouseCursor(mouse_cursor_map[imgui_cursor])
} else {
rl.SetMouseCursor(rl.MouseCursor.DEFAULT)
}
}
}
}
}
render_draw_data :: proc(draw_data: ^imgui.DrawData) {
rl.rlDrawRenderBatchActive()
rl.rlDisableBackfaceCulling()
command_lists: []^imgui.DrawList = mem.slice_ptr(draw_data.CmdLists.Data, int(draw_data.CmdLists.Size))
for command_list in command_lists {
cmd_slice: []imgui.DrawCmd = mem.slice_ptr(command_list.CmdBuffer.Data, int(command_list.CmdBuffer.Size))
for i in 0..<command_list.CmdBuffer.Size {
cmd := cmd_slice[i]
enable_scissor(
cmd.ClipRect.x - draw_data.DisplayPos.x,
cmd.ClipRect.y,
cmd.ClipRect.z - (cmd.ClipRect.x - draw_data.DisplayPos.x),
cmd.ClipRect.w - (cmd.ClipRect.y - draw_data.DisplayPos.y)
)
if cmd.UserCallback != nil {
cmd.UserCallback(command_list, &cmd)
continue
}
render_triangles(cmd.ElemCount, cmd.IdxOffset, command_list.IdxBuffer, command_list.VtxBuffer, cmd.TextureId)
rl.rlDrawRenderBatchActive()
}
}
rl.rlSetTexture(0)
rl.rlDisableScissorTest()
rl.rlEnableBackfaceCulling()
}
@private
enable_scissor :: proc(x: f32, y: f32, width: f32, height: f32) {
rl.rlEnableScissorTest()
io: ^imgui.IO = imgui.GetIO()
rl.rlScissor(
i32(x * io.DisplayFramebufferScale.x),
i32((io.DisplaySize.y - math.floor(y + height)) * io.DisplayFramebufferScale.y),
i32(width * io.DisplayFramebufferScale.x),
i32(height * io.DisplayFramebufferScale.y)
)
}
@private
render_triangles :: proc(count: u32, index_start: u32, index_buffer: imgui.Vector_DrawIdx, vert_buffer: imgui.Vector_DrawVert, texture_ptr: imgui.TextureID) {
if count < 3 {
return
}
texture: ^rl.Texture = transmute(^rl.Texture)texture_ptr
texture_id: u32 = (texture == nil) ? 0 : texture.id
rl.rlBegin(rl.RL_TRIANGLES)
rl.rlSetTexture(texture_id)
index_slice: []imgui.DrawIdx = mem.slice_ptr(index_buffer.Data, int(index_buffer.Size))
vert_slice: []imgui.DrawVert = mem.slice_ptr(vert_buffer.Data, int(vert_buffer.Size))
for i: u32 = 0; i <= (count - 3); i += 3 {
if rl.rlCheckRenderBatchLimit(3) != 0 {
rl.rlBegin(rl.RL_TRIANGLES)
rl.rlSetTexture(texture_id)
}
index_a := index_slice[index_start + i]
index_b := index_slice[index_start + i + 1]
index_c := index_slice[index_start + i + 2]
vertex_a := vert_slice[index_a]
vertex_b := vert_slice[index_b]
vertex_c := vert_slice[index_c]
draw_triangle_vert :: proc(vert: imgui.DrawVert) {
c: rl.Color = transmute(rl.Color)vert.col
rl.rlColor4ub(c.r, c.g, c.b, c.a)
rl.rlTexCoord2f(vert.uv.x, vert.uv.y)
rl.rlVertex2f(vert.pos.x, vert.pos.y)
}
draw_triangle_vert(vertex_a)
draw_triangle_vert(vertex_b)
draw_triangle_vert(vertex_c)
}
rl.rlEnd()
}
is_control_down :: proc() -> bool { return rl.IsKeyDown(rl.KeyboardKey.RIGHT_CONTROL) || rl.IsKeyDown(rl.KeyboardKey.LEFT_CONTROL); }
is_shift_down :: proc() -> bool { return rl.IsKeyDown(rl.KeyboardKey.RIGHT_SHIFT) || rl.IsKeyDown(rl.KeyboardKey.LEFT_SHIFT); }
is_alt_down :: proc() -> bool { return rl.IsKeyDown(rl.KeyboardKey.RIGHT_ALT) || rl.IsKeyDown(rl.KeyboardKey.LEFT_ALT); }
is_super_down :: proc() -> bool { return rl.IsKeyDown(rl.KeyboardKey.RIGHT_SUPER) || rl.IsKeyDown(rl.KeyboardKey.LEFT_SUPER); }
process_events :: proc() -> bool {
io: ^imgui.IO = imgui.GetIO()
focused := rl.IsWindowFocused()
if (focused != last_frame_focused) {
imgui.IO_AddFocusEvent(io, focused)
}
last_frame_focused = focused
// Handle modifers for key evets so that shortcuts work
ctrl_down := is_control_down()
if ctrl_down != last_control_pressed {
imgui.IO_AddKeyEvent(io, imgui.Key.ImGuiMod_Ctrl, ctrl_down)
}
last_control_pressed = ctrl_down
shift_down := is_shift_down()
if shift_down != last_shift_pressed {
imgui.IO_AddKeyEvent(io, imgui.Key.ImGuiMod_Shift, shift_down)
}
last_shift_pressed = shift_down
alt_down := is_alt_down()
if alt_down != last_alt_pressed {
imgui.IO_AddKeyEvent(io, imgui.Key.ImGuiMod_Alt, alt_down)
}
last_alt_pressed = alt_down
super_down := is_super_down()
if super_down != last_super_pressed {
imgui.IO_AddKeyEvent(io, imgui.Key.ImGuiMod_Super, super_down)
}
last_super_pressed = super_down
// Get pressed keys, they are in event order
key_id: rl.KeyboardKey = rl.GetKeyPressed()
for key_id != rl.KeyboardKey.KEY_NULL {
key, ok := raylib_key_map[key_id]
if ok {
imgui.IO_AddKeyEvent(io, key, true)
}
key_id = rl.GetKeyPressed()
}
// Check for released keys
for key in raylib_key_map {
if rl.IsKeyReleased(key) {
imgui.IO_AddKeyEvent(io, raylib_key_map[key], false)
}
}
// Add text input in order
pressed: rune = rl.GetCharPressed()
for pressed != 0 {
imgui.IO_AddInputCharacter(io, u32(pressed))
pressed = rl.GetCharPressed()
}
return true
}
@private
setup_globals :: proc() {
last_frame_focused = rl.IsWindowFocused()
last_control_pressed = false
last_shift_pressed = false
last_alt_pressed = false
last_super_pressed = false
}
@private
setup_keymap :: proc() {
raylib_key_map[rl.KeyboardKey.APOSTROPHE] = imgui.Key.Apostrophe
raylib_key_map[rl.KeyboardKey.COMMA] = imgui.Key.Comma
raylib_key_map[rl.KeyboardKey.MINUS] = imgui.Key.Minus
raylib_key_map[rl.KeyboardKey.PERIOD] = imgui.Key.Period
raylib_key_map[rl.KeyboardKey.SLASH] = imgui.Key.Slash
raylib_key_map[rl.KeyboardKey.ZERO] = imgui.Key._0
raylib_key_map[rl.KeyboardKey.ONE] = imgui.Key._1
raylib_key_map[rl.KeyboardKey.TWO] = imgui.Key._2
raylib_key_map[rl.KeyboardKey.THREE] = imgui.Key._3
raylib_key_map[rl.KeyboardKey.FOUR] = imgui.Key._4
raylib_key_map[rl.KeyboardKey.FIVE] = imgui.Key._5
raylib_key_map[rl.KeyboardKey.SIX] = imgui.Key._6
raylib_key_map[rl.KeyboardKey.SEVEN] = imgui.Key._7
raylib_key_map[rl.KeyboardKey.EIGHT] = imgui.Key._8
raylib_key_map[rl.KeyboardKey.NINE] = imgui.Key._9
raylib_key_map[rl.KeyboardKey.SEMICOLON] = imgui.Key.Semicolon
raylib_key_map[rl.KeyboardKey.EQUAL] = imgui.Key.Equal
raylib_key_map[rl.KeyboardKey.A] = imgui.Key.A
raylib_key_map[rl.KeyboardKey.B] = imgui.Key.B
raylib_key_map[rl.KeyboardKey.C] = imgui.Key.C
raylib_key_map[rl.KeyboardKey.D] = imgui.Key.D
raylib_key_map[rl.KeyboardKey.E] = imgui.Key.E
raylib_key_map[rl.KeyboardKey.F] = imgui.Key.F
raylib_key_map[rl.KeyboardKey.G] = imgui.Key.G
raylib_key_map[rl.KeyboardKey.H] = imgui.Key.H
raylib_key_map[rl.KeyboardKey.I] = imgui.Key.I
raylib_key_map[rl.KeyboardKey.J] = imgui.Key.J
raylib_key_map[rl.KeyboardKey.K] = imgui.Key.K
raylib_key_map[rl.KeyboardKey.L] = imgui.Key.L
raylib_key_map[rl.KeyboardKey.M] = imgui.Key.M
raylib_key_map[rl.KeyboardKey.N] = imgui.Key.N
raylib_key_map[rl.KeyboardKey.O] = imgui.Key.O
raylib_key_map[rl.KeyboardKey.P] = imgui.Key.P
raylib_key_map[rl.KeyboardKey.Q] = imgui.Key.Q
raylib_key_map[rl.KeyboardKey.R] = imgui.Key.R
raylib_key_map[rl.KeyboardKey.S] = imgui.Key.S
raylib_key_map[rl.KeyboardKey.T] = imgui.Key.T
raylib_key_map[rl.KeyboardKey.U] = imgui.Key.U
raylib_key_map[rl.KeyboardKey.V] = imgui.Key.V
raylib_key_map[rl.KeyboardKey.W] = imgui.Key.W
raylib_key_map[rl.KeyboardKey.X] = imgui.Key.X
raylib_key_map[rl.KeyboardKey.Y] = imgui.Key.Y
raylib_key_map[rl.KeyboardKey.Z] = imgui.Key.Z
raylib_key_map[rl.KeyboardKey.SPACE] = imgui.Key.Space
raylib_key_map[rl.KeyboardKey.ESCAPE] = imgui.Key.Escape
raylib_key_map[rl.KeyboardKey.ENTER] = imgui.Key.Enter
raylib_key_map[rl.KeyboardKey.TAB] = imgui.Key.Tab
raylib_key_map[rl.KeyboardKey.BACKSPACE] = imgui.Key.Backspace
raylib_key_map[rl.KeyboardKey.INSERT] = imgui.Key.Insert
raylib_key_map[rl.KeyboardKey.DELETE] = imgui.Key.Delete
raylib_key_map[rl.KeyboardKey.RIGHT] = imgui.Key.RightArrow
raylib_key_map[rl.KeyboardKey.LEFT] = imgui.Key.LeftArrow
raylib_key_map[rl.KeyboardKey.DOWN] = imgui.Key.DownArrow
raylib_key_map[rl.KeyboardKey.UP] = imgui.Key.UpArrow
raylib_key_map[rl.KeyboardKey.PAGE_UP] = imgui.Key.PageUp
raylib_key_map[rl.KeyboardKey.PAGE_DOWN] = imgui.Key.PageDown
raylib_key_map[rl.KeyboardKey.HOME] = imgui.Key.Home
raylib_key_map[rl.KeyboardKey.END] = imgui.Key.End
raylib_key_map[rl.KeyboardKey.CAPS_LOCK] = imgui.Key.CapsLock
raylib_key_map[rl.KeyboardKey.SCROLL_LOCK] = imgui.Key.ScrollLock
raylib_key_map[rl.KeyboardKey.NUM_LOCK] = imgui.Key.NumLock
raylib_key_map[rl.KeyboardKey.PRINT_SCREEN] = imgui.Key.PrintScreen
raylib_key_map[rl.KeyboardKey.PAUSE] = imgui.Key.Pause
raylib_key_map[rl.KeyboardKey.F1] = imgui.Key.F1
raylib_key_map[rl.KeyboardKey.F2] = imgui.Key.F2
raylib_key_map[rl.KeyboardKey.F3] = imgui.Key.F3
raylib_key_map[rl.KeyboardKey.F4] = imgui.Key.F4
raylib_key_map[rl.KeyboardKey.F5] = imgui.Key.F5
raylib_key_map[rl.KeyboardKey.F6] = imgui.Key.F6
raylib_key_map[rl.KeyboardKey.F7] = imgui.Key.F7
raylib_key_map[rl.KeyboardKey.F8] = imgui.Key.F8
raylib_key_map[rl.KeyboardKey.F9] = imgui.Key.F9
raylib_key_map[rl.KeyboardKey.F10] = imgui.Key.F10
raylib_key_map[rl.KeyboardKey.F11] = imgui.Key.F11
raylib_key_map[rl.KeyboardKey.F12] = imgui.Key.F12
raylib_key_map[rl.KeyboardKey.LEFT_SHIFT] = imgui.Key.LeftShift
raylib_key_map[rl.KeyboardKey.LEFT_CONTROL] = imgui.Key.LeftCtrl
raylib_key_map[rl.KeyboardKey.LEFT_ALT] = imgui.Key.LeftAlt
raylib_key_map[rl.KeyboardKey.LEFT_SUPER] = imgui.Key.LeftSuper
raylib_key_map[rl.KeyboardKey.RIGHT_SHIFT] = imgui.Key.RightShift
raylib_key_map[rl.KeyboardKey.RIGHT_CONTROL] = imgui.Key.RightCtrl
raylib_key_map[rl.KeyboardKey.RIGHT_ALT] = imgui.Key.RightAlt
raylib_key_map[rl.KeyboardKey.RIGHT_SUPER] = imgui.Key.RightSuper
raylib_key_map[rl.KeyboardKey.KB_MENU] = imgui.Key.Menu
raylib_key_map[rl.KeyboardKey.LEFT_BRACKET] = imgui.Key.LeftBracket
raylib_key_map[rl.KeyboardKey.BACKSLASH] = imgui.Key.Backslash
raylib_key_map[rl.KeyboardKey.RIGHT_BRACKET] = imgui.Key.RightBracket
raylib_key_map[rl.KeyboardKey.GRAVE] = imgui.Key.GraveAccent
raylib_key_map[rl.KeyboardKey.KP_0] = imgui.Key.Keypad0
raylib_key_map[rl.KeyboardKey.KP_1] = imgui.Key.Keypad1
raylib_key_map[rl.KeyboardKey.KP_2] = imgui.Key.Keypad2
raylib_key_map[rl.KeyboardKey.KP_3] = imgui.Key.Keypad3
raylib_key_map[rl.KeyboardKey.KP_4] = imgui.Key.Keypad4
raylib_key_map[rl.KeyboardKey.KP_5] = imgui.Key.Keypad5
raylib_key_map[rl.KeyboardKey.KP_6] = imgui.Key.Keypad6
raylib_key_map[rl.KeyboardKey.KP_7] = imgui.Key.Keypad7
raylib_key_map[rl.KeyboardKey.KP_8] = imgui.Key.Keypad8
raylib_key_map[rl.KeyboardKey.KP_9] = imgui.Key.Keypad9
raylib_key_map[rl.KeyboardKey.KP_DECIMAL] = imgui.Key.KeypadDecimal
raylib_key_map[rl.KeyboardKey.KP_DIVIDE] = imgui.Key.KeypadDivide
raylib_key_map[rl.KeyboardKey.KP_MULTIPLY] = imgui.Key.KeypadMultiply
raylib_key_map[rl.KeyboardKey.KP_SUBTRACT] = imgui.Key.KeypadSubtract
raylib_key_map[rl.KeyboardKey.KP_ADD] = imgui.Key.KeypadAdd
raylib_key_map[rl.KeyboardKey.KP_ENTER] = imgui.Key.KeypadEnter
raylib_key_map[rl.KeyboardKey.KP_EQUAL] = imgui.Key.KeypadEqual
}
@private
setup_mouse_cursor :: proc() {
mouse_cursor_map[imgui.MouseCursor.Arrow] = rl.MouseCursor.ARROW;
mouse_cursor_map[imgui.MouseCursor.TextInput] = rl.MouseCursor.IBEAM;
mouse_cursor_map[imgui.MouseCursor.Hand] = rl.MouseCursor.POINTING_HAND;
mouse_cursor_map[imgui.MouseCursor.ResizeAll] = rl.MouseCursor.RESIZE_ALL;
mouse_cursor_map[imgui.MouseCursor.ResizeEW] = rl.MouseCursor.RESIZE_EW;
mouse_cursor_map[imgui.MouseCursor.ResizeNESW] = rl.MouseCursor.RESIZE_NESW;
mouse_cursor_map[imgui.MouseCursor.ResizeNS] = rl.MouseCursor.RESIZE_NS;
mouse_cursor_map[imgui.MouseCursor.ResizeNWSE] = rl.MouseCursor.RESIZE_NWSE;
mouse_cursor_map[imgui.MouseCursor.NotAllowed] = rl.MouseCursor.NOT_ALLOWED;
}
@private
setup_backend :: proc() {
io: ^imgui.IO = imgui.GetIO()
io.BackendPlatformName = "imgui_impl_raylib"
io.BackendFlags |= { imgui.BackendFlag.HasMouseCursors }
io.MousePos = { 0, 0 }
io.SetClipboardTextFn = set_clip_text_callback
io.GetClipboardTextFn = get_clip_text_callback
io.ClipboardUserData = nil
}
@private
set_clip_text_callback :: proc "c" (user_data: rawptr, text: cstring) {
rl.SetClipboardText(text)
}
@private
get_clip_text_callback :: proc "c" (user_data: rawptr) -> cstring {
return rl.GetClipboardText()
}
Submodule
+1
Submodule odin-imgui added at 0615247fab