Базовая функция, оверайдить которую можно в любом модуле. Кей приходит только если никто другой не Занял кнопку, и фокус Модуль = модулю, где функция заоверайжена.
Что значит Занял кнопку ? Функция возращает боол. Если вернуть Тру - ипут остановится, и никаким другим модулем обрабатываться не будет. Т.е функции Ариала не сработают, например, Еск - не выполнит ничего, если инпут кей вернет тру.
Добавить шорткат
Создание команды
Самый "правильный" способ. Позволяет изменять кнопки в редакторе, и уже имеет все функции для лога информации о шорткате. Но при этом имеет ряд недостатков: 1. Поддерживает только IE_Pressed и IE_Repeat, но не IE_Released. 2. Работает, только если никто другой не заберет инпут Key, и не переключит фокус на себя.
Теперь как добавить. Каждый FUICommandInfo создается через переменную команды, которая регистрируется в:
class FBuildingToolsEditorCommands : public TCommands<FBuildingToolsEditorCommands>
{
public:
FBuildingToolsEditorCommands()
: TCommands<FBuildingToolsEditorCommands>(
"BuildingToolsEditor",
// Context name for fast lookup
NSLOCTEXT("Contexts", "BuildingToolsEditor", "Building Tools"),
// Localized context name for displaying
NAME_None,
//"LevelEditor" // Parent
FEditorStyle::GetStyleSetName() // Icon Style Set
)
{
}
virtual void RegisterCommands() override;
TSharedPtr<FUICommandInfo> Command;
};
void FBuildingToolsEditorCommands::RegisterCommands()
{
// FInputChord() - сюда указывать кнопку, на которую запускать команду
// EUserInterfaceActionType важна только для UI
UI_COMMAND(Command, "UniqueIDName", "CommandDescription",
EUserInterfaceActionType::Button, FInputChord());
// А это если мы хотим не создавать все команды EditorCommands, а создавать
// их где-то еще
for (const auto Command : BuildingToolsModes::GetCommands())
{
Command->RegisterUICommand(this);
}
}
Регистрация модуля c Командами
Но от куда берется сама FBuildingToolsEditorCommands ? Она регистрируется в классе модуля через статическую функцию:
Самая большая беда, что один КоммандИнфо должен быть зареган лишь единожды и никогда больше. Если зарегестрировать дважды - будет краш. Поэтому нужно убедиться, что каждый комманд инфо будет уникальный
Создание комманды-класса
Для этой уникальности поместим каждую комманду в класс обжект
UCLASS(abstract, Transient)
class BUILDINGTOOLS_API UBTCommand : public UObject
{
GENERATED_BODY()
public:
/** Registers the UI command for this mesh editor command */
virtual void RegisterUICommand(class FBindingContext* BindingContext) PURE_VIRTUAL(,);
/** Gets the UI command info for this command */
const TSharedPtr<FUICommandInfo>& GetUICommandInfo() const
{
return UICommandInfo;
}
protected:
/** Our UI command for this action */
TSharedPtr<FUICommandInfo> UICommandInfo;
};
Теперь создаем наследника и указываем всю инфу о команде:
Так же как и раньше, но не совсем. Как можно видеть в прошлом блоке - использовался именно UI_COMMAND_EXT. Это нужно для того, чтобы регестрировать комманды именно в других функциях.
void FBuildingToolsEditorCommands::RegisterCommands()
{
HarvestCommands();
// А это если мы хотим не создавать все команды EditorCommands, а создавать
// их где-то еще
for (const auto Command : Commands)
{
Command->RegisterUICommand(this);
}
}
Самый надежный способ принять инпут. Независимо от того, какой модуль сейчас в фокусе - Пре Инпут обработается перед этим. Для этого есть и ИнпутПроцессор. Создадим его:
class FBTInputProcessor : public IInputProcessor, public TSharedFromThis<FBTInputProcessor>
{
public:
FBTInputProcessor(){};
virtual ~FBTInputProcessor(){};
//Если не добавить тик, он будет считаться абстрактным
virtual void Tick(const float DeltaTime, FSlateApplication& SlateApp, TSharedRef<ICursor> Cursor) override;
/** Key down input */
virtual bool HandleKeyDownEvent(FSlateApplication& SlateApp, const FKeyEvent& InKeyEvent) override;
/** Key up input */
virtual bool HandleKeyUpEvent(FSlateApplication& SlateApp, const FKeyEvent& InKeyEvent) override;
public:
TDelegate<bool(FKey InKey, EInputEvent InEvent)> PreInputKeyDelegate;
};