mirror of
				https://github.com/Ed94/HandmadeHero.git
				synced 2025-10-31 06:50:54 -07:00 
			
		
		
		
	Day 17 complete
This commit is contained in:
		| @@ -141,10 +141,11 @@ void update_and_render( InputState* input, OffscreenBuffer* back_buffer, SoundBu | ||||
| #endif | ||||
|  | ||||
| 	EngineState* state = rcast( EngineState*, memory->Persistent ); | ||||
|  | ||||
| 	do_once_start | ||||
| 		assert( sizeof(EngineState) <= memory->PersistentSize ); | ||||
|  | ||||
| 		state->ToneVolume = 3000; | ||||
| 		state->ToneVolume = 1000; | ||||
| 		state->WaveToneHz = 262; | ||||
| 		state->WavePeriod = sound_buffer->SamplesPerSecond / state->WaveToneHz; | ||||
|  | ||||
| @@ -167,128 +168,108 @@ void update_and_render( InputState* input, OffscreenBuffer* back_buffer, SoundBu | ||||
| 	do_once_end | ||||
|  | ||||
| 	ControllerState* controller = & input->Controllers[0]; | ||||
| 	 | ||||
| 	// Abstracting the actionables as booleans and processing within this scope  | ||||
| 	// for now until proper callbacks for input bindings are setup. | ||||
| 	b32 move_up    = false; | ||||
| 	b32 move_down  = false; | ||||
| 	b32 move_left  = false; | ||||
| 	b32 move_right = false; | ||||
| 	 | ||||
| 	b32 action_up    = false; | ||||
| 	b32 action_down  = false; | ||||
| 	b32 action_left  = false; | ||||
| 	b32 action_right = false; | ||||
| 	 | ||||
| 	f32 analog_threshold = 0.5f; | ||||
| 	 | ||||
| 	b32 raise_volume  = false; | ||||
| 	b32 lower_volume  = false; | ||||
| 	b32 raise_tone_hz = false; | ||||
| 	b32 lower_tone_hz = false; | ||||
| 	 | ||||
| 	b32 toggle_wave_tone = false; | ||||
|  | ||||
| 	if ( controller->DSPad ) | ||||
| 	{ | ||||
| 		DualsensePadState* pad = controller->DSPad; | ||||
|  | ||||
| 		x_offset += pad->DPad.Right.State; | ||||
| 		x_offset -= pad->DPad.Left.State; | ||||
| 		y_offset += pad->DPad.Down.State; | ||||
| 		y_offset -= pad->DPad.Up.State; | ||||
|  | ||||
| 		x_offset += scast(u32, pad->Stick.Left.X.End); | ||||
| 		y_offset += scast(u32, pad->Stick.Left.Y.End); | ||||
|  | ||||
| 		if ( pad->Triangle.State ) | ||||
| 		{ | ||||
| 			state->ToneVolume += 10; | ||||
| 		} | ||||
| 		if ( pad->Circle.State ) | ||||
| 		{ | ||||
| 			state->ToneVolume -= 10; | ||||
| 		} | ||||
|  | ||||
| 		if ( pad->Square.State ) | ||||
| 		{ | ||||
| 			state->WaveToneHz += 1; | ||||
| 			state->WavePeriod  = sound_buffer->SamplesPerSecond / state->WaveToneHz; | ||||
| 		} | ||||
| 		if ( pad->X.State ) | ||||
| 		{ | ||||
| 			state->WaveToneHz -= 1; | ||||
| 			state->WavePeriod  = sound_buffer->SamplesPerSecond / state->WaveToneHz; | ||||
| 		} | ||||
|  | ||||
| 		if ( pad->Options.State ) | ||||
| 		{ | ||||
| 			wave_switch ^= true; | ||||
| 		} | ||||
|  | ||||
| 		if ( pad->Share.State ) | ||||
| 		{ | ||||
| 			// TODO(Ed) : Add rumble test | ||||
| 		} | ||||
| 		 | ||||
| 		move_right |= pad->DPad.Right.EndedDown || pad->Stick.Left.X.End >  analog_threshold; | ||||
| 		move_left  |= pad->DPad.Left.EndedDown  || pad->Stick.Left.X.End < -analog_threshold; | ||||
| 		move_up    |= pad->DPad.Up.EndedDown    || pad->Stick.Left.Y.End >  analog_threshold; | ||||
| 		move_down  |= pad->DPad.Down.EndedDown  || pad->Stick.Left.Y.End < -analog_threshold; | ||||
| 		 | ||||
| 		raise_volume |= pad->Triangle.EndedDown; | ||||
| 		lower_volume |= pad->Circle.EndedDown; | ||||
| 		 | ||||
| 		raise_tone_hz |= pad->Square.EndedDown; | ||||
| 		lower_tone_hz |= pad->X.EndedDown; | ||||
| 		 | ||||
| 		toggle_wave_tone |= pad->Options.EndedDown; | ||||
| 	} | ||||
| 	if ( controller->XPad ) | ||||
| 	{ | ||||
| 		XInputPadState* pad = controller->XPad; | ||||
|  | ||||
| 		x_offset += pad->DPad.Right.State; | ||||
| 		x_offset -= pad->DPad.Left.State; | ||||
| 		y_offset -= pad->DPad.Down.State; | ||||
| 		y_offset += pad->DPad.Up.State; | ||||
|  | ||||
| 		x_offset += scast(u32, pad->Stick.Left.X.End); | ||||
| 		y_offset += scast(u32, pad->Stick.Left.Y.End); | ||||
|  | ||||
| 		if ( pad->Y.State ) | ||||
| 		{ | ||||
| 			state->ToneVolume += 10; | ||||
| 		} | ||||
| 		if ( pad->B.State ) | ||||
| 		{ | ||||
| 			state->ToneVolume -= 10; | ||||
| 		} | ||||
|  | ||||
| 		if ( pad->X.State ) | ||||
| 		{ | ||||
| 			state->WaveToneHz += 1; | ||||
| 			state->WavePeriod  = sound_buffer->SamplesPerSecond / state->WaveToneHz; | ||||
| 		} | ||||
| 		if ( pad->A.State ) | ||||
| 		{ | ||||
| 			state->WaveToneHz -= 1; | ||||
| 			state->WavePeriod  = sound_buffer->SamplesPerSecond / state->WaveToneHz; | ||||
| 		} | ||||
|  | ||||
| 		if ( pad->Start.State ) | ||||
| 		{ | ||||
| 			wave_switch ^= true; | ||||
| 		} | ||||
|  | ||||
| 		if ( pad->Back.State ) | ||||
| 		{ | ||||
| 			// TODO(Ed) : Add rumble test | ||||
| 		} | ||||
| 		 | ||||
| 		move_right |= pad->DPad.Right.EndedDown || pad->Stick.Left.X.End >  analog_threshold; | ||||
| 		move_left  |= pad->DPad.Left.EndedDown  || pad->Stick.Left.X.End < -analog_threshold; | ||||
| 		move_up    |= pad->DPad.Up.EndedDown    || pad->Stick.Left.Y.End >  analog_threshold; | ||||
| 		move_down  |= pad->DPad.Down.EndedDown  || pad->Stick.Left.Y.End < -analog_threshold; | ||||
| 		 | ||||
| 		raise_volume |= pad->Y.EndedDown; | ||||
| 		lower_volume |= pad->B.EndedDown; | ||||
| 		 | ||||
| 		raise_tone_hz |= pad->X.EndedDown; | ||||
| 		lower_tone_hz |= pad->A.EndedDown; | ||||
| 		 | ||||
| 		toggle_wave_tone |= pad->Start.EndedDown; | ||||
| 	} | ||||
| 	if ( controller->Keyboard ) | ||||
| 	{ | ||||
| 		KeyboardState* keyboard = controller->Keyboard; | ||||
| 		 | ||||
| 		move_right |= keyboard->D.EndedDown; | ||||
| 		move_left  |= keyboard->A.EndedDown; | ||||
| 		move_up    |= keyboard->W.EndedDown; | ||||
| 		move_down  |= keyboard->S.EndedDown; | ||||
| 		 | ||||
| 		raise_volume |= keyboard->Up.EndedDown; | ||||
| 		lower_volume |= keyboard->Down.EndedDown; | ||||
| 		 | ||||
| 		raise_tone_hz |= keyboard->Right.EndedDown; | ||||
| 		lower_tone_hz |= keyboard->Left.EndedDown; | ||||
| 		 | ||||
| 		toggle_wave_tone |= keyboard->Space.EndedDown; | ||||
| 	} | ||||
| 	 | ||||
| 	x_offset += move_right; | ||||
| 	x_offset -= move_left; | ||||
| 	y_offset += move_down; | ||||
| 	y_offset -= move_up; | ||||
|  | ||||
| 		x_offset += keyboard->D.State; | ||||
| 		x_offset -= keyboard->A.State; | ||||
| 		y_offset += keyboard->W.State; | ||||
| 		y_offset -= keyboard->S.State; | ||||
| 	if ( raise_volume ) | ||||
| 	{ | ||||
| 		state->ToneVolume += 10; | ||||
| 	} | ||||
| 	if ( lower_volume ) | ||||
| 	{ | ||||
| 		state->ToneVolume -= 10; | ||||
| 	} | ||||
|  | ||||
| 		if ( keyboard->Esc.State ) | ||||
| 		{ | ||||
| 			// TODO : Add exit game | ||||
| 		} | ||||
| 	if ( raise_tone_hz ) | ||||
| 	{ | ||||
| 		state->WaveToneHz += 1; | ||||
| 		state->WavePeriod  = sound_buffer->SamplesPerSecond / state->WaveToneHz; | ||||
| 	} | ||||
| 	if ( lower_tone_hz ) | ||||
| 	{ | ||||
| 		state->WaveToneHz -= 1; | ||||
| 		state->WavePeriod  = sound_buffer->SamplesPerSecond / state->WaveToneHz; | ||||
| 	} | ||||
|  | ||||
| 		if ( keyboard->Space.State ) | ||||
| 		{ | ||||
| 			wave_switch ^= true; | ||||
| 		} | ||||
|  | ||||
| 		if ( keyboard->Up.State ) | ||||
| 		{ | ||||
| 			state->ToneVolume += 10; | ||||
| 		} | ||||
| 		if ( keyboard->Down.State ) | ||||
| 		{ | ||||
| 			state->ToneVolume -= 10; | ||||
| 		} | ||||
| 		if ( keyboard->Left.State ) | ||||
| 		{ | ||||
| 			state->WaveToneHz -= 1; | ||||
| 			state->WavePeriod  = sound_buffer->SamplesPerSecond / state->WaveToneHz; | ||||
| 		} | ||||
| 		if ( keyboard->Right.State ) | ||||
| 		{ | ||||
| 			state->WaveToneHz += 1; | ||||
| 			state->WavePeriod  = sound_buffer->SamplesPerSecond / state->WaveToneHz; | ||||
| 		} | ||||
| 	if ( toggle_wave_tone ) | ||||
| 	{ | ||||
| 		wave_switch ^= true; | ||||
| 	} | ||||
|  | ||||
| 	// TODO(Ed) : Allow sample offsets here for more robust platform options | ||||
|   | ||||
							
								
								
									
										113
									
								
								project/engine.h
									
									
									
									
									
								
							
							
						
						
									
										113
									
								
								project/engine.h
									
									
									
									
									
								
							| @@ -56,7 +56,7 @@ struct SoundBuffer | ||||
| struct DigitalBtn | ||||
| { | ||||
| 	s32 HalfTransitions; | ||||
| 	b32 State; | ||||
| 	b32 EndedDown; | ||||
| }; | ||||
| #define DigitalBtn_Up   0 | ||||
| #define DigitalBtn_Down 1 | ||||
| @@ -67,6 +67,9 @@ struct AnalogAxis | ||||
| 	f32 End; | ||||
| 	f32 Min; | ||||
| 	f32 Max; | ||||
|  | ||||
| 	// Platform doesn't provide this, we process in the engine layer. | ||||
| 	f32 Average; | ||||
| }; | ||||
|  | ||||
| struct AnalogStick | ||||
| @@ -75,20 +78,24 @@ struct AnalogStick | ||||
| 	AnalogAxis Y; | ||||
| }; | ||||
|  | ||||
| struct KeyboardState | ||||
| union KeyboardState | ||||
| { | ||||
| 	DigitalBtn Q; | ||||
| 	DigitalBtn E; | ||||
| 	DigitalBtn W; | ||||
| 	DigitalBtn A; | ||||
| 	DigitalBtn S; | ||||
| 	DigitalBtn D; | ||||
| 	DigitalBtn Esc; | ||||
| 	DigitalBtn Up; | ||||
| 	DigitalBtn Down; | ||||
| 	DigitalBtn Left; | ||||
| 	DigitalBtn Right; | ||||
| 	DigitalBtn Space; | ||||
| 	DigitalBtn Keys[12]; | ||||
| 	struct { | ||||
| 		DigitalBtn Q; | ||||
| 		DigitalBtn E; | ||||
| 		DigitalBtn W; | ||||
| 		DigitalBtn A; | ||||
| 		DigitalBtn S; | ||||
| 		DigitalBtn D; | ||||
| 		DigitalBtn Escape; | ||||
| 		DigitalBtn Backspace; | ||||
| 		DigitalBtn Up; | ||||
| 		DigitalBtn Down; | ||||
| 		DigitalBtn Left; | ||||
| 		DigitalBtn Right; | ||||
| 		DigitalBtn Space; | ||||
| 	}; | ||||
| }; | ||||
|  | ||||
| struct MousesState | ||||
| @@ -128,11 +135,6 @@ struct XInputPadState | ||||
| 			DigitalBtn RightShoulder; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
| 	b32 using_analog() | ||||
| 	{ | ||||
| 		return true; | ||||
| 	}; | ||||
| }; | ||||
|  | ||||
| struct DualsensePadState | ||||
| @@ -165,11 +167,6 @@ struct DualsensePadState | ||||
| 			DigitalBtn R1; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
| 	b32 using_analog() | ||||
| 	{ | ||||
| 		return true; | ||||
| 	}; | ||||
| }; | ||||
|  | ||||
| struct ControllerState | ||||
| @@ -185,10 +182,76 @@ struct InputState | ||||
| 	ControllerState Controllers[4]; | ||||
| }; | ||||
|  | ||||
| b32 input_using_analog(); | ||||
| using InputBindCallback             = void( void* ); | ||||
| using InputBindCallback_DigitalBtn  = void( engine::DigitalBtn*  Button ); | ||||
| using InputBindCallback_AnalogAxis  = void( engine::AnalogAxis*  Axis ); | ||||
| using InputBindCallback_AnalogStick = void( engine::AnalogStick* Stick ); | ||||
|  | ||||
| struct InputMode | ||||
| { | ||||
| 	InputBindCallback* Binds; | ||||
| 	s32                NumBinds; | ||||
| 	char _PAD_[4]; | ||||
| }; | ||||
|  | ||||
| void input_mode_pop( InputMode* mode ); | ||||
| void input_mode_pop( InputMode* mode ); | ||||
|  | ||||
| // Needs a contextual reference to four things: | ||||
| // Timing, Input, Bitmap Buffer, Sound Buffer | ||||
| void update_and_render( InputState* input, OffscreenBuffer* back_buffer, SoundBuffer* sound_buffer, Memory* memory ); | ||||
|  | ||||
| NS_ENGINE_END | ||||
|  | ||||
| // TODO(Ed) : Move this to handmade game layer later. | ||||
|  | ||||
| #define NS_HANDMADE_BEGIN namespace handmade { | ||||
| #define NS_HANDMADE_END   } | ||||
|  | ||||
| NS_HANDMADE_BEGIN | ||||
|  | ||||
| // We want a 'binding' to have multiple binds to active it (most likely) | ||||
| struct Actionable | ||||
| { | ||||
| 	char const*                Name; | ||||
| 	engine::InputBindCallback* Binds; | ||||
| 	s32                        NumBinds; | ||||
| 	char _PAD_[4]; | ||||
| }; | ||||
|  | ||||
| struct ActionableMode | ||||
| { | ||||
| 	 | ||||
| }; | ||||
|  | ||||
| /* | ||||
| 	Platform Layer: | ||||
|  | ||||
| 	Controller : Keyboard & Mouse, XPad, DSPad | ||||
|  | ||||
| 	---VV--- | ||||
|  | ||||
| 	Engine Layer: | ||||
|  | ||||
| 	InputBinding callbacks (per-game-logic frame basis) | ||||
| 	Push/Pop input modes (binding sets) | ||||
|  | ||||
| 	---VV--- | ||||
|  | ||||
| 	Game Layer: | ||||
|  | ||||
| 	Actionables : Binding Sets where a raw input, or input interpretation leads to an player action. | ||||
| 	ActionSet   : Actionables.Push/Pop -> Input.Push/Pop ? | ||||
| 	Player : Controller, Actionables, ActionSets | ||||
| */ | ||||
|  | ||||
| struct Player | ||||
| { | ||||
| 	// So far just has an assigned controller. | ||||
| 	engine::ControllerState* Controller; | ||||
| 	 | ||||
| 	// Possilby some other stuff in the future. | ||||
| }; | ||||
|  | ||||
| NS_HANDMADE_END | ||||
|  | ||||
|   | ||||
| @@ -16,3 +16,4 @@ int gen_main() | ||||
| 	return 0; | ||||
| } | ||||
| #endif | ||||
|  | ||||
|   | ||||
| @@ -29,6 +29,7 @@ | ||||
| #endif | ||||
|  | ||||
| #include <math.h> // TODO : Implement math ourselves | ||||
| #include <stdio.h> | ||||
| #include "engine.cpp" | ||||
|  | ||||
|  | ||||
| @@ -188,6 +189,60 @@ b32 debug_file_write_content( char* file_path, u32 content_size, void* content_m | ||||
| } | ||||
| #endif | ||||
|  | ||||
| internal void | ||||
| input_process_digital_btn( engine::DigitalBtn* old_state, engine::DigitalBtn* new_state, u32 raw_btns, u32 btn_flag ) | ||||
| { | ||||
| #define had_transition() ( old_state->EndedDown == new_state->EndedDown ) | ||||
| 	new_state->EndedDown       = (raw_btns & btn_flag) > 0; | ||||
| 	new_state->HalfTransitions = had_transition() ? 1 : 0; | ||||
| #undef had_transition | ||||
| } | ||||
|  | ||||
| internal f32 | ||||
| xinput_process_axis_value( s16 value, s16 deadzone_threshold ) | ||||
| { | ||||
| 	f32 result = 0; | ||||
| 	if ( value < -deadzone_threshold ) | ||||
| 	{ | ||||
| 		result = scast(f32, value + deadzone_threshold) / (32768.0f - scast(f32, deadzone_threshold)); | ||||
| 	} | ||||
| 	else if ( value > deadzone_threshold ) | ||||
| 	{ | ||||
| 		result = scast(f32, value + deadzone_threshold) / (32767.0f - scast(f32, deadzone_threshold)); | ||||
| 	} | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| internal f32 | ||||
| input_process_axis_value( f32 value, f32 deadzone_threshold ) | ||||
| { | ||||
| 	f32 result = 0; | ||||
| 	if ( value < -deadzone_threshold  ) | ||||
| 	{ | ||||
| 		result = (value + deadzone_threshold ) / (1.0f - deadzone_threshold ); | ||||
| 		 | ||||
| 		if (result < -1.0f)  | ||||
| 			result = -1.0f; // Clamp to ensure it doesn't go below -1 | ||||
| 	} | ||||
| 	else if ( value > deadzone_threshold ) | ||||
| 	{ | ||||
| 		result = (value - deadzone_threshold ) / (1.0f - deadzone_threshold ); | ||||
| 		 | ||||
| 		if (result > 1.0f)  | ||||
| 			result = 1.0f; // Clamp to ensure it doesn't exceed 1 | ||||
| 	} | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| internal void | ||||
| input_process_keyboard_key( engine::DigitalBtn* key, b32 is_down ) | ||||
| { | ||||
| 	// This assert fails all the time, have no idea why. I'm just going to use GetAsyncKeyState instead, using the messaging events is horrible. | ||||
| 	// assert( key->EndedDown != is_down ) | ||||
| 	key->EndedDown        = is_down; | ||||
| 	key->HalfTransitions += is_down; | ||||
| } | ||||
|  | ||||
| internal void | ||||
| init_sound(HWND window_handle, s32 samples_per_second, s32 buffer_size ) | ||||
| { | ||||
| @@ -487,19 +542,115 @@ main_window_callback( | ||||
| } | ||||
|  | ||||
| internal void | ||||
| input_process_digital_btn( engine::DigitalBtn* old_state, engine::DigitalBtn* new_state, u32 raw_btns, u32 btn_flag ) | ||||
| process_pending_window_messages( engine::KeyboardState* keyboard ) | ||||
| { | ||||
| #define had_transition() ( old_state->State == new_state->State ) | ||||
| 	new_state->State           = (raw_btns & btn_flag); | ||||
| 	new_state->HalfTransitions = had_transition() ? 1 : 0; | ||||
| #undef had_transition | ||||
| } | ||||
| 	MSG window_msg_info; | ||||
| 	while ( PeekMessageA( & window_msg_info, 0, 0, 0, PM_Remove_Messages_From_Queue ) ) | ||||
| 	{ | ||||
| 		if ( window_msg_info.message == WM_QUIT  ) | ||||
| 		{ | ||||
| 			OutputDebugStringA("WM_QUIT\n"); | ||||
| 			Running = false; | ||||
| 		} | ||||
|  | ||||
| internal void | ||||
| input_process_keyboard_key( engine::DigitalBtn* key, b32 is_down ) | ||||
| { | ||||
| 	key->State            = is_down; | ||||
| 	key->HalfTransitions += is_down; | ||||
| 		// Keyboard input handling | ||||
| 		switch (window_msg_info.message) | ||||
| 		{ | ||||
| 			// I rather do this with GetAsyncKeyState... | ||||
| 			case WM_SYSKEYDOWN: | ||||
| 			case WM_SYSKEYUP: | ||||
| 		#if 0 | ||||
| 			case WM_KEYDOWN: | ||||
| 			case WM_KEYUP: | ||||
| 		#endif | ||||
| 			{ | ||||
| 				WPARAM vk_code  = window_msg_info.wParam; | ||||
| 				b32    is_down  = scast(b32, (window_msg_info.lParam >> 31) == 0 ); | ||||
| 				b32    was_down = scast(b32, (window_msg_info.lParam >> 30) ); | ||||
| 				b32    alt_down = scast(b32, (window_msg_info.lParam & (1 << 29)) ); | ||||
|  | ||||
| 				switch ( vk_code ) | ||||
| 				{ | ||||
| 				#if 0 | ||||
| 					case 'Q': | ||||
| 					{ | ||||
| 						input_process_keyboard_key( & keyboard->Q, is_down ); | ||||
| 					} | ||||
| 					break; | ||||
| 					case 'E': | ||||
| 					{ | ||||
| 						input_process_keyboard_key( & keyboard->E, is_down ); | ||||
| 					} | ||||
| 					break; | ||||
| 					case 'W': | ||||
| 					{ | ||||
| 						input_process_keyboard_key( & keyboard->W, is_down ); | ||||
| 					} | ||||
| 					break; | ||||
| 					case 'A': | ||||
| 					{ | ||||
| 						input_process_keyboard_key( & keyboard->A, is_down ); | ||||
| 					} | ||||
| 					break; | ||||
| 					case 'S': | ||||
| 					{ | ||||
| 						input_process_keyboard_key( & keyboard->S, is_down ); | ||||
| 					} | ||||
| 					break; | ||||
| 					case 'D': | ||||
| 					{ | ||||
| 						input_process_keyboard_key( & keyboard->D, is_down ); | ||||
| 					} | ||||
| 					break; | ||||
| 					case VK_ESCAPE: | ||||
| 					{ | ||||
| 						input_process_keyboard_key( & keyboard->Escape, is_down ); | ||||
| 					} | ||||
| 					break; | ||||
| 					case VK_BACK: | ||||
| 						input_process_keyboard_key( & keyboard->Backspace, is_down ); | ||||
| 					break; | ||||
| 					case VK_UP: | ||||
| 					{ | ||||
| 						input_process_keyboard_key( & keyboard->Up, is_down ); | ||||
| 					} | ||||
| 					break; | ||||
| 					case VK_DOWN: | ||||
| 					{ | ||||
| 						input_process_keyboard_key( & keyboard->Down, is_down ); | ||||
| 					} | ||||
| 					break; | ||||
| 					case VK_LEFT: | ||||
| 					{ | ||||
| 						input_process_keyboard_key( & keyboard->Left, is_down ); | ||||
| 					} | ||||
| 					break; | ||||
| 					case VK_RIGHT: | ||||
| 					{ | ||||
| 						input_process_keyboard_key( & keyboard->Right, is_down ); | ||||
| 					} | ||||
| 					break; | ||||
| 					case VK_SPACE: | ||||
| 					{ | ||||
| 						input_process_keyboard_key( & keyboard->Space, is_down ); | ||||
| 					} | ||||
| 					break; | ||||
| 				#endif | ||||
| 					case VK_F4: | ||||
| 					{ | ||||
| 						if ( alt_down ) | ||||
| 							Running = false; | ||||
| 					} | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 			break; | ||||
|  | ||||
| 			default: | ||||
| 				TranslateMessage( & window_msg_info ); | ||||
| 				DispatchMessageW( & window_msg_info ); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| NS_PLATFORM_END | ||||
| @@ -561,7 +712,6 @@ WinMain( | ||||
|  | ||||
| 	WNDCLASSW window_class {}; | ||||
| 	HWND window_handle = nullptr; | ||||
| 	MSG window_msg_info; | ||||
| 	{ | ||||
| 		window_class.style = CS_Horizontal_Redraw | CS_Vertical_Redraw; | ||||
| 		window_class.lpfnWndProc = main_window_callback; | ||||
| @@ -635,17 +785,18 @@ WinMain( | ||||
|  | ||||
| 	engine::InputState input {}; | ||||
|  | ||||
| 	engine::KeyboardState keyboard; | ||||
| 	input.Controllers[0].Keyboard = & keyboard; | ||||
| 	engine::KeyboardState keyboard_states[2] {}; | ||||
| 	engine::KeyboardState* old_keyboard = & keyboard_states[0]; | ||||
| 	engine::KeyboardState* new_keyboard = & keyboard_states[1]; | ||||
| 	// Important: Assuming keyboard always connected for now, and assigning to first controller. | ||||
|  | ||||
| 	using EngineXInputPadStates = engine::XInputPadState[ Max_Controllers ]; | ||||
| 	EngineXInputPadStates xpad_states[2]; | ||||
| 	EngineXInputPadStates xpad_states[2] {}; | ||||
| 	EngineXInputPadStates* old_xpads = & xpad_states[0]; | ||||
| 	EngineXInputPadStates* new_xpads = & xpad_states[1]; | ||||
|  | ||||
| 	using EngineDSPadStates = engine::DualsensePadState[Max_Controllers]; | ||||
| 	EngineDSPadStates ds_pad_states[2]; | ||||
| 	EngineDSPadStates ds_pad_states[2] {}; | ||||
| 	EngineDSPadStates* old_ds_pads = & ds_pad_states[0]; | ||||
| 	EngineDSPadStates* new_ds_pads = & ds_pad_states[1]; | ||||
|  | ||||
| @@ -684,116 +835,50 @@ WinMain( | ||||
| 	Running = true; | ||||
| 	while( Running ) | ||||
| 	{ | ||||
| 		keyboard = {}; | ||||
|  | ||||
| 		// Window Management | ||||
| 		// Handeled properly in the input section. | ||||
| 	#if 0 | ||||
| 		swap( old_keyboard, new_keyboard ); | ||||
| 		*new_keyboard = {}; | ||||
| 		for ( u32 key_index = 0; key_index < array_count( new_keyboard->Keys ); ++ key_index ) | ||||
| 		{ | ||||
| 			while ( PeekMessageW( & window_msg_info, 0, 0, 0, PM_Remove_Messages_From_Queue ) ) | ||||
| 			{ | ||||
| 				if ( window_msg_info.message == WM_QUIT  ) | ||||
| 				{ | ||||
| 					OutputDebugStringA("WM_QUIT\n"); | ||||
| 					Running = false; | ||||
| 				} | ||||
| 			engine::DigitalBtn* old_key = & old_keyboard->Keys[ key_index ]; | ||||
| 			engine::DigitalBtn* new_key = & new_keyboard->Keys[ key_index ]; | ||||
|  | ||||
|  | ||||
| 				// Keyboard input handling | ||||
| 				switch (window_msg_info.message) | ||||
| 				{ | ||||
| 					case WM_SYSKEYDOWN: | ||||
| 					case WM_SYSKEYUP: | ||||
| 					case WM_KEYDOWN: | ||||
| 					case WM_KEYUP: | ||||
| 					{ | ||||
| 						WPARAM vk_code  = window_msg_info.wParam; | ||||
| 						b32    is_down  = scast(b32, (window_msg_info.lParam >> 31) == 0 ); | ||||
| 						b32    was_down = scast(b32, (window_msg_info.lParam >> 30) ); | ||||
| 						b32    alt_down = scast(b32, (window_msg_info.lParam & (1 << 29)) ); | ||||
|  | ||||
| 						switch ( vk_code ) | ||||
| 						{ | ||||
| 							case 'Q': | ||||
| 							{ | ||||
| 								input_process_keyboard_key( & keyboard.Q, is_down ); | ||||
| 							} | ||||
| 							break; | ||||
| 							case 'E': | ||||
| 							{ | ||||
| 								input_process_keyboard_key( & keyboard.E, is_down ); | ||||
| 							} | ||||
| 							break; | ||||
| 							case 'W': | ||||
| 							{ | ||||
| 								input_process_keyboard_key( & keyboard.W, is_down ); | ||||
| 							} | ||||
| 							break; | ||||
| 							case 'A': | ||||
| 							{ | ||||
| 								input_process_keyboard_key( & keyboard.A, is_down ); | ||||
| 							} | ||||
| 							break; | ||||
| 							case 'S': | ||||
| 							{ | ||||
| 								input_process_keyboard_key( & keyboard.S, is_down ); | ||||
| 							} | ||||
| 							break; | ||||
| 							case 'D': | ||||
| 							{ | ||||
| 								input_process_keyboard_key( & keyboard.D, is_down ); | ||||
| 							} | ||||
| 							break; | ||||
| 							case VK_ESCAPE: | ||||
| 							{ | ||||
| 								input_process_keyboard_key( & keyboard.Esc, is_down ); | ||||
| 							} | ||||
| 							break; | ||||
| 							case VK_UP: | ||||
| 							{ | ||||
| 								input_process_keyboard_key( & keyboard.Up, is_down ); | ||||
| 							} | ||||
| 							break; | ||||
| 							case VK_DOWN: | ||||
| 							{ | ||||
| 								input_process_keyboard_key( & keyboard.Down, is_down ); | ||||
| 							} | ||||
| 							break; | ||||
| 							case VK_LEFT: | ||||
| 							{ | ||||
| 								input_process_keyboard_key( & keyboard.Left, is_down ); | ||||
| 							} | ||||
| 							break; | ||||
| 							case VK_RIGHT: | ||||
| 							{ | ||||
| 								input_process_keyboard_key( & keyboard.Right, is_down ); | ||||
| 							} | ||||
| 							break; | ||||
| 							case VK_SPACE: | ||||
| 							{ | ||||
| 								input_process_keyboard_key( & keyboard.Space, is_down ); | ||||
| 							} | ||||
| 							break; | ||||
| 							case VK_F4: | ||||
| 							{ | ||||
| 								if ( alt_down ) | ||||
| 									Running = false; | ||||
| 							} | ||||
| 							break; | ||||
| 						} | ||||
| 					} | ||||
| 					break; | ||||
|  | ||||
| 					default: | ||||
| 						TranslateMessage( & window_msg_info ); | ||||
| 						DispatchMessageW( & window_msg_info ); | ||||
| 				} | ||||
| 			} | ||||
| 			new_key->EndedDown = old_key->EndedDown; | ||||
| 		} | ||||
| 	#endif | ||||
| 		process_pending_window_messages( new_keyboard ); | ||||
| 		 | ||||
| 		 | ||||
| 		input.Controllers[0].Keyboard = new_keyboard; | ||||
| 		// printf("Q- Old: %d, New: %d\n", old_keyboard->Q.EndedDown, new_keyboard->Q.EndedDown); | ||||
| 		printf("Q- HTOld: %d, HTNew: %d\n", old_keyboard->Q.HalfTransitions, new_keyboard->Q.HalfTransitions); | ||||
|  | ||||
| 		// Input | ||||
| 		// TODO(Ed) : Setup user definable deadzones for triggers and sticks. | ||||
| 		{ | ||||
| 			// Swapping at the beginning of the input frame instead of the end. | ||||
| 			swap( old_xpads,   new_xpads ); | ||||
| 			swap( old_ds_pads, new_ds_pads ); | ||||
| 			swap( old_keyboard, new_keyboard ); | ||||
| 			swap( old_xpads,    new_xpads ); | ||||
| 			swap( old_ds_pads,  new_ds_pads ); | ||||
| 			 | ||||
| 			// Keyboard Polling | ||||
| 			{ | ||||
| 				constexpr u32 is_down = 0x8000; | ||||
| 				input_process_digital_btn( & old_keyboard->Q,         & new_keyboard->Q,         GetAsyncKeyState( 'Q' ),       is_down ); | ||||
| 				input_process_digital_btn( & old_keyboard->E,         & new_keyboard->E,         GetAsyncKeyState( 'E' ),       is_down ); | ||||
| 				input_process_digital_btn( & old_keyboard->W,         & new_keyboard->W,         GetAsyncKeyState( 'W' ),       is_down ); | ||||
| 				input_process_digital_btn( & old_keyboard->A,         & new_keyboard->A,         GetAsyncKeyState( 'A' ),       is_down ); | ||||
| 				input_process_digital_btn( & old_keyboard->S,         & new_keyboard->S,         GetAsyncKeyState( 'S' ),       is_down ); | ||||
| 				input_process_digital_btn( & old_keyboard->D,         & new_keyboard->D,         GetAsyncKeyState( 'D' ),       is_down ); | ||||
| 				input_process_digital_btn( & old_keyboard->Escape,    & new_keyboard->Escape,    GetAsyncKeyState( VK_ESCAPE ), is_down ); | ||||
| 				input_process_digital_btn( & old_keyboard->Backspace, & new_keyboard->Backspace, GetAsyncKeyState( VK_BACK ),   is_down ); | ||||
| 				input_process_digital_btn( & old_keyboard->Up,        & new_keyboard->Up,        GetAsyncKeyState( VK_UP ),     is_down ); | ||||
| 				input_process_digital_btn( & old_keyboard->Down,      & new_keyboard->Down,      GetAsyncKeyState( VK_DOWN ),   is_down ); | ||||
| 				input_process_digital_btn( & old_keyboard->Left,      & new_keyboard->Left,      GetAsyncKeyState( VK_LEFT ),   is_down ); | ||||
| 				input_process_digital_btn( & old_keyboard->Right,     & new_keyboard->Right,     GetAsyncKeyState( VK_RIGHT ),  is_down ); | ||||
| 				input_process_digital_btn( & old_keyboard->Space,     & new_keyboard->Space,     GetAsyncKeyState( VK_SPACE ),  is_down ); | ||||
| 			} | ||||
|  | ||||
| 			// XInput Polling | ||||
| 			// TODO(Ed) : Should we poll this more frequently? | ||||
| @@ -826,46 +911,16 @@ WinMain( | ||||
| 					new_xpad->Stick.Left.X.Start = old_xpad->Stick.Left.X.End; | ||||
| 					new_xpad->Stick.Left.Y.Start = old_xpad->Stick.Left.Y.End; | ||||
|  | ||||
| 					// TODO(Ed) : Compress this into a proc | ||||
| 					f32 X; | ||||
| 					if ( xpad->sThumbLX < 0 ) | ||||
| 					{ | ||||
| 						X = scast(f32, xpad->sThumbLX) / scast(f32, -S16_MIN); | ||||
| 					} | ||||
| 					else | ||||
| 					{ | ||||
| 						X = scast(f32, xpad->sThumbLX) / scast(f32, S16_MAX); | ||||
| 					} | ||||
| 					f32 left_x = xinput_process_axis_value( xpad->sThumbLX, XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE ); | ||||
| 					f32 left_y = xinput_process_axis_value( xpad->sThumbLY, XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE ); | ||||
|  | ||||
| 					// TODO(Ed) : Min/Max macros!!! | ||||
| 					new_xpad->Stick.Left.X.Min = new_xpad->Stick.Left.X.Max = new_xpad->Stick.Left.X.End = X; | ||||
|  | ||||
| 					f32 Y; | ||||
| 					if ( xpad->sThumbLY < 0 ) | ||||
| 					{ | ||||
| 						Y = scast(f32, xpad->sThumbLY) / scast(f32, -S16_MIN); | ||||
| 					} | ||||
| 					else | ||||
| 					{ | ||||
| 						Y = scast(f32, xpad->sThumbLY) / scast(f32, S16_MAX); | ||||
| 					} | ||||
|  | ||||
| 					// TODO(Ed) : Min/Max macros!!! | ||||
| 					new_xpad->Stick.Left.Y.Min = new_xpad->Stick.Left.Y.Max = new_xpad->Stick.Left.Y.End = Y; | ||||
|  | ||||
|  | ||||
|  | ||||
| 					// epad->Stick.Left.X.End  = xpad->sThumbLX; | ||||
| 					// epad->Stick.Left.Y.End  = xpad->sThumbLY; | ||||
| 					// epad->Stick.Right.X.End = xpad->sThumbRX; | ||||
| 					// epad->Stick.Right.X.End = xpad->sThumbRY; | ||||
|  | ||||
| 					// TODO(Ed) : Dead zone processing!!!!!!!!!!!!!!! | ||||
| 					// XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE | ||||
| 					// XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE | ||||
|  | ||||
| 					// S16_MAX | ||||
| 					// S16_MIN | ||||
| 					new_xpad->Stick.Left.X.Min = new_xpad->Stick.Left.X.Max = new_xpad->Stick.Left.X.End = left_x; | ||||
| 					new_xpad->Stick.Left.Y.Min = new_xpad->Stick.Left.Y.Max = new_xpad->Stick.Left.Y.End = left_y; | ||||
| 					 | ||||
| 					// TODO(Ed): Make this actually an average for later | ||||
| 					new_xpad->Stick.Left.X.Average = left_x; | ||||
| 					new_xpad->Stick.Left.Y.Average = left_y; | ||||
|  | ||||
| 					input.Controllers[ controller_index ].XPad = new_xpad; | ||||
| 				} | ||||
| @@ -888,7 +943,7 @@ WinMain( | ||||
| 				if ( jsl_device_index > 4 ) | ||||
| 					break; | ||||
|  | ||||
| 				JOY_SHOCK_STATE       state = JslGetSimpleState( jsl_device_handles[ jsl_device_index ] ); | ||||
| 				JOY_SHOCK_STATE state = JslGetSimpleState( jsl_device_handles[ jsl_device_index ] ); | ||||
| 				engine::DualsensePadState* old_ds_pad  = old_ds_pads[ jsl_device_index ]; | ||||
| 				engine::DualsensePadState* new_ds_pad  = new_ds_pads[ jsl_device_index ]; | ||||
|  | ||||
| @@ -908,10 +963,20 @@ WinMain( | ||||
| 				input_process_digital_btn( & old_ds_pad->L1, & new_ds_pad->L1, state.buttons, JSMASK_L ); | ||||
| 				input_process_digital_btn( & old_ds_pad->R1, & new_ds_pad->R1, state.buttons, JSMASK_R ); | ||||
|  | ||||
| 				// epad->Stick.Left.X.End  = state.stickLX; | ||||
| 				// epad->Stick.Left.Y.End  = state.stickLY; | ||||
| 				// epad->Stick.Right.X.End = state.stickRX; | ||||
| 				// epad->Stick.Right.X.End = state.stickRY; | ||||
| 				new_ds_pad->Stick.Left.X.Start = old_ds_pad->Stick.Left.X.End; | ||||
| 				new_ds_pad->Stick.Left.Y.Start = old_ds_pad->Stick.Left.Y.End; | ||||
|  | ||||
| 				// Joyshock abstracts the sticks to a float value already for us of -1.f to 1.f. | ||||
| 				// We'll assume a deadzone of 10% for now. | ||||
| 				f32 left_x = input_process_axis_value( state.stickLX, 0.1f ); | ||||
| 				f32 left_y = input_process_axis_value( state.stickLY, 0.1f ); | ||||
|  | ||||
| 				new_ds_pad->Stick.Left.X.Min = new_ds_pad->Stick.Left.X.Max = new_ds_pad->Stick.Left.X.End = left_x; | ||||
| 				new_ds_pad->Stick.Left.Y.Min = new_ds_pad->Stick.Left.Y.Max = new_ds_pad->Stick.Left.Y.End = left_y; | ||||
| 				 | ||||
| 				// TODO(Ed): Make this actually an average for later | ||||
| 				new_ds_pad->Stick.Left.X.Average = left_x; | ||||
| 				new_ds_pad->Stick.Left.Y.Average = left_y; | ||||
|  | ||||
| 				input.Controllers[ jsl_device_index ].DSPad = new_ds_pad; | ||||
| 			} | ||||
|   | ||||
| @@ -52,9 +52,9 @@ | ||||
|  | ||||
| #if Build_Development | ||||
| #	define assert( expression ) \ | ||||
| 		if ( !( expression ) )   \ | ||||
| 		{                        \ | ||||
| 			*( int* )0 = 0;      \ | ||||
| 		if ( !( expression ) )  \ | ||||
| 		{                       \ | ||||
| 			__debugbreak();     \ | ||||
| 		} | ||||
| 	// platform::assertion_failure( __FILE__, __LINE__, #expression ); | ||||
| #else | ||||
| @@ -67,3 +67,41 @@ | ||||
| #define ensure( condition, expression ) | ||||
| #define fatal( message ) | ||||
| #endif | ||||
|  | ||||
| // Just experimenting with a way to check for global variables being accessed from the wrong place. | ||||
| // (Could also be done with gencpp technically) | ||||
| #if 0 | ||||
| enum class EGlobalVarsAllowFuncs | ||||
| { | ||||
| 	ProcessPendingWindowMessages, | ||||
| 	Num, | ||||
| 	Invalid, | ||||
| }; | ||||
| EGlobalVarsAllowFuncs to_type( char const* proc_name ) | ||||
| { | ||||
| 	char const* global_vars_allowed_funcs[] { | ||||
| 		"process_pending_window_messages" | ||||
| 	}; | ||||
|  | ||||
| 	if ( proc_name ) | ||||
| 	{ | ||||
| 		for ( u32 idx = 0; idx < array_count( global_vars_allowed_funcs ); ++idx ) | ||||
| 		{ | ||||
| 			if ( strcmp( proc_name, global_vars_allowed_funcs[idx] ) == 0 ) | ||||
| 			{ | ||||
| 				return scast( EGlobalVarsAllowFuncs, idx ); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return EGlobalVarsAllowFuncs::Invalid; | ||||
| } | ||||
|  | ||||
| #if Build_Development | ||||
| #	define checked_global_getter( global_var, procedure ) \ | ||||
| 	( ensure( to_type(procedure) != EGlobalVarsAllowFuncs::Invalid), global_var ) | ||||
| #else | ||||
| #	define checked_global_getter( global_var, procedure ) global_var | ||||
| #endif | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -12,7 +12,7 @@ | ||||
| #pragma warning( disable: 4189 ) // Support for unused variables | ||||
| #pragma warning( disable: 4514 ) // Support for unused inline functions | ||||
| #pragma warning( disable: 4505 ) // Support for unused static functions | ||||
| #pragma warning( disable: 5045 )  // Compiler will insert Spectre mitigation for memory load if /Qspectre switch specified | ||||
| #pragma warning( disable: 5045 ) // Compiler will insert Spectre mitigation for memory load if /Qspectre switch specified | ||||
|  | ||||
| #include "grime.h" | ||||
| #include "macros.h" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user