Skip to content

Commit

Permalink
Add option to disable hat-to-buttons interpolation
Browse files Browse the repository at this point in the history
  • Loading branch information
fredemmott committed Jun 30, 2022
1 parent 6a382b3 commit cc8ad70
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 6 deletions.
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,19 @@ stick.Hat1 >> HatToButtons(
);
```

Finally, interpolation can be disabled so that buttons are only pressed when the
hat is pointing *exactly* at them - for example, with an 8 way hat with 4 buttons,
NE on the hat will not trigger N or E buttons:

```C++
stick.Hat1 >> HatToButtons(
HatToButtons::Interpolation::None,
vj.Button2,
vj.Button3,
vj.Button4,
vj.Button5);
```
## LatchedToMomentaryButton
Some controllers have buttons that 'latch' or maintain their state, such as toggle switches that stay in position, or
Expand Down
12 changes: 11 additions & 1 deletion lib/HatToButtons.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,22 @@ void HatToButtons::map(Hat::Value value) {
}

const auto step = 36000 / mButtons.size();

if (mInterpolation == Interpolation::None) {
auto offset = 0;
for (auto i = 0; i < mButtons.size(); ++i) {
mButtons[i]->map(value == offset);
offset += step;
}
return;
}

// Let's say we have 4 buttons: N, E, S, W
// If the hat is at NE, we want both N and E on, so there's an area that's
// "NE" - which goes half way from true NE to E - in another words, the N
// button is pressed when the hat is between WNW and ENE, and covers 3/8ths
// of the area
const auto range = (36000 * 3) / (mButtons.size() * 2);
const auto range = ((36000 * 3) / (mButtons.size() * 2));
// first one is special, as North should be on for a bit both sides of 0
auto offset = range / 2;
mButtons[0]->map(value <= offset || value > 36000 - offset);
Expand Down
23 changes: 19 additions & 4 deletions lib/HatToButtons.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,16 @@ namespace fredemmott::inputmapping {
class MappableVJoyOutput;

class HatToButtons final : public Sink<Hat> {
private:
std::optional<ButtonSinkPtr> mCenter;
std::vector<ButtonSinkPtr> mButtons;

public:
enum class Interpolation {
// divide range by number of buttons, only press button when hat is pointing
// *exactly* at it - e.g. 0 degrees == press button 1, 1 degree and 359 degrees
// == press nothing
None,
// fill the range, and interpolate. e.g. if there are 4 buttons, if hat is
// pointing North East, press both buttons 1 and 2
MultiPress,
};
class CenterButton {
private:
ButtonSinkPtr mButton;
Expand Down Expand Up @@ -75,9 +80,19 @@ class HatToButtons final : public Sink<Hat> {
convert_to_any_sink_ptr(std::forward<Rest>(rest))...};
}

template <class... Rest>
HatToButtons(Interpolation interpolation, Rest&&... rest)
: HatToButtons(std::forward<Rest>(rest)...) {
mInterpolation = interpolation;
}

virtual void map(Hat::Value value) override;

private:
Interpolation mInterpolation = Interpolation::MultiPress;
std::optional<ButtonSinkPtr> mCenter;
std::vector<ButtonSinkPtr> mButtons;

void assignToVJoy(MappableVJoyOutput* output, uint8_t first, uint8_t count);
};

Expand Down
27 changes: 26 additions & 1 deletion tests/HatToButtons_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,31 @@ TEST_CASE("HatToButtons") {
REQUIRE(!s);
REQUIRE(!w);
}

SECTION("Without Interpolation") {
hat >> HatToButtons(HatToButtons::Interpolation::None, &n, &e, &s, &w);
hat.emit(Hat::NORTH);
REQUIRE(n);
REQUIRE(!e);
REQUIRE(!s);
REQUIRE(!w);
hat.emit(Hat::NORTH + 1);
REQUIRE(!n);
REQUIRE(!e);
hat.emit(Hat::MAX - 1);
REQUIRE(!n);
REQUIRE(!w);
hat.emit(Hat::EAST);
REQUIRE(!n);
REQUIRE(!w);
REQUIRE(!s);
hat.emit(Hat::EAST - 1);
REQUIRE(!n);
REQUIRE(!e);
hat.emit(Hat::EAST + 1);
REQUIRE(!e);
REQUIRE(!s);
}
}

namespace {
Expand All @@ -142,4 +167,4 @@ static void static_test() {
bool center;
HatToButtons(HatToButtons::CenterButton(&center), &o, 123, 4);
}
}// namespace
}// namespace

0 comments on commit cc8ad70

Please sign in to comment.