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/nmVTKRenderLayer.cpp

141 lines
3.3 KiB
C++

#include "nmVTKRenderLayer.h"
#include <QCoreApplication>
#include <QThread>
#include <vtkProp.h>
#include <vtkRenderer.h>
namespace {
// VTK 对象没有跨线程保护,所有图层状态必须在 GUI 线程修改。
bool isLayerGuiThread()
{
QCoreApplication* pApplication = QCoreApplication::instance();
return pApplication == NULL ||
pApplication->thread() == QThread::currentThread();
}
}
nmVTKRenderLayer::nmVTKRenderLayer(const QString& sLayerId)
: m_sLayerId(sLayerId),
m_bVisible(true),
m_pRenderProp(NULL),
m_pRenderer(NULL),
m_pOwningScene(NULL)
{
Q_ASSERT(isLayerGuiThread());
// 稳定 ID 只用于 Scene 查找,不承担可翻译的界面文案。
}
nmVTKRenderLayer::~nmVTKRenderLayer()
{
Q_ASSERT(isLayerGuiThread());
Q_ASSERT(m_pOwningScene == NULL);
// 主 Prop 由基类智能指针继续持有,因此此时 detach 不依赖派生类成员。
detach();
m_pRenderProp = NULL;
m_pOwningScene = NULL;
}
QString nmVTKRenderLayer::getLayerId() const
{
return m_sLayerId;
}
bool nmVTKRenderLayer::attach(vtkRenderer* pRenderer)
{
Q_ASSERT(isLayerGuiThread());
if(!isLayerGuiThread() || pRenderer == NULL || m_pRenderProp == NULL) {
return false;
}
if(m_pRenderer == pRenderer) {
// 幂等挂载不重复增加 Renderer 对 Prop 的引用。
return true;
}
// 一个图层同一时刻只能挂载到一个 Renderer。
detach();
m_pRenderProp->SetVisibility(m_bVisible ? 1 : 0);
pRenderer->AddViewProp(m_pRenderProp);
m_pRenderer = pRenderer;
return true;
}
void nmVTKRenderLayer::detach()
{
Q_ASSERT(isLayerGuiThread());
if(m_pRenderer != NULL && m_pRenderProp != NULL) {
m_pRenderer->RemoveViewProp(m_pRenderProp);
}
m_pRenderer = NULL;
}
void nmVTKRenderLayer::setVisible(bool bVisible)
{
Q_ASSERT(isLayerGuiThread());
if(!isLayerGuiThread()) {
return;
}
m_bVisible = bVisible;
if(m_pRenderProp != NULL) {
m_pRenderProp->SetVisibility(bVisible ? 1 : 0);
}
}
bool nmVTKRenderLayer::isVisible() const
{
return m_bVisible;
}
bool nmVTKRenderLayer::isAttached() const
{
return m_pRenderer != NULL;
}
bool nmVTKRenderLayer::setRenderProp(vtkProp* pProp)
{
Q_ASSERT(isLayerGuiThread());
if(!isLayerGuiThread() || isAttached() || pProp == NULL) {
return false;
}
// vtkSmartPointer 接管一个 VTK 引用,派生类可继续持有同一对象。
m_pRenderProp = pProp;
m_pRenderProp->SetVisibility(m_bVisible ? 1 : 0);
return true;
}
vtkProp* nmVTKRenderLayer::getRenderProp() const
{
return m_pRenderProp;
}
vtkRenderer* nmVTKRenderLayer::getAttachedRenderer() const
{
return m_pRenderer;
}
bool nmVTKRenderLayer::claimSceneOwnership(nmVTKScene* pScene)
{
Q_ASSERT(isLayerGuiThread());
if(!isLayerGuiThread() || pScene == NULL || m_pOwningScene != NULL) {
return false;
}
// 所有权与 Renderer 挂载状态分开记录,公开 detach 不会释放 Scene 所有权。
m_pOwningScene = pScene;
return true;
}
bool nmVTKRenderLayer::releaseSceneOwnership(nmVTKScene* pScene)
{
Q_ASSERT(isLayerGuiThread());
if(!isLayerGuiThread() || pScene == NULL || m_pOwningScene != pScene) {
return false;
}
m_pOwningScene = NULL;
return true;
}