feat(input): assess world objects on right click

Port SmartBox's release-completed sr_Examine gesture through the configurable SelectRight binding. Cancel camera drags at the shared retail three-pixel threshold, then reuse the canonical picker, selection pulse, and appraisal request path without inventing another wire or UI owner.

Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-24 05:42:28 +02:00
parent 6718ee45a0
commit 5ad32d5753
16 changed files with 394 additions and 13 deletions

View file

@ -26,7 +26,7 @@ namespace AcDream.UI.Abstractions.Input;
/// </summary>
public sealed class KeyBindings
{
private const int CurrentSchemaVersion = 4;
private const int CurrentSchemaVersion = 5;
private readonly List<Binding> _bindings = new();
@ -324,7 +324,8 @@ public sealed class KeyBindings
InputAction.SelectLeft));
b.Add(new(
new KeyChord(InputDispatcher.MouseButtonToKey(MouseButton.Right), ModifierMask.None, Device: 1),
InputAction.SelectRight));
InputAction.SelectRight,
ActivationType.Click));
b.Add(new(
new KeyChord(InputDispatcher.MouseButtonToKey(MouseButton.Middle), ModifierMask.None, Device: 1),
InputAction.SelectMid));
@ -367,9 +368,9 @@ public sealed class KeyBindings
InputAction.AcdreamToggleFlyMode));
// K-fix1 (2026-04-26): RMB-hold camera orbit. Coexists with the
// SelectRight Press binding above — Press fires on click,
// AcdreamRmbOrbitHold fires on hold/release transitions so the
// chase camera can free-orbit while the user drags the mouse.
// SelectRight Click binding above resolves only after a stationary
// release. AcdreamRmbOrbitHold fires on hold/release transitions so
// the chase camera can free-orbit while the user drags the mouse.
// Without this, RMB-orbit silently broke when K.1c flipped the
// default keymap from AcdreamCurrentDefaults to RetailDefaults.
b.Add(new(
@ -435,6 +436,7 @@ public sealed class KeyBindings
var chord = new KeyChord(silkKey, mods, device);
action = MigrateLegacyQuickSlotIntent(version, action, chord, activation);
activation = MigrateCombatAttackActivation(version, action, activation);
activation = MigrateSelectRightActivation(version, action, activation);
InputScope scope = defaults.ForAction(action)
.Select(binding => binding.Scope)
.DefaultIfEmpty(InputScope.Game)
@ -562,6 +564,21 @@ public sealed class KeyBindings
: activation;
}
/// <summary>
/// Schema v4 fired SelectRight on mouse-down. Retail's SmartBox resolves
/// right-click examination on mouse-up only when the pointer did not turn
/// into a drag, so preserve the user's chord while upgrading its gesture.
/// </summary>
private static ActivationType MigrateSelectRightActivation(
int version,
InputAction action,
ActivationType activation)
=> version < 5
&& action == InputAction.SelectRight
&& activation == ActivationType.Press
? ActivationType.Click
: activation;
private static ModifierMask ParseModifiers(JsonElement bindingEl)
{
if (!bindingEl.TryGetProperty("mod", out var modEl)) return ModifierMask.None;