mirror of
https://github.com/kevinporetti/UnrealImGui.git
synced 2025-01-18 08:20:32 +00:00
Added custom property type layout for FImGuiKeyInfo.
This commit is contained in:
parent
a90f217ab3
commit
9ab12850fb
@ -64,6 +64,7 @@ public class ImGui : ModuleRules
|
||||
PrivateDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"EditorStyle",
|
||||
"Settings",
|
||||
"UnrealEd",
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "ImGuiEditor.h"
|
||||
|
||||
#include "ImGuiKeyInfoCustomization.h"
|
||||
#include "ImGuiSettings.h"
|
||||
|
||||
#include <ISettingsModule.h>
|
||||
@ -22,6 +23,11 @@ namespace
|
||||
{
|
||||
return FModuleManager::GetModulePtr<ISettingsModule>("Settings");
|
||||
}
|
||||
|
||||
FPropertyEditorModule* GetPropertyEditorModule()
|
||||
{
|
||||
return FModuleManager::GetModulePtr<FPropertyEditorModule>("PropertyEditor");
|
||||
}
|
||||
}
|
||||
|
||||
FImGuiEditor::FImGuiEditor()
|
||||
@ -56,6 +62,17 @@ void FImGuiEditor::Register()
|
||||
GetMutableDefault<UImGuiSettings>());
|
||||
}
|
||||
}
|
||||
|
||||
if (!bCustomPropertyTypeLayoutsRegistered)
|
||||
{
|
||||
if (FPropertyEditorModule* PropertyModule = GetPropertyEditorModule())
|
||||
{
|
||||
bCustomPropertyTypeLayoutsRegistered = true;
|
||||
|
||||
PropertyModule->RegisterCustomPropertyTypeLayout("ImGuiKeyInfo",
|
||||
FOnGetPropertyTypeCustomizationInstance::CreateStatic(&FImGuiKeyInfoCustomization::MakeInstance));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FImGuiEditor::Unregister()
|
||||
@ -69,6 +86,16 @@ void FImGuiEditor::Unregister()
|
||||
SettingsModule->UnregisterSettings(SETTINGS_CONTAINER);
|
||||
}
|
||||
}
|
||||
|
||||
if (bCustomPropertyTypeLayoutsRegistered)
|
||||
{
|
||||
bCustomPropertyTypeLayoutsRegistered = false;
|
||||
|
||||
if (FPropertyEditorModule* PropertyModule = GetPropertyEditorModule())
|
||||
{
|
||||
PropertyModule->UnregisterCustomPropertyTypeLayout("ImGuiKeyInfo");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FImGuiEditor::CreateRegistrator()
|
||||
|
@ -14,7 +14,7 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
bool IsRegistrationCompleted() const { return bSettingsRegistered; }
|
||||
bool IsRegistrationCompleted() const { return bSettingsRegistered && bCustomPropertyTypeLayoutsRegistered; }
|
||||
|
||||
void Register();
|
||||
void Unregister();
|
||||
@ -25,6 +25,7 @@ private:
|
||||
FDelegateHandle RegistratorHandle;
|
||||
|
||||
bool bSettingsRegistered = false;
|
||||
bool bCustomPropertyTypeLayoutsRegistered = false;
|
||||
};
|
||||
|
||||
#endif // WITH_EDITOR
|
||||
|
211
Source/ImGui/Private/Editor/ImGuiKeyInfoCustomization.cpp
Normal file
211
Source/ImGui/Private/Editor/ImGuiKeyInfoCustomization.cpp
Normal file
@ -0,0 +1,211 @@
|
||||
// Distributed under the MIT License (MIT) (see accompanying LICENSE file)
|
||||
|
||||
#include "ImGuiPrivatePCH.h"
|
||||
|
||||
#if WITH_EDITOR
|
||||
|
||||
#include "ImGuiKeyInfoCustomization.h"
|
||||
|
||||
#include "ImGuiSettings.h"
|
||||
|
||||
#include <PropertyCustomizationHelpers.h>
|
||||
#include <SKeySelector.h>
|
||||
#include <Widgets/SCompoundWidget.h>
|
||||
#include <Widgets/Input/SCheckBox.h>
|
||||
|
||||
|
||||
#define LOCTEXT_NAMESPACE "ImGuiEditor"
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
// Helper widgets
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace
|
||||
{
|
||||
class SPropertyKeySelector : public SCompoundWidget
|
||||
{
|
||||
public:
|
||||
SLATE_BEGIN_ARGS(SPropertyKeySelector)
|
||||
{}
|
||||
SLATE_ARGUMENT(TSharedPtr<IPropertyHandle>, 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<FKey> GetCurrentKey() const
|
||||
{
|
||||
TArray<void*> RawPtrs;
|
||||
KeyHandle->AccessRawData(RawPtrs);
|
||||
|
||||
if (RawPtrs.Num())
|
||||
{
|
||||
FKey* KeyPtr = static_cast<FKey*>(RawPtrs[0]);
|
||||
|
||||
if (KeyPtr)
|
||||
{
|
||||
for (int32 Index = 1; Index < RawPtrs.Num(); Index++)
|
||||
{
|
||||
if (*static_cast<FKey*>(RawPtrs[Index]) != *KeyPtr)
|
||||
{
|
||||
return TOptional<FKey>();
|
||||
}
|
||||
}
|
||||
|
||||
return *KeyPtr;
|
||||
}
|
||||
}
|
||||
|
||||
return FKey();
|
||||
}
|
||||
|
||||
void OnKeyChanged(TSharedPtr<FKey> SelectedKey)
|
||||
{
|
||||
KeyHandle->SetValueFromFormattedString(SelectedKey->ToString());
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
TSharedPtr<IPropertyHandle> KeyHandle;
|
||||
};
|
||||
|
||||
class SPropertyTriStateCheckBox : public SCompoundWidget
|
||||
{
|
||||
public:
|
||||
|
||||
using FCheckBoxStateRaw = std::underlying_type<ECheckBoxState>::type;
|
||||
|
||||
SLATE_BEGIN_ARGS(SPropertyTriStateCheckBox)
|
||||
{}
|
||||
SLATE_ARGUMENT(TSharedPtr<IPropertyHandle>, 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<ECheckBoxState>(GetPropertyRawValue());
|
||||
}
|
||||
|
||||
void OnCheckBoxStateChanged(ECheckBoxState State)
|
||||
{
|
||||
const FCheckBoxStateRaw PrevEnumValue = (GetPropertyRawValue() + 2) % 3;
|
||||
PropertyHandle.Get()->SetValue(PrevEnumValue);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
TSharedPtr<IPropertyHandle> PropertyHandle;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
// FImGuiKeyInfoCustomization implementation
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace InputConstants
|
||||
{
|
||||
static const FMargin PropertyPadding(2.0f, 0.0f, 2.0f, 0.0f);
|
||||
}
|
||||
|
||||
TSharedRef<IPropertyTypeCustomization> FImGuiKeyInfoCustomization::MakeInstance()
|
||||
{
|
||||
return MakeShareable(new FImGuiKeyInfoCustomization);
|
||||
}
|
||||
|
||||
void FImGuiKeyInfoCustomization::CustomizeHeader(TSharedRef<IPropertyHandle> InStructPropertyHandle, FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& StructCustomizationUtils)
|
||||
{
|
||||
TSharedPtr<IPropertyHandle> KeyHandle = InStructPropertyHandle->GetChildHandle(GET_MEMBER_NAME_CHECKED(FImGuiKeyInfo, Key));
|
||||
TSharedPtr<IPropertyHandle> ShiftHandle = InStructPropertyHandle->GetChildHandle(GET_MEMBER_NAME_CHECKED(FImGuiKeyInfo, Shift));
|
||||
TSharedPtr<IPropertyHandle> CtrlHandle = InStructPropertyHandle->GetChildHandle(GET_MEMBER_NAME_CHECKED(FImGuiKeyInfo, Ctrl));
|
||||
TSharedPtr<IPropertyHandle> AltHandle = InStructPropertyHandle->GetChildHandle(GET_MEMBER_NAME_CHECKED(FImGuiKeyInfo, Alt));
|
||||
TSharedPtr<IPropertyHandle> 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<IPropertyHandle> InStructPropertyHandle, IDetailChildrenBuilder& StructBuilder, IPropertyTypeCustomizationUtils& StructCustomizationUtils)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
|
||||
#endif // WITH_EDITOR
|
26
Source/ImGui/Private/Editor/ImGuiKeyInfoCustomization.h
Normal file
26
Source/ImGui/Private/Editor/ImGuiKeyInfoCustomization.h
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#if WITH_EDITOR
|
||||
|
||||
#include <IPropertyTypeCustomization.h>
|
||||
#include <PropertyHandle.h>
|
||||
|
||||
|
||||
class FDetailWidgetRow;
|
||||
class IDetailChildrenBuilder;
|
||||
class IPropertyHandle;
|
||||
|
||||
// Property type customization for FImGuiKeyInfo.
|
||||
class FImGuiKeyInfoCustomization : public IPropertyTypeCustomization
|
||||
{
|
||||
public:
|
||||
static TSharedRef<IPropertyTypeCustomization> MakeInstance();
|
||||
|
||||
// IPropertyTypeCustomization interface
|
||||
virtual void CustomizeHeader(TSharedRef<IPropertyHandle> InStructPropertyHandle, FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& StructCustomizationUtils) override;
|
||||
virtual void CustomizeChildren(TSharedRef<IPropertyHandle> InStructPropertyHandle, IDetailChildrenBuilder& StructBuilder, IPropertyTypeCustomizationUtils& StructCustomizationUtils) override;
|
||||
};
|
||||
|
||||
#endif // WITH_EDITOR
|
@ -70,19 +70,19 @@ protected:
|
||||
|
||||
// Path to own implementation of ImGui Input Handler allowing to customize handling of keyboard and gamepad input.
|
||||
// If not set then default handler is used.
|
||||
UPROPERTY(EditAnywhere, config, Category = "Input", meta = (MetaClass = "ImGuiInputHandler"))
|
||||
UPROPERTY(EditAnywhere, config, Category = "Extensions", meta = (MetaClass = "ImGuiInputHandler"))
|
||||
FStringClassReference ImGuiInputHandlerClass;
|
||||
|
||||
// Define a custom key binding to 'ImGui.SwitchInputMode' command. Mapping will be only set if Key property in this
|
||||
// structure is set to a valid key. Modifier keys can be either completely ignored (Undetermined), required to be
|
||||
// pressed (Checked) or required to be not pressed (Unchecked).
|
||||
UPROPERTY(EditAnywhere, config, Category = "Input")
|
||||
// Define a custom key binding to 'ImGui.SwitchInputMode' command. Binding is only set if key is valid.
|
||||
// Note that modifier key properties can be set to one of the three values: undetermined means that state of the given
|
||||
// modifier is not tested, checked means that it needs to be pressed and unchecked means that it cannot be pressed.
|
||||
//
|
||||
// This binding is using Player Input's DebugExecBindings which only works in non-shipment builds.
|
||||
UPROPERTY(EditAnywhere, config, Category = "Keyboard Shortcuts")
|
||||
FImGuiKeyInfo SwitchInputModeKey;
|
||||
|
||||
private:
|
||||
|
||||
void UpdateSwitchInputModeBinding();
|
||||
|
||||
#if WITH_EDITOR
|
||||
|
||||
void RegisterPropertyChangedDelegate();
|
||||
|
@ -90,7 +90,7 @@ private:
|
||||
* Also note that input handler functions are only called when ImGui Widget is receiving input events, what can be for
|
||||
* instance suppressed by opening console.
|
||||
*
|
||||
* See @ Project Settings/Plugins/ImGui/Input/ImGuiInputHandlerClass property to set custom implementation.
|
||||
* See @ Project Settings/Plugins/ImGui/Extensions/ImGuiInputHandlerClass property to set custom implementation.
|
||||
*/
|
||||
UCLASS()
|
||||
class IMGUI_API UImGuiInputHandler : public UObject
|
||||
|
Loading…
Reference in New Issue
Block a user