I think I tracked down the issue.
With a game pad connected...
In handmade.cpp...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 | void GameUpdateAndRender(/*...*/)
{
//...
for (/* all controllers */)
{
game_controller_input *Controller = GetController(Input, ControllerIndex);
if(Controller->IsAnalog)
{
//...process StickAverageX value
}
else
{
//...process MoveLeft or MoveRight
}
//...processs ActionDown
}
//...
}
|
The focus here is that keyboard input for MoveLeft or MoveRight is processed only
for non-analog controllers. ActionDown is for all controllers. (This is where the "root"
problem lies. I was too focused on the platform code when a clear read of the game code
might have saved time.)
There is no check for unconnected controllers but means that unconnected controllers use
the default value for IsAnalog, which is 0 == false so they are processed for keyboard.
Unconnected controllers will never alter MoveLeft, MoveRight, or ActionDown so they have
no effect.
In win32_handmade.cpp...
With a connected controller...but keybaord input only
ActionDown is first set by the keybaord through Win32ProcessPendingMessages,
| //...
else if(VKCode == VK_DOWN)
{
Win32ProcessKeyboardMessage(&KeyboardController->ActionDown, IsDown);
}
//...
|
Next the iteration through the controllers happens. The key is the game pad is
untouched so it remains in a default state. The logic to toggle IsAnalog has no effect
and IsAnalog should be false.
But then gamepad is polled
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 | //...
Win32ProcessXInputDigitalButton(
(NewController->StickAverageX < -Threshold) ? 1 : 0,
&OldController->MoveLeft, 1,
&NewController->MoveLeft);
Win32ProcessXInputDigitalButton(
(NewController->StickAverageX > Threshold) ? 1 : 0,
&OldController->MoveRight, 1,
&NewController->MoveRight);
//...
Win32ProcessXInputDigitalButton(Pad->wButtons,
&OldController->ActionDown, XINPUT_GAMEPAD_A,
&NewController->ActionDown);
//...
void Win32ProcessXInputDigitalButton(/*...*/)
{
NewState->EndedDown = ((XInputButtonState & ButtonBit) == ButtonBit);
NewState->HalfTransitionCount = (OldState->EndedDown != NewState->EndedDown) ? 1 : 0;
}
|
and the keyboard MoveLeft, MoveRight, and ActionDown get over-written.
Finally, the swapping of input controlers at the end of each frame is ok as long as
the keyboard input is sent to the current input controller[0] after controller[0]
is updated with the previous keyboard state.
This explains why in my code when the gamepad is not connected, the keyboard input
is fine but "disappears" when the gamepad is connected.
I think.
- tim