Fixed input event buffer issues
Queue doesn't properly act as a ring buffer had to roll my own. I want to make a allocated ring buffer as well...
This commit is contained in:
parent
ce1d31f0d4
commit
55b80da8e5
@ -172,8 +172,8 @@ LRU_reload :: proc( cache : ^LRU_Cache, allocator : Allocator )
|
||||
|
||||
LRU_hash_key :: #force_inline proc( key : u64 ) -> ( hash : u64 ) {
|
||||
bytes := transmute( [8]byte ) key
|
||||
// hash = fnv64a( bytes[:] )
|
||||
hash = cast(u64) crc64( bytes[:] )
|
||||
hash = fnv64a( bytes[:] )
|
||||
// hash = cast(u64) crc64( bytes[:] )
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -754,7 +754,7 @@ reset_batch_codepoint_state :: proc( ctx : ^Context ) {
|
||||
shape_text_cached :: proc( ctx : ^Context, font : FontID, text_utf8 : string ) -> ^ShapedText
|
||||
{
|
||||
font := font
|
||||
hash := cast(u64) crc32( transmute([]u8) text_utf8 )
|
||||
hash := cast(u64) crc64( transmute([]u8) text_utf8 )
|
||||
// hash := label_hash( text_utf8 )
|
||||
|
||||
shape_cache := & ctx.shape_cache
|
||||
|
96
code/grime/.ring_buffer.odin
Normal file
96
code/grime/.ring_buffer.odin
Normal file
@ -0,0 +1,96 @@
|
||||
package grime
|
||||
|
||||
import "core:mem"
|
||||
|
||||
RingBuffer :: struct($T: typeid) {
|
||||
data: []T,
|
||||
head: int,
|
||||
tail: int,
|
||||
len: int,
|
||||
is_full: bool,
|
||||
}
|
||||
|
||||
init :: proc(rb: ^RingBuffer($T), capacity: int, allocator := context.allocator) -> mem.Allocator_Error {
|
||||
data, err := make([]T, capacity, allocator)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rb.data = data
|
||||
rb.head = 0
|
||||
rb.tail = 0
|
||||
rb.len = 0
|
||||
rb.is_full = false
|
||||
return nil
|
||||
}
|
||||
|
||||
destroy :: proc(rb: ^RingBuffer($T)) {
|
||||
delete(rb.data)
|
||||
rb^ = {}
|
||||
}
|
||||
|
||||
len :: proc(rb: RingBuffer($T)) -> int {
|
||||
return rb.len
|
||||
}
|
||||
|
||||
cap :: proc(rb: RingBuffer($T)) -> int {
|
||||
return len(rb.data)
|
||||
}
|
||||
|
||||
is_empty :: proc(rb: RingBuffer($T)) -> bool {
|
||||
return rb.len == 0
|
||||
}
|
||||
|
||||
is_full :: proc(rb: RingBuffer($T)) -> bool {
|
||||
return rb.is_full
|
||||
}
|
||||
|
||||
push_back :: proc(rb: ^RingBuffer($T), value: T) {
|
||||
if rb.is_full {
|
||||
rb.data[rb.head] = value
|
||||
rb.head = (rb.head + 1) % len(rb.data)
|
||||
rb.tail = rb.head
|
||||
} else {
|
||||
rb.data[rb.tail] = value
|
||||
rb.tail = (rb.tail + 1) % len(rb.data)
|
||||
rb.len += 1
|
||||
rb.is_full = rb.len == len(rb.data)
|
||||
}
|
||||
}
|
||||
|
||||
pop_front :: proc(rb: ^RingBuffer($T)) -> (T, bool) {
|
||||
if rb.len == 0 {
|
||||
return T{}, false
|
||||
}
|
||||
|
||||
value := rb.data[rb.head]
|
||||
rb.head = (rb.head + 1) % len(rb.data)
|
||||
rb.len -= 1
|
||||
rb.is_full = false
|
||||
return value, true
|
||||
}
|
||||
|
||||
get :: proc(rb: RingBuffer($T), index: int) -> (T, bool) {
|
||||
if index < 0 || index >= rb.len {
|
||||
return T{}, false
|
||||
}
|
||||
actual_index := (rb.head + index) % len(rb.data)
|
||||
return rb.data[actual_index], true
|
||||
}
|
||||
|
||||
RingBufferIterator :: struct($T: typeid) {
|
||||
rb: ^RingBuffer(T),
|
||||
current: int,
|
||||
}
|
||||
|
||||
iterator :: proc(rb: ^RingBuffer($T)) -> RingBufferIterator(T) {
|
||||
return RingBufferIterator(T){rb = rb, current = 0}
|
||||
}
|
||||
|
||||
next :: proc(it: ^RingBufferIterator($T)) -> (T, bool) {
|
||||
if it.current >= it.rb.len {
|
||||
return T{}, false
|
||||
}
|
||||
value, _ := get(it.rb^, it.current)
|
||||
it.current += 1
|
||||
return value, true
|
||||
}
|
@ -186,15 +186,15 @@ array_back :: proc( self : Array($Type) ) -> Type {
|
||||
return value
|
||||
}
|
||||
|
||||
// array_push_back :: proc( using self : Array( $ Type)) -> b32 {
|
||||
// if num == capacity {
|
||||
// return false
|
||||
// }
|
||||
array_push_back :: proc( using self : Array( $ Type)) -> b32 {
|
||||
if num == capacity {
|
||||
return false
|
||||
}
|
||||
|
||||
// data[ num ] = value
|
||||
// num += 1
|
||||
// return true
|
||||
// }
|
||||
data[ num ] = value
|
||||
num += 1
|
||||
return true
|
||||
}
|
||||
|
||||
array_clear :: proc "contextless" ( using self : Array( $ Type ), zero_data : b32 = false ) {
|
||||
if zero_data {
|
||||
|
@ -1 +0,0 @@
|
||||
package grime
|
@ -8,7 +8,7 @@ was I believe exclusively when I didn't set the base addresss of vmem
|
||||
OR when I was attempting to use Casey's brute force replay feature with memory.
|
||||
5-26-2024 Update:
|
||||
TODO(Ed): There is a Raw_Map structure defined in base:runtime/core.odin
|
||||
We can use the regulare dynamic
|
||||
We can use the regulare dynamic
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
|
||||
This implementation uses two ZPL-Based Arrays to hold entires and the actual hash table.
|
||||
|
@ -148,6 +148,7 @@ is_power_of_two :: proc {
|
||||
|
||||
iterator :: proc {
|
||||
iterator_queue,
|
||||
iterator_ringbuf_fixed,
|
||||
}
|
||||
|
||||
make :: proc {
|
||||
|
@ -1,7 +1,9 @@
|
||||
package grime
|
||||
|
||||
import "base:runtime"
|
||||
import "core:container/queue"
|
||||
|
||||
// Note(Ed): Fixed size queue DOES NOT act as a RING BUFFER
|
||||
make_queue :: proc( $QueueType : typeid/Queue($Type), capacity := queue.DEFAULT_CAPACITY, allocator := context.allocator, fixed_cap : bool = false ) -> (result : Queue(Type), error : AllocatorError)
|
||||
{
|
||||
allocator := allocator
|
||||
@ -19,7 +21,9 @@ make_queue :: proc( $QueueType : typeid/Queue($Type), capacity := queue.DEFAULT_
|
||||
|
||||
push_back_slice_queue :: proc( self : ^$QueueType / Queue($Type), slice : []Type ) -> ( error : AllocatorError )
|
||||
{
|
||||
if len(slice) == 0 do return
|
||||
queue.push_back_elems( self, ..slice )
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
168
code/grime/ring_buffer_fixed.odin
Normal file
168
code/grime/ring_buffer_fixed.odin
Normal file
@ -0,0 +1,168 @@
|
||||
package grime
|
||||
|
||||
RingBufferFixed :: struct( $Type: typeid, $Size: u32 ) {
|
||||
head : u32,
|
||||
tail : u32,
|
||||
num : u32,
|
||||
items : [Size] Type,
|
||||
}
|
||||
|
||||
ringbuf_fixed_clear :: #force_inline proc "contextless" ( using buffer : ^RingBufferFixed( $Type, $Size)) {
|
||||
head = 0
|
||||
tail = 0
|
||||
num = 0
|
||||
}
|
||||
|
||||
ringbuf_fixed_is_full :: #force_inline proc "contextless" ( using buffer : RingBufferFixed( $Type, $Size)) -> bool {
|
||||
return num == Size
|
||||
}
|
||||
|
||||
ringbuf_fixed_is_empty :: #force_inline proc "contextless" ( using buffer : RingBufferFixed( $Type, $Size)) -> bool {
|
||||
return num == 0
|
||||
}
|
||||
|
||||
ringbuf_fixed_peek_front_ref :: #force_inline proc "contextless" ( using buffer : ^RingBufferFixed( $Type, $Size)) -> ^Type {
|
||||
assert(num > 0, "Attempted to peek an empty ring buffer")
|
||||
return & items[ head ]
|
||||
}
|
||||
|
||||
ringbuf_fixed_peek_front :: #force_inline proc "contextless" ( using buffer : RingBufferFixed( $Type, $Size)) -> Type {
|
||||
assert(num > 0, "Attempted to peek an empty ring buffer")
|
||||
return items[ head ]
|
||||
}
|
||||
|
||||
ringbuf_fixed_peak_back :: #force_inline proc ( using buffer : RingBufferFixed( $Type, $Size)) -> Type {
|
||||
assert(num > 0, "Attempted to peek an empty ring buffer")
|
||||
|
||||
buf_size := u32(Size)
|
||||
index := (tail - 1 + buf_size) % buf_size
|
||||
return items[ index ]
|
||||
}
|
||||
|
||||
ringbuf_fixed_push :: #force_inline proc(using buffer: ^RingBufferFixed($Type, $Size), value: Type) {
|
||||
if num == Size do head = (head + 1) % Size
|
||||
else do num += 1
|
||||
|
||||
items[ tail ] = value
|
||||
tail = (tail + 1) % Size
|
||||
}
|
||||
|
||||
ringbuf_fixed_push_slice :: proc(buffer: ^RingBufferFixed($Type, $Size), slice: []Type) -> u32
|
||||
{
|
||||
size := u32(Size)
|
||||
slice_size := u32(len(slice))
|
||||
|
||||
// assert( slice_size <= size, "Attempting to append a slice that is larger than the ring buffer!" )
|
||||
if slice_size == 0 do return 0
|
||||
|
||||
items_to_add := min( slice_size, size)
|
||||
items_added : u32 = 0
|
||||
|
||||
if items_to_add > Size - buffer.num
|
||||
{
|
||||
// Some or all existing items will be overwritten
|
||||
overwrite_count := items_to_add - (Size - buffer.num)
|
||||
buffer.head = (buffer.head + overwrite_count) % size
|
||||
buffer.num = size
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer.num += items_to_add
|
||||
}
|
||||
|
||||
if items_to_add <= size
|
||||
{
|
||||
// Case 1: Slice fits entirely or partially in the buffer
|
||||
space_to_end := size - buffer.tail
|
||||
first_chunk := min(items_to_add, space_to_end)
|
||||
|
||||
// First copy: from tail to end of buffer
|
||||
copy( buffer.items[ buffer.tail: ] , slice[ :first_chunk ] )
|
||||
|
||||
if first_chunk < items_to_add {
|
||||
// Second copy: wrap around to start of buffer
|
||||
second_chunk := items_to_add - first_chunk
|
||||
copy( buffer.items[:], slice[ first_chunk : items_to_add ] )
|
||||
}
|
||||
|
||||
buffer.tail = (buffer.tail + items_to_add) % Size
|
||||
items_added = items_to_add
|
||||
}
|
||||
else
|
||||
{
|
||||
// Case 2: Slice is larger than buffer, only keep last Size elements
|
||||
to_add := slice[ slice_size - size: ]
|
||||
|
||||
// First copy: from start of buffer to end
|
||||
first_chunk := min(Size, u32(len(to_add)))
|
||||
copy( buffer.items[:], to_add[ :first_chunk ] )
|
||||
|
||||
if first_chunk < Size
|
||||
{
|
||||
// Second copy: wrap around
|
||||
copy( buffer.items[ first_chunk: ], to_add[ first_chunk: ] )
|
||||
}
|
||||
|
||||
buffer.head = 0
|
||||
buffer.tail = 0
|
||||
buffer.num = Size
|
||||
items_added = Size
|
||||
}
|
||||
|
||||
return items_added
|
||||
}
|
||||
|
||||
ringbuf_fixed_pop :: #force_inline proc "contextless" ( using buffer : ^RingBufferFixed( $Type, $Size )) -> Type {
|
||||
assert(num > 0, "Attempted to pop an empty ring buffer")
|
||||
value := items[ head ]
|
||||
head = ( head + 1 ) % Size
|
||||
num -= 1
|
||||
return value
|
||||
}
|
||||
|
||||
RingBufferFixedIterator :: struct( $Type : typeid) {
|
||||
items : []Type,
|
||||
head : u32,
|
||||
tail : u32,
|
||||
index : u32,
|
||||
remaining : u32,
|
||||
}
|
||||
|
||||
iterator_ringbuf_fixed :: proc(buffer: ^RingBufferFixed($Type, $Size)) -> RingBufferFixedIterator(Type)
|
||||
{
|
||||
iter := RingBufferFixedIterator(Type){
|
||||
items = buffer.items[:],
|
||||
head = buffer.head,
|
||||
tail = buffer.tail,
|
||||
remaining = buffer.num,
|
||||
}
|
||||
|
||||
buff_size := u32(Size)
|
||||
|
||||
if buffer.num > 0 {
|
||||
// Start from the last pushed item (one before tail)
|
||||
iter.index = (buffer.tail - 1 + buff_size) % buff_size
|
||||
} else {
|
||||
iter.index = buffer.tail // This will not be used as remaining is 0
|
||||
}
|
||||
|
||||
return iter
|
||||
}
|
||||
|
||||
next_ringbuf_fixed_iterator :: proc(iter : ^RingBufferFixedIterator( $Type)) -> ^Type
|
||||
{
|
||||
using iter
|
||||
if remaining == 0 {
|
||||
return nil // If there are no items left to iterate over
|
||||
}
|
||||
|
||||
buf_size := cast(u32) len(items)
|
||||
|
||||
result := &items[index]
|
||||
|
||||
// Decrement index and wrap around if necessary
|
||||
index = (index - 1 + buf_size) % buf_size
|
||||
|
||||
remaining -= 1
|
||||
return result
|
||||
}
|
@ -12,7 +12,7 @@ stack_clear :: #force_inline proc ( using stack : ^StackFixed( $Type, $Size)) {
|
||||
}
|
||||
|
||||
stack_push :: #force_inline proc( using stack : ^ StackFixed( $ Type, $ Size ), value : Type ) {
|
||||
assert( idx < len( items ), "Attempted to push on a full stack" )
|
||||
assert( idx < u32(len( items )), "Attempted to push on a full stack" )
|
||||
|
||||
items[ idx ] = value
|
||||
idx += 1
|
||||
|
@ -1,3 +0,0 @@
|
||||
package sectr
|
||||
|
||||
|
@ -112,14 +112,14 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem
|
||||
using input_events
|
||||
|
||||
error : AllocatorError
|
||||
events, error = make( Queue(InputEvent), 4 * Kilo, persistent_allocator(), fixed_cap = true )
|
||||
ensure(error == AllocatorError.None, "Failed to allocate input.events array")
|
||||
// events, error = make( RingBuffer(InputEvent), 4 * Kilo, persistent_allocator(), fixed_cap = true )
|
||||
// ensure(error == AllocatorError.None, "Failed to allocate input.events array")
|
||||
|
||||
key_events, error = make( Queue(InputKeyEvent), Kilo, persistent_allocator(), fixed_cap = true )
|
||||
ensure(error == AllocatorError.None, "Failed to allocate key_events array")
|
||||
// key_events, error = make( RingBuffer(InputKeyEvent), Kilo, persistent_allocator(), fixed_cap = true )
|
||||
// ensure(error == AllocatorError.None, "Failed to allocate key_events array")
|
||||
|
||||
mouse_events, error = make( Queue(InputMouseEvent), 2 * Kilo, persistent_allocator(), fixed_cap = true )
|
||||
ensure(error == AllocatorError.None, "Failed to allocate mouse_events array")
|
||||
// mouse_events, error = make( RingBuffer(InputMouseEvent), 3 * Kilo, persistent_allocator(), fixed_cap = true )
|
||||
// ensure(error == AllocatorError.None, "Failed to allocate mouse_events array")
|
||||
|
||||
codes_pressed, error = make( Array(rune), Kilo, persistent_slab_allocator() )
|
||||
ensure(error == AllocatorError.None, "Failed to allocate codes_pressed array")
|
||||
@ -422,9 +422,9 @@ hot_reload :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_
|
||||
// input_reload()
|
||||
{
|
||||
using input_events
|
||||
reload( & events, runtime.nil_allocator())
|
||||
reload( & key_events, runtime.nil_allocator())
|
||||
reload( & mouse_events, runtime.nil_allocator())
|
||||
// reload( & events, runtime.nil_allocator())
|
||||
// reload( & key_events, runtime.nil_allocator())
|
||||
// reload( & mouse_events, runtime.nil_allocator())
|
||||
codes_pressed.backing = persistent_slab_allocator()
|
||||
staged_input_events.backing = persistent_slab_allocator()
|
||||
}
|
||||
@ -532,7 +532,7 @@ tick_frametime :: #force_inline proc( client_tick : ^time.Tick, host_delta_time_
|
||||
|
||||
// profile("Client tick timing processing")
|
||||
|
||||
config.engine_refresh_hz = uint(monitor_refresh_hz)
|
||||
// config.engine_refresh_hz = uint(monitor_refresh_hz)
|
||||
// config.engine_refresh_hz = 10
|
||||
frametime_target_ms = 1.0 / f64(config.engine_refresh_hz) * S_To_MS
|
||||
sub_ms_granularity_required := frametime_target_ms <= Frametime_High_Perf_Threshold_MS
|
||||
|
@ -73,7 +73,8 @@ sokol_app_log_callback :: proc "c" (
|
||||
message_or_null: cstring,
|
||||
line_nr: u32,
|
||||
filename_or_null: cstring,
|
||||
user_data: rawptr) {
|
||||
user_data: rawptr)
|
||||
{
|
||||
context = get_state().sokol_context
|
||||
|
||||
odin_level : LogLevel
|
||||
|
@ -80,13 +80,13 @@ render :: proc()
|
||||
profile(#procedure)
|
||||
state := get_state(); using state // TODO(Ed): Prefer passing static context to through the callstack
|
||||
|
||||
clear_pass := gfx.Pass { action = render_data.pass_actions.bg_clear_black, swapchain = sokol_glue.swapchain() }
|
||||
clear_pass.action.colors[0].clear_value = transmute(gfx.Color) normalize_rgba8( config.color_theme.bg )
|
||||
|
||||
// TODO(Ed): Eventually we want to only update when state is dirty/user has done an action
|
||||
gfx.begin_pass(gfx.Pass { action = render_data.pass_actions.bg_clear_black, swapchain = sokol_glue.swapchain() })
|
||||
gfx.begin_pass(clear_pass)
|
||||
gfx.end_pass();
|
||||
|
||||
// render_mode_3d()
|
||||
|
||||
render_mode_2d_workspace()
|
||||
render_mode_screenspace()
|
||||
|
||||
@ -133,25 +133,35 @@ render_mode_screenspace :: proc()
|
||||
cam := & project.workspace.cam
|
||||
win_extent := state.app_window.extent
|
||||
|
||||
ve.configure_snap( & font_provider_data.ve_font_cache, u32(state.app_window.extent.x * 2.0), u32(state.app_window.extent.y * 2.0) )
|
||||
|
||||
render_screen_ui()
|
||||
|
||||
screen_extent := app_window.extent
|
||||
screen_size := app_window.extent * 2
|
||||
screen_ratio := screen_size.x * ( 1.0 / screen_size.y )
|
||||
|
||||
gp.begin( i32(screen_size.x), i32(screen_size.y) )
|
||||
gp.viewport(0, 0, i32(screen_size.x), i32(screen_size.y))
|
||||
gp.project( -screen_extent.x, screen_extent.x, screen_extent.y, -screen_extent.y )
|
||||
ve.configure_snap( & font_provider_data.ve_font_cache, u32(state.app_window.extent.x * 2.0), u32(state.app_window.extent.y * 2.0) )
|
||||
|
||||
gp_set_color(Color_Screen_Center_Dot)
|
||||
draw_filled_circle(0, 0, 2, 24)
|
||||
render_screen_ui()
|
||||
|
||||
gfx.begin_pass( gfx.Pass { action = render_data.pass_actions.empty_action, swapchain = sokol_glue.swapchain() })
|
||||
gp.flush()
|
||||
gp.end()
|
||||
gfx.end_pass()
|
||||
Render_Reference_Dots:
|
||||
{
|
||||
gp.begin( i32(screen_size.x), i32(screen_size.y) )
|
||||
gp.viewport(0, 0, i32(screen_size.x), i32(screen_size.y))
|
||||
gp.project( -screen_extent.x, screen_extent.x, screen_extent.y, -screen_extent.y )
|
||||
|
||||
gp_set_color(Color_Screen_Center_Dot)
|
||||
draw_filled_circle(0, 0, 2, 24)
|
||||
|
||||
Mouse_Position:
|
||||
{
|
||||
mouse_pos := input.mouse.pos
|
||||
gp_set_color({ 180, 180, 180, 20})
|
||||
draw_filled_circle( mouse_pos.x, mouse_pos.y, 4, 24 )
|
||||
}
|
||||
|
||||
gfx.begin_pass( gfx.Pass { action = render_data.pass_actions.empty_action, swapchain = sokol_glue.swapchain() })
|
||||
gp.flush()
|
||||
gp.end()
|
||||
gfx.end_pass()
|
||||
}
|
||||
|
||||
|
||||
debug_draw_text :: proc( content : string, pos : Vec2, size : f32, color := Color_White, font : FontID = Font_Default )
|
||||
@ -183,8 +193,8 @@ render_mode_screenspace :: proc()
|
||||
cam := & project.workspace.cam
|
||||
screen_corners := screen_get_corners()
|
||||
|
||||
position := screen_corners.top_right
|
||||
position.x -= app_window.extent.x * 0.5
|
||||
position := screen_corners.top_left
|
||||
position.x = 0
|
||||
position.y -= debug.draw_debug_text_y
|
||||
|
||||
content := str_fmt_buffer( draw_text_scratch[:], format, ..args )
|
||||
@ -201,18 +211,33 @@ render_mode_screenspace :: proc()
|
||||
fps_msg_pos := screen_get_corners().top_right - { fps_msg_width, 0 } - { 5, 5 }
|
||||
debug_draw_text( fps_msg, fps_msg_pos, 38.0, color = Color_Red )
|
||||
|
||||
// debug_text( "Screen Width : %v", rl.GetScreenWidth () )
|
||||
// debug_text( "Screen Height: %v", rl.GetScreenHeight() )
|
||||
// debug_text( "frametime_target_ms : %f ms", frametime_target_ms )
|
||||
debug_text( "Screen Width : %v", screen_size.x )
|
||||
debug_text( "Screen Height: %v", screen_size.y )
|
||||
debug_text( "frametime_target_ms : %f ms", frametime_target_ms )
|
||||
debug_text( "frametime : %0.3f ms", frametime_delta32() )
|
||||
// debug_text( "frametime_last_elapsed_ms : %f ms", frametime_elapsed_ms )
|
||||
debug_text( "frametime_last_elapsed_ms : %f ms", frametime_elapsed_ms )
|
||||
if replay.mode == ReplayMode.Record {
|
||||
debug_text( "Recording Input")
|
||||
}
|
||||
if replay.mode == ReplayMode.Playback {
|
||||
debug_text( "Replaying Input")
|
||||
}
|
||||
// debug_text("Zoom Target: %v", project.workspace.zoom_target)
|
||||
debug_text("Zoom Target: %v", project.workspace.zoom_target)
|
||||
|
||||
if true
|
||||
{
|
||||
using input_events
|
||||
|
||||
id := 0
|
||||
iter_obj := iterator( & mouse_events ); iter := & iter_obj
|
||||
for event := next( iter ); event != nil; event = next( iter )
|
||||
{
|
||||
if id >= 4 do break
|
||||
id += 1
|
||||
|
||||
debug_text("Mouse Event: %v", event )
|
||||
}
|
||||
}
|
||||
|
||||
if debug.mouse_vis {
|
||||
debug_text("Mouse scroll: %v", input.mouse.scroll )
|
||||
|
@ -1,60 +0,0 @@
|
||||
/*
|
||||
The default arena allocator Odin provides does fragmented resizes even for the last most allocated block getting resized.
|
||||
This is an alternative to alleviates that.
|
||||
|
||||
TODO(Ed): Implement? Maybe we should trash this I' haven't seen a need to step away from using odin's
|
||||
*/
|
||||
package sectr
|
||||
|
||||
import "core:mem"
|
||||
|
||||
// Initialize a sub-section of our virtual memory as a sub-arena
|
||||
sub_arena_init :: proc( address : ^byte, size : int ) -> ( ^ Arena) {
|
||||
Arena :: mem.Arena
|
||||
|
||||
arena_size :: size_of( Arena)
|
||||
sub_arena := cast( ^ Arena ) address
|
||||
mem_slice := slice_ptr( ptr_offset( address, arena_size), size )
|
||||
arena_init( sub_arena, mem_slice )
|
||||
return sub_arena
|
||||
}
|
||||
|
||||
ArenaFixedHeader :: struct {
|
||||
data : []byte,
|
||||
offset : uint,
|
||||
peak_used : uint,
|
||||
}
|
||||
|
||||
ArenaFixed :: struct {
|
||||
using header : ^ArenaFixedHeader,
|
||||
}
|
||||
|
||||
arena_fixed_init :: proc( backing : []byte ) -> (arena : ArenaFixed) {
|
||||
header_size := size_of(ArenaFixedHeader)
|
||||
|
||||
verify(len(backing) >= (header_size + Kilobyte), "Attempted to init an arena with less than kilobyte of memory...")
|
||||
|
||||
arena.header = cast(^ArenaFixedHeader) raw_data(backing)
|
||||
using arena.header
|
||||
data_ptr := cast([^]byte) (cast( [^]ArenaFixedHeader) arena.header)[ 1:]
|
||||
data = slice_ptr( data_ptr, len(backing) - header_size )
|
||||
offset = 0
|
||||
peak_used = 0
|
||||
return
|
||||
}
|
||||
|
||||
arena_fixed_allocator_proc :: proc(
|
||||
allocator_data : rawptr,
|
||||
mode : AllocatorMode,
|
||||
size : int,
|
||||
alignment : int,
|
||||
old_memory : rawptr,
|
||||
old_size : int,
|
||||
location := #caller_location
|
||||
) -> ([]byte, AllocatorError)
|
||||
{
|
||||
|
||||
|
||||
return nil, .Out_Of_Memory
|
||||
}
|
||||
|
@ -30,8 +30,8 @@ import "base:runtime"
|
||||
|
||||
import c "core:c/libc"
|
||||
|
||||
import "core:container/queue"
|
||||
Queue :: queue.Queue
|
||||
// import "core:container/queue"
|
||||
// Queue :: queue.Queue
|
||||
|
||||
// import "core:dynlib"
|
||||
|
||||
@ -188,12 +188,26 @@ import "codebase:grime"
|
||||
hmap_zpl_reload :: grime.hmap_zpl_reload
|
||||
hmap_zpl_set :: grime.hmap_zpl_set
|
||||
|
||||
make_queue :: grime.make_queue
|
||||
// make_queue :: grime.make_queue
|
||||
|
||||
next_queue_iterator :: grime.next_queue_iterator
|
||||
// next_queue_iterator :: grime.next_queue_iterator
|
||||
|
||||
Pool :: grime.Pool
|
||||
|
||||
RingBufferFixed :: grime.RingBufferFixed
|
||||
RingBufferFixedIterator :: grime.RingBufferFixedIterator
|
||||
|
||||
ringbuf_fixed_clear :: grime.ringbuf_fixed_clear
|
||||
ringbuf_fixed_is_full :: grime.ringbuf_fixed_is_full
|
||||
ringbuf_fixed_is_empty :: grime.ringbuf_fixed_is_empty
|
||||
ringbuf_fixed_peak_back :: grime.ringbuf_fixed_peak_back
|
||||
ringbuf_fixed_push :: grime.ringbuf_fixed_push
|
||||
ringbuf_fixed_push_slice :: grime.ringbuf_fixed_push_slice
|
||||
ringbuf_fixed_pop :: grime.ringbuf_fixed_pop
|
||||
|
||||
iterator_ringbuf_fixed :: grime.iterator_ringbuf_fixed
|
||||
next_ringbuf_fixed_iterator :: grime.next_ringbuf_fixed_iterator
|
||||
|
||||
Slab :: grime.Slab
|
||||
SlabPolicy :: grime.SlabPolicy
|
||||
SlabSizeClass :: grime.SlabSizeClass
|
||||
@ -368,14 +382,15 @@ is_power_of_two :: proc {
|
||||
}
|
||||
|
||||
iterator :: proc {
|
||||
grime.iterator_queue,
|
||||
// grime.iterator_queue,
|
||||
grime.iterator_ringbuf_fixed,
|
||||
}
|
||||
|
||||
make :: proc {
|
||||
array_init,
|
||||
hmap_chained_init,
|
||||
hmap_zpl_init,
|
||||
make_queue,
|
||||
// make_queue,
|
||||
|
||||
// Usual
|
||||
make_slice,
|
||||
@ -396,16 +411,17 @@ mov_avg_exp :: proc {
|
||||
}
|
||||
|
||||
next :: proc {
|
||||
next_queue_iterator,
|
||||
// next_queue_iterator,
|
||||
next_ringbuf_fixed_iterator,
|
||||
}
|
||||
|
||||
peek_back :: proc {
|
||||
queue.peek_back,
|
||||
ringbuf_fixed_peak_back,
|
||||
}
|
||||
|
||||
peek_front :: proc {
|
||||
queue.peek_front,
|
||||
}
|
||||
// peek_front :: proc {
|
||||
// queue.peek_front,
|
||||
// }
|
||||
|
||||
pixels_to_cm :: proc {
|
||||
f32_pixels_to_cm,
|
||||
@ -444,8 +460,11 @@ pressed :: proc {
|
||||
}
|
||||
|
||||
push :: proc {
|
||||
queue.push_back,
|
||||
grime.push_back_slice_queue,
|
||||
ringbuf_fixed_push,
|
||||
ringbuf_fixed_push_slice,
|
||||
|
||||
// queue.push_back,
|
||||
// grime.push_back_slice_queue,
|
||||
|
||||
stack_push,
|
||||
stack_allocator_push,
|
||||
@ -476,10 +495,6 @@ reload :: proc {
|
||||
grime.reload_map,
|
||||
}
|
||||
|
||||
space_left :: proc {
|
||||
queue.space,
|
||||
}
|
||||
|
||||
scope :: proc {
|
||||
ui_layout_scope_via_layout,
|
||||
ui_layout_scope_via_combo,
|
||||
|
@ -53,9 +53,9 @@ InputMouseEvent :: struct {
|
||||
}
|
||||
|
||||
InputEvents :: struct {
|
||||
events : Queue(InputEvent),
|
||||
key_events : Queue(InputKeyEvent),
|
||||
mouse_events : Queue(InputMouseEvent),
|
||||
events : RingBufferFixed(InputEvent, 640),
|
||||
key_events : RingBufferFixed(InputKeyEvent, 128),
|
||||
mouse_events : RingBufferFixed(InputMouseEvent, 512),
|
||||
|
||||
codes_pressed : Array(rune),
|
||||
}
|
||||
@ -138,6 +138,8 @@ pull_staged_input_events :: proc( input : ^InputState, input_events : ^InputEve
|
||||
scroll = event.mouse.scroll,
|
||||
modifiers = event.modifiers,
|
||||
})
|
||||
// logf("Detected scroll: %v", event.mouse.scroll)
|
||||
|
||||
case .Mouse_Move:
|
||||
push( & mouse_events, InputMouseEvent {
|
||||
frame_id = event.frame_id,
|
||||
@ -200,8 +202,8 @@ poll_input_events :: proc( input, prev_input : ^InputState, input_events : Input
|
||||
@static prev_frame : u64 = 0
|
||||
|
||||
last_frame : u64 = 0
|
||||
if events.len > 0 {
|
||||
last_frame = peek_back( & events).frame_id
|
||||
if events.num > 0 {
|
||||
last_frame = peek_back( events).frame_id
|
||||
}
|
||||
|
||||
// No new events, don't update
|
||||
@ -209,18 +211,19 @@ poll_input_events :: proc( input, prev_input : ^InputState, input_events : Input
|
||||
|
||||
Iterate_Key_Events:
|
||||
{
|
||||
iter_obj := iterator( key_events ); iter := & iter_obj
|
||||
iter_obj := iterator( & key_events ); iter := & iter_obj
|
||||
for event := next( iter ); event != nil; event = next( iter )
|
||||
{
|
||||
// logf("last_frame (iter): %v", last_frame)
|
||||
// logf("frame (iter): %v", event.frame_id )
|
||||
if last_frame > event.frame_id {
|
||||
break
|
||||
}
|
||||
// logf("last_frame (iter): %v", last_frame)
|
||||
// logf("frame (iter): %v", event.frame_id )
|
||||
|
||||
key := & input.keyboard.keys[event.key]
|
||||
prev_key := prev_input.keyboard.keys[event.key]
|
||||
|
||||
// logf("key event: %v", event)
|
||||
|
||||
first_transition := key.half_transitions == 0
|
||||
|
||||
#partial switch event.type {
|
||||
@ -237,7 +240,7 @@ poll_input_events :: proc( input, prev_input : ^InputState, input_events : Input
|
||||
|
||||
Iterate_Mouse_Events:
|
||||
{
|
||||
iter_obj := iterator( mouse_events ); iter := & iter_obj
|
||||
iter_obj := iterator( & mouse_events ); iter := & iter_obj
|
||||
for event := next( iter ); event != nil; event = next( iter )
|
||||
{
|
||||
if last_frame > event.frame_id {
|
||||
@ -252,6 +255,8 @@ poll_input_events :: proc( input, prev_input : ^InputState, input_events : Input
|
||||
btn.ended_down = ended_down
|
||||
}
|
||||
|
||||
// logf("mouse event: %v", event)
|
||||
|
||||
#partial switch event.type {
|
||||
case .Mouse_Pressed:
|
||||
btn := & input.mouse.btns[event.btn]
|
||||
@ -264,7 +269,7 @@ poll_input_events :: proc( input, prev_input : ^InputState, input_events : Input
|
||||
process_digital_btn( btn, prev_btn, false )
|
||||
|
||||
case .Mouse_Scroll:
|
||||
input.mouse.scroll += event.scroll.x
|
||||
input.mouse.scroll += event.scroll
|
||||
|
||||
case .Mouse_Move:
|
||||
case .Mouse_Enter:
|
||||
|
Loading…
Reference in New Issue
Block a user