Finished fixing input back to prev-sokol feature parity
This commit is contained in:
		| @@ -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 | ||||
| } | ||||
|   | ||||
| @@ -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() | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -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") | ||||
|   | ||||
| @@ -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 { | ||||
|   | ||||
| @@ -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 | ||||
| 	{ | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -399,6 +399,10 @@ next :: proc { | ||||
| 	next_queue_iterator, | ||||
| } | ||||
|  | ||||
| peek_back :: proc { | ||||
| 	queue.peek_back, | ||||
| } | ||||
|  | ||||
| peek_front :: proc { | ||||
| 	queue.peek_front, | ||||
| } | ||||
|   | ||||
| @@ -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 { | ||||
|   | ||||
| @@ -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, | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user