Blender V4.3
GHOST_NDOFManagerUnix.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
6#include "GHOST_System.hh"
7
8/* Logging, use `ghost.ndof.unix.*` prefix. */
9#include "CLG_log.h"
10
11#include <cstdio>
12#include <spnav.h>
13#include <unistd.h>
14
15static const char *spnav_sock_path = "/var/run/spnav.sock";
16
17static CLG_LogRef LOG_NDOF_UNIX = {"ghost.ndof.unix"};
18#define LOG (&LOG_NDOF_UNIX)
19
21 : GHOST_NDOFManager(sys), available_(false)
22{
23 if (access(spnav_sock_path, F_OK) != 0) {
24 CLOG_INFO(LOG, 1, "'spacenavd' not found at \"%s\"", spnav_sock_path);
25 }
26 else if (spnav_open() != -1) {
27 CLOG_INFO(LOG, 1, "'spacenavd' found at\"%s\"", spnav_sock_path);
28 available_ = true;
29
30 /* determine exactly which device (if any) is plugged in */
31
32#define MAX_LINE_LENGTH 100
33
34 /* look for USB devices with Logitech or 3Dconnexion's vendor ID */
35 FILE *command_output = popen("lsusb | grep '046d:\\|256f:'", "r");
36 if (command_output) {
37 char line[MAX_LINE_LENGTH] = {0};
38 while (fgets(line, MAX_LINE_LENGTH, command_output)) {
39 ushort vendor_id = 0, product_id = 0;
40 if (sscanf(line, "Bus %*d Device %*d: ID %hx:%hx", &vendor_id, &product_id) == 2) {
41 if (setDevice(vendor_id, product_id)) {
42 break; /* stop looking once the first 3D mouse is found */
43 }
44 }
45 }
46 pclose(command_output);
47 }
48 }
49}
50
52{
53 if (available_) {
54 spnav_close();
55 }
56}
57
59{
60 return available_;
61}
62
63/*
64 * Workaround for a problem where we don't enter the 'GHOST_kFinished' state,
65 * this causes any proceeding event to have a very high 'dt' (time delta),
66 * many seconds for eg, causing the view to jump.
67 *
68 * this workaround expects continuous events, if we miss a motion event,
69 * immediately send a dummy event with no motion to ensure the finished state is reached.
70 */
71#define USE_FINISH_GLITCH_WORKAROUND
72/* TODO: make this available on all platforms */
73
74#ifdef USE_FINISH_GLITCH_WORKAROUND
75static bool motion_test_prev = false;
76#endif
77
79{
80 bool anyProcessed = false;
81
82 if (available_) {
83 spnav_event e;
84
85#ifdef USE_FINISH_GLITCH_WORKAROUND
86 bool motion_test = false;
87#endif
88
89 while (spnav_poll_event(&e)) {
90 switch (e.type) {
91 case SPNAV_EVENT_MOTION: {
92 /* convert to blender view coords */
94 const int t[3] = {int(e.motion.x), int(e.motion.y), int(-e.motion.z)};
95 const int r[3] = {int(-e.motion.rx), int(-e.motion.ry), int(e.motion.rz)};
96
97 updateTranslation(t, now);
98 updateRotation(r, now);
99#ifdef USE_FINISH_GLITCH_WORKAROUND
100 motion_test = true;
101#endif
102 break;
103 }
104 case SPNAV_EVENT_BUTTON:
106 updateButton(e.button.bnum, e.button.press, now);
107 break;
108 }
109 anyProcessed = true;
110 }
111
112#ifdef USE_FINISH_GLITCH_WORKAROUND
113 if (motion_test_prev == true && motion_test == false) {
115 const int v[3] = {0, 0, 0};
116
117 updateTranslation(v, now);
118 updateRotation(v, now);
119
120 anyProcessed = true;
121 }
122 motion_test_prev = motion_test;
123#endif
124 }
125
126 return anyProcessed;
127}
unsigned short ushort
#define CLOG_INFO(clg_ref, level,...)
Definition CLG_log.h:179
static bool motion_test_prev
static const char * spnav_sock_path
static CLG_LogRef LOG_NDOF_UNIX
#define MAX_LINE_LENGTH
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
virtual uint64_t getMilliSeconds() const =0
GHOST_NDOFManagerUnix(GHOST_System &)
void updateButton(int button_number, bool press, uint64_t time)
void updateTranslation(const int t[3], uint64_t time)
GHOST_System & system_
void updateRotation(const int r[3], uint64_t time)
bool setDevice(unsigned short vendor_id, unsigned short product_id)
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
#define LOG(severity)
Definition log.h:33
unsigned __int64 uint64_t
Definition stdint.h:90