diff --git a/code/grime/queue.odin b/code/grime/queue.odin index 6cd18eb..737dde3 100644 --- a/code/grime/queue.odin +++ b/code/grime/queue.odin @@ -19,24 +19,29 @@ make_queue :: proc( $QueueType : typeid/Queue($Type), capacity := queue.DEFAULT_ push_back_slice_queue :: proc( self : ^$QueueType / Queue($Type), slice : []Type ) -> ( error : AllocatorError ) { - num := cast(uint) len(slice) - - if uint( space_left( self^ )) < num { - error = queue._grow( self, self.len + num ) - if error != .None do return - } - - size := uint(len(self.data)) - insert_from := (self.offset + self.len) % size - insert_to := num - - if insert_from + insert_to > size { - insert_to = size - insert_from - } - - copy( self.data[ insert_from : ], slice[ : insert_to ]) - copy( self.data[ : insert_from ], slice[ insert_to : ]) + queue.push_back_elems( self, ..slice ) return + + // num := cast(uint) len(slice) + + // if uint( space_left( self^ )) < num { + // error = queue._grow( self, self.len + num ) + // if error != .None do return + // } + + // size := uint(len(self.data)) + // insert_from := (self.offset + self.len) % size + // insert_to := num + + // if insert_from + insert_to > size { + // insert_to = size - insert_from + // } + + // copy( self.data[ insert_from : ], slice[ : insert_to ]) + // copy( self.data[ : insert_from ], slice[ insert_to : ]) + + // self.len += num + // return } QueueIterator :: struct( $Type : typeid ) { @@ -60,8 +65,10 @@ iterator_queue :: proc( queue : $QueueType / Queue($Type) ) -> QueueIterator(Typ next_queue_iterator :: proc( iter : ^QueueIterator($Type) ) -> ^Type { using iter - front_id := (length + offset ) % len(data) - elem_id := (length + offset - index) % len(data) + data_size := cast(uint) len(data) + + front_id := (length + offset ) % data_size + elem_id := (length + offset - index -1 ) % data_size if elem_id == front_id do return nil elem := & data[ elem_id ] diff --git a/code/sectr/colors.odin b/code/sectr/colors.odin index 07a0907..a45953a 100644 --- a/code/sectr/colors.odin +++ b/code/sectr/colors.odin @@ -4,11 +4,13 @@ RGBA8 :: struct { r, g, b, a : u8 } RGBAN :: [4]f32 normalize_rgba8 :: #force_inline proc( color : RGBA8 ) -> RGBAN { + quotient : f32 = 1.0 / 255 + result := RGBAN { - 1.0 / f32(color.r), - 1.0 / f32(color.g), - 1.0 / f32(color.b), - 1.0 / f32(color.a), + f32(color.r) * quotient, + f32(color.g) * quotient, + f32(color.b) * quotient, + f32(color.a) * quotient, } return result } diff --git a/code/sectr/engine/client_api.odin b/code/sectr/engine/client_api.odin index c529df2..dd71511 100644 --- a/code/sectr/engine/client_api.odin +++ b/code/sectr/engine/client_api.odin @@ -112,13 +112,13 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem using input_events error : AllocatorError - events, error = make( Queue(InputEvent), 4 * Kilo, persistent_slab_allocator() ) + events, error = make( Queue(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_slab_allocator() ) + key_events, error = make( Queue(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_slab_allocator() ) + mouse_events, error = make( Queue(InputMouseEvent), 2 * 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() ) @@ -132,8 +132,8 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem // TODO(Ed): Make this actually load from an ini { using config - resolution_width = 1600 - resolution_height = 900 + resolution_width = 1000 + resolution_height = 600 refresh_rate = 0 cam_min_zoom = 0.10 @@ -418,10 +418,10 @@ hot_reload :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_ // input_reload() { using input_events - reload( & events, persistent_slab_allocator()) - reload( & key_events, persistent_slab_allocator()) - reload( & mouse_events, persistent_slab_allocator()) - codes_pressed.backing = persistent_slab_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() } diff --git a/code/sectr/engine/client_api_sokol_callbacks.odin b/code/sectr/engine/client_api_sokol_callbacks.odin index 3334bb9..d522cb8 100644 --- a/code/sectr/engine/client_api_sokol_callbacks.odin +++ b/code/sectr/engine/client_api_sokol_callbacks.odin @@ -119,55 +119,74 @@ sokol_app_event_callback :: proc "c" (sokol_event : ^sokol_app.Event) logf("%v", sokol_event) case .KEY_DOWN: + if sokol_event.key_repeat do return + type = .Key_Pressed key = to_key_from_sokol( sokol_event.key_code ) modifiers = to_modifiers_code_from_sokol( sokol_event.modifiers ) sokol_app.consume_event() + append_staged_input_events( event ) + // logf("Key pressed(sokol): %v", key) + // logf("frame (sokol): %v", frame_id ) case .KEY_UP: + if sokol_event.key_repeat do return + type = .Key_Released key = to_key_from_sokol( sokol_event.key_code ) modifiers = to_modifiers_code_from_sokol( sokol_event.modifiers ) sokol_app.consume_event() + append_staged_input_events( event ) + // logf("Key released(sokol): %v", key) + // logf("frame (sokol): %v", frame_id ) case .CHAR: + if sokol_event.key_repeat do return + type = .Unicode codepoint = transmute(rune) sokol_event.char_code modifiers = to_modifiers_code_from_sokol( sokol_event.modifiers ) sokol_app.consume_event() + append_staged_input_events( event ) case .MOUSE_DOWN: type = .Mouse_Pressed mouse.btn = to_mouse_btn_from_sokol( sokol_event.mouse_button ) modifiers = to_modifiers_code_from_sokol( sokol_event.modifiers ) sokol_app.consume_event() + append_staged_input_events( event ) case .MOUSE_UP: type = .Mouse_Released mouse.btn = to_mouse_btn_from_sokol( sokol_event.mouse_button ) modifiers = to_modifiers_code_from_sokol( sokol_event.modifiers ) sokol_app.consume_event() + append_staged_input_events( event ) case .MOUSE_SCROLL: type = .Mouse_Scroll mouse.scroll = { sokol_event.scroll_x, sokol_event.scroll_y } modifiers = to_modifiers_code_from_sokol( sokol_event.modifiers ) sokol_app.consume_event() + append_staged_input_events( event ) case .MOUSE_MOVE: type = .Mouse_Move modifiers = to_modifiers_code_from_sokol( sokol_event.modifiers ) sokol_app.consume_event() + append_staged_input_events( event ) case .MOUSE_ENTER: type = .Mouse_Enter modifiers = to_modifiers_code_from_sokol( sokol_event.modifiers ) sokol_app.consume_event() + append_staged_input_events( event ) case .MOUSE_LEAVE: type = .Mouse_Leave modifiers = to_modifiers_code_from_sokol( sokol_event.modifiers ) sokol_app.consume_event() + append_staged_input_events( event ) // TODO(Ed): Add support case .TOUCHES_BEGAN: @@ -211,8 +230,6 @@ sokol_app_event_callback :: proc "c" (sokol_event : ^sokol_app.Event) monitor_refresh_hz := sokol_app.refresh_rate() sokol_app.consume_event() } - - append_staged_input_events( event ) } #endregion("Sokol App") diff --git a/code/sectr/engine/render.odin b/code/sectr/engine/render.odin index 7e20c28..7cc2d76 100644 --- a/code/sectr/engine/render.odin +++ b/code/sectr/engine/render.odin @@ -113,7 +113,7 @@ render_mode_screenspace :: proc() screen_corners := screen_get_corners() position := screen_corners.top_right - position.x -= app_window.extent.x + position.x -= app_window.extent.x * 0.5 position.y -= debug.draw_debug_text_y content := str_fmt_buffer( draw_text_scratch[:], format, ..args ) @@ -122,37 +122,36 @@ render_mode_screenspace :: proc() debug.draw_debug_text_y += 14 } - // "Draw text" using immediate mode api - { - font_provider := & state.font_provider_data - using font_provider - - @static index : i32 - text_test_str := str_fmt("frametime : %0.6f\nframetime(sokol): %0.2f\nframe id : %d\nsokol_frame: %d", frametime_delta_ms, sokol_app.frame_delta() * S_To_MS, frame, sokol_app.frame_count() ) - // log(text_test_str) - // text_test_str := str_fmt("HELLO VE FONT CACHE!") - // text_test_str := str_fmt("C") - - // font_provider := & state.font_provider_data - // fdef := hmap_chained_get( font_cache, default_font.key ) - - width := app_window.extent.x * 2 - height := app_window.extent.y * 2 - - ve.set_colour( & ve_font_cache, { 1.0, 1.0, 1.0, 1.0 } ) - ve.configure_snap( & ve_font_cache, u32(state.app_window.extent.x * 2.0), u32(state.app_window.extent.y * 2.0) ) - - ve.draw_text( & ve_font_cache, font_provider_resolve_draw_id(default_font), text_test_str, {0.0, 0.975}, Vec2{1 / width, 1 / height} ) - } - debug.debug_text_vis = true if debug.debug_text_vis { - fps_msg := str_fmt( "FPS: %f", fps_avg) - fps_msg_width := cast(f32) u32(measure_text_size( fps_msg, default_font, 12.0, 0.0 ).x) + 0.5 + fps_msg := str_fmt( "FPS: %0.2f", fps_avg) + fps_msg_width := measure_text_size( fps_msg, default_font, 12.0, 0.0 ).x fps_msg_pos := screen_get_corners().top_right - { fps_msg_width, 0 } - { 5, 5 } - debug_draw_text( fps_msg, fps_msg_pos, 12.0, color = Color_White ) - // debug_draw_text( fps_msg, {}, 12.0, color = Color_White ) + 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( "frametime : %f ms", frametime_delta_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) + + if debug.mouse_vis { + debug_text("Mouse scroll: %v", input.mouse.scroll ) + debug_text("Mouse Delta : %v", input.mouse.delta ) + debug_text("Mouse Position (Render) : %v", input.mouse.raw_pos ) + debug_text("Mouse Position (Screen) : %v", input.mouse.pos ) + debug_text("Mouse Position (Workspace View): %v", screen_to_ws_view_pos(input.mouse.pos) ) + // rl.DrawCircleV( input.mouse.raw_pos, 10, Color_White_A125 ) + // rl.DrawCircleV( screen_to_render_pos(input.mouse.pos), 2, Color_BG ) + } render_text_layer() } @@ -300,7 +299,7 @@ render_text_layer :: proc() fs_target_uniform := Ve_Draw_Text_Fs_Params { down_sample = 0, - colour = {1.0, 1.0, 1.0, 1}, + colour = draw_call.colour, } if draw_call.pass == .Target_Uncached { diff --git a/code/sectr/engine/update.odin b/code/sectr/engine/update.odin index 06f3fe6..0ad4248 100644 --- a/code/sectr/engine/update.odin +++ b/code/sectr/engine/update.odin @@ -78,12 +78,17 @@ update :: proc( delta_time : f64 ) -> b32 project.workspace.cam.view = transmute(Vec2) window.extent } - state.input, state.input_prev = swap( state.input, state.input_prev ) + // state.input, state.input_prev = swap( state.input, state.input_prev ) + { + temp := state.input_prev + state.input_prev = state.input + state.input = temp + } pull_staged_input_events( state.input, & state.input_events, state.staged_input_events ) poll_input_events( state.input, state.input_prev, state.input_events ) debug_actions : DebugActions = {} - // poll_debug_actions( & debug_actions, state.input ) + poll_debug_actions( & debug_actions, state.input ) // Saving & Loading { diff --git a/code/sectr/font/provider_VEFontCache.odin b/code/sectr/font/provider_VEFontCache.odin index 6405dd1..dbee9ea 100644 --- a/code/sectr/font/provider_VEFontCache.odin +++ b/code/sectr/font/provider_VEFontCache.odin @@ -552,6 +552,7 @@ font_load :: proc(path_file : string, for font_size : i32 = Font_Size_Interval; font_size <= Font_Largest_Px_Size; font_size += Font_Size_Interval { + logf("Loading at size %v", font_size) id := (font_size / Font_Size_Interval) + (font_size % Font_Size_Interval) ve_id := & def.size_table[id - 1] ve_id^ = ve.load_font( & provider_data.ve_font_cache, desired_id, font_data, 14.0 ) @@ -567,12 +568,12 @@ font_provider_resolve_draw_id :: proc( id : FontID, size := Font_Use_Default_Siz { state := get_state(); using state - even_size := math.round(size * (1.0 / f32(Font_Size_Interval))) * f32(Font_Size_Interval) - size := clamp( i32( even_size), 4, Font_Largest_Px_Size ) - def := hmap_chained_get( font_provider_data.font_cache, id.key ) - size = size if size != i32(Font_Use_Default_Size) else def.default_size + def := hmap_chained_get( font_provider_data.font_cache, id.key ) + size := size == 0.0 ? f32(def.default_size) : size + even_size := math.round(size * (1.0 / f32(Font_Size_Interval))) * f32(Font_Size_Interval) + resolved_size := clamp( i32( even_size), 2, Font_Largest_Px_Size ) - id := (size / Font_Size_Interval) + (size % Font_Size_Interval) + id := (resolved_size / Font_Size_Interval) + (resolved_size % Font_Size_Interval) ve_id := def.size_table[ id - 1 ] width := app_window.extent.x * 2 diff --git a/code/sectr/grime/mappings.odin b/code/sectr/grime/mappings.odin index fe37289..8aa86d3 100644 --- a/code/sectr/grime/mappings.odin +++ b/code/sectr/grime/mappings.odin @@ -399,6 +399,10 @@ next :: proc { next_queue_iterator, } +peek_back :: proc { + queue.peek_back, +} + peek_front :: proc { queue.peek_front, } diff --git a/code/sectr/input/events.odin b/code/sectr/input/events.odin index 4a8fc87..6643a81 100644 --- a/code/sectr/input/events.odin +++ b/code/sectr/input/events.odin @@ -88,6 +88,9 @@ pull_staged_input_events :: proc( input : ^InputState, input_events : ^InputEve key = event.key, modifiers = event.modifiers }) + // logf("Key pressed(event pushed): %v", event.key) + // logf("last key event frame: %v", peek_back(& key_events).frame_id) + // logf("last event frame: %v", peek_back(& events).frame_id) case .Key_Released: push( & key_events, InputKeyEvent { @@ -96,6 +99,9 @@ pull_staged_input_events :: proc( input : ^InputState, input_events : ^InputEve key = event.key, modifiers = event.modifiers }) + // logf("Key released(event rpushed): %v", event.key) + // logf("last key event frame: %v", peek_back(& key_events).frame_id) + // logf("last event frame: %v", peek_back(& events).frame_id) case .Unicode: append( & codes_pressed, event.codepoint ) @@ -175,22 +181,39 @@ poll_input_events :: proc( input, prev_input : ^InputState, input_events : Input input.keyboard = {} input.mouse = {} + // logf("m's value is: %v (prev)", prev_input.keyboard.keys[KeyCode.M] ) + + for prev_key, id in prev_input.keyboard.keys { + input.keyboard.keys[id].ended_down = prev_key.ended_down + } + + for prev_btn, id in prev_input.mouse.btns { + input.mouse.btns[id].ended_down = prev_btn.ended_down + } + input_events := input_events using input_events - @static prev_frame : u64 = u64_max + @static prev_frame : u64 = 0 - last_frame := peek_front( & events).frame_id + last_frame : u64 = 0 + if events.len > 0 { + last_frame = peek_back( & events).frame_id + } // No new events, don't update - if prev_frame != 0 && last_frame == prev_frame do return + if last_frame == prev_frame do return Iterate_Key_Events: { iter_obj := iterator( key_events ); iter := & iter_obj for event := next( iter ); event != nil; event = next( iter ) { - if last_frame == event.frame_id do return + 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] @@ -206,9 +229,6 @@ poll_input_events :: proc( input, prev_input : ^InputState, input_events : Input key.half_transitions += 1 key.ended_down = false } - - frame_transition := first_transition && prev_key.ended_down != key.ended_down ? i32(1) : i32(0) - key.half_transitions += frame_transition } } @@ -217,7 +237,9 @@ poll_input_events :: proc( input, prev_input : ^InputState, input_events : Input iter_obj := iterator( mouse_events ); iter := & iter_obj for event := next( iter ); event != nil; event = next( iter ) { - if last_frame == event.frame_id do return + if last_frame > event.frame_id { + break + } process_digital_btn :: proc( btn : ^DigitalBtn, prev_btn : DigitalBtn, ended_down : b32 ) { @@ -225,9 +247,6 @@ poll_input_events :: proc( input, prev_input : ^InputState, input_events : Input btn.half_transitions += 1 btn.ended_down = ended_down - - frame_transition := first_transition && prev_btn.ended_down != btn.ended_down ? i32(1) : i32(0) - btn.half_transitions += frame_transition } #partial switch event.type { diff --git a/code/sectr/input/input.odin b/code/sectr/input/input.odin index 605e6eb..35058e1 100644 --- a/code/sectr/input/input.odin +++ b/code/sectr/input/input.odin @@ -39,26 +39,30 @@ MouseBtn :: enum u32 { KeyboardState :: struct #raw_union { keys : [KeyCode.count] DigitalBtn, using individual : struct { - - ignored : DigitalBtn, + null : DigitalBtn, // 0x00 + ignored : DigitalBtn, // 0x01 // GFLW / Sokol menu, world_1, world_2 : DigitalBtn, + // 0x02 - 0x04 __0x05_0x07_Unassigned__ : [ 3 * size_of( DigitalBtn)] u8, tab, backspace : DigitalBtn, + // 0x08 - 0x09 right, left, up, down : DigitalBtn, + // 0x0A - 0x0D - enter : DigitalBtn, + enter : DigitalBtn, // 0x0E __0x0F_Unassigned__ : [ 1 * size_of( DigitalBtn)] u8, caps_lock, scroll_lock, num_lock : DigitalBtn, + // 0x10 - 0x12 left_alt, left_shift, @@ -66,6 +70,7 @@ KeyboardState :: struct #raw_union { right_alt, right_shift, right_control : DigitalBtn, + // 0x13 - 0x18 print_screen, pause, @@ -75,6 +80,7 @@ KeyboardState :: struct #raw_union { page_up, page_down, space : DigitalBtn, + // 0x19 - 0x20 exlamation, quote_dbl, @@ -91,17 +97,18 @@ KeyboardState :: struct #raw_union { minus, period, slash : DigitalBtn, + // 0x21 - 0x2F - nrow_0, - nrow_1, - nrow_2, - nrow_3, - nrow_4, - nrow_5, - nrow_6, - nrow_7, - nrow_8, - nrow_9, + nrow_0, // 0x30 + nrow_1, // 0x31 + nrow_2, // 0x32 + nrow_3, // 0x33 + nrow_4, // 0x34 + nrow_5, // 0x35 + nrow_6, // 0x36 + nrow_7, // 0x37 + nrow_8, // 0x38 + nrow_9, // 0x39 __0x3A_Unassigned__ : [ 1 * size_of(DigitalBtn)] u8, diff --git a/docs/input sys design.pur b/docs/input sys design.pur new file mode 100644 index 0000000..a5498b5 Binary files /dev/null and b/docs/input sys design.pur differ