// Distributed under the MIT License (MIT) (see accompanying LICENSE file) #include "ImGuiPrivatePCH.h" #if WITH_EDITOR #include "ImGuiKeyInfoCustomization.h" #include "ImGuiModuleSettings.h" #include #include #include #include #define LOCTEXT_NAMESPACE "ImGuiEditor" //---------------------------------------------------------------------------------------------------- // Helper widgets //---------------------------------------------------------------------------------------------------- namespace { class SPropertyKeySelector : public SCompoundWidget { public: SLATE_BEGIN_ARGS(SPropertyKeySelector) {} SLATE_ARGUMENT(TSharedPtr, KeyHandle) SLATE_ATTRIBUTE(FSlateFontInfo, Font) SLATE_END_ARGS() void Construct(const FArguments& InArgs) { KeyHandle = InArgs._KeyHandle; ChildSlot [ SNew(SKeySelector) .CurrentKey(this, &SPropertyKeySelector::GetCurrentKey) .OnKeyChanged(this, &SPropertyKeySelector::OnKeyChanged) .Font(InArgs._Font) ]; } TOptional GetCurrentKey() const { TArray RawPtrs; KeyHandle->AccessRawData(RawPtrs); if (RawPtrs.Num()) { FKey* KeyPtr = static_cast(RawPtrs[0]); if (KeyPtr) { for (int32 Index = 1; Index < RawPtrs.Num(); Index++) { if (*static_cast(RawPtrs[Index]) != *KeyPtr) { return TOptional(); } } return *KeyPtr; } } return FKey(); } void OnKeyChanged(TSharedPtr SelectedKey) { KeyHandle->SetValueFromFormattedString(SelectedKey->ToString()); } private: TSharedPtr KeyHandle; }; class SPropertyTriStateCheckBox : public SCompoundWidget { public: using FCheckBoxStateRaw = std::underlying_type::type; SLATE_BEGIN_ARGS(SPropertyTriStateCheckBox) {} SLATE_ARGUMENT(TSharedPtr, PropertyHandle) SLATE_END_ARGS() void Construct(const FArguments& InArgs) { PropertyHandle = InArgs._PropertyHandle; // We are abusing SCheckBox a bit but our GetPropertyValue with custom OnCheckBoxStateChanged implementation // gives a checkbox that allows to cycle between all three states. ChildSlot [ SNew(SCheckBox) .IsChecked(this, &SPropertyTriStateCheckBox::GetPropertyValue) .OnCheckStateChanged(this, &SPropertyTriStateCheckBox::OnCheckBoxStateChanged) ]; } FCheckBoxStateRaw GetPropertyRawValue() const { FCheckBoxStateRaw Value; PropertyHandle.Get()->GetValue(Value); return Value; } ECheckBoxState GetPropertyValue() const { return static_cast(GetPropertyRawValue()); } void OnCheckBoxStateChanged(ECheckBoxState State) { const FCheckBoxStateRaw PrevEnumValue = (GetPropertyRawValue() + 2) % 3; PropertyHandle.Get()->SetValue(PrevEnumValue); } private: TSharedPtr PropertyHandle; }; } //---------------------------------------------------------------------------------------------------- // FImGuiKeyInfoCustomization implementation //---------------------------------------------------------------------------------------------------- namespace InputConstants { static const FMargin PropertyPadding(0.0f, 0.0f, 4.0f, 0.0f); } TSharedRef FImGuiKeyInfoCustomization::MakeInstance() { return MakeShareable(new FImGuiKeyInfoCustomization); } void FImGuiKeyInfoCustomization::CustomizeHeader(TSharedRef InStructPropertyHandle, FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& StructCustomizationUtils) { TSharedPtr KeyHandle = InStructPropertyHandle->GetChildHandle(GET_MEMBER_NAME_CHECKED(FImGuiKeyInfo, Key)); TSharedPtr ShiftHandle = InStructPropertyHandle->GetChildHandle(GET_MEMBER_NAME_CHECKED(FImGuiKeyInfo, Shift)); TSharedPtr CtrlHandle = InStructPropertyHandle->GetChildHandle(GET_MEMBER_NAME_CHECKED(FImGuiKeyInfo, Ctrl)); TSharedPtr AltHandle = InStructPropertyHandle->GetChildHandle(GET_MEMBER_NAME_CHECKED(FImGuiKeyInfo, Alt)); TSharedPtr CmdHandle = InStructPropertyHandle->GetChildHandle(GET_MEMBER_NAME_CHECKED(FImGuiKeyInfo, Cmd)); #define ADD_CHECK_BOX_SLOT(Handle) \ + SHorizontalBox::Slot()\ .Padding(InputConstants::PropertyPadding)\ .HAlign(HAlign_Left)\ .VAlign(VAlign_Center)\ .AutoWidth()\ [\ Handle->CreatePropertyNameWidget()\ ]\ + SHorizontalBox::Slot()\ .Padding(InputConstants::PropertyPadding)\ .HAlign(HAlign_Left)\ .VAlign(VAlign_Center)\ .AutoWidth()\ [\ SNew(SPropertyTriStateCheckBox).PropertyHandle(Handle)\ ] HeaderRow .NameContent() [ InStructPropertyHandle->CreatePropertyNameWidget() ] .ValueContent() .MaxDesiredWidth(400.f) [ SNew(SHorizontalBox) + SHorizontalBox::Slot() .Padding(InputConstants::PropertyPadding) .AutoWidth() [ SNew(SBox) .WidthOverride(200.f) [ SNew(SPropertyKeySelector) .KeyHandle(KeyHandle) .Font(StructCustomizationUtils.GetRegularFont()) ] ] ADD_CHECK_BOX_SLOT(ShiftHandle) ADD_CHECK_BOX_SLOT(CtrlHandle) ADD_CHECK_BOX_SLOT(AltHandle) ADD_CHECK_BOX_SLOT(CmdHandle) ]; #undef ADD_CHECK_BOX_SLOT } void FImGuiKeyInfoCustomization::CustomizeChildren(TSharedRef InStructPropertyHandle, IDetailChildrenBuilder& StructBuilder, IPropertyTypeCustomizationUtils& StructCustomizationUtils) { } #undef LOCTEXT_NAMESPACE #endif // WITH_EDITOR