diff --git a/Source/Editor/CustomEditors/Editors/BindableButtonEditor.cs b/Source/Editor/CustomEditors/Editors/BindableButtonEditor.cs
new file mode 100644
index 000000000..80d873cdf
--- /dev/null
+++ b/Source/Editor/CustomEditors/Editors/BindableButtonEditor.cs
@@ -0,0 +1,96 @@
+using FlaxEditor.GUI;
+using FlaxEngine;
+using FlaxEngine.GUI;
+
+namespace FlaxEditor.CustomEditors.Editors
+{
+ ///
+ /// Base class for custom button editors.
+ /// See , and .
+ ///
+ public class BindableButtonEditor : EnumEditor
+ {
+ private bool _isListeningForInput;
+ private Button _button;
+
+ ///
+ /// Where or not we are currently listening for any input.
+ ///
+ protected bool IsListeningForInput
+ {
+ get => _isListeningForInput;
+ set
+ {
+ _isListeningForInput = value;
+ if (_isListeningForInput)
+ SetupButton();
+ else
+ ResetButton();
+ }
+ }
+
+ ///
+ /// The window this editor is attached to.
+ /// Useful to hook into for key pressed, mouse buttons etc.
+ ///
+ protected Window Window { get; private set; }
+
+ ///
+ public override void Initialize(LayoutElementsContainer layout)
+ {
+ Window = layout.Control.RootWindow.Window;
+
+ var panel = layout.CustomContainer();
+ panel.CustomControl.SlotsHorizontally = 2;
+ panel.CustomControl.SlotsVertically = 1;
+
+ var button = panel.Button("Listen");
+ _button = button.Button;
+ _button.Clicked += OnButtonClicked;
+ ResetButton();
+
+ var padding = panel.CustomControl.SlotPadding;
+ panel.CustomControl.Height = ComboBox.DefaultHeight + padding.Height;
+
+ base.Initialize(panel);
+ }
+
+ ///
+ protected override void Deinitialize()
+ {
+ _button.Clicked -= OnButtonClicked;
+ base.Deinitialize();
+ }
+
+ private void ResetButton()
+ {
+ _button.Text = "Listen";
+ _button.BorderThickness = 1;
+
+ var style = FlaxEngine.GUI.Style.Current;
+ _button.BorderColor = style.BorderNormal;
+ _button.BorderColorHighlighted = style.BorderHighlighted;
+ _button.BorderColorSelected = style.BorderSelected;
+ }
+
+ private void SetupButton()
+ {
+ _button.Text = "Listening...";
+ _button.BorderThickness = 2;
+
+ var color = FlaxEngine.GUI.Style.Current.ProgressNormal;
+ _button.BorderColor = color;
+ _button.BorderColorHighlighted = color;
+ _button.BorderColorSelected = color;
+ }
+
+ private void OnButtonClicked()
+ {
+ _isListeningForInput = !_isListeningForInput;
+ if (_isListeningForInput)
+ SetupButton();
+ else
+ ResetButton();
+ }
+ }
+}
diff --git a/Source/Editor/CustomEditors/Editors/GamepadButtonEditor.cs b/Source/Editor/CustomEditors/Editors/GamepadButtonEditor.cs
new file mode 100644
index 000000000..7bae24922
--- /dev/null
+++ b/Source/Editor/CustomEditors/Editors/GamepadButtonEditor.cs
@@ -0,0 +1,51 @@
+using System;
+using FlaxEngine;
+
+namespace FlaxEditor.CustomEditors.Editors
+{
+ ///
+ /// Custom editor for .
+ /// Allows capturing gamepad buttons and assigning them
+ /// to the edited value.
+ ///
+ [CustomEditor(typeof(GamepadButton))]
+ public class GamepadButtonEditor : BindableButtonEditor
+ {
+ ///
+ public override void Initialize(LayoutElementsContainer layout)
+ {
+ base.Initialize(layout);
+ FlaxEngine.Scripting.Update += ScriptingOnUpdate;
+ }
+
+ ///
+ protected override void Deinitialize()
+ {
+ FlaxEngine.Scripting.Update -= ScriptingOnUpdate;
+ base.Deinitialize();
+ }
+
+ private void ScriptingOnUpdate()
+ {
+ if (!IsListeningForInput)
+ return;
+
+ // Since there is no way to get an event about
+ // which gamepad pressed what button, we have
+ // to poll all gamepads and buttons manually.
+ for (var i = 0; i < Input.GamepadsCount; i++)
+ {
+ var pad = Input.Gamepads[i];
+ foreach (var btn in Enum.GetValues())
+ {
+ if (pad.GetButtonUp(btn))
+ {
+ IsListeningForInput = false;
+ SetValue(btn);
+ return;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/Source/Editor/CustomEditors/Editors/KeyboardKeysEditor.cs b/Source/Editor/CustomEditors/Editors/KeyboardKeysEditor.cs
new file mode 100644
index 000000000..765527b7e
--- /dev/null
+++ b/Source/Editor/CustomEditors/Editors/KeyboardKeysEditor.cs
@@ -0,0 +1,36 @@
+using FlaxEngine;
+
+namespace FlaxEditor.CustomEditors.Editors
+{
+ ///
+ /// Custom editor for .
+ /// Allows capturing key presses and assigning them
+ /// to the edited value.
+ ///
+ [CustomEditor(typeof(KeyboardKeys))]
+ public class KeyboardKeysEditor : BindableButtonEditor
+ {
+ ///
+ public override void Initialize(LayoutElementsContainer layout)
+ {
+ base.Initialize(layout);
+ Window.KeyUp += WindowOnKeyUp;
+ }
+
+ ///
+ protected override void Deinitialize()
+ {
+ Window.KeyUp -= WindowOnKeyUp;
+ base.Deinitialize();
+ }
+
+ private void WindowOnKeyUp(KeyboardKeys key)
+ {
+ if (!IsListeningForInput)
+ return;
+ IsListeningForInput = false;
+
+ SetValue(key);
+ }
+ }
+}
diff --git a/Source/Editor/CustomEditors/Editors/MouseButtonEditor.cs b/Source/Editor/CustomEditors/Editors/MouseButtonEditor.cs
new file mode 100644
index 000000000..7964d3a4d
--- /dev/null
+++ b/Source/Editor/CustomEditors/Editors/MouseButtonEditor.cs
@@ -0,0 +1,37 @@
+using FlaxEngine;
+
+namespace FlaxEditor.CustomEditors.Editors
+{
+ ///
+ /// Custom editor for .
+ /// Allows capturing mouse button presses and assigning them
+ /// to the edited value.
+ ///
+ [CustomEditor(typeof(MouseButton))]
+ public class MouseButtonEditor : BindableButtonEditor
+ {
+ ///
+ public override void Initialize(LayoutElementsContainer layout)
+ {
+ base.Initialize(layout);
+ Window.MouseUp += WindowOnMouseUp;
+ }
+
+ ///
+ protected override void Deinitialize()
+ {
+ Window.MouseUp -= WindowOnMouseUp;
+ base.Deinitialize();
+ }
+
+ private void WindowOnMouseUp(ref Float2 mouse, MouseButton button, ref bool handled)
+ {
+ if (!IsListeningForInput)
+ return;
+ IsListeningForInput = false;
+
+ SetValue(button);
+ handled = true;
+ }
+ }
+}