diff --git a/src/cdogs/gamedata.c b/src/cdogs/gamedata.c index 075ace5e1..433e9190b 100644 --- a/src/cdogs/gamedata.c +++ b/src/cdogs/gamedata.c @@ -409,8 +409,13 @@ void GetPlayerCmds( int i; for (i = 0; i < MAX_PLAYERS; i++) { + if (playerDatas[i].inputDevice == INPUT_DEVICE_UNSET) + { + continue; + } (*cmds)[i] = GetOnePlayerCmd( - &gConfig.Input.PlayerKeys[i], keyFunc, mouseFunc, joyFunc, + &gConfig.Input.PlayerKeys[playerDatas[i].deviceIndex], + keyFunc, mouseFunc, joyFunc, playerDatas[i].inputDevice, playerDatas[i].deviceIndex); } } @@ -446,7 +451,7 @@ int GetMenuCmd(struct PlayerData playerDatas[MAX_PLAYERS]) int GetGameCmd( InputDevices *devices, InputConfig *config, - int player, struct PlayerData *playerData, Vec2i playerPos) + struct PlayerData *playerData, Vec2i playerPos) { int cmd = 0; joystick_t *joystick = &devices->joysticks.joys[0]; @@ -456,7 +461,7 @@ int GetGameCmd( case INPUT_DEVICE_KEYBOARD: cmd = GetKeyboardCmd( &devices->keyboard, - &config->PlayerKeys[player].Keys, + &config->PlayerKeys[playerData->deviceIndex].Keys, KeyIsDown); break; case INPUT_DEVICE_MOUSE: diff --git a/src/cdogs/gamedata.h b/src/cdogs/gamedata.h index c6a5eff5a..1cd872f0e 100644 --- a/src/cdogs/gamedata.h +++ b/src/cdogs/gamedata.h @@ -292,7 +292,7 @@ void GetPlayerCmds( int GetMenuCmd(struct PlayerData playerDatas[MAX_PLAYERS]); int GetGameCmd( InputDevices *devices, InputConfig *config, - int player, struct PlayerData *playerData, Vec2i playerPos); + struct PlayerData *playerData, Vec2i playerPos); int GameIsMouseUsed(struct PlayerData playerDatas[MAX_PLAYERS]); #endif diff --git a/src/cdogs/utils.h b/src/cdogs/utils.h index 17ee87faf..58e30dff5 100644 --- a/src/cdogs/utils.h +++ b/src/cdogs/utils.h @@ -119,6 +119,7 @@ double ToDegrees(double radians); typedef enum { + INPUT_DEVICE_UNSET, INPUT_DEVICE_KEYBOARD, INPUT_DEVICE_MOUSE, INPUT_DEVICE_JOYSTICK, diff --git a/src/game.c b/src/game.c index 3e0ca348d..146a13f34 100644 --- a/src/game.c +++ b/src/game.c @@ -490,7 +490,7 @@ int HandleKey(int cmd, int *isPaused) { cmd |= GetGameCmd( &gInputDevices, &gConfig.Input, - i, &gPlayerDatas[i], Vec2iZero()); + &gPlayerDatas[i], Vec2iZero()); } } } @@ -630,7 +630,6 @@ int gameloop(void) cmds[i] = GetGameCmd( &gInputDevices, &gConfig.Input, - i, &gPlayerDatas[i], GetPlayerCenter(&gGraphicsDevice, i)); cmdAll |= cmds[i]; diff --git a/src/menu_utils.c b/src/menu_utils.c index d86dcd517..b57e642ae 100644 --- a/src/menu_utils.c +++ b/src/menu_utils.c @@ -73,37 +73,41 @@ void MenuDisplayPlayerControls( switch (d->pData->inputDevice) { case INPUT_DEVICE_KEYBOARD: - sprintf(s, "(%s, %s, %s, %s, %s and %s)", - SDL_GetKeyName(d->keys->Keys.left), - SDL_GetKeyName(d->keys->Keys.right), - SDL_GetKeyName(d->keys->Keys.up), - SDL_GetKeyName(d->keys->Keys.down), - SDL_GetKeyName(d->keys->Keys.button1), - SDL_GetKeyName(d->keys->Keys.button2)); - textWidth = TextGetStringWidth(s); - if (textWidth < 125) - { - textPos.x = pos.x - textWidth / 2; - DrawTextString(s, g, textPos); - } - else { - sprintf(s, "(%s, %s, %s,", - SDL_GetKeyName(d->keys->Keys.left), - SDL_GetKeyName(d->keys->Keys.right), - SDL_GetKeyName(d->keys->Keys.up)); - textWidth = TextGetStringWidth(s); - textPos.x = pos.x - textWidth / 2; - textPos.y -= 10; - DrawTextString(s, g, textPos); - sprintf(s, "%s, %s and %s)", - SDL_GetKeyName(d->keys->Keys.down), - SDL_GetKeyName(d->keys->Keys.button1), - SDL_GetKeyName(d->keys->Keys.button2)); + input_keys_t *keys = + &d->inputConfig->PlayerKeys[d->pData->deviceIndex].Keys; + sprintf(s, "(%s, %s, %s, %s, %s and %s)", + SDL_GetKeyName(keys->left), + SDL_GetKeyName(keys->right), + SDL_GetKeyName(keys->up), + SDL_GetKeyName(keys->down), + SDL_GetKeyName(keys->button1), + SDL_GetKeyName(keys->button2)); textWidth = TextGetStringWidth(s); - textPos.x = pos.x - textWidth / 2; - textPos.y += 10; - DrawTextString(s, g, textPos); + if (textWidth < 125) + { + textPos.x = pos.x - textWidth / 2; + DrawTextString(s, g, textPos); + } + else + { + sprintf(s, "(%s, %s, %s,", + SDL_GetKeyName(keys->left), + SDL_GetKeyName(keys->right), + SDL_GetKeyName(keys->up)); + textWidth = TextGetStringWidth(s); + textPos.x = pos.x - textWidth / 2; + textPos.y -= 10; + DrawTextString(s, g, textPos); + sprintf(s, "%s, %s and %s)", + SDL_GetKeyName(keys->down), + SDL_GetKeyName(keys->button1), + SDL_GetKeyName(keys->button2)); + textWidth = TextGetStringWidth(s); + textPos.x = pos.x - textWidth / 2; + textPos.y += 10; + DrawTextString(s, g, textPos); + } } break; case INPUT_DEVICE_MOUSE: diff --git a/src/menu_utils.h b/src/menu_utils.h index 563008c7a..306231240 100644 --- a/src/menu_utils.h +++ b/src/menu_utils.h @@ -44,7 +44,7 @@ void MenuDisplayPlayer(GraphicsDevice *g, Vec2i pos, Vec2i size, void *data); typedef struct { struct PlayerData *pData; - KeyConfig *keys; + InputConfig *inputConfig; } MenuDisplayPlayerControlsData; void MenuDisplayPlayerControls( GraphicsDevice *g, Vec2i pos, Vec2i size, void *data); diff --git a/src/player_select_menus.c b/src/player_select_menus.c index 45b51dfd7..127e9c7b1 100644 --- a/src/player_select_menus.c +++ b/src/player_select_menus.c @@ -499,7 +499,7 @@ static menu_t *CreateSaveTemplateMenu( void PlayerSelectMenusCreate( PlayerSelectMenu *menu, int numPlayers, int player, Character *c, struct PlayerData *pData, - InputDevices *input, GraphicsDevice *graphics, KeyConfig *key) + InputDevices *input, GraphicsDevice *graphics, InputConfig *inputConfig) { MenuSystem *ms = &menu->ms; PlayerSelectMenuData *data = &menu->data; @@ -513,7 +513,7 @@ void PlayerSelectMenusCreate( data->display.c = c; data->display.currentMenu = &ms->current; data->display.pData = pData; - data->controls.keys = key; + data->controls.inputConfig = inputConfig; data->controls.pData = pData; switch (numPlayers) diff --git a/src/player_select_menus.h b/src/player_select_menus.h index c117025ec..89eaac5d5 100644 --- a/src/player_select_menus.h +++ b/src/player_select_menus.h @@ -64,7 +64,7 @@ typedef struct void PlayerSelectMenusCreate( PlayerSelectMenu *menu, int numPlayers, int player, Character *c, struct PlayerData *pData, - InputDevices *input, GraphicsDevice *graphics, KeyConfig *key); + InputDevices *input, GraphicsDevice *graphics, InputConfig *inputConfig); // TODO: load templates from file typedef struct diff --git a/src/prep.c b/src/prep.c index 687c4ae25..6a28f2037 100644 --- a/src/prep.c +++ b/src/prep.c @@ -132,16 +132,93 @@ int NumPlayersSelection( return res; } + +static void AssignPlayerInputDevices( + int hasInputDevice[MAX_PLAYERS], int numPlayers, + struct PlayerData playerDatas[MAX_PLAYERS], + InputDevices *inputDevices, InputConfig *inputConfig) +{ + int i; + int assignedKeyboards[MAX_KEYBOARD_CONFIGS]; + int assignedMouse = 0; + int assignedJoysticks[MAX_JOYSTICKS]; + memset(assignedKeyboards, 0, sizeof assignedKeyboards); + memset(assignedJoysticks, 0, sizeof assignedJoysticks); + + for (i = 0; i < numPlayers; i++) + { + int j; + if (hasInputDevice[i]) + { + // Find all the assigned devices + switch (playerDatas[i].inputDevice) + { + case INPUT_DEVICE_KEYBOARD: + assignedKeyboards[playerDatas[i].deviceIndex] = 1; + break; + case INPUT_DEVICE_MOUSE: + assignedMouse = 1; + break; + case INPUT_DEVICE_JOYSTICK: + assignedJoysticks[playerDatas[i].deviceIndex] = 1; + break; + } + continue; + } + + // Try to assign devices to players + // For each unassigned player, check if any device has button 1 pressed + for (j = 0; j < MAX_KEYBOARD_CONFIGS; j++) + { + if (KeyIsPressed( + &inputDevices->keyboard, + inputConfig->PlayerKeys[j].Keys.button1) && + !assignedKeyboards[j]) + { + hasInputDevice[i] = 1; + playerDatas[i].inputDevice = INPUT_DEVICE_KEYBOARD; + playerDatas[i].deviceIndex = j; + assignedKeyboards[j] = 1; + continue; + } + } + if (MouseIsPressed(&inputDevices->mouse, SDL_BUTTON_LEFT) && + !assignedMouse) + { + hasInputDevice[i] = 1; + playerDatas[i].inputDevice = INPUT_DEVICE_MOUSE; + playerDatas[i].deviceIndex = 0; + assignedMouse = 1; + continue; + } + for (j = 0; j < inputDevices->joysticks.numJoys; j++) + { + if (JoyIsPressed( + &inputDevices->joysticks.joys[j], CMD_BUTTON1) && + !assignedJoysticks[j]) + { + hasInputDevice[i] = 1; + playerDatas[i].inputDevice = INPUT_DEVICE_JOYSTICK; + playerDatas[i].deviceIndex = j; + assignedJoysticks[j] = 1; + continue; + } + } + } +} + int PlayerSelection(int numPlayers, GraphicsDevice *graphics) { int i; + int hasInputDevice[MAX_PLAYERS]; PlayerSelectMenu menus[MAX_PLAYERS]; for (i = 0; i < numPlayers; i++) { PlayerSelectMenusCreate( &menus[i], numPlayers, i, &gCampaign.Setting.characters.players[i], &gPlayerDatas[i], - &gInputDevices, graphics, &gConfig.Input.PlayerKeys[i]); + &gInputDevices, graphics, &gConfig.Input); + hasInputDevice[i] = 0; } KeyInit(&gInputDevices.keyboard); @@ -158,7 +235,10 @@ int PlayerSelection(int numPlayers, GraphicsDevice *graphics) GetPlayerCmds(&cmds, gPlayerDatas); for (i = 0; i < numPlayers; i++) { - MenuProcessCmd(&menus[i].ms, cmds[i]); + if (hasInputDevice[i]) + { + MenuProcessCmd(&menus[i].ms, cmds[i]); + } } for (i = 0; i < numPlayers; i++) { @@ -172,10 +252,40 @@ int PlayerSelection(int numPlayers, GraphicsDevice *graphics) break; } + AssignPlayerInputDevices( + hasInputDevice, numPlayers, + gPlayerDatas, &gInputDevices, &gConfig.Input); + GraphicsBlitBkg(graphics); for (i = 0; i < numPlayers; i++) { - MenuDisplay(&menus[i].ms); + if (hasInputDevice[i]) + { + MenuDisplay(&menus[i].ms); + } + else + { + Vec2i center; + const char *prompt = "Press Fire to join..."; + Vec2i offset = Vec2iScaleDiv(TextGetSize(prompt), -2); + int w = graphics->cachedConfig.ResolutionWidth; + int h = graphics->cachedConfig.ResolutionHeight; + switch (numPlayers) + { + case 1: + // Center of screen + center = Vec2iNew(w / 2, h / 2); + break; + case 2: + // Side by side + center = Vec2iNew(i * w / 2 + w / 4, h / 2); + break; + default: + assert(0 && "not implemented"); + break; + } + DrawTextString(prompt, graphics, Vec2iAdd(center, offset)); + } } BlitFlip(graphics, &gConfig.Graphics); SDL_Delay(10); @@ -197,7 +307,7 @@ int PlayerEquip(int numPlayers, GraphicsDevice *graphics) WeaponMenuCreate( &menus[i], numPlayers, i, &gCampaign.Setting.characters.players[i], &gPlayerDatas[i], - &gInputDevices, graphics, &gConfig.Input.PlayerKeys[i]); + &gInputDevices, graphics, &gConfig.Input); } debug(D_NORMAL, "\n"); @@ -214,11 +324,20 @@ int PlayerEquip(int numPlayers, GraphicsDevice *graphics) GetPlayerCmds(&cmds, gPlayerDatas); for (i = 0; i < numPlayers; i++) { - MenuProcessCmd(&menus[i].ms, cmds[i]); + if (!MenuIsExit(&menus[i].ms)) + { + MenuProcessCmd(&menus[i].ms, cmds[i]); + } + else if (gPlayerDatas[i].weaponCount == 0) + { + // Check exit condition; must have selected at least one weapon + // Otherwise reset the current menu + menus[i].ms.current = menus[i].ms.root; + } } for (i = 0; i < numPlayers; i++) { - if (!MenuIsExit(&menus[i].ms) || gPlayerDatas[i].weaponCount == 0) + if (!MenuIsExit(&menus[i].ms)) { isDone = 0; } diff --git a/src/prep.h b/src/prep.h index cca22a854..b3548834e 100644 --- a/src/prep.h +++ b/src/prep.h @@ -56,7 +56,11 @@ int NumPlayersSelection( int *numPlayers, campaign_mode_e mode, GraphicsDevice *graphics, InputDevices *input); + +// Allow input devices to take control players, +// and select player name and appearance int PlayerSelection(int numPlayers, GraphicsDevice *graphics); + int PlayerEquip(int numPlayers, GraphicsDevice *graphics); #endif diff --git a/src/weapon_menu.c b/src/weapon_menu.c index 3d026efcb..6bb04c0dd 100644 --- a/src/weapon_menu.c +++ b/src/weapon_menu.c @@ -102,7 +102,7 @@ static void DisplayEquippedWeapons( void WeaponMenuCreate( WeaponMenu *menu, int numPlayers, int player, Character *c, struct PlayerData *pData, - InputDevices *input, GraphicsDevice *graphics, KeyConfig *key) + InputDevices *input, GraphicsDevice *graphics, InputConfig *inputConfig) { MenuSystem *ms = &menu->ms; WeaponMenuData *data = &menu->data; @@ -115,7 +115,7 @@ void WeaponMenuCreate( data->display.c = c; data->display.currentMenu = &ms->current; data->display.pData = pData; - data->controls.keys = key; + data->controls.inputConfig = inputConfig; data->controls.pData = pData; switch (numPlayers) diff --git a/src/weapon_menu.h b/src/weapon_menu.h index 87557f08c..161e0c3c5 100644 --- a/src/weapon_menu.h +++ b/src/weapon_menu.h @@ -46,6 +46,6 @@ typedef struct void WeaponMenuCreate( WeaponMenu *menu, int numPlayers, int player, Character *c, struct PlayerData *pData, - InputDevices *input, GraphicsDevice *graphics, KeyConfig *key); + InputDevices *input, GraphicsDevice *graphics, InputConfig *inputConfig); #endif