CogInput: Improve CogWindow_Actions

- Remove the need of the Input DataAsset used to identify the input mapping context
- Display the Input Contexts in priority order
- Cleanup the UI
This commit is contained in:
Arnaud Jamin
2025-01-09 00:54:26 -05:00
parent 469aab67d3
commit cb98140f1d
13 changed files with 294 additions and 216 deletions
-1
View File
@@ -19,7 +19,6 @@ bIgnoreMissingCookedAssetRegistryData=False
+PrimaryAssetTypesToScan=(PrimaryAssetType="PrimaryAssetLabel",AssetBaseClass="/Script/Engine.PrimaryAssetLabel",bHasBlueprintClasses=False,bIsEditorOnly=True,Directories=((Path="/Game")),SpecificAssets=,Rules=(Priority=-1,ChunkId=-1,bApplyRecursively=True,CookRule=Unknown))
+PrimaryAssetTypesToScan=(PrimaryAssetType="CogAbilityDataAsset",AssetBaseClass="/Script/CogAbility.CogAbilityDataAsset",bHasBlueprintClasses=False,bIsEditorOnly=False,Directories=((Path="/Game/Core/Debug")),SpecificAssets=,Rules=(Priority=-1,ChunkId=-1,bApplyRecursively=True,CookRule=DevelopmentAlwaysProductionNeverCook))
+PrimaryAssetTypesToScan=(PrimaryAssetType="CogEngineDataAsset",AssetBaseClass="/Script/CogEngine.CogEngineDataAsset",bHasBlueprintClasses=False,bIsEditorOnly=False,Directories=((Path="/Game/Core/Debug")),SpecificAssets=,Rules=(Priority=-1,ChunkId=-1,bApplyRecursively=True,CookRule=DevelopmentAlwaysProductionNeverCook))
+PrimaryAssetTypesToScan=(PrimaryAssetType="CogInputDataAsset",AssetBaseClass="/Script/CogInput.CogInputDataAsset",bHasBlueprintClasses=False,bIsEditorOnly=False,Directories=((Path="/Game/Core/Debug")),SpecificAssets=,Rules=(Priority=-1,ChunkId=-1,bApplyRecursively=True,CookRule=DevelopmentAlwaysProductionNeverCook))
bOnlyCookProductionAssets=False
bShouldManagerDetermineTypeAndName=False
bShouldGuessTypeAndNameInEditor=True
Binary file not shown.
Binary file not shown.
@@ -33,13 +33,13 @@ void FCogWindowWidgets::EndTableTooltip()
//--------------------------------------------------------------------------------------------------------------------------
void FCogWindowWidgets::ThinSeparatorText(const char* Label)
{
ImGui::PushStyleVar(ImGuiStyleVar_SeparatorTextBorderSize, 2);
ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(100, 100, 100, 255));
ImGui::PushStyleVar(ImGuiStyleVar_SeparatorTextBorderSize, 2);
ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(100, 100, 100, 255));
ImGui::SeparatorText(Label);
ImGui::SeparatorText(Label);
ImGui::PopStyleColor();
ImGui::PopStyleVar();
ImGui::PopStyleVar();
}
//--------------------------------------------------------------------------------------------------------------------------
@@ -226,10 +226,10 @@ void FCogWindowWidgets::AddTextWithShadow(ImDrawList* DrawList, const ImVec2& Po
//--------------------------------------------------------------------------------------------------------------------------
void FCogWindowWidgets::SearchBar(ImGuiTextFilter& Filter, float Width /*= -1*/)
{
const ImGuiWindow* Window = FCogImguiHelper::GetCurrentWindow();
const ImVec2 Pos1 = Window->DC.CursorPos;
const ImGuiWindow* Window = FCogImguiHelper::GetCurrentWindow();
const ImVec2 Pos1 = Window->DC.CursorPos;
Filter.Draw("##Filter", Width);
const ImVec2 Pos2 = Window->DC.CursorPosPrevLine;
const ImVec2 Pos2 = Window->DC.CursorPosPrevLine;
if (ImGui::IsItemActive() == false && Filter.Filters.empty())
{
@@ -355,7 +355,7 @@ bool FCogWindowWidgets::ComboboxEnum(const char* Label, UEnum* Enum, int64 Curre
}
//--------------------------------------------------------------------------------------------------------------------------
bool FCogWindowWidgets::CheckBoxState(const char* Label, ECheckBoxState& State)
bool FCogWindowWidgets::CheckBoxState(const char* Label, ECheckBoxState& State, bool ShowTooltip)
{
const char* TooltipText = "Invalid";
@@ -399,14 +399,14 @@ bool FCogWindowWidgets::CheckBoxState(const char* Label, ECheckBoxState& State)
ImGui::PopStyleColor(5);
if (ImGui::IsItemHovered(ImGuiHoveredFlags_Stationary))
if (ShowTooltip)
{
ImGui::SetTooltip("%s", TooltipText);
ImGui::SetItemTooltip("%s", TooltipText);
}
if (IsPressed)
if (IsPressed)
{
switch (State)
switch (State)
{
case ECheckBoxState::Checked: State = ECheckBoxState::Unchecked; break;
case ECheckBoxState::Unchecked: State = ECheckBoxState::Undetermined; break;
@@ -682,7 +682,7 @@ bool FCogWindowWidgets::CollisionProfileChannel(const UCollisionProfile& Collisi
bool Result = false;
FCogImguiHelper::ColorEdit4("Color", ChannelColor, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel);
ImGui::SameLine();
ImGui::SameLine();
bool IsCollisionActive = (Channels & ECC_TO_BITFIELD(ChannelIndex)) > 0;
const FName ChannelName = CollisionProfile.ReturnChannelNameFromContainerIndex(ChannelIndex);
@@ -700,7 +700,7 @@ bool FCogWindowWidgets::CollisionProfileChannel(const UCollisionProfile& Collisi
}
}
return Result;
return Result;
}
//--------------------------------------------------------------------------------------------------------------------------
@@ -822,7 +822,7 @@ bool FCogWindowWidgets::ActorsList(AActor*& NewSelection, const UWorld& World, c
{
for (int32 i = Clipper.DisplayStart; i < Clipper.DisplayEnd; i++)
{
AActor* Actor = Actors[i];
AActor* Actor = Actors[i];
if (Actor == nullptr)
{
continue;
@@ -880,9 +880,9 @@ bool FCogWindowWidgets::MenuActorsCombo(const char* StrID, AActor*& NewSelection
const ImVec2 Pos1 = ImGui::GetCursorScreenPos();
const float Width = FCogImguiHelper::GetNextItemWidth();
//-----------------------------------
// Combo button
//-----------------------------------
//-----------------------------------
// Combo button
//-----------------------------------
{
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f));
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0.0f, 0.5f));
@@ -920,8 +920,8 @@ bool FCogWindowWidgets::MenuActorsCombo(const char* StrID, AActor*& NewSelection
}
//-----------------------------------
// Popup
//-----------------------------------
// Popup
//-----------------------------------
const ImVec2 Pos2 = ImGui::GetCursorScreenPos();
ImGui::SetNextWindowPos(ImVec2(Pos1.x, Pos1.y + ImGui::GetFrameHeight()));
if (ImGui::BeginPopup("ActorListPopup"))
@@ -946,10 +946,10 @@ bool FCogWindowWidgets::MenuActorsCombo(const char* StrID, AActor*& NewSelection
//--------------------------------------------------------------------------------------------------------------------------
void FCogWindowWidgets::ActorContextMenu(AActor& Selection, const FCogWindowActorContextMenuFunction& ContextMenuFunction)
{
if (ContextMenuFunction == nullptr)
{
if (ContextMenuFunction == nullptr)
{
return;
}
}
ImGui::SetNextWindowSize(ImVec2(GetFontWidth() * 30, 0));
if (ImGui::BeginPopupContextItem())
@@ -962,7 +962,7 @@ void FCogWindowWidgets::ActorContextMenu(AActor& Selection, const FCogWindowActo
//--------------------------------------------------------------------------------------------------------------------------
void FCogWindowWidgets::ActorFrame(const AActor& Actor)
{
const APlayerController* PlayerController = Actor.GetWorld()->GetFirstPlayerController();
const APlayerController* PlayerController = Actor.GetWorld()->GetFirstPlayerController();
if (PlayerController == nullptr)
{
return;
@@ -77,7 +77,7 @@ public:
static bool ComboboxEnum(const char* Label, const FEnumProperty* EnumProperty, uint8* PointerToEnumValue);
static bool CheckBoxState(const char* Label, ECheckBoxState& State);
static bool CheckBoxState(const char* Label, ECheckBoxState& State, bool ShowTooltip = true);
static bool InputKey(const char* Label, FCogImGuiKeyInfo& KeyInfo);
@@ -1,9 +1,9 @@
#include "CogInjectActionInfo.h"
#include "CogInputActionInfo.h"
#include "EnhancedInputSubsystems.h"
//--------------------------------------------------------------------------------------------------------------------------
void FCogInjectActionInfo::Inject(UEnhancedInputLocalPlayerSubsystem& EnhancedInput, bool IsTimeToRepeat)
void FCogInputActionInfo::Inject(UEnhancedInputLocalPlayerSubsystem& EnhancedInput, bool IsTimeToRepeat)
{
if (Action == nullptr)
{
@@ -1,12 +1,11 @@
#include "CogInputWindow_Actions.h"
#include "CogInputDataAsset.h"
#include "CogWindowHelper.h"
#include "CogWindowWidgets.h"
#include "Engine/LocalPlayer.h"
#include "Engine/World.h"
#include "EnhancedInputSubsystems.h"
#include "GameFramework/Pawn.h"
#include "imgui_internal.h"
#include "InputAction.h"
#include "InputMappingContext.h"
@@ -17,7 +16,6 @@ void FCogInputWindow_Actions::Initialize()
bHasMenu = true;
Asset = GetAsset<UCogInputDataAsset>();
Config = GetConfig<UCogInputConfig_Actions>();
}
@@ -26,10 +24,7 @@ void FCogInputWindow_Actions::RenderHelp()
{
ImGui::Text(
"This window displays the current state of each Input Action. "
"It can also be used to inject inputs to help debugging. "
"The input action are read from a Input Mapping Context defined in '%s' data asset. "
, TCHAR_TO_ANSI(*GetNameSafe(Asset.Get()))
);
"It can also be used to inject inputs to help debugging.");
}
//--------------------------------------------------------------------------------------------------------------------------
@@ -45,12 +40,6 @@ void FCogInputWindow_Actions::RenderContent()
{
Super::RenderContent();
if (Asset == nullptr)
{
ImGui::TextDisabled("Invalid Asset");
return;
}
ULocalPlayer* LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController();
if (LocalPlayer == nullptr)
{
@@ -65,122 +54,222 @@ void FCogInputWindow_Actions::RenderContent()
return;
}
if(EnhancedInputSubsystem->GetPlayerInput() == nullptr)
UEnhancedPlayerInput* PlayerInput = EnhancedInputSubsystem->GetPlayerInput();
if(PlayerInput == nullptr)
{
ImGui::TextDisabled("No Player Input");
return;
}
const bool IsControlDown = (ImGui::GetCurrentContext()->IO.KeyMods & ImGuiMod_Ctrl) != 0;
if (ImGui::BeginMenuBar())
{
if (ImGui::BeginMenu("Options"))
{
ImGui::Checkbox("Show Header", &Config->ShowHeader);
ImGui::SliderFloat("##Repeat", &Config->RepeatPeriod, 0.1f, 10.0f, "Repeat: %0.1fs");
ImGui::EndMenu();
}
if (ImGui::MenuItem("Reset"))
{
for (FCogInjectActionInfo& ActionInfo : Actions)
for (FCogInputMappingContextInfo Mapping : Mappings)
{
ActionInfo.Reset();
for (FCogInputActionInfo& Action : Mapping.Actions)
{
Action.Reset();
}
}
}
ImGui::EndMenuBar();
}
if (Actions.Num() == 0)
//--------------------------------------------------------------------------
// Get all the existing mapping. This is not publicly exposed so we rob it.
//--------------------------------------------------------------------------
TArray<FCogInputMappingContextInfo, TInlineAllocator<8>> AllAppliedMappings;
if (const CogInputMappingContextMap* AppliedMappingContexts = &PRIVATE_ACCESS_PTR(PlayerInput, UEnhancedPlayerInput_AppliedInputContexts))
{
for (TObjectPtr<const UInputMappingContext> MappingContext : Asset->MappingContexts)
for (auto& kv : *AppliedMappingContexts)
{
for (const FEnhancedActionKeyMapping& Mapping : MappingContext->GetMappings())
{
if (Mapping.Action != nullptr && Actions.ContainsByPredicate([&Mapping](const FCogInjectActionInfo& ActionInfo) { return Mapping.Action == ActionInfo.Action; }) == false)
{
FCogInjectActionInfo& ActionInfo = Actions.AddDefaulted_GetRef();
ActionInfo.Action = Mapping.Action;
}
}
FCogInputMappingContextInfo& MappingInfo = AllAppliedMappings.AddDefaulted_GetRef();
MappingInfo.MappingContext = kv.Key;
MappingInfo.Priority = kv.Value;
}
Actions.Sort([](const FCogInjectActionInfo& Lhs, const FCogInjectActionInfo& Rhs)
{
return GetNameSafe(Lhs.Action).Compare(GetNameSafe(Rhs.Action)) < 0;
});
}
if (ImGui::BeginTable("Actions", 3, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Resizable | ImGuiTableFlags_NoBordersInBodyUntilResize))
//--------------------------------------------------------------------------
// Remove mappings that are not present anymore.
//--------------------------------------------------------------------------
for (int32 i = Mappings.Num() - 1; i >= 0; i--)
{
ImGui::TableSetupColumn("Action", ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableSetupColumn("Inject", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableHeadersRow();
int Index = 0;
for (FCogInjectActionInfo& ActionInfo : Actions)
{
ImGui::PushID(Index);
const auto ActionName = StringCast<ANSICHAR>(*ActionInfo.Action->GetName());
FInputActionValue ActionValue = EnhancedInputSubsystem->GetPlayerInput()->GetActionValue(ActionInfo.Action);
switch (ActionInfo.Action->ValueType)
const FCogInputMappingContextInfo& MappingInfo = Mappings[i];
if (AllAppliedMappings.ContainsByPredicate([&MappingInfo](const FCogInputMappingContextInfo& m)
{
case EInputActionValueType::Boolean:
{
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::Text("%s", ActionName.Get());
return m.MappingContext == MappingInfo.MappingContext;
}))
{
continue;
}
const ImVec4 ActiveColor(1, 0.8f, 0, 1);
const ImVec4 InnactiveColor(0.3f, 0.3f, 0.3f, 1);
const ImVec2 ButtonSize(FCogWindowWidgets::GetFontWidth() * 10, 0);
Mappings.RemoveAt(i);
}
ImGui::TableNextColumn();
ImGui::BeginDisabled();
bool Value = ActionValue.Get<bool>();
FCogWindowWidgets::ToggleButton(&Value, "Pressed##Value", "Released##Value", ActiveColor, InnactiveColor, ButtonSize);
ImGui::EndDisabled();
//--------------------------------------------------------------------------
// Add mappings that were not yet added.
//--------------------------------------------------------------------------
for (FCogInputMappingContextInfo& MappingInfo : AllAppliedMappings)
{
//----------------------------------------------------
// The mapping was already added
//----------------------------------------------------
if (Mappings.ContainsByPredicate([&MappingInfo](const FCogInputMappingContextInfo& m) { return m.MappingContext == MappingInfo.MappingContext; }))
{
continue;
}
ImGui::TableNextColumn();
FCogWindowWidgets::ToggleButton(&ActionInfo.bPressed, "Pressed##Inject", "Released##Inject", ActiveColor, InnactiveColor, ButtonSize);
ImGui::SameLine();
FCogWindowWidgets::ToggleButton(&ActionInfo.bRepeat, "Repeat", "Repeat", ActiveColor, InnactiveColor, ButtonSize);
break;
}
//----------------------------------------------------
// Add the mapping
//----------------------------------------------------
FCogInputMappingContextInfo& NewMappingInfo = Mappings.AddDefaulted_GetRef();
NewMappingInfo.MappingContext = MappingInfo.MappingContext;
NewMappingInfo.Priority = MappingInfo.Priority;
case EInputActionValueType::Axis1D:
{
const float Value = ActionValue.Get<float>();
DrawAxis("%s", ActionName.Get(), Value, &ActionInfo.X);
break;
}
case EInputActionValueType::Axis2D:
{
const FVector2D Value = ActionValue.Get<FVector2D>();
DrawAxis("%s X", ActionName.Get(), Value.X, &ActionInfo.X);
DrawAxis("%s Y", ActionName.Get(), Value.Y, &ActionInfo.Y);
break;
}
case EInputActionValueType::Axis3D:
{
const FVector Value = ActionValue.Get<FVector>();
DrawAxis("%s X", ActionName.Get(), Value.X, &ActionInfo.X);
DrawAxis("%s Y", ActionName.Get(), Value.Y, &ActionInfo.Y);
DrawAxis("%s Z", ActionName.Get(), Value.Z, &ActionInfo.Z);
break;
}
//----------------------------------------------------
// Add all the mapping actions
//----------------------------------------------------
for (const FEnhancedActionKeyMapping& Mapping : NewMappingInfo.MappingContext->GetMappings())
{
TObjectPtr<const UInputAction> Action = Mapping.Action;
if (Action == nullptr)
{
continue;
}
ImGui::PopID();
Index++;
//----------------------------------------------------
// Actions are present multiple time, as many times
// as they are mapped to key. We only want to display
// the same action once per mapping
//----------------------------------------------------
if (NewMappingInfo.Actions.ContainsByPredicate([&Action](const FCogInputActionInfo& m){ return m.Action == Action; }))
{
continue;
}
FCogInputActionInfo& ActionInfo = NewMappingInfo.Actions.AddDefaulted_GetRef();
ActionInfo.Action = Mapping.Action;
}
Mappings.Sort([](const FCogInputMappingContextInfo& Lhs, const FCogInputMappingContextInfo& Rhs)
{
return Lhs.Priority < Rhs.Priority;
});
}
int Index = 0;
for (FCogInputMappingContextInfo& Mapping : Mappings)
{
const auto MappingName = StringCast<ANSICHAR>(*Mapping.MappingContext.GetName());
const bool Open = ImGui::CollapsingHeader(MappingName.Get(), ImGuiTreeNodeFlags_DefaultOpen);
if (Open && ImGui::BeginTable("Actions", 3, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Resizable | ImGuiTableFlags_NoBordersInBodyUntilResize))
{
ImGui::TableSetupColumn("Action", ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("Current", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableSetupColumn("Inject", ImGuiTableColumnFlags_WidthStretch);
if (Config->ShowHeader)
{
ImGui::TableHeadersRow();
}
for (FCogInputActionInfo& ActionInfo : Mapping.Actions)
{
ImGui::PushID(Index);
const auto ActionName = StringCast<ANSICHAR>(*ActionInfo.Action->GetName());
FInputActionValue ActionValue = PlayerInput->GetActionValue(ActionInfo.Action);
switch (ActionInfo.Action->ValueType)
{
case EInputActionValueType::Boolean:
{
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::Text("%s", ActionName.Get());
const ImVec4 ActiveColor(1, 0.8f, 0, 1);
const ImVec4 InactiveColor(0.3f, 0.3f, 0.3f, 1);
const ImVec2 ButtonSize(FCogWindowWidgets::GetFontWidth() * 10, 0);
ImGui::TableNextColumn();
ImGui::BeginDisabled();
bool Value = ActionValue.Get<bool>();
ImGui::Checkbox("##Current", &Value);
ImGui::EndDisabled();
ImGui::TableNextColumn();
ECheckBoxState State = ActionInfo.bRepeat ? ECheckBoxState::Undetermined : ActionInfo.bPressed ? ECheckBoxState::Checked : ECheckBoxState::Unchecked;
if (FCogWindowWidgets::CheckBoxState("##Inject", State, false))
{
if (IsControlDown)
{
ActionInfo.bRepeat = !ActionInfo.bRepeat;
ActionInfo.bPressed = false;
}
else
{
ActionInfo.bPressed = !ActionInfo.bPressed;
ActionInfo.bRepeat = false;
}
}
if (ImGui::IsItemHovered(ImGuiHoveredFlags_Stationary | ImGuiHoveredFlags_DelayShort))
{
ImGui::BeginTooltip();
ImGui::TextColored(ImVec4(1.0f, 1.0f, 1.0f, IsControlDown ? 1.0f : 0.5f), "Repeat [CTRL]");
ImGui::EndTooltip();
}
break;
}
case EInputActionValueType::Axis1D:
{
const float Value = ActionValue.Get<float>();
DrawAxis("%s", ActionName.Get(), Value, &ActionInfo.X);
break;
}
case EInputActionValueType::Axis2D:
{
const FVector2D Value = ActionValue.Get<FVector2D>();
DrawAxis("%s X", ActionName.Get(), Value.X, &ActionInfo.X);
DrawAxis("%s Y", ActionName.Get(), Value.Y, &ActionInfo.Y);
break;
}
case EInputActionValueType::Axis3D:
{
const FVector Value = ActionValue.Get<FVector>();
DrawAxis("%s X", ActionName.Get(), Value.X, &ActionInfo.X);
DrawAxis("%s Y", ActionName.Get(), Value.Y, &ActionInfo.Y);
DrawAxis("%s Z", ActionName.Get(), Value.Z, &ActionInfo.Z);
break;
}
}
ImGui::PopID();
Index++;
}
ImGui::EndTable();
}
ImGui::EndTable();
}
}
@@ -214,9 +303,12 @@ void FCogInputWindow_Actions::RenderTick(float DeltaSeconds)
IsTimeToRepeat = true;
}
for (FCogInjectActionInfo& ActionInfo : Actions)
for (FCogInputMappingContextInfo Mapping : Mappings)
{
ActionInfo.Inject(*EnhancedInput, IsTimeToRepeat);
for (FCogInputActionInfo& ActionInfo : Mapping.Actions)
{
ActionInfo.Inject(*EnhancedInput, IsTimeToRepeat);
}
}
}
@@ -1,7 +1,6 @@
#include "CogInputWindow_Gamepad.h"
#include "CogImguiHelper.h"
#include "CogInputDataAsset.h"
#include "CogWindowWidgets.h"
#include "Engine/LocalPlayer.h"
#include "Engine/World.h"
@@ -14,7 +13,6 @@ void FCogInputWindow_Gamepad::Initialize()
{
Super::Initialize();
Asset = GetAsset<UCogInputDataAsset>();
Config = GetConfig<UCogInputConfig_Gamepad>();
}
@@ -43,7 +41,7 @@ void FCogInputWindow_Gamepad::ResetConfig()
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogInputWindow_Gamepad::RenderButtonContextMenu(const FKey& Key, FCogInjectActionInfo* ActionInfoButton)
void FCogInputWindow_Gamepad::RenderButtonContextMenu(const FKey& Key, FCogInputActionInfo* ActionInfoButton)
{
if (ActionInfoButton != nullptr)
{
@@ -66,7 +64,7 @@ void FCogInputWindow_Gamepad::RenderButtonContextMenu(const FKey& Key, FCogInjec
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogInputWindow_Gamepad::RenderStickContextMenu(const FKey& Key, FCogInjectActionInfo* ActionInfo2D, bool& InvertY, float& Sensitivity)
void FCogInputWindow_Gamepad::RenderStickContextMenu(const FKey& Key, FCogInputActionInfo* ActionInfo2D, bool& InvertY, float& Sensitivity)
{
if (ActionInfo2D != nullptr)
{
@@ -83,7 +81,7 @@ void FCogInputWindow_Gamepad::RenderStickContextMenu(const FKey& Key, FCogInject
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogInputWindow_Gamepad::OnButtonClicked(FCogInjectActionInfo* ActionInfo)
void FCogInputWindow_Gamepad::OnButtonClicked(FCogInputActionInfo* ActionInfo)
{
if (ActionInfo == nullptr)
{
@@ -116,7 +114,7 @@ void FCogInputWindow_Gamepad::RenderButton(const FKey& Key, const ImVec2& Relati
const ImVec2 Position = (CanvasMin + CanvasSize * RelativePosition) - Alignment * Size;
bool IsPressed = false;
FCogInjectActionInfo* ActionInfo = Actions.Find(Key);
FCogInputActionInfo* ActionInfo = Actions.Find(Key);
if (ActionInfo != nullptr)
{
if (ActionInfo->Action != nullptr)
@@ -169,8 +167,8 @@ void FCogInputWindow_Gamepad::RenderStick(const FKey& Key2D, const FKey& KeyBool
{
ImGui::PushID((void*)(&Key2D));
FCogInjectActionInfo* ActionInfoBool = Actions.Find(KeyBool);
FCogInjectActionInfo* ActionInfo2D = Actions.Find(Key2D);
FCogInputActionInfo* ActionInfoBool = Actions.Find(KeyBool);
FCogInputActionInfo* ActionInfo2D = Actions.Find(Key2D);
FVector Value = Input->GetRawVectorKeyValue(Key2D);
if (ActionInfo2D != nullptr && ActionInfo2D->Action != nullptr)
@@ -288,48 +286,44 @@ void FCogInputWindow_Gamepad::RenderContent()
return;
}
if (Asset == nullptr)
if (Actions.Num() == 0)
{
ImGui::TextDisabled("Invalid Asset");
}
else
{
if (Actions.Num() == 0)
{
Actions.FindOrAdd(EKeys:: Gamepad_Left2D);
Actions.FindOrAdd(EKeys:: Gamepad_LeftX);
Actions.FindOrAdd(EKeys:: Gamepad_LeftY);
Actions.FindOrAdd(EKeys:: Gamepad_Right2D);
Actions.FindOrAdd(EKeys:: Gamepad_RightX);
Actions.FindOrAdd(EKeys:: Gamepad_RightY);
Actions.FindOrAdd(EKeys:: Gamepad_LeftTriggerAxis);
Actions.FindOrAdd(EKeys:: Gamepad_RightTriggerAxis);
Actions.FindOrAdd(EKeys:: Gamepad_LeftThumbstick);
Actions.FindOrAdd(EKeys:: Gamepad_RightThumbstick);
Actions.FindOrAdd(EKeys:: Gamepad_Special_Left);
Actions.FindOrAdd(EKeys:: Gamepad_Special_Left_X);
Actions.FindOrAdd(EKeys:: Gamepad_Special_Left_Y);
Actions.FindOrAdd(EKeys:: Gamepad_Special_Right);
Actions.FindOrAdd(EKeys:: Gamepad_FaceButton_Bottom);
Actions.FindOrAdd(EKeys:: Gamepad_FaceButton_Right);
Actions.FindOrAdd(EKeys:: Gamepad_FaceButton_Left);
Actions.FindOrAdd(EKeys:: Gamepad_FaceButton_Top);
Actions.FindOrAdd(EKeys:: Gamepad_LeftShoulder);
Actions.FindOrAdd(EKeys:: Gamepad_RightShoulder);
Actions.FindOrAdd(EKeys:: Gamepad_LeftTrigger);
Actions.FindOrAdd(EKeys:: Gamepad_RightTrigger);
Actions.FindOrAdd(EKeys:: Gamepad_DPad_Up);
Actions.FindOrAdd(EKeys:: Gamepad_DPad_Down);
Actions.FindOrAdd(EKeys:: Gamepad_DPad_Right);
Actions.FindOrAdd(EKeys:: Gamepad_DPad_Left);
Actions.FindOrAdd(EKeys:: Gamepad_Left2D);
Actions.FindOrAdd(EKeys:: Gamepad_LeftX);
Actions.FindOrAdd(EKeys:: Gamepad_LeftY);
Actions.FindOrAdd(EKeys:: Gamepad_Right2D);
Actions.FindOrAdd(EKeys:: Gamepad_RightX);
Actions.FindOrAdd(EKeys:: Gamepad_RightY);
Actions.FindOrAdd(EKeys:: Gamepad_LeftTriggerAxis);
Actions.FindOrAdd(EKeys:: Gamepad_RightTriggerAxis);
Actions.FindOrAdd(EKeys:: Gamepad_LeftThumbstick);
Actions.FindOrAdd(EKeys:: Gamepad_RightThumbstick);
Actions.FindOrAdd(EKeys:: Gamepad_Special_Left);
Actions.FindOrAdd(EKeys:: Gamepad_Special_Left_X);
Actions.FindOrAdd(EKeys:: Gamepad_Special_Left_Y);
Actions.FindOrAdd(EKeys:: Gamepad_Special_Right);
Actions.FindOrAdd(EKeys:: Gamepad_FaceButton_Bottom);
Actions.FindOrAdd(EKeys:: Gamepad_FaceButton_Right);
Actions.FindOrAdd(EKeys:: Gamepad_FaceButton_Left);
Actions.FindOrAdd(EKeys:: Gamepad_FaceButton_Top);
Actions.FindOrAdd(EKeys:: Gamepad_LeftShoulder);
Actions.FindOrAdd(EKeys:: Gamepad_RightShoulder);
Actions.FindOrAdd(EKeys:: Gamepad_LeftTrigger);
Actions.FindOrAdd(EKeys:: Gamepad_RightTrigger);
Actions.FindOrAdd(EKeys:: Gamepad_DPad_Up);
Actions.FindOrAdd(EKeys:: Gamepad_DPad_Down);
Actions.FindOrAdd(EKeys:: Gamepad_DPad_Right);
Actions.FindOrAdd(EKeys:: Gamepad_DPad_Left);
for (TObjectPtr<const UInputMappingContext> MappingContext : Asset->MappingContexts)
if (const CogInputMappingContextMap* AppliedMappingContexts = &PRIVATE_ACCESS_PTR(Input, UEnhancedPlayerInput_AppliedInputContexts))
{
for (auto& kv : *AppliedMappingContexts)
{
for (const FEnhancedActionKeyMapping& Mapping : MappingContext->GetMappings())
for (const FEnhancedActionKeyMapping& Mapping : kv.Key->GetMappings())
{
if (Mapping.Action != nullptr)
{
FCogInjectActionInfo& ActionInfo = Actions.FindOrAdd(Mapping.Key);
FCogInputActionInfo& ActionInfo = Actions.FindOrAdd(Mapping.Key);
ActionInfo.Action = Mapping.Action;
}
}
@@ -337,7 +331,6 @@ void FCogInputWindow_Gamepad::RenderContent()
}
}
constexpr float AspectRatio = 0.55f;
constexpr float StickAmplitude = 0.04f;
constexpr float StickRadius = 0.08f;
@@ -345,8 +338,8 @@ void FCogInputWindow_Gamepad::RenderContent()
constexpr float GamepadRound = 0.15f;
constexpr float HandleWidth = 0.26f;
constexpr ImVec2 DPadButtonSize(0.08f, 0.08f);
constexpr float DpadButtonDistance = 0.075f;
constexpr float DpadButtonRounding = 0.1f;
constexpr float DPadButtonDistance = 0.075f;
constexpr float DPadButtonRounding = 0.1f;
constexpr ImVec2 SpecialButtonSize(0.08f, 0.04f);
constexpr float SpecialButtonRound = 0.05f;
constexpr float SpecialButtonDistance = 0.15f;
@@ -420,19 +413,19 @@ void FCogInputWindow_Gamepad::RenderContent()
// DPad Buttons
//------------------------------
constexpr ImVec2 DPad_Pos(0.15f, 0.44f);
RenderButton(EKeys::Gamepad_DPad_Up, DPad_Pos + ImVec2(0.0f, -DpadButtonDistance / AspectRatio), DPadButtonSize, ImVec2(0.5f, 0.5f), DpadButtonRounding);
RenderButton(EKeys::Gamepad_DPad_Down, DPad_Pos + ImVec2(0.0f, DpadButtonDistance / AspectRatio), DPadButtonSize, ImVec2(0.5f, 0.5f), DpadButtonRounding);
RenderButton(EKeys::Gamepad_DPad_Left, DPad_Pos + ImVec2(-DpadButtonDistance, 0.0f), DPadButtonSize, ImVec2(0.5f, 0.5f), DpadButtonRounding);
RenderButton(EKeys::Gamepad_DPad_Right, DPad_Pos + ImVec2(DpadButtonDistance, 0.0f), DPadButtonSize, ImVec2(0.5f, 0.5f), DpadButtonRounding);
RenderButton(EKeys::Gamepad_DPad_Up, DPad_Pos + ImVec2(0.0f, -DPadButtonDistance / AspectRatio), DPadButtonSize, ImVec2(0.5f, 0.5f), DPadButtonRounding);
RenderButton(EKeys::Gamepad_DPad_Down, DPad_Pos + ImVec2(0.0f, DPadButtonDistance / AspectRatio), DPadButtonSize, ImVec2(0.5f, 0.5f), DPadButtonRounding);
RenderButton(EKeys::Gamepad_DPad_Left, DPad_Pos + ImVec2(-DPadButtonDistance, 0.0f), DPadButtonSize, ImVec2(0.5f, 0.5f), DPadButtonRounding);
RenderButton(EKeys::Gamepad_DPad_Right, DPad_Pos + ImVec2(DPadButtonDistance, 0.0f), DPadButtonSize, ImVec2(0.5f, 0.5f), DPadButtonRounding);
//------------------------------
// Face Buttons
//------------------------------
constexpr ImVec2 Face_Pos(1.0f - 0.15f, 0.44f);
RenderButton(EKeys::Gamepad_FaceButton_Top, Face_Pos + ImVec2(0.0f, -DpadButtonDistance / AspectRatio), DPadButtonSize, ImVec2(0.5f, 0.5f), DpadButtonRounding);
RenderButton(EKeys::Gamepad_FaceButton_Bottom, Face_Pos + ImVec2(0.0f, DpadButtonDistance / AspectRatio), DPadButtonSize, ImVec2(0.5f, 0.5f), DpadButtonRounding);
RenderButton(EKeys::Gamepad_FaceButton_Left, Face_Pos + ImVec2(-DpadButtonDistance, 0.0f), DPadButtonSize, ImVec2(0.5f, 0.5f), DpadButtonRounding);
RenderButton(EKeys::Gamepad_FaceButton_Right, Face_Pos + ImVec2(DpadButtonDistance, 0.0f), DPadButtonSize, ImVec2(0.5f, 0.5f), DpadButtonRounding);
RenderButton(EKeys::Gamepad_FaceButton_Top, Face_Pos + ImVec2(0.0f, -DPadButtonDistance / AspectRatio), DPadButtonSize, ImVec2(0.5f, 0.5f), DPadButtonRounding);
RenderButton(EKeys::Gamepad_FaceButton_Bottom, Face_Pos + ImVec2(0.0f, DPadButtonDistance / AspectRatio), DPadButtonSize, ImVec2(0.5f, 0.5f), DPadButtonRounding);
RenderButton(EKeys::Gamepad_FaceButton_Left, Face_Pos + ImVec2(-DPadButtonDistance, 0.0f), DPadButtonSize, ImVec2(0.5f, 0.5f), DPadButtonRounding);
RenderButton(EKeys::Gamepad_FaceButton_Right, Face_Pos + ImVec2(DPadButtonDistance, 0.0f), DPadButtonSize, ImVec2(0.5f, 0.5f), DPadButtonRounding);
//------------------------------
// Special Buttons
@@ -475,7 +468,7 @@ void FCogInputWindow_Gamepad::RenderTick(float DeltaSeconds)
for (auto& Entry : Actions)
{
FCogInjectActionInfo& ActionInfo = Entry.Value;
FCogInputActionInfo& ActionInfo = Entry.Value;
ActionInfo.Inject(*EnhancedInput, IsTimeToRepeat);
}
}
@@ -1,13 +1,19 @@
#pragma once
#include "CoreMinimal.h"
#include "CogDebugRob.h"
#include "EnhancedPlayerInput.h"
class UInputAction;
class UInputMappingContext;
class UEnhancedInputLocalPlayerSubsystem;
struct FCogInjectActionInfo
typedef TMap<TObjectPtr<const UInputMappingContext>, int32> CogInputMappingContextMap;
DEFINE_PRIVATE_ACCESSOR_VARIABLE(UEnhancedPlayerInput_AppliedInputContexts, UEnhancedPlayerInput, CogInputMappingContextMap, AppliedInputContexts);
struct FCogInputActionInfo
{
const UInputAction* Action = nullptr;
TObjectPtr<const UInputAction> Action;
bool bPressed = false;
@@ -36,3 +42,12 @@ struct FCogInjectActionInfo
void Inject(UEnhancedInputLocalPlayerSubsystem& EnhancedInput, bool IsTimeToRepeat);
};
struct FCogInputMappingContextInfo
{
TObjectPtr<const UInputMappingContext> MappingContext;
int32 Priority = 0;
TArray<FCogInputActionInfo> Actions;
};
@@ -1,20 +0,0 @@
#pragma once
#include "CoreMinimal.h"
#include "Engine/DataAsset.h"
#include "CogInputDataAsset.generated.h"
class UInputAction;
class UInputMappingContext;
UCLASS(Blueprintable)
class COGINPUT_API UCogInputDataAsset : public UPrimaryDataAsset
{
GENERATED_BODY()
public:
UCogInputDataAsset() {}
UPROPERTY(EditAnywhere)
TArray<TObjectPtr<const UInputMappingContext>> MappingContexts;
};
@@ -2,13 +2,12 @@
#include "CoreMinimal.h"
#include "CogCommonConfig.h"
#include "CogInjectActionInfo.h"
#include "CogInputActionInfo.h"
#include "CogWindow.h"
#include "CogInputWindow_Actions.generated.h"
class UInputAction;
class UCogInputConfig_Actions;
class UCogInputDataAsset;
//--------------------------------------------------------------------------------------------------------------------------
class COGINPUT_API FCogInputWindow_Actions : public FCogWindow
@@ -35,11 +34,9 @@ private:
float RepeatTime = 0.0f;
TObjectPtr<const UCogInputDataAsset> Asset = nullptr;
TObjectPtr<UCogInputConfig_Actions> Config = nullptr;
TArray<FCogInjectActionInfo> Actions;
TArray<FCogInputMappingContextInfo> Mappings;
};
//--------------------------------------------------------------------------------------------------------------------------
@@ -53,10 +50,14 @@ public:
UPROPERTY(Config)
float RepeatPeriod = 0.5f;
UPROPERTY(Config)
bool ShowHeader = true;
virtual void Reset() override
{
Super::Reset();
RepeatPeriod = 0.5f;
ShowHeader = true;
}
};
@@ -2,7 +2,7 @@
#include "CoreMinimal.h"
#include "CogCommonConfig.h"
#include "CogInjectActionInfo.h"
#include "CogInputActionInfo.h"
#include "CogWindow.h"
#include "imgui.h"
#include "InputCoreTypes.h"
@@ -37,19 +37,17 @@ protected:
virtual void RenderStick(const FKey& Key2D, const FKey& KeyBool, bool& InvertY, float& Sensitivity, float Amplitude, const ImVec2& Position, float Radius);
virtual void OnButtonClicked(FCogInjectActionInfo* ActionInfo);
virtual void OnButtonClicked(FCogInputActionInfo* ActionInfo);
virtual void RenderMainContextMenu();
virtual void RenderButtonContextMenu(const FKey& Key, FCogInjectActionInfo* ActionInfoButton);
virtual void RenderButtonContextMenu(const FKey& Key, FCogInputActionInfo* ActionInfoButton);
virtual void RenderStickContextMenu(const FKey& Key, FCogInjectActionInfo* ActionInfo2D, bool& InvertY, float& Sensitivity);
TObjectPtr<const UCogInputDataAsset> Asset;
virtual void RenderStickContextMenu(const FKey& Key, FCogInputActionInfo* ActionInfo2D, bool& InvertY, float& Sensitivity);
TObjectPtr<UCogInputConfig_Gamepad> Config;
TMap<FKey, FCogInjectActionInfo> Actions;
TMap<FKey, FCogInputActionInfo> Actions;
UEnhancedPlayerInput* Input = nullptr;
@@ -18,14 +18,14 @@ UCogSampleGameplayAbility::UCogSampleGameplayAbility()
//--------------------------------------------------------------------------------------------------------------------------
void UCogSampleGameplayAbility::PreActivate(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, FOnGameplayAbilityEnded::FDelegate* OnGameplayAbilityEndedDelegate, const FGameplayEventData* TriggerEventData)
{
COG_LOG_ABILITY(ELogVerbosity::Verbose, this, TEXT("PreActivate"));
COG_LOG_ABILITY(ELogVerbosity::Verbose, this, TEXT(""));
Super::PreActivate(Handle, ActorInfo, ActivationInfo, OnGameplayAbilityEndedDelegate, TriggerEventData);
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogSampleGameplayAbility::ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData)
{
COG_LOG_ABILITY(ELogVerbosity::Verbose, this, TEXT("PredictionKey:%s"), *GetAbilitySystemComponentFromActorInfo_Checked()->ScopedPredictionKey.ToString());
COG_LOG_ABILITY(ELogVerbosity::Verbose, this, TEXT(""));
Super::ActivateAbility(Handle, ActorInfo, ActivationInfo, TriggerEventData);
}