forked from solvespace/solvespace
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
274 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
//----------------------------------------------------------------------------- | ||
// Cross-platform handling of spnavdev 6-dof input. | ||
// | ||
// Copyright 2021 Collabora, Ltd. | ||
//----------------------------------------------------------------------------- | ||
|
||
#include "spnavdevice.h" | ||
#include "config.h" | ||
|
||
#ifdef HAVE_SPNAVDEV | ||
# include "spnavdev.h" | ||
# include <string> | ||
# include <solvespace.h> | ||
|
||
NavDeviceWrapper::NavDeviceWrapper(const char* device) { | ||
dev = spndev_open(device); | ||
if(dev == nullptr) { | ||
return; | ||
} | ||
|
||
int fd = spndev_fd(dev); | ||
populateAxes(); | ||
populateButtons(); | ||
} | ||
NavDeviceWrapper::~NavDeviceWrapper() { | ||
if(dev != nullptr) { | ||
spndev_close(dev); | ||
dev = nullptr; | ||
} | ||
} | ||
|
||
static double transformIndex(union spndev_event const& ev, | ||
NavDeviceWrapper::AxisData const& axisData) { | ||
ssassert(ev.type == SPNDEV_MOTION, "shouldn't be in here if not a motion event"); | ||
if(axisData.spnavdevIndex < 0) { | ||
return 0; | ||
} | ||
return double(ev.mot.v[axisData.spnavdevIndex]); | ||
} | ||
bool NavDeviceWrapper::process(SolveSpace::Platform::SixDofEvent& event) { | ||
using SolveSpace::Platform::SixDofEvent; | ||
union spndev_event ev; | ||
if(0 == spndev_process(dev, &ev)) { | ||
return false; | ||
} | ||
if(ctrlPressed) { | ||
event.controlDown = true; | ||
} | ||
if(shiftPressed) { | ||
event.shiftDown = true; | ||
} | ||
switch(ev.type) { | ||
case SPNDEV_MOTION: | ||
event.type = SixDofEvent::Type::MOTION; | ||
event.translationX = transformIndex(ev, axes[0]); | ||
event.translationY = transformIndex(ev, axes[1]); | ||
event.translationZ = transformIndex(ev, axes[2]); | ||
event.rotationX = transformIndex(ev, axes[3]) * 0.001; | ||
event.rotationY = transformIndex(ev, axes[4]) * 0.001; | ||
event.rotationZ = transformIndex(ev, axes[5]) * 0.001; | ||
return true; | ||
case SPNDEV_BUTTON: { | ||
if(ev.bn.num >= buttons.size()) { | ||
return false; | ||
} | ||
const NavButton meaning = buttons[ev.bn.num]; | ||
auto type = ev.bn.press ? SixDofEvent::Type::PRESS : SixDofEvent::Type::RELEASE; | ||
switch(meaning) { | ||
case NavButton::UNUSED: | ||
// we don't handle this button. | ||
return false; | ||
|
||
case NavButton::SHIFT: | ||
// handled internally to this class | ||
shiftPressed = type == SixDofEvent::Type::PRESS; | ||
return false; | ||
|
||
case NavButton::CTRL: | ||
// handled internally to this class | ||
ctrlPressed = type == SixDofEvent::Type::PRESS; | ||
return false; | ||
|
||
case NavButton::FIT: | ||
event.button = SixDofEvent::Button::FIT; | ||
event.type = type; | ||
return true; | ||
} | ||
break; | ||
} | ||
default: return false; | ||
} | ||
return false; | ||
} | ||
|
||
void NavDeviceWrapper::populateAxes() { | ||
using std::begin; | ||
using std::end; | ||
const std::string axis_names[] = {"Tx", "Ty", "Tz", "Rx", "Ry", "Rz"}; | ||
const auto b = begin(axis_names); | ||
const auto e = end(axis_names); | ||
const auto num_axes = spndev_num_axes(dev); | ||
for(int axis_idx = 0; axis_idx < num_axes; ++axis_idx) { | ||
auto axis_name = spndev_axis_name(dev, axis_idx); | ||
auto it = std::find_if(b, e, [&](std::string const& name) { return name == axis_name; }); | ||
if(it != e) { | ||
ptrdiff_t remapped_index = std::distance(b, it); | ||
axes[remapped_index] = AxisData{axis_idx}; | ||
} | ||
} | ||
} | ||
|
||
void NavDeviceWrapper::populateButtons() { | ||
using std::begin; | ||
using std::end; | ||
using ButtonData = std::pair<std::string, NavButton>; | ||
const ButtonData button_name_pairs[] = { | ||
{"CTRL", NavButton::CTRL}, | ||
{"FIT", NavButton::FIT}, | ||
{"SHIFT", NavButton::SHIFT}, | ||
}; | ||
|
||
const auto b = begin(button_name_pairs); | ||
const auto e = end(button_name_pairs); | ||
const auto num_buttons = spndev_num_buttons(dev); | ||
buttons.resize(num_buttons); | ||
for(int button_idx = 0; button_idx < num_buttons; ++button_idx) { | ||
auto button_name = spndev_button_name(dev, button_idx); | ||
auto it = | ||
std::find_if(b, e, [&](ButtonData const& data) { return data.first == button_name; }); | ||
if(it != e) { | ||
buttons[button_idx] = it->second; | ||
} | ||
} | ||
} | ||
|
||
#else | ||
|
||
NavDeviceWrapper::NavDeviceWrapper(const char* device) { | ||
} | ||
NavDeviceWrapper::~NavDeviceWrapper() { | ||
} | ||
|
||
bool NavDeviceWrapper::process(SolveSpace::Platform::SixDofEvent&) { | ||
return false; | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
//----------------------------------------------------------------------------- | ||
// Cross-platform handling of spnavdev 6-dof input. | ||
// | ||
// Copyright 2021 Collabora, Ltd. | ||
//----------------------------------------------------------------------------- | ||
|
||
#ifndef SOLVESPACE_SPNAVDEVICE_H | ||
#define SOLVESPACE_SPNAVDEVICE_H | ||
#include <vector> | ||
#include <array> | ||
|
||
namespace SolveSpace { | ||
namespace Platform { | ||
struct SixDofEvent; | ||
} | ||
} // namespace SolveSpace | ||
struct spndev; | ||
|
||
class NavDeviceWrapper { | ||
public: | ||
explicit NavDeviceWrapper(const char* device = nullptr); | ||
~NavDeviceWrapper(); | ||
|
||
// no copy, no move | ||
NavDeviceWrapper(NavDeviceWrapper const&) = delete; | ||
NavDeviceWrapper& operator=(NavDeviceWrapper const&) = delete; | ||
NavDeviceWrapper(NavDeviceWrapper&&) = delete; | ||
NavDeviceWrapper& operator=(NavDeviceWrapper&&) = delete; | ||
|
||
bool active() const noexcept { | ||
return dev != nullptr; | ||
} | ||
|
||
//! true when the event has data in it to deal with. | ||
bool process(SolveSpace::Platform::SixDofEvent& event); | ||
|
||
enum class NavButton { | ||
UNUSED, | ||
FIT, | ||
CTRL, | ||
SHIFT, | ||
}; | ||
struct AxisData { | ||
AxisData() = default; | ||
AxisData(int spnavdevIndex_) : spnavdevIndex(spnavdevIndex_) { | ||
} | ||
|
||
int spnavdevIndex = -1; | ||
}; | ||
|
||
private: | ||
void populateAxes(); | ||
void populateButtons(); | ||
struct spndev* dev = nullptr; | ||
//! indexed by the spnavdev index | ||
std::vector<NavButton> buttons; | ||
//! indexed by our internal axis index. | ||
std::array<AxisData, 6> axes; | ||
bool ctrlPressed = false; | ||
bool shiftPressed = false; | ||
}; | ||
#endif // !SOLVESPACE_SPNAVDEVICE_H |