Base input pass updated for sokol possibly done (untested)
Still need to figure out input event consumption, I don't want to do it with the event ring. I would like to setup input binding layers and then have the push/pop input contextes with a set of bindings. If the bindings are detected it should "consume" that binding from further use for the buffered time period. This will be really important with how heavily model this app will be.I
This commit is contained in:
		
							
								
								
									
										18
									
								
								code/grime/hot_reload.odin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								code/grime/hot_reload.odin
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| package grime | ||||
|  | ||||
| import "base:runtime" | ||||
|  | ||||
| reload_array :: proc( self : [dynamic]$Type, allocator : Allocator ) { | ||||
| 	raw          := transmute(runtime.Raw_Dynamic_Array) self | ||||
| 	raw.allocator = allocator | ||||
| } | ||||
|  | ||||
| reload_queue :: proc( self : Queue($Type), allocator : Allocator ) { | ||||
| 	raw_array          := transmute(runtime.Raw_Dynamic_Array) self.data | ||||
| 	raw_array.allocator = allocator | ||||
| } | ||||
|  | ||||
| reload_map :: proc( self : map [$KeyType] $EntryType, allocator : Allocator ) { | ||||
| 	raw          := transmute(runtime.Raw_Map) self | ||||
| 	raw.allocator = allocator | ||||
| } | ||||
| @@ -29,6 +29,9 @@ import "base:runtime" | ||||
| import c "core:c/libc" | ||||
| 	mem_fmt :: c.memset | ||||
|  | ||||
| import "core:container/queue" | ||||
| 	Queue :: queue.Queue | ||||
|  | ||||
| import "core:dynlib" | ||||
|  | ||||
| import "core:hash" | ||||
| @@ -143,11 +146,17 @@ is_power_of_two :: proc { | ||||
| 	is_power_of_two_uintptr, | ||||
| } | ||||
|  | ||||
| iterator :: proc { | ||||
| 	iterator_queue, | ||||
| } | ||||
|  | ||||
| make :: proc { | ||||
| 	array_init, | ||||
| 	hmap_chained_init, | ||||
| 	hmap_zpl_init, | ||||
|  | ||||
| 	make_queue, | ||||
|  | ||||
| 	// Usual | ||||
| 	make_slice, | ||||
| 	make_dynamic_array, | ||||
| @@ -157,10 +166,24 @@ make :: proc { | ||||
| 	make_multi_pointer, | ||||
| } | ||||
|  | ||||
| next :: proc { | ||||
| 	next_queue_iterator, | ||||
| } | ||||
|  | ||||
| push :: proc { | ||||
| 	stack_push, | ||||
| } | ||||
|  | ||||
| space_left :: proc { | ||||
| 	queue.space, | ||||
| } | ||||
|  | ||||
| reload :: proc { | ||||
| 	reload_array, | ||||
| 	reload_queue, | ||||
| 	reload_map, | ||||
| } | ||||
|  | ||||
| to_runes :: proc { | ||||
| 	string_to_runes, | ||||
| } | ||||
|   | ||||
							
								
								
									
										61
									
								
								code/grime/queue.odin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								code/grime/queue.odin
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,61 @@ | ||||
| package grime | ||||
|  | ||||
| import "core:container/queue" | ||||
|  | ||||
| make_queue :: proc( $QueueType : typeid/Queue($Type), capacity := queue.DEFAULT_CAPACITY, allocator := context.allocator ) -> (result : Queue(Type), error : AllocatorError) | ||||
| { | ||||
| 	queue.init( & result, capacity, allocator ) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| 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 : ]) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| QueueIterator :: struct( $Type : typeid ) { | ||||
| 	data   : []Type, | ||||
| 	length : uint, | ||||
| 	offset : uint, | ||||
| 	index  : uint, | ||||
| } | ||||
|  | ||||
| iterator_queue :: proc( queue : $QueueType / Queue($Type) ) -> QueueIterator(Type) | ||||
| { | ||||
| 	iter := QueueIterator(Type) { | ||||
| 		data   = queue.data[:], | ||||
| 		length = queue.len, | ||||
| 		offset = queue.offset, | ||||
| 		index  = 0, | ||||
| 	} | ||||
| 	return iter | ||||
| } | ||||
|  | ||||
| next_queue_iterator :: proc( iter : ^QueueIterator($Type) ) -> ^Type | ||||
| { | ||||
| 	using iter | ||||
| 	front_id := (length + offset        ) % len(data) | ||||
| 	elem_id  := (length + offset - index) % len(data) | ||||
| 	if elem_id == front_id do return nil | ||||
|  | ||||
| 	elem  := & data[ elem_id ] | ||||
| 	index += 1 | ||||
| 	return elem | ||||
| } | ||||
| @@ -181,7 +181,7 @@ load_sectr_api :: proc( version_id : i32 ) -> (loaded_module : sectr.ModuleAPI) | ||||
|  | ||||
| 	startup     := cast( type_of( sectr.startup        )) os_lib_get_proc( lib, "startup" ) | ||||
| 	shutdown    := cast( type_of( sectr.sectr_shutdown )) os_lib_get_proc( lib, "sectr_shutdown" ) | ||||
| 	reload      := cast( type_of( sectr.reload         )) os_lib_get_proc( lib, "reload" ) | ||||
| 	reload      := cast( type_of( sectr.hot_reload     )) os_lib_get_proc( lib, "hot_reload" ) | ||||
| 	tick        := cast( type_of( sectr.tick           )) os_lib_get_proc( lib, "tick" ) | ||||
| 	clean_frame := cast( type_of( sectr.clean_frame    )) os_lib_get_proc( lib, "clean_frame" ) | ||||
|  | ||||
|   | ||||
| @@ -252,8 +252,8 @@ ui_screen_settings_menu :: proc( captures : rawptr = nil ) -> ( should_raise : b | ||||
| 					} | ||||
|  | ||||
| 					if input_box.active { | ||||
| 						array_append( & value_str, input.codes_pressed ) | ||||
| 						array_clear( input.codes_pressed ) | ||||
| 						append( & value_str, input_events.codes_pressed ) | ||||
| 						clear( input_events.codes_pressed ) | ||||
| 					} | ||||
| 					else if input_box.was_active | ||||
| 					{ | ||||
| @@ -264,8 +264,8 @@ ui_screen_settings_menu :: proc( captures : rawptr = nil ) -> ( should_raise : b | ||||
| 					} | ||||
| 					else | ||||
| 					{ | ||||
| 						array_clear( value_str) | ||||
| 						array_append( & value_str, to_runes(str_fmt("%v", config.engine_refresh_hz))) | ||||
| 						clear( value_str) | ||||
| 						append( & value_str, to_runes(str_fmt("%v", config.engine_refresh_hz))) | ||||
| 					} | ||||
| 					ui_parent(input_box) | ||||
|  | ||||
|   | ||||
| @@ -210,6 +210,8 @@ State :: struct { | ||||
| 	input_prev : ^InputState, | ||||
| 	input      : ^InputState, | ||||
|  | ||||
| 	input_events : InputEvents, | ||||
|  | ||||
| 	// Note(Ed): Do not modify directly, use its interface in app/event.odin | ||||
| 	staged_input_events : Array(InputEvent), | ||||
| 	// TODO(Ed): Add a multi-threaded guard for accessing or mutating staged_input_events. | ||||
|   | ||||
| @@ -30,7 +30,7 @@ ModuleAPI :: struct { | ||||
|  | ||||
| 	startup     : type_of( startup ), | ||||
| 	shutdown    : type_of( sectr_shutdown ), | ||||
| 	reload      : type_of( reload ), | ||||
| 	reload      : type_of( hot_reload ), | ||||
| 	tick        : type_of( tick ), | ||||
| 	clean_frame : type_of( clean_frame ), | ||||
| } | ||||
| @@ -107,24 +107,23 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem | ||||
| 	{ | ||||
| 		input      = & input_data[1] | ||||
| 		input_prev = & input_data[0] | ||||
| 		for & input in input_data { | ||||
| 			using input | ||||
| 			error : AllocatorError | ||||
|  | ||||
| 			events, error  = make( Array(InputEvent), Kilo, persistent_slab_allocator() ) | ||||
| 			ensure(error == AllocatorError.None, "Failed to allocate input.events array") | ||||
| 		using input_events | ||||
|  | ||||
| 			key_events, error = make( Array(InputKeyEvent), Kilo, persistent_slab_allocator() ) | ||||
| 			ensure(error == AllocatorError.None, "Failed to allocate key_events array") | ||||
| 		error : AllocatorError | ||||
| 		events, error  = make( Queue(InputEvent), 4 * Kilo, persistent_allocator() ) | ||||
| 		ensure(error == AllocatorError.None, "Failed to allocate input.events array") | ||||
|  | ||||
| 			mouse_events, error = make( Array(InputMouseEvent), Kilo, persistent_slab_allocator() ) | ||||
| 			ensure(error == AllocatorError.None, "Failed to allocate mouse_events array") | ||||
| 		key_events, error = make( Queue(InputKeyEvent), Kilo, persistent_allocator() ) | ||||
| 		ensure(error == AllocatorError.None, "Failed to allocate key_events array") | ||||
|  | ||||
| 			codes_pressed, error = make( Array(rune), Kilo, persistent_slab_allocator() ) | ||||
| 			ensure(error == AllocatorError.None, "Failed to allocate codes_pressed array") | ||||
| 		} | ||||
| 		mouse_events, error = make( Queue(InputMouseEvent), 2 * Kilo, persistent_allocator() ) | ||||
| 		ensure(error == AllocatorError.None, "Failed to allocate mouse_events array") | ||||
|  | ||||
| 		input_staged_events, error  := make( Array(InputEvent), Kilo, persistent_slab_allocator() ) | ||||
| 		codes_pressed, error = make( Array(rune), Kilo, persistent_allocator() ) | ||||
| 		ensure(error == AllocatorError.None, "Failed to allocate codes_pressed array") | ||||
|  | ||||
| 		staged_input_events, error = make( Array(InputEvent), 8 * Kilo, persistent_allocator() ) | ||||
| 		ensure(error == AllocatorError.None, "Failed to allocate input_staged_events array") | ||||
| 	} | ||||
|  | ||||
| @@ -396,7 +395,7 @@ sectr_shutdown :: proc() | ||||
| } | ||||
|  | ||||
| @export | ||||
| reload :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem, files_buffer_mem : ^VArena, host_logger : ^ Logger ) | ||||
| hot_reload :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem, files_buffer_mem : ^VArena, host_logger : ^ Logger ) | ||||
| { | ||||
| 	spall.SCOPED_EVENT( & prof.ctx, & prof.buffer, #procedure ) | ||||
| 	set_profiler_module_context( prof ) | ||||
| @@ -484,7 +483,6 @@ tick :: proc( host_delta_time_ms : f64, host_delta_ns : Duration ) -> b32 | ||||
| 	return ! should_close | ||||
| } | ||||
|  | ||||
|  | ||||
| // Lifted out of tick so that sokol_app_frame_callback can do it as well. | ||||
| tick_work_frame :: #force_inline proc( host_delta_time_ms : f64 ) -> b32 | ||||
| { | ||||
| @@ -542,6 +540,7 @@ tick_work_frame :: #force_inline proc( host_delta_time_ms : f64 ) -> b32 | ||||
| // Lifted out of tick so that sokol_app_frame_callback can do it as well. | ||||
| tick_frametime :: #force_inline proc( client_tick : ^time.Tick, host_delta_time_ms : f64, host_delta_ns : Duration ) | ||||
| { | ||||
| 	profile(#procedure) | ||||
| 	state := get_state(); using state | ||||
| 	context.allocator      = frame_slab_allocator() | ||||
| 	context.temp_allocator = transient_allocator() | ||||
| @@ -598,7 +597,7 @@ tick_frametime :: #force_inline proc( client_tick : ^time.Tick, host_delta_time_ | ||||
| @export | ||||
| clean_frame :: proc() | ||||
| { | ||||
| 	// profile( #procedure) | ||||
| 	profile( #procedure) | ||||
| 	state := get_state(); using state | ||||
| 	context.logger = to_odin_logger( & Memory_App.logger ) | ||||
|  | ||||
|   | ||||
| @@ -15,10 +15,12 @@ sokol_app_init_callback :: proc "c" () { | ||||
|  | ||||
| // This is being filled in but we're directly controlling the lifetime of sokol_app's execution. | ||||
| // So this will only get called during window pan or resize events (on Win32 at least) | ||||
| sokol_app_frame_callback :: proc "c" () { | ||||
| sokol_app_frame_callback :: proc "c" () | ||||
| { | ||||
| 	context = get_state().sokol_context | ||||
| 	state  := get_state() | ||||
| 	profile(#procedure) | ||||
|  | ||||
| 	state  := get_state() | ||||
| 	should_close : b32 | ||||
|  | ||||
| 	sokol_width  := sokol_app.widthf() | ||||
| @@ -38,10 +40,12 @@ sokol_app_frame_callback :: proc "c" () { | ||||
| 	sokol_delta_ms := sokol_app.frame_delta() | ||||
| 	sokol_delta_ns := transmute(Duration) sokol_delta_ms * MS_To_NS | ||||
|  | ||||
| 	profile_begin("Client Tick") | ||||
| 	client_tick := time.tick_now() | ||||
| 	should_close |= tick_work_frame( sokol_delta_ms ) | ||||
| 	tick_frametime( & client_tick, sokol_delta_ms, sokol_delta_ns ) | ||||
| 	profile_end() | ||||
|  | ||||
| 	tick_frametime( & client_tick, sokol_delta_ms, sokol_delta_ns ) | ||||
| 	window.resized = false | ||||
| } | ||||
|  | ||||
| @@ -118,43 +122,52 @@ sokol_app_event_callback :: proc "c" (sokol_event : ^sokol_app.Event) | ||||
| 			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() | ||||
|  | ||||
| 		case .KEY_UP: | ||||
| 			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() | ||||
|  | ||||
| 		case .CHAR: | ||||
| 			type      = .Unicode | ||||
| 			codepoint = transmute(rune) sokol_event.char_code | ||||
| 			modifiers = to_modifiers_code_from_sokol( sokol_event.modifiers ) | ||||
| 			sokol_app.consume_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() | ||||
|  | ||||
| 		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() | ||||
|  | ||||
| 		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() | ||||
|  | ||||
| 		case .MOUSE_MOVE: | ||||
| 			type      = .Mouse_Move | ||||
| 			modifiers = to_modifiers_code_from_sokol( sokol_event.modifiers ) | ||||
| 			sokol_app.consume_event() | ||||
|  | ||||
| 		case .MOUSE_ENTER: | ||||
| 			type      = .Mouse_Enter | ||||
| 			modifiers = to_modifiers_code_from_sokol( sokol_event.modifiers ) | ||||
| 			sokol_app.consume_event() | ||||
|  | ||||
| 		case .MOUSE_LEAVE: | ||||
| 			type      = .Mouse_Leave | ||||
| 			modifiers = to_modifiers_code_from_sokol( sokol_event.modifiers ) | ||||
| 			sokol_app.consume_event() | ||||
|  | ||||
| 		// TODO(Ed): Add support | ||||
| 		case .TOUCHES_BEGAN: | ||||
| @@ -163,30 +176,43 @@ sokol_app_event_callback :: proc "c" (sokol_event : ^sokol_app.Event) | ||||
| 		case .TOUCHES_CANCELLED: | ||||
|  | ||||
| 		case .RESIZED: | ||||
| 			sokol_app.consume_event() | ||||
|  | ||||
| 		case .ICONIFIED: | ||||
| 			sokol_app.consume_event() | ||||
|  | ||||
| 		case .RESTORED: | ||||
| 			sokol_app.consume_event() | ||||
|  | ||||
| 		case .FOCUSED: | ||||
| 			sokol_app.consume_event() | ||||
|  | ||||
| 		case .UNFOCUSED: | ||||
| 			sokol_app.consume_event() | ||||
|  | ||||
| 		case .SUSPENDED: | ||||
| 			sokol_app.consume_event() | ||||
|  | ||||
| 		case .RESUMED: | ||||
| 			sokol_app.consume_event() | ||||
|  | ||||
| 		case .QUIT_REQUESTED: | ||||
| 			sokol_app.consume_event() | ||||
|  | ||||
| 		case .CLIPBOARD_PASTED: | ||||
| 			sokol_app.consume_event() | ||||
|  | ||||
| 		case .FILES_DROPPED: | ||||
| 			sokol_app.consume_event() | ||||
|  | ||||
| 		case .DISPLAY_CHANGED: | ||||
| 			logf("sokol_app - event: Display changed") | ||||
| 			logf("refresh rate: %v", sokol_app.refresh_rate()) | ||||
| 			monitor_refresh_hz := sokol_app.refresh_rate() | ||||
| 			sokol_app.consume_event() | ||||
| 	} | ||||
|  | ||||
| 	append_staged_input_events( event ) | ||||
| } | ||||
|  | ||||
| #endregion("Sokol App") | ||||
|   | ||||
| @@ -79,7 +79,8 @@ update :: proc( delta_time : f64 ) -> b32 | ||||
| 	} | ||||
|  | ||||
| 	state.input, state.input_prev = swap( state.input, state.input_prev ) | ||||
| 	pull_staged_input_events(  state.input, & state.staged_input_events ) | ||||
| 	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 ) | ||||
| @@ -165,7 +166,7 @@ update :: proc( delta_time : f64 ) -> b32 | ||||
| 		switch config.cam_zoom_mode | ||||
| 		{ | ||||
| 			case .Smooth: | ||||
| 				zoom_delta            := input.mouse.vertical_wheel * config.cam_zoom_sensitivity_smooth | ||||
| 				zoom_delta            := input.mouse.scroll.y * config.cam_zoom_sensitivity_smooth | ||||
| 				workspace.zoom_target *= 1 + zoom_delta * f32(delta_time) | ||||
| 				workspace.zoom_target  = clamp(workspace.zoom_target, config.cam_min_zoom, config.cam_max_zoom) | ||||
|  | ||||
| @@ -174,7 +175,7 @@ update :: proc( delta_time : f64 ) -> b32 | ||||
| 				cam.zoom    += (workspace.zoom_target - cam.zoom) * lerp_factor * f32(delta_time) | ||||
| 				cam.zoom     = clamp(cam.zoom, config.cam_min_zoom, config.cam_max_zoom) // Ensure cam.zoom stays within bounds | ||||
| 			case .Digital: | ||||
| 				zoom_delta            := input.mouse.vertical_wheel * config.cam_zoom_sensitivity_digital | ||||
| 				zoom_delta            := input.mouse.scroll.y * config.cam_zoom_sensitivity_digital | ||||
| 				workspace.zoom_target  = clamp(workspace.zoom_target + zoom_delta, config.cam_min_zoom, config.cam_max_zoom) | ||||
| 				cam.zoom = workspace.zoom_target | ||||
| 		} | ||||
|   | ||||
| @@ -30,6 +30,9 @@ import "base:runtime" | ||||
|  | ||||
| import c "core:c/libc" | ||||
|  | ||||
| import "core:container/queue" | ||||
| 	Queue :: queue.Queue | ||||
|  | ||||
| // import "core:dynlib" | ||||
|  | ||||
| import "core:hash" | ||||
| @@ -49,6 +52,9 @@ import fmt_io "core:fmt" | ||||
|  | ||||
| import "core:math" | ||||
|  | ||||
| import "core:math/bits" | ||||
| 	u64_max :: bits.U64_MAX  | ||||
|  | ||||
| import "core:mem" | ||||
| 	align_forward_int       :: mem.align_forward_int | ||||
| 	align_forward_uint      :: mem.align_forward_uint | ||||
| @@ -158,6 +164,7 @@ import "codebase:grime" | ||||
| 	array_to_slice     :: grime.array_to_slice | ||||
| 	array_init         :: grime.array_init | ||||
| 	array_append       :: grime.array_append | ||||
| 	array_append_array :: grime.array_append_array | ||||
| 	array_append_at    :: grime.array_append_at | ||||
| 	array_clear        :: grime.array_clear | ||||
| 	array_free         :: grime.array_free | ||||
| @@ -181,6 +188,10 @@ import "codebase:grime" | ||||
| 	hmap_zpl_reload :: grime.hmap_zpl_reload | ||||
| 	hmap_zpl_set    :: grime.hmap_zpl_set | ||||
|  | ||||
| 	make_queue :: grime.make_queue | ||||
|  | ||||
| 	next_queue_iterator :: grime.next_queue_iterator | ||||
|  | ||||
| 	Pool :: grime.Pool | ||||
|  | ||||
| 	Slab          :: grime.Slab | ||||
| @@ -308,6 +319,10 @@ bivec3 :: proc { | ||||
| 	vec3_to_bivec3, | ||||
| } | ||||
|  | ||||
| clear :: proc{ | ||||
| 	grime.array_clear, | ||||
| } | ||||
|  | ||||
| cm_to_pixels :: proc { | ||||
| 	f32_cm_to_pixels, | ||||
| 	vec2_cm_to_pixels, | ||||
| @@ -352,10 +367,15 @@ is_power_of_two :: proc { | ||||
| 	is_power_of_two_uintptr, | ||||
| } | ||||
|  | ||||
| iterator :: proc { | ||||
| 	grime.iterator_queue, | ||||
| } | ||||
|  | ||||
| make :: proc { | ||||
| 	array_init, | ||||
| 	hmap_chained_init, | ||||
| 	hmap_zpl_init, | ||||
| 	make_queue, | ||||
|  | ||||
| 	// Usual | ||||
| 	make_slice, | ||||
| @@ -375,6 +395,14 @@ mov_avg_exp :: proc { | ||||
| 	mov_avg_exp_f64, | ||||
| } | ||||
|  | ||||
| next :: proc { | ||||
| 	next_queue_iterator, | ||||
| } | ||||
|  | ||||
| peek_front :: proc { | ||||
| 	queue.peek_front, | ||||
| } | ||||
|  | ||||
| pixels_to_cm :: proc { | ||||
| 	f32_pixels_to_cm, | ||||
| 	vec2_pixels_to_cm, | ||||
| @@ -412,6 +440,9 @@ pressed :: proc { | ||||
| } | ||||
|  | ||||
| push :: proc { | ||||
| 	queue.push_back, | ||||
| 	grime.push_back_slice_queue, | ||||
|  | ||||
| 	stack_push, | ||||
| 	stack_allocator_push, | ||||
|  | ||||
| @@ -435,6 +466,29 @@ released :: proc { | ||||
| 	btn_released, | ||||
| } | ||||
|  | ||||
| reload :: proc { | ||||
| 	grime.reload_array, | ||||
| 	grime.reload_queue, | ||||
| 	grime.reload_map, | ||||
| } | ||||
|  | ||||
| space_left :: proc { | ||||
| 	queue.space, | ||||
| } | ||||
|  | ||||
| scope :: proc { | ||||
| 	ui_layout_scope_via_layout, | ||||
| 	ui_layout_scope_via_combo, | ||||
|  | ||||
| 	ui_style_scope_via_style, | ||||
| 	ui_style_scope_via_combo, | ||||
|  | ||||
| 	ui_theme_scope_via_layout_style, | ||||
| 	ui_theme_scope_via_combos, | ||||
| 	ui_theme_scope_via_proc, | ||||
| 	ui_theme_scope_via_theme, | ||||
| } | ||||
|  | ||||
| sqrt :: proc{ | ||||
| 	math.sqrt_f16, | ||||
| 	math.sqrt_f16le, | ||||
| @@ -451,19 +505,6 @@ inverse_sqrt :: proc { | ||||
| 	inverse_sqrt_f32, | ||||
| } | ||||
|  | ||||
| scope :: proc { | ||||
| 	ui_layout_scope_via_layout, | ||||
| 	ui_layout_scope_via_combo, | ||||
|  | ||||
| 	ui_style_scope_via_style, | ||||
| 	ui_style_scope_via_combo, | ||||
|  | ||||
| 	ui_theme_scope_via_layout_style, | ||||
| 	ui_theme_scope_via_combos, | ||||
| 	ui_theme_scope_via_proc, | ||||
| 	ui_theme_scope_via_theme, | ||||
| } | ||||
|  | ||||
| sub :: proc { | ||||
| 	sub_point3, | ||||
| 	sub_range2, | ||||
|   | ||||
| @@ -1,63 +0,0 @@ | ||||
| package sectr | ||||
|  | ||||
| InputEventType :: enum u32 { | ||||
| 	Key_Pressed, | ||||
| 	Key_Released, | ||||
| 	Mouse_Pressed, | ||||
| 	Mouse_Released, | ||||
| 	Mouse_Scroll, | ||||
| 	Mouse_Move, | ||||
| 	Mouse_Enter, | ||||
| 	Mouse_Leave, | ||||
| 	Unicode, | ||||
| } | ||||
|  | ||||
| InputEvent :: struct | ||||
| { | ||||
| 	frame_id    : u64, | ||||
| 	type        : InputEventType, | ||||
| 	key         : KeyCode, | ||||
| 	modifiers   : ModifierCodeFlags, | ||||
| 	mouse       : struct { | ||||
| 		btn    : MouseBtn, | ||||
| 		pos    : Vec2, | ||||
| 		delta  : Vec2, | ||||
| 		scroll : Vec2, | ||||
| 	}, | ||||
| 	codepoint : rune, | ||||
|  | ||||
| 	// num_touches : u32, | ||||
| 	// touches     : Touchpoint, | ||||
|  | ||||
| 	_sokol_frame_id : u64, | ||||
| } | ||||
|  | ||||
| InputKeyEvent :: struct { | ||||
| 	frame_id    : u64, | ||||
| 	type        : InputEventType, | ||||
| 	key         : KeyCode, | ||||
| 	modifiers   : ModifierCodeFlags, | ||||
| } | ||||
|  | ||||
| InputMouseEvent :: struct { | ||||
| 	frame_id    : u64, | ||||
| 	type        : InputEventType, | ||||
| 	key         : KeyCode, | ||||
| 	modifiers   : ModifierCodeFlags, | ||||
| } | ||||
|  | ||||
| // Note(Ed): There is a staged_input_events : Array(InputEvent), in the state.odin's State struct | ||||
|  | ||||
| append_staged_input_events :: #force_inline proc() { | ||||
| 	// TODO(Ed) : Add guards for multi-threading | ||||
|  | ||||
| 	state := get_state() | ||||
| 	array_append( & state.staged_input_events, event ) | ||||
| } | ||||
|  | ||||
| pull_staged_input_events :: proc(  input : ^InputState, staged_events : ^Array(InputEvent) ) | ||||
| { | ||||
| 	// TODO(Ed) : Add guards for multi-threading | ||||
|  | ||||
| 	 | ||||
| } | ||||
							
								
								
									
										259
									
								
								code/sectr/input/events.odin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										259
									
								
								code/sectr/input/events.odin
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,259 @@ | ||||
| package sectr | ||||
|  | ||||
| InputEventType :: enum u32 { | ||||
| 	Key_Pressed, | ||||
| 	Key_Released, | ||||
| 	Mouse_Pressed, | ||||
| 	Mouse_Released, | ||||
| 	Mouse_Scroll, | ||||
| 	Mouse_Move, | ||||
| 	Mouse_Enter, | ||||
| 	Mouse_Leave, | ||||
| 	Unicode, | ||||
| } | ||||
|  | ||||
| InputEvent :: struct | ||||
| { | ||||
| 	frame_id    : u64, | ||||
| 	type        : InputEventType, | ||||
| 	key         : KeyCode, | ||||
| 	modifiers   : ModifierCodeFlags, | ||||
| 	mouse       : struct { | ||||
| 		btn    : MouseBtn, | ||||
| 		pos    : Vec2, | ||||
| 		delta  : Vec2, | ||||
| 		scroll : Vec2, | ||||
| 	}, | ||||
| 	codepoint : rune, | ||||
|  | ||||
| 	// num_touches : u32, | ||||
| 	// touches     : Touchpoint, | ||||
|  | ||||
| 	_sokol_frame_id : u64, | ||||
| } | ||||
|  | ||||
| // TODO(Ed): May just use input event exclusively in the future and have pointers for key and mouse event filters | ||||
| // I'm on the fence about this as I don't want to force  | ||||
|  | ||||
| InputKeyEvent :: struct { | ||||
| 	frame_id    : u64, | ||||
| 	type        : InputEventType, | ||||
| 	key         : KeyCode, | ||||
| 	modifiers   : ModifierCodeFlags, | ||||
| } | ||||
|  | ||||
| InputMouseEvent :: struct { | ||||
| 	frame_id    : u64, | ||||
| 	type        : InputEventType, | ||||
| 	btn         : MouseBtn, | ||||
| 	pos         : Vec2, | ||||
| 	delta       : Vec2, | ||||
| 	scroll      : Vec2, | ||||
| 	modifiers   : ModifierCodeFlags, | ||||
| } | ||||
|  | ||||
| InputEvents :: struct { | ||||
| 	events       : Queue(InputEvent), | ||||
| 	key_events   : Queue(InputKeyEvent), | ||||
| 	mouse_events : Queue(InputMouseEvent), | ||||
|  | ||||
| 	codes_pressed : Array(rune), | ||||
| } | ||||
|  | ||||
| // Note(Ed): There is a staged_input_events : Array(InputEvent), in the state.odin's State struct | ||||
|  | ||||
| append_staged_input_events :: #force_inline proc( event : InputEvent ) { | ||||
| 	// TODO(Ed) : Add guards for multi-threading | ||||
|  | ||||
| 	state := get_state() | ||||
| 	append( & state.staged_input_events, event ) | ||||
| } | ||||
|  | ||||
| pull_staged_input_events :: proc(  input : ^InputState, input_events : ^InputEvents, staged_events : Array(InputEvent) ) | ||||
| { | ||||
| 	// TODO(Ed) : Add guards for multi-threading | ||||
|  | ||||
| 	staged_events_slice := array_to_slice(staged_events) | ||||
| 	push( & input_events.events, staged_events_slice ) | ||||
|  | ||||
| 	using input_events | ||||
|  | ||||
| 	for event in staged_events_slice | ||||
| 	{ | ||||
| 		switch event.type { | ||||
| 			case .Key_Pressed: | ||||
| 				push( & key_events, InputKeyEvent { | ||||
| 					frame_id  = event.frame_id, | ||||
| 					type      = event.type, | ||||
| 					key       = event.key, | ||||
| 					modifiers = event.modifiers | ||||
| 				}) | ||||
|  | ||||
| 			case .Key_Released: | ||||
| 				push( & key_events, InputKeyEvent { | ||||
| 					frame_id  = event.frame_id, | ||||
| 					type      = event.type, | ||||
| 					key       = event.key, | ||||
| 					modifiers = event.modifiers | ||||
| 				}) | ||||
|  | ||||
| 			case .Unicode: | ||||
| 				append( & codes_pressed, event.codepoint ) | ||||
|  | ||||
| 			case .Mouse_Pressed: | ||||
| 				push( & mouse_events, InputMouseEvent { | ||||
| 					frame_id    = event.frame_id, | ||||
| 					type        = event.type, | ||||
| 					btn         = event.mouse.btn, | ||||
| 					pos         = event.mouse.pos, | ||||
| 					delta       = event.mouse.delta, | ||||
| 					scroll      = event.mouse.scroll, | ||||
| 					modifiers   = event.modifiers, | ||||
| 				}) | ||||
|  | ||||
| 			case .Mouse_Released: | ||||
| 				push( & mouse_events, InputMouseEvent { | ||||
| 					frame_id    = event.frame_id, | ||||
| 					type        = event.type, | ||||
| 					btn         = event.mouse.btn, | ||||
| 					pos         = event.mouse.pos, | ||||
| 					delta       = event.mouse.delta, | ||||
| 					scroll      = event.mouse.scroll, | ||||
| 					modifiers   = event.modifiers, | ||||
| 				}) | ||||
|  | ||||
| 			case .Mouse_Scroll: | ||||
| 				push( & mouse_events, InputMouseEvent { | ||||
| 					frame_id    = event.frame_id, | ||||
| 					type        = event.type, | ||||
| 					btn         = event.mouse.btn, | ||||
| 					pos         = event.mouse.pos, | ||||
| 					delta       = event.mouse.delta, | ||||
| 					scroll      = event.mouse.scroll, | ||||
| 					modifiers   = event.modifiers, | ||||
| 				}) | ||||
| 			case .Mouse_Move: | ||||
| 				push( & mouse_events, InputMouseEvent { | ||||
| 					frame_id    = event.frame_id, | ||||
| 					type        = event.type, | ||||
| 					btn         = event.mouse.btn, | ||||
| 					pos         = event.mouse.pos, | ||||
| 					delta       = event.mouse.delta, | ||||
| 					scroll      = event.mouse.scroll, | ||||
| 					modifiers   = event.modifiers, | ||||
| 				}) | ||||
|  | ||||
| 			case .Mouse_Enter: | ||||
| 				push( & mouse_events, InputMouseEvent { | ||||
| 					frame_id    = event.frame_id, | ||||
| 					type        = event.type, | ||||
| 					btn         = event.mouse.btn, | ||||
| 					pos         = event.mouse.pos, | ||||
| 					delta       = event.mouse.delta, | ||||
| 					scroll      = event.mouse.scroll, | ||||
| 					modifiers   = event.modifiers, | ||||
| 				}) | ||||
|  | ||||
| 			case .Mouse_Leave: | ||||
| 				push( & mouse_events, InputMouseEvent { | ||||
| 					frame_id    = event.frame_id, | ||||
| 					type        = event.type, | ||||
| 					btn         = event.mouse.btn, | ||||
| 					pos         = event.mouse.pos, | ||||
| 					delta       = event.mouse.delta, | ||||
| 					scroll      = event.mouse.scroll, | ||||
| 					modifiers   = event.modifiers, | ||||
| 				}) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	clear( staged_events ) | ||||
| } | ||||
|  | ||||
| poll_input_events :: proc( input, prev_input : ^InputState, input_events : InputEvents ) | ||||
| { | ||||
| 	input.keyboard = {} | ||||
| 	input.mouse    = {} | ||||
|  | ||||
| 	input_events := input_events | ||||
| 	using input_events | ||||
|  | ||||
| 	@static prev_frame : u64 = u64_max | ||||
|  | ||||
| 	last_frame := peek_front( & events).frame_id | ||||
|  | ||||
| 	// No new events, don't update | ||||
| 	if prev_frame != 0 && 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 | ||||
|  | ||||
| 			key      := & input.keyboard.keys[event.key] | ||||
| 			prev_key :=   prev_input.keyboard.keys[event.key] | ||||
|  | ||||
| 			first_transition := key.half_transitions == 0 | ||||
|  | ||||
| 			#partial switch event.type { | ||||
| 				case .Key_Pressed: | ||||
| 					key.half_transitions += 1 | ||||
| 					key.ended_down        = true | ||||
|  | ||||
| 				case .Key_Released: | ||||
| 					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 | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	Iterate_Mouse_Events: | ||||
| 	{ | ||||
| 		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 | ||||
|  | ||||
| 			process_digital_btn :: proc( btn : ^DigitalBtn, prev_btn : DigitalBtn, ended_down : b32 ) | ||||
| 			{ | ||||
| 				first_transition := btn.half_transitions == 0 | ||||
|  | ||||
| 				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 { | ||||
| 				case .Mouse_Pressed: | ||||
| 					btn      := & input.mouse.btns[event.btn] | ||||
| 					prev_btn :=   prev_input.mouse.btns[event.btn] | ||||
| 					process_digital_btn( btn, prev_btn, true ) | ||||
|  | ||||
| 				case .Mouse_Released: | ||||
| 					btn      := & input.mouse.btns[event.btn] | ||||
| 					prev_btn :=   prev_input.mouse.btns[event.btn] | ||||
| 					process_digital_btn( btn, prev_btn, false ) | ||||
|  | ||||
| 				case .Mouse_Scroll: | ||||
| 					input.mouse.scroll += event.scroll.x | ||||
|  | ||||
| 				case .Mouse_Move: | ||||
| 				case .Mouse_Enter: | ||||
| 				case .Mouse_Leave: | ||||
| 					// Handled elsewhere | ||||
| 			} | ||||
|  | ||||
| 			input.mouse.pos   = event.pos | ||||
| 			input.mouse.delta = event.delta | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	prev_frame = last_frame | ||||
| } | ||||
| @@ -10,7 +10,7 @@ AnalogStick :: struct { | ||||
|  | ||||
| DigitalBtn :: struct { | ||||
| 	half_transitions : i32, | ||||
| 	ended_down       : b32 | ||||
| 	ended_down       : b32, | ||||
| } | ||||
|  | ||||
| btn_pressed :: proc( btn : DigitalBtn ) -> b32 { | ||||
| @@ -167,11 +167,11 @@ MouseState :: struct { | ||||
| 		      btns       : [16] DigitalBtn, | ||||
| 		using individual : struct { | ||||
| 			left, middle, right        : DigitalBtn, | ||||
| 			side, forward, back, extra : DigitalBtn | ||||
| 			side, forward, back, extra : DigitalBtn, | ||||
| 		} | ||||
| 	}, | ||||
| 	raw_pos, pos, delta              : Vec2, | ||||
| 	vertical_wheel, horizontal_wheel : AnalogAxis | ||||
| 	raw_pos, pos, delta : Vec2, | ||||
| 	scroll              : [2]AnalogAxis, | ||||
| } | ||||
|  | ||||
| mouse_world_delta :: #force_inline proc "contextless" () -> Vec2 { | ||||
| @@ -183,10 +183,4 @@ mouse_world_delta :: #force_inline proc "contextless" () -> Vec2 { | ||||
| InputState :: struct { | ||||
| 	keyboard : KeyboardState, | ||||
| 	mouse    : MouseState, | ||||
|  | ||||
| 	events       : Array(InputEvent), | ||||
| 	key_events   : Array(InputKeyEvent), | ||||
| 	mouse_events : Array(InputMouseEvent), | ||||
|  | ||||
| 	codes_pressed : Array(rune), | ||||
| } | ||||
|   | ||||
| @@ -7,43 +7,18 @@ import sokol_app "thirdparty:sokol/app" | ||||
|  | ||||
| to_modifiers_code_from_sokol :: proc( sokol_modifiers : u32 ) -> ( modifiers : ModifierCodeFlags ) | ||||
| { | ||||
| 	if sokol_modifiers & sokol_app.MODIFIER_SHIFT != 0 { | ||||
| 		modifiers |= { .Shift } | ||||
| 	} | ||||
| 	if sokol_modifiers & sokol_app.MODIFIER_CTRL != 0 { | ||||
| 		modifiers |= { .Control } | ||||
| 	} | ||||
| 	if sokol_modifiers & sokol_app.MODIFIER_ALT != 0 { | ||||
| 		modifiers |= { .Alt } | ||||
| 	} | ||||
| 	if sokol_modifiers & sokol_app.MODIFIER_LMB != 0 { | ||||
| 		modifiers |= { .Left_Mouse } | ||||
| 	} | ||||
| 	if sokol_modifiers & sokol_app.MODIFIER_RMB != 0 { | ||||
| 		modifiers |= { .Right_Mouse } | ||||
| 	} | ||||
| 	if sokol_modifiers & sokol_app.MODIFIER_MMB != 0 { | ||||
| 		modifiers |= { .Middle_Mouse } | ||||
| 	} | ||||
| 	if sokol_modifiers & sokol_app.MODIFIER_LSHIFT != 0 { | ||||
| 		modifiers |= { .Left_Shift } | ||||
| 	} | ||||
| 	if sokol_modifiers & sokol_app.MODIFIER_RSHIFT != 0 { | ||||
| 		modifiers |= { .Right_Shift } | ||||
| 	} | ||||
| 	if sokol_modifiers & sokol_app.MODIFIER_LCTRL != 0 { | ||||
| 		modifiers |= { .Left_Control } | ||||
| 	} | ||||
| 	if sokol_modifiers & sokol_app.MODIFIER_RCTRL != 0 { | ||||
| 		modifiers |= { .Right_Control } | ||||
| 	} | ||||
| 	if sokol_modifiers & sokol_app.MODIFIER_LALT != 0 { | ||||
| 		modifiers |= { .Left_Alt } | ||||
| 	} | ||||
| 	if sokol_modifiers & sokol_app.MODIFIER_RALT != 0 { | ||||
| 		modifiers |= { .Right_Alt } | ||||
| 	} | ||||
|  | ||||
| 	if sokol_modifiers & sokol_app.MODIFIER_SHIFT  != 0 do modifiers |= { .Shift } | ||||
| 	if sokol_modifiers & sokol_app.MODIFIER_CTRL   != 0 do modifiers |= { .Control } | ||||
| 	if sokol_modifiers & sokol_app.MODIFIER_ALT    != 0 do modifiers |= { .Alt } | ||||
| 	if sokol_modifiers & sokol_app.MODIFIER_LMB    != 0 do modifiers |= { .Left_Mouse } | ||||
| 	if sokol_modifiers & sokol_app.MODIFIER_RMB    != 0 do modifiers |= { .Right_Mouse } | ||||
| 	if sokol_modifiers & sokol_app.MODIFIER_MMB    != 0 do modifiers |= { .Middle_Mouse } | ||||
| 	if sokol_modifiers & sokol_app.MODIFIER_LSHIFT != 0 do modifiers |= { .Left_Shift } | ||||
| 	if sokol_modifiers & sokol_app.MODIFIER_RSHIFT != 0 do modifiers |= { .Right_Shift } | ||||
| 	if sokol_modifiers & sokol_app.MODIFIER_LCTRL  != 0 do modifiers |= { .Left_Control } | ||||
| 	if sokol_modifiers & sokol_app.MODIFIER_RCTRL  != 0 do modifiers |= { .Right_Control } | ||||
| 	if sokol_modifiers & sokol_app.MODIFIER_LALT   != 0 do modifiers |= { .Left_Alt } | ||||
| 	if sokol_modifiers & sokol_app.MODIFIER_RALT   != 0 do modifiers |= { .Right_Alt } | ||||
| 	return | ||||
| } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user