Revision control
Copy as Markdown
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:significant reason:default
#include "qquick3dxrcontroller_p.h"
#include "qquick3dxrinputmanager_p.h"
#if !defined(Q_OS_VISIONOS)
# include "openxr/qopenxrinputmanager_p.h"
#endif
#include "qquick3dxrview_p.h"
#include "qquick3dxractionmapper_p.h"
#include <QtGui/qquaternion.h>
QT_BEGIN_NAMESPACE
/*!
\qmltype XrController
\inherits Node
\inqmlmodule QtQuick3D.Xr
\brief A tracked spatial node that tracks the position and orientation of an input controller.
The XrController is a tracked spatial node that tracks the position and orientation of an input controller.
Since this is a tracked node, its spatial properties should be considered read-only.
\sa XrInputAction
*/
QQuick3DXrController::QQuick3DXrController()
{
m_inputManager = QQuick3DXrInputManager::instance();
}
/*!
\qmlproperty enumeration QtQuick3D.Xr::XrController::controller
Specifies the controller to track.
It can be one of:
\value XrController.LeftController
\value XrController.RightController
\value XrController.UnknownController
\value XrController.LeftHand (alias for \c LeftController)
\value XrController.RightHand (alias for \c RightController)
*/
QQuick3DXrController::Controller QQuick3DXrController::controller() const
{
return static_cast<QQuick3DXrController::Controller>(m_controller);
}
void QQuick3DXrController::setController(QQuick3DXrController::Controller newController)
{
if (m_controller == newController)
return;
m_controller = newController;
emit controllerChanged();
disconnect(m_isActiveConnection);
QQuick3DXrInputManager::instance()->registerController(this);
auto *input = handInput();
if (input) {
setIsActive(input->isActive());
setVisible(m_isActive); // ### position not set yet, so might show up briefly in wrong location
m_isActiveConnection = connect(input, &QQuick3DXrHandInput::isActiveChanged, this, [this, input]{
setIsActive(input->isActive());
setVisible(m_isActive);
});
connect(input, &QQuick3DXrHandInput::pokePositionChanged, this, &QQuick3DXrController::pokePositionChanged);
connect(input, &QQuick3DXrHandInput::jointPositionsChanged, this, &QQuick3DXrController::jointPositionsChanged);
connect(input, &QQuick3DXrHandInput::jointRotationsChanged, this, &QQuick3DXrController::jointRotationsChanged);
connect(input, &QQuick3DXrHandInput::jointDataUpdated, this, &QQuick3DXrController::jointDataUpdated);
} else {
setIsActive(false);
setVisible(false);
}
}
QQuick3DXrHandInput *QQuick3DXrController::handInput() const
{
if (m_inputManager && m_inputManager->isValid()) {
if (m_controller == Controller::ControllerRight)
return m_inputManager->rightHandInput();
else if (m_controller == Controller::ControllerLeft)
return m_inputManager->leftHandInput();
}
return nullptr;
}
/*!
\qmlproperty enumeration XrController::poseSpace
Specifies the pose of the controller to track, that is, the orientation and
position relative to the physical controller.
It can be one of:
\value XrController.AimPose Used when aiming at something, such as with \l XrVirtualMouse.
\value XrController.GripPose Used when grabbing something, such as when holding an object in the hand.
\default XrController.AimPose
*/
QQuick3DXrController::HandPoseSpace QQuick3DXrController::poseSpace() const
{
return m_poseSpace;
}
void QQuick3DXrController::setPoseSpace(HandPoseSpace newPoseSpace)
{
if (m_poseSpace == newPoseSpace)
return;
m_poseSpace = newPoseSpace;
QQuick3DXrInputManager::instance()->registerController(this);
emit poseSpaceChanged();
}
/*!
\qmlproperty vector3d XrController::pokePosition
\readonly
This property holds the position to be used for touch interactions.
Typically, it will be the tip of the index finger when tracking a hand.
\sa XrView::processTouch, XrView::setTouchpoint
*/
QVector3D QQuick3DXrController::pokePosition() const
{
auto *input = handInput();
if (input)
return input->pokePosition();
return {};
}
/*!
\qmlproperty list<vector3d> XrController::jointPositions
\readonly
When using hand tracking, this property holds the positions of all the bones in the hand.
\sa jointRotations, XrHandModel
*/
QList<QVector3D> QQuick3DXrController::jointPositions() const
{
auto *input = handInput();
if (input)
return input->jointPositions();
return {};
}
/*!
\qmlproperty list<quaternion> XrController::jointRotations
\readonly
When using hand tracking, this property holds the orientation of all the bones in the hand.
\sa jointPositions, XrHandModel
*/
QList<QQuaternion> QQuick3DXrController::jointRotations() const
{
auto *input = handInput();
if (input)
return input->jointRotations();
return {};
}
/*!
\qmlproperty bool XrController::isActive
\brief Indicates whether the controller is providing input.
\readonly
This property is true if the corresponding physical controller is present
and tracking.
*/
bool QQuick3DXrController::isActive() const
{
return m_isActive;
}
void QQuick3DXrController::setIsActive(bool isActive)
{
if (m_isActive == isActive)
return;
m_isActive = isActive;
emit isActiveChanged();
}
QtQuick3DXr::Handedness QtQuick3DXr::handednessForController(QtQuick3DXr::Controller controller)
{
QSSG_ASSERT(controller != QtQuick3DXr::Controller::UnknownController, return QtQuick3DXr::Handedness::Right);
switch (controller) {
case QtQuick3DXr::Controller::LeftController:
return QtQuick3DXr::Handedness::Left;
case QtQuick3DXr::Controller::RightController:
return QtQuick3DXr::Handedness::Right;
default:
Q_UNREACHABLE();
}
}
QT_END_NAMESPACE