Skip to content

Commit

Permalink
Add option for custom devices to have dedicted wheel up/down controls
Browse files Browse the repository at this point in the history
  • Loading branch information
fredemmott committed Jul 22, 2024
1 parent 7840d13 commit 851a99e
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 9 deletions.
6 changes: 6 additions & 0 deletions docs/hardware/pointctrl/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ In both modes:
- short-tap FCU3 to switch to normal mode
- long-press FCU3 to switch to scroll mode

### Modal with left click lock

Like modal, but additionally, pressing FCU1 and FCU2 together ends scroll mode with 'left click' held. This can be useful for 'click-hold-and-scroll' controls.

This feature requires HTCC v1.1 or above.

## Projection distance

The PointCTRL HMS only detects left/right and up/down position - not distance. You can choose what distance is used for emulated VR controllers in the registry at:
Expand Down
13 changes: 13 additions & 0 deletions docs/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ DWORD:
- 1: Classic
- 2: Modal (intended for MSFS, but no longer required due to other changes)
- 3: Modal, but long-pressing buttons 1 & 2 together enters scroll lock mode but with button 1 held
- 4: For custom devices; FCU3 is ignored, `GameControllerWheelUpButton` and `GameControllerWheelDown` buttons are used instead

### ShortPressLongPressMilliseconds

Expand Down Expand Up @@ -292,6 +293,18 @@ DWORD button indices starting at 0.

FCU L1 is the button farthest from your wrist on your left hand, L3 is closest. R1-R3 are the buttons on your right hand.

### GameControllerWheelUpButton

DWORD button indices starting at 0

If you want to use separate buttons for 'wheel up' and 'wheel down' instead of emulating a pointctrl, set `PointCtrlFCUMapping` to `4` (dedicated scroll buttons), and this to a desired button index.

### GameControllerWheelDownButton

DWORD button indices starting at 0

If you want to use separate buttons for 'wheel up' and 'wheel down' instead of emulating a pointctrl, set `PointCtrlFCUMapping` to `4` (dedicated scroll buttons), and this to a desired button index.

## Developers only

Changing these settings can have unexpected effects; parts of HTCC may assume they're at their default values and break if they're changed.
Expand Down
4 changes: 4 additions & 0 deletions src/SettingsApp/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -110,11 +110,15 @@
CornerRadius="4"
BorderThickness="1">
<ComboBox
x:Name="FCUMapping"
Header="FCU button mapping:"
SelectedIndex="{x:Bind PointCtrlFCUMapping}">
<x:String>Disabled</x:String>
<x:String>Classic</x:String>
<x:String>Modal</x:String>
<x:String>Modal with left button lock</x:String>
<!-- removed at runtime unless it's set -->
<x:String>UNSUPPORTED: dedicated wheel up and down buttons</x:String>
</ComboBox>
</StackPanel>
<!-- Workarounds -->
Expand Down
8 changes: 8 additions & 0 deletions src/SettingsApp/MainWindow.xaml.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@ MainWindow::MainWindow() {
Title(L"HTCC Settings");
InitVersion();

if (
HTCC::Config::PointCtrlFCUMapping
!= HTCC::PointCtrlFCUMapping::DedicatedScrollButtons) {
auto items = FCUMapping().Items();
items.RemoveAt(
static_cast<uint32_t>(HTCC::PointCtrlFCUMapping::DedicatedScrollButtons));
}

// Get an AppWindow so that we can resize...
auto windowNative = this->try_as<::IWindowNative>();
if (!windowNative) {
Expand Down
5 changes: 5 additions & 0 deletions src/lib/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ enum class PointCtrlFCUMapping : DWORD {
Classic = 1,
Modal = 2,
ModalWithLeftLock = 3,
// Not supported on a PointCtrl device, but usable with others if you edit the
// registry
DedicatedScrollButtons = 4,
};
enum class HandTrackingOrientation : DWORD {
Raw = 0,
Expand Down Expand Up @@ -149,6 +152,8 @@ enum class HandTrackingHands : DWORD {
IT(uint8_t, PointCtrlFCUButtonR1, 3) \
IT(uint8_t, PointCtrlFCUButtonR2, 4) \
IT(uint8_t, PointCtrlFCUButtonR3, 5) \
IT(uint8_t, GameControllerWheelUpButton, 0) \
IT(uint8_t, GameControllerWheelDownButton, 0) \
IT(uint32_t, PointCtrlSleepMilliseconds, 20000) \
IT(bool, ForceHaveXRExtHandTracking, false) \
IT(bool, ForceHaveXRFBHandTrackingAim, false)
Expand Down
26 changes: 23 additions & 3 deletions src/lib/PointCtrlSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,8 @@ std::tuple<InputState, InputState> PointCtrlSource::Update(
case PointCtrlFCUMapping::ModalWithLeftLock:
MapActionsModal(hand, now, buttons);
break;
case PointCtrlFCUMapping::DedicatedScrollButtons:
MapActionsDedicatedScrollButtons(hand, now, buttons);
}
}

Expand Down Expand Up @@ -299,8 +301,8 @@ bool PointCtrlSource::IsConnected() const {

void PointCtrlSource::MapActionsClassic(
Hand* hand,
XrTime now,
const decltype(DIJOYSTATE2::rgbButtons)& buttons) {
[[maybe_unused]] XrTime now,
const RawButtons& buttons) {
auto& state = hand->mState.mActions;
const auto b1 = HAS_BUTTON(HAND_FCUB(hand->mHand, 1));
const auto b2 = HAS_BUTTON(HAND_FCUB(hand->mHand, 2));
Expand All @@ -324,10 +326,28 @@ void PointCtrlSource::MapActionsClassic(
}
}

void PointCtrlSource::MapActionsDedicatedScrollButtons(
Hand* hand,
XrTime now,
const RawButtons& buttons) {
auto& state = hand->mState.mActions;
state.mPrimary = HAS_BUTTON(HAND_FCUB(hand->mHand, 1));
state.mSecondary = HAS_BUTTON(HAND_FCUB(hand->mHand, 2));
state.mValueChange = ActionState::ValueChange::None;

const auto scrollUp = HAS_BUTTON(Config::GameControllerWheelUpButton);
const auto scrollDown = HAS_BUTTON(Config::GameControllerWheelDownButton);
if (scrollUp && !scrollDown) {
state.mValueChange = ActionState::ValueChange::Decrease;
} else if (scrollDown && !scrollUp) {
state.mValueChange = ActionState::ValueChange::Increase;
}
}

void PointCtrlSource::MapActionsModal(
Hand* hand,
XrTime now,
const decltype(DIJOYSTATE2::rgbButtons)& buttons) {
const RawButtons& buttons) {
auto& state = hand->mState.mActions;
const auto b1 = HAS_BUTTON(HAND_FCUB(hand->mHand, 1));
const auto b2 = HAS_BUTTON(HAND_FCUB(hand->mHand, 2));
Expand Down
13 changes: 7 additions & 6 deletions src/lib/PointCtrlSource.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class PointCtrlSource final : public InputSource {
std::tuple<InputState, InputState> Update(PointerMode, const FrameInfo&)
override;

// Just used for calibration
struct RawValues {
uint16_t mX {};
uint16_t mY {};
Expand Down Expand Up @@ -116,12 +117,12 @@ class PointCtrlSource final : public InputSource {

void UpdatePose(const FrameInfo&, InputState* hand);
void UpdateWakeState(bool hasButtons, XrTime now, Hand* hand);
void MapActionsClassic(
Hand*,
XrTime now,
const decltype(DIJOYSTATE2::rgbButtons)&);
void
MapActionsModal(Hand*, XrTime now, const decltype(DIJOYSTATE2::rgbButtons)&);

using RawButtons = decltype(DIJOYSTATE2::rgbButtons);

void MapActionsClassic(Hand*, XrTime now, const RawButtons&);
void MapActionsModal(Hand*, XrTime now, const RawButtons&);
void MapActionsDedicatedScrollButtons(Hand*, XrTime now, const RawButtons&);
};

}// namespace HandTrackedCockpitClicking

0 comments on commit 851a99e

Please sign in to comment.