You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nmWTAI-Platform/Src/nmNum/nmRender/nmVTKInteractionManager.cpp

146 lines
4.2 KiB
C++

#include "nmVTKInteractionManager.h"
#include "nmVTKPivotCameraInteractorStyle.h"
#include <QCoreApplication>
#include <QThread>
#include <vtkInteractorStyle.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
namespace {
// InteractorStyle 会注册 VTK 观察关系,绑定与解除都限定在 GUI 线程。
bool isInteractionGuiThread()
{
QCoreApplication* pApplication = QCoreApplication::instance();
return pApplication == nullptr ||
pApplication->thread() == QThread::currentThread();
}
}
nmVTKInteractionManager::nmVTKInteractionManager(
nmVTKCameraController* pCameraController)
: m_pInteractor(nullptr),
m_pDefaultStyle(
vtkSmartPointer<nmVTKPivotCameraInteractorStyle>::New()),
m_pActiveStyle(nullptr)
{
Q_ASSERT(isInteractionGuiThread());
m_pDefaultStyle->setCameraController(pCameraController);
}
nmVTKInteractionManager::~nmVTKInteractionManager()
{
Q_ASSERT(isInteractionGuiThread());
// Interactor 持有 Style 引用,必须先清除绑定再释放智能指针。
unbindInteractor();
m_pActiveStyle = nullptr;
if(m_pDefaultStyle != nullptr) {
m_pDefaultStyle->setCameraController(nullptr);
}
m_pDefaultStyle = nullptr;
}
bool nmVTKInteractionManager::bindInteractor(
vtkRenderWindowInteractor* pInteractor,
vtkRenderer* pRenderer)
{
Q_ASSERT(isInteractionGuiThread());
if(!isInteractionGuiThread() || pInteractor == nullptr ||
m_pDefaultStyle == nullptr) {
return false;
}
if(m_pInteractor != pInteractor) {
// 切换对象前先清除旧 Interactor 持有的 Style 引用。
unbindInteractor();
m_pInteractor = pInteractor;
}
m_pDefaultStyle->SetDefaultRenderer(pRenderer);
m_pDefaultStyle->SetCurrentRenderer(pRenderer);
return restoreDefaultInteraction();
}
bool nmVTKInteractionManager::installInteractionStyle(
vtkInteractorStyle* pStyle)
{
Q_ASSERT(isInteractionGuiThread());
if(!isInteractionGuiThread() || m_pInteractor == nullptr || pStyle == nullptr) {
return false;
}
// 管理器和 Interactor 各持有一个 VTK 引用,直到恢复或清除当前模式。
m_pActiveStyle = pStyle;
m_pInteractor->SetInteractorStyle(m_pActiveStyle);
return true;
}
bool nmVTKInteractionManager::restoreDefaultInteraction()
{
Q_ASSERT(isInteractionGuiThread());
if(!isInteractionGuiThread() || m_pInteractor == nullptr ||
m_pDefaultStyle == nullptr) {
return false;
}
// 后续工具临时替换样式后,可通过本入口回到唯一默认交互模式。
return installInteractionStyle(m_pDefaultStyle);
}
void nmVTKInteractionManager::clearInteractionStyle()
{
Q_ASSERT(isInteractionGuiThread());
if(!isInteractionGuiThread()) {
return;
}
if(m_pInteractor != nullptr) {
m_pInteractor->SetInteractorStyle(nullptr);
}
m_pActiveStyle = nullptr;
}
void nmVTKInteractionManager::unbindInteractor()
{
Q_ASSERT(isInteractionGuiThread());
if(!isInteractionGuiThread()) {
return;
}
// 本管理器定义单一活动模式边界,解绑时不保留任何旧 Style。
clearInteractionStyle();
if(m_pDefaultStyle != nullptr) {
// DefaultRenderer 会覆盖 CurrentRenderer必须先解除前者。
m_pDefaultStyle->SetDefaultRenderer(nullptr);
m_pDefaultStyle->SetCurrentRenderer(nullptr);
}
m_pInteractor = nullptr;
}
vtkRenderWindowInteractor* nmVTKInteractionManager::getInteractor() const
{
return m_pInteractor;
}
vtkInteractorStyleTrackballCamera*
nmVTKInteractionManager::getDefaultStyle() const
{
return m_pDefaultStyle.GetPointer();
}
vtkInteractorStyle* nmVTKInteractionManager::getActiveStyle() const
{
return m_pActiveStyle;
}
bool nmVTKInteractionManager::isDefaultInteractionActive() const
{
vtkInteractorStyle* pDefaultStyle = m_pDefaultStyle.GetPointer();
vtkInteractorStyle* pActiveStyle = m_pActiveStyle.GetPointer();
return m_pInteractor != nullptr && pDefaultStyle != nullptr &&
pActiveStyle == pDefaultStyle &&
m_pInteractor->GetInteractorStyle() == pDefaultStyle;
}