Files
test2/intern/ghost/intern/GHOST_NDOFManagerUnix.cc
Campbell Barton e955c94ed3 License Headers: Set copyright to "Blender Authors", add AUTHORS
Listing the "Blender Foundation" as copyright holder implied the Blender
Foundation holds copyright to files which may include work from many
developers.

While keeping copyright on headers makes sense for isolated libraries,
Blender's own code may be refactored or moved between files in a way
that makes the per file copyright holders less meaningful.

Copyright references to the "Blender Foundation" have been replaced with
"Blender Authors", with the exception of `./extern/` since these this
contains libraries which are more isolated, any changed to license
headers there can be handled on a case-by-case basis.

Some directories in `./intern/` have also been excluded:

- `./intern/cycles/` it's own `AUTHORS` file is planned.
- `./intern/opensubdiv/`.

An "AUTHORS" file has been added, using the chromium projects authors
file as a template.

Design task: #110784

Ref !110783.
2023-08-16 00:20:26 +10:00

128 lines
3.4 KiB
C++

/* SPDX-FileCopyrightText: 2011-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "GHOST_NDOFManagerUnix.hh"
#include "GHOST_System.hh"
/* Logging, use `ghost.ndof.unix.*` prefix. */
#include "CLG_log.h"
#include <cstdio>
#include <spnav.h>
#include <unistd.h>
static const char *spnav_sock_path = "/var/run/spnav.sock";
static CLG_LogRef LOG_NDOF_UNIX = {"ghost.ndof.unix"};
#define LOG (&LOG_NDOF_UNIX)
GHOST_NDOFManagerUnix::GHOST_NDOFManagerUnix(GHOST_System &sys)
: GHOST_NDOFManager(sys), available_(false)
{
if (access(spnav_sock_path, F_OK) != 0) {
CLOG_INFO(LOG, 1, "'spacenavd' not found at \"%s\"", spnav_sock_path);
}
else if (spnav_open() != -1) {
CLOG_INFO(LOG, 1, "'spacenavd' found at\"%s\"", spnav_sock_path);
available_ = true;
/* determine exactly which device (if any) is plugged in */
#define MAX_LINE_LENGTH 100
/* look for USB devices with Logitech or 3Dconnexion's vendor ID */
FILE *command_output = popen("lsusb | grep '046d:\\|256f:'", "r");
if (command_output) {
char line[MAX_LINE_LENGTH] = {0};
while (fgets(line, MAX_LINE_LENGTH, command_output)) {
ushort vendor_id = 0, product_id = 0;
if (sscanf(line, "Bus %*d Device %*d: ID %hx:%hx", &vendor_id, &product_id) == 2) {
if (setDevice(vendor_id, product_id)) {
break; /* stop looking once the first 3D mouse is found */
}
}
}
pclose(command_output);
}
}
}
GHOST_NDOFManagerUnix::~GHOST_NDOFManagerUnix()
{
if (available_) {
spnav_close();
}
}
bool GHOST_NDOFManagerUnix::available()
{
return available_;
}
/*
* Workaround for a problem where we don't enter the 'GHOST_kFinished' state,
* this causes any proceeding event to have a very high 'dt' (time delta),
* many seconds for eg, causing the view to jump.
*
* this workaround expects continuous events, if we miss a motion event,
* immediately send a dummy event with no motion to ensure the finished state is reached.
*/
#define USE_FINISH_GLITCH_WORKAROUND
/* TODO: make this available on all platforms */
#ifdef USE_FINISH_GLITCH_WORKAROUND
static bool motion_test_prev = false;
#endif
bool GHOST_NDOFManagerUnix::processEvents()
{
bool anyProcessed = false;
if (available_) {
spnav_event e;
#ifdef USE_FINISH_GLITCH_WORKAROUND
bool motion_test = false;
#endif
while (spnav_poll_event(&e)) {
switch (e.type) {
case SPNAV_EVENT_MOTION: {
/* convert to blender view coords */
uint64_t now = system_.getMilliSeconds();
const int t[3] = {int(e.motion.x), int(e.motion.y), int(-e.motion.z)};
const int r[3] = {int(-e.motion.rx), int(-e.motion.ry), int(e.motion.rz)};
updateTranslation(t, now);
updateRotation(r, now);
#ifdef USE_FINISH_GLITCH_WORKAROUND
motion_test = true;
#endif
break;
}
case SPNAV_EVENT_BUTTON:
uint64_t now = system_.getMilliSeconds();
updateButton(e.button.bnum, e.button.press, now);
break;
}
anyProcessed = true;
}
#ifdef USE_FINISH_GLITCH_WORKAROUND
if (motion_test_prev == true && motion_test == false) {
uint64_t now = system_.getMilliSeconds();
const int v[3] = {0, 0, 0};
updateTranslation(v, now);
updateRotation(v, now);
anyProcessed = true;
}
motion_test_prev = motion_test;
#endif
}
return anyProcessed;
}