October3d55/M/AutoSettings/Source/AutoSettingsInput/Private/Tests/InputMappingTests.cpp

256 lines
13 KiB
C++

// Copyright Sam Bonifacio. All Rights Reserved.
#include "CoreTypes.h"
#include "InputMappingManager.h"
#include "PlayerInputMappings.h"
#include "Misc/AutomationTest.h"
#include "Misc/AutoSettingsInputConfig.h"
#if WITH_DEV_AUTOMATION_TESTS
/**
* Check that when null base preset is specified, the resulting layout is empty
*/
IMPLEMENT_SIMPLE_AUTOMATION_TEST(FEmptyPresetTest, "AutoSettings.Input.EmptyPreset", EAutomationTestFlags_ApplicationContextMask | EAutomationTestFlags::SmokeFilter)
bool FEmptyPresetTest::RunTest(const FString& Parameters)
{
UAutoSettingsInputConfig* Config = NewObject<UAutoSettingsInputConfig>();
const FPlayerInputMappings PlayerInputMappings = FPlayerInputMappings(true, Config);
// Check layout has nothing bound
const FInputMappingLayout MergedLayout = PlayerInputMappings.BuildMergedMappingLayout();
TestEqual(TEXT("Layout must have no actions bound"), MergedLayout.GetActions().Num(), 0);
TestEqual(TEXT("Layout must have no axes bound"), MergedLayout.GetAxes().Num(), 0);
return true;
}
/**
* Check that when an empty base preset tag is specified, the resulting layout is built on a default preset from the config
*/
IMPLEMENT_SIMPLE_AUTOMATION_TEST(FDefaultPresetTest, "AutoSettings.Input.DefaultPreset", EAutomationTestFlags_ApplicationContextMask | EAutomationTestFlags::SmokeFilter)
bool FDefaultPresetTest::RunTest(const FString& Parameters)
{
UAutoSettingsInputConfig* Config = NewObject<UAutoSettingsInputConfig>();
// Add a preset to config
Config->InputPresets.Add(FInputMappingPreset(FGameplayTag::EmptyTag, false, Config));
FInputMappingPreset& Preset = Config->InputPresets.Last();
Preset.InputLayout.MappingGroups.Add(FInputMappingGroup(Config));
FInputMappingGroup& MappingGroup = Preset.InputLayout.MappingGroups.Last();
MappingGroup.ActionMappings.Add(FConfigActionKeyMapping(FInputActionKeyMapping(TEXT("Jump"), EKeys::SpaceBar)));
// Null base preset false, because we want to test with config preset
const FPlayerInputMappings PlayerInputMappings = FPlayerInputMappings(false, Config);
// Check second action is now bound
const FInputActionKeyMapping JumpAction = PlayerInputMappings.BuildMergedMappingLayout().GetAction(0, FName(TEXT("Jump")));
TestEqual(TEXT("Must inherit from default preset"), JumpAction.Key, EKeys::SpaceBar);
return true;
}
/**
* Check that the config object is registered at different levels of the input structure
*/
IMPLEMENT_SIMPLE_AUTOMATION_TEST(FConfigRegisteredTest, "AutoSettings.Input.ConfigRegistered", EAutomationTestFlags_ApplicationContextMask | EAutomationTestFlags::SmokeFilter)
bool FConfigRegisteredTest::RunTest(const FString& Parameters)
{
UAutoSettingsInputConfig* Config = NewObject<UAutoSettingsInputConfig>();
FPlayerInputMappings PlayerInputMappings = FPlayerInputMappings(true, Config);
PlayerInputMappings.AddAxisOverride(FInputAxisKeyMapping(FName(TEXT("MoveForward")), EKeys::I), 0, false);
TestEqual(TEXT("MappingOverrides must have the created config"), PlayerInputMappings.MappingOverrides.Config->_getUObject(), Cast<UObject>(Config));
TestEqual(TEXT("MappingGroup must have the created config"), PlayerInputMappings.MappingOverrides.MappingGroups[0].Config->_getUObject(), Cast<UObject>(Config));
return true;
}
/**
* Check that when a button is bound to an axis, the binding is applied correctly
*/
IMPLEMENT_SIMPLE_AUTOMATION_TEST(FMapPreviousAxisButtonTest, "AutoSettings.Input.BindPreviousAxisButton", EAutomationTestFlags_ApplicationContextMask | EAutomationTestFlags::SmokeFilter)
bool FMapPreviousAxisButtonTest::RunTest(const FString& Parameters)
{
UAutoSettingsInputConfig* Config = NewObject<UAutoSettingsInputConfig>();
FPlayerInputMappings PlayerInputMappings = FPlayerInputMappings(true, Config);
PlayerInputMappings.AddAxisOverride(FInputAxisKeyMapping(FName(TEXT("MoveForward")), EKeys::MouseY), 0, false);
PlayerInputMappings.AddAxisOverride(FInputAxisKeyMapping(FName(TEXT("MoveForward")), EKeys::W), 0, false);
const FInputAxisKeyMapping Axis = PlayerInputMappings.BuildMergedMappingLayout().GetAxis(0, FName(TEXT("MoveForward")), 1.f);
TestEqual(TEXT("Latest override must be current"), Axis.Key, EKeys::W);
return true;
}
/**
* Check that Multiple Bindings Per Key set to false correctly unbinds previous mappings
*/
IMPLEMENT_SIMPLE_AUTOMATION_TEST(FMultipleBindingsPerKeyDisallowTest, "AutoSettings.Input.MultipleBindingsPerKey.Disallow", EAutomationTestFlags_ApplicationContextMask | EAutomationTestFlags::SmokeFilter)
bool FMultipleBindingsPerKeyDisallowTest::RunTest(const FString& Parameters)
{
UAutoSettingsInputConfig* Config = NewObject<UAutoSettingsInputConfig>();
ensure(Config->AllowMultipleBindingsPerKey == false);
FPlayerInputMappings PlayerInputMappings = FPlayerInputMappings(true, Config);
// Bind two actions to the same key
PlayerInputMappings.AddActionOverride(FInputActionKeyMapping(FName(TEXT("FireWeapon")), EKeys::LeftMouseButton), 0, false);
PlayerInputMappings.AddActionOverride(FInputActionKeyMapping(FName(TEXT("Jump")), EKeys::LeftMouseButton), 0, false);
// Check second action is now bound
const FInputActionKeyMapping JumpAction = PlayerInputMappings.BuildMergedMappingLayout().GetAction(0, FName(TEXT("Jump")));
TestEqual(TEXT("Second action must be bound"), JumpAction.Key, EKeys::LeftMouseButton);
// Check first action is now unbound
const FInputActionKeyMapping FireWeaponAction = PlayerInputMappings.BuildMergedMappingLayout().GetAction(0, FName(TEXT("FireWeapon")));
TestEqual(TEXT("First action must be unbound by the second"), FireWeaponAction.Key, EKeys::Invalid);
return true;
}
/**
* Check that Multiple Bindings Per Key set to true correctly preserves previous mappings
*/
IMPLEMENT_SIMPLE_AUTOMATION_TEST(FMultipleBindingsPerKeyAllowTest, "AutoSettings.Input.MultipleBindingsPerKey.Allow", EAutomationTestFlags_ApplicationContextMask | EAutomationTestFlags::SmokeFilter)
bool FMultipleBindingsPerKeyAllowTest::RunTest(const FString& Parameters)
{
UAutoSettingsInputConfig* Config = NewObject<UAutoSettingsInputConfig>();
Config->AllowMultipleBindingsPerKey = true;
FPlayerInputMappings PlayerInputMappings = FPlayerInputMappings(true, Config);
// Bind two actions to the same key
PlayerInputMappings.AddActionOverride(FInputActionKeyMapping(FName(TEXT("FireWeapon")), EKeys::LeftMouseButton), 0, false);
PlayerInputMappings.AddActionOverride(FInputActionKeyMapping(FName(TEXT("Jump")), EKeys::LeftMouseButton), 0, false);
// Check second action is now bound
const FInputActionKeyMapping JumpAction = PlayerInputMappings.BuildMergedMappingLayout().GetAction(0, FName(TEXT("Jump")));
TestEqual(TEXT("Second action must be bound"), JumpAction.Key, EKeys::LeftMouseButton);
// Check first action is still bound
const FInputActionKeyMapping FireWeaponAction = PlayerInputMappings.BuildMergedMappingLayout().GetAction(0, FName(TEXT("FireWeapon")));
TestEqual(TEXT("First action must still be bound"), FireWeaponAction.Key, EKeys::LeftMouseButton);
return true;
}
/**
* Check that linked mapping groups functions correctly by unbinding mappings on linked groups, but not on other groups
*/
IMPLEMENT_SIMPLE_AUTOMATION_TEST(FLinkedMappingGroupsTest, "AutoSettings.Input.LinkedMappingGroups", EAutomationTestFlags_ApplicationContextMask | EAutomationTestFlags::SmokeFilter)
bool FLinkedMappingGroupsTest::RunTest(const FString& Parameters)
{
UAutoSettingsInputConfig* Config = NewObject<UAutoSettingsInputConfig>();
Config->AllowMultipleBindingsPerKey = true;
Config->MappingGroupLinks.Add(FMappingGroupLink({ 0, 1 }));
FPlayerInputMappings PlayerInputMappings = FPlayerInputMappings(true, Config);
// Bind two actions on linked groups to the same key
PlayerInputMappings.AddActionOverride(FInputActionKeyMapping(FName(TEXT("FireWeapon")), EKeys::LeftMouseButton), 0, false);
PlayerInputMappings.AddActionOverride(FInputActionKeyMapping(FName(TEXT("Jump")), EKeys::LeftMouseButton), 1, false);
// Bind another action on an unlinked group
PlayerInputMappings.AddActionOverride(FInputActionKeyMapping(FName(TEXT("Crouch")), EKeys::LeftMouseButton), 2, false);
// Check second action is now bound
const FInputActionKeyMapping JumpAction = PlayerInputMappings.BuildMergedMappingLayout().GetAction(1, FName(TEXT("Jump")));
TestEqual(TEXT("Second action must be bound"), JumpAction.Key, EKeys::LeftMouseButton);
// Check first action is unbound
const FInputActionKeyMapping FireWeaponAction = PlayerInputMappings.BuildMergedMappingLayout().GetAction(0, FName(TEXT("FireWeapon")));
TestEqual(TEXT("First action must be unbound by the second"), FireWeaponAction.Key, EKeys::Invalid);
// Check third action is bound
const FInputActionKeyMapping CrouchAction = PlayerInputMappings.BuildMergedMappingLayout().GetAction(2, FName(TEXT("Crouch")));
TestEqual(TEXT("Third action must be bound"), CrouchAction.Key, EKeys::LeftMouseButton);
return true;
}
/**
* Check that deprecated mapping properties can be migrated
*/
IMPLEMENT_SIMPLE_AUTOMATION_TEST(FMigrateDeprecatedPropertiesTest, "AutoSettings.Input.MigrateDeprecatedProperties", EAutomationTestFlags_ApplicationContextMask | EAutomationTestFlags::SmokeFilter)
bool FMigrateDeprecatedPropertiesTest::RunTest(const FString& Parameters)
{
UAutoSettingsInputConfig* Config = NewObject<UAutoSettingsInputConfig>();
// Add a preset to config
Config->InputPresets.Add(FInputMappingPreset(FGameplayTag::EmptyTag, false, Config));
FInputMappingPreset& Preset = Config->InputPresets.Last();
Preset.InputLayout.MappingGroups.Add(FInputMappingGroup(Config));
FInputMappingGroup& MappingGroup = Preset.InputLayout.MappingGroups.Last();
// Add a preset mapping
MappingGroup.ActionMappings.Add(FConfigActionKeyMapping(FInputActionKeyMapping(TEXT("Jump"), EKeys::SpaceBar)));
// Create raw PlayerInputMappings as if it were an old version loaded from config
FPlayerInputMappings PlayerInputMappings = FPlayerInputMappings();
PlayerInputMappings.PlayerIndex_DEPRECATED = 1;
PlayerInputMappings.BasePresetTag = FGameplayTag::EmptyTag;
PlayerInputMappings.Preset_DEPRECATED.MappingGroups_DEPRECATED.AddDefaulted();
// Add some mappings
PlayerInputMappings.Preset_DEPRECATED.MappingGroups_DEPRECATED[0].ActionMappings.Add(FConfigActionKeyMapping(FInputActionKeyMapping(TEXT("Jump"), EKeys::SpaceBar)));
PlayerInputMappings.Preset_DEPRECATED.MappingGroups_DEPRECATED[0].ActionMappings.Add(FConfigActionKeyMapping(FInputActionKeyMapping(TEXT("FireWeapon"), EKeys::LeftMouseButton)));
// Migrate
PlayerInputMappings.SetConfig(Config);
PlayerInputMappings.MigrateDeprecatedProperties();
// Jump override should now be invalid, because it already exists on the preset
FInputActionKeyMapping JumpAction = PlayerInputMappings.MappingOverrides.GetAction(0, TEXT("Jump"));
TestEqual(TEXT("Jump key"), JumpAction.Key, EKeys::Invalid);
// Fire weapon should be bound to left mouse button
FInputActionKeyMapping FireWeaponAction = PlayerInputMappings.MappingOverrides.GetAction(0, TEXT("FireWeapon"));
TestEqual(TEXT("Fire weapon key"), FireWeaponAction.Key, EKeys::LeftMouseButton);
return true;
}
/**
* Check preserved actions are respected
*/
IMPLEMENT_SIMPLE_AUTOMATION_TEST(FPreservedActionsTest, "AutoSettings.Input.PreservedActions", EAutomationTestFlags_ApplicationContextMask | EAutomationTestFlags::SmokeFilter)
bool FPreservedActionsTest::RunTest(const FString& Parameters)
{
UAutoSettingsInputConfig* Config = NewObject<UAutoSettingsInputConfig>();
// Add a preset to config
Config->InputPresets.Add(FInputMappingPreset(FGameplayTag::EmptyTag, false, Config));
FInputMappingPreset& Preset = Config->InputPresets.Last();
Preset.InputLayout.MappingGroups.Add(FInputMappingGroup(Config));
FInputMappingGroup& MappingGroup = Preset.InputLayout.MappingGroups.Last();
// Add a preset mapping
MappingGroup.ActionMappings.Add(FConfigActionKeyMapping(FInputActionKeyMapping(TEXT("UIAction"), EKeys::Escape)));
MappingGroup.ActionMappings.Add(FConfigActionKeyMapping(FInputActionKeyMapping(TEXT("Jump"), EKeys::SpaceBar)));
// Add the UI action as a preserved action
Config->PreservedActions.Add(TEXT("UIAction"));
FPlayerInputMappings PlayerInputMappings = FPlayerInputMappings(false, Config);
// Test UIAction is initially bound to escape
const FInputActionKeyMapping UIActionBefore = PlayerInputMappings.BuildMergedMappingLayout().GetAction(0, FName(TEXT("UIAction")));
TestEqual(TEXT("UI action must be bound before rebinding"), UIActionBefore.Key, EKeys::Escape);
// Rebind Jump to escape
PlayerInputMappings.AddActionOverride(FInputActionKeyMapping(FName(TEXT("Jump")), EKeys::Escape), 0, false);
// Test UIAction is still bound to escape
const FInputActionKeyMapping UIActionAfter = PlayerInputMappings.BuildMergedMappingLayout().GetAction(0, FName(TEXT("UIAction")));
TestEqual(TEXT("UI action must be bound after rebinding"), UIActionAfter.Key, EKeys::Escape);
return true;
}
#endif