Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions .github/workflows/build-wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ jobs:
PIP_EXTRA_INDEX_URL: "https://vtk.org/files/wheel-sdks"
CIBW_ENVIRONMENT_PASS_LINUX: "PIP_EXTRA_INDEX_URL"
CIBW_BUILD: ${{ inputs.build-target }}
# Required to make tests pass (VTK needs them)
CIBW_BEFORE_ALL_LINUX: "yum install -y mesa-libGL-devel glx-utils freeglut-devel"
CIBW_BEFORE_ALL_LINUX: "yum install -y mesa-libGL-devel glx-utils freeglut-devel mesa-libOSMesa"
CIBW_ENVIRONMENT_LINUX: "VTK_DEFAULT_OPENGL_WINDOW=vtkOSOpenGLRenderWindow"
# Global test setup
CIBW_TEST_REQUIRES: "pytest virtualenv"
CIBW_TEST_REQUIRES: "pytest"
# Do not repair, everything is already put just as needed to make it work
CIBW_REPAIR_WHEEL_COMMAND_LINUX: "
python -m pip install wheel &&
Expand All @@ -58,15 +58,16 @@ jobs:
- name: Build wheel
uses: pypa/cibuildwheel@v3.3.1
env:
CIBW_TEST_COMMAND: "python -m pytest {project}/LayerDM -m runtime --verbose"
CIBW_TEST_COMMAND: "python -m pytest {project}/LayerDM --verbose"
with:
package-dir: LayerDM
output-dir: wheelhouse

- name: Build wheel SDK
uses: pypa/cibuildwheel@v3.3.1
env:
CIBW_TEST_COMMAND: "python -m pytest {project}/LayerDM -m sdk --verbose"
CIBW_TEST_REQUIRES: "pytest virtualenv"
CIBW_TEST_COMMAND: "python -m pytest {project}/LayerDMSDK --verbose"
with:
package-dir: LayerDMSDK
output-dir: wheelhouse
Expand Down
36 changes: 36 additions & 0 deletions Docs/_static/css/custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,39 @@ a.icon-home img.logo {
.rst-content dl dd {
margin: 0px;
}

/* Ensure mermaid fullscreen modal and container stay light themed for rtd compatibility*/
.mermaid-fullscreen-modal,
.mermaid-fullscreen-modal.dark-theme {
background: rgba(255, 255, 255, 0.98) !important;
}

.mermaid-container-fullscreen,
.mermaid-container-fullscreen.dark-theme {
background: white !important;
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3) !important;
}

.mermaid-fullscreen-close,
.mermaid-fullscreen-close.dark-theme {
background: rgba(255, 255, 255, 0.95) !important;
border: 1px solid rgba(0, 0, 0, 0.2) !important;
color: #333 !important;
}

.mermaid-fullscreen-close:hover,
.mermaid-fullscreen-close.dark-theme:hover {
background: white !important;
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4) !important;
}

.mermaid-fullscreen-btn.dark-theme {
background: rgba(255, 255, 255, 0.95) !important;
border: 1px solid rgba(0, 0, 0, 0.3) !important;
color: #333 !important;
}

.mermaid-fullscreen-btn.dark-theme:hover {
background: rgba(255, 255, 255, 1) !important;
box-shadow: 0 3px 10px rgba(0, 0, 0, 0.3) !important;
}
13 changes: 13 additions & 0 deletions Docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,19 @@ def custom_exhale_mapping(kind):
"css/custom.css",
]

# -- Mermaid configuration ----------------------------------------------------
mermaid_version = "12.0.0"

# Force light theme to match RTD light background
mermaid_light_theme = "redux-color"
mermaid_dark_theme = "redux-color"

# Mermaid initialization settings
mermaid_init_config = {
"theme": "redux-color",
"look": "neo",
}

# -- Graphviz options -------------------------------------------------
graphviz_output_format = "svg"
graphviz_dot_args = [
Expand Down
4 changes: 2 additions & 2 deletions Docs/extension_architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ The main classes of the library and their responsibilities are summarized below

| Class | Description |
|------------------------------------------|----------------------------------------------------------------------------------------------|
| vtkMRMLLayerDMPipelineI | Interface for display pipelines. Handles interaction, rendering, camera, and observer logic. |
| vtkMRMLLayerDMPipeline | Interface for display pipelines. Handles interaction, rendering, camera, and observer logic. |
| vtkMRMLLayerDisplayableManager | Main displayable manager. Initializes pipeline manager and delegates scene updates. |
| vtkMRMLLayerDMCameraSynchronizer | Synchronizes default camera with renderer or slice node state. |
| vtkMRMLLayerDMLayerManager | Manages renderer layers based on pipeline layer/camera pairs. |
| vtkMRMLLayerDMPipelineCreatorI | Interface for pipeline creation. Supports custom instantiation logic. |
| vtkMRMLLayerDMPipelineCreator | Interface for pipeline creation. Supports custom instantiation logic. |
| vtkMRMLLayerDMPipelineCallbackCreator | Callback-based implementation of pipeline creator. |
| vtkMRMLLayerDMPipelineScriptedCreator | Python lambda-based pipeline creator. |
| vtkMRMLLayerDMPipelineFactory | Singleton factory for pipeline instantiation and registration. |
Expand Down
42 changes: 21 additions & 21 deletions Docs/getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ To get started, developers need to implement the following classes / logic:

## Pipeline

Pipeline objects derive from the vtkMRMLLayerDMPipelineI base class in C++ and the vtkMRMLLayerDMScriptedPipeline in
Pipeline objects derive from the vtkMRMLLayerDMPipeline base class in C++ and the vtkMRMLLayerDMScriptedPipeline in
python.

Pipeline implementation can be split in two:
Expand Down Expand Up @@ -55,15 +55,15 @@ class MyPipeline(vtkMRMLLayerDMScriptedPipeline):
## Refreshing the display

By default, the display is refreshed when the pipeline is created. Afterwards, refreshing its display should be
connected to the object events and the `ResetDisplay` method should be called.
connected to the object events and the `UpdateDisplay` method should be called.

Calling this method will call the `UpdatePipeline` method and will request a render from the widget.
Calling this method will call the `UpdateFromMRML` method and will request a render from the widget.

```python
class MyPipeline(vtkMRMLLayerDMScriptedPipeline):
def UpdatePipeline(self):
def UpdateFromMRML(self):
"""
Triggered by self.ResetDisplay() calls:
Triggered by self.UpdateDisplay() calls:
- Called automatically at pipeline creation / add to the render window
- Called automatically when switching renderer
Override to update the representation of the pipeline in the different views.
Expand All @@ -78,15 +78,15 @@ class MyPipeline(vtkMRMLLayerDMScriptedPipeline):
def OnUpdate(self, obj, eventId, callData):
"""
Observer update callback.
Triggered when any object & events observed using UpdateObserver is triggered.
Triggered when any object & events observed using UpdateObservation is triggered.

:param obj: vtkObject instance which triggered the callback
:param eventId: Event id which triggered the callback
:param callData: Optional observer call data. Use self.CastCallData(callData, vtkType) to convert to Python
"""

# Calling reset display will trigger the UpdatePipeline method call
self.ResetDisplay()
# Calling reset display will trigger the UpdateFromMRML method call
self.UpdateDisplay()
```

## Rendering on top of other actors
Expand Down Expand Up @@ -123,16 +123,16 @@ modified, the event ID and call data.

* `virtual void OnUpdate(vtkObject* obj, unsigned long eventId, void* callData)`: Callback when observed event triggers.

To observe other objet events, the `UpdateObserver` can be used.
To observe other objet events, the `UpdateObservation` can be used.

* `bool UpdateObserver(vtkObject* prevObj, vtkObject* obj, const std::vector<unsigned long>& events) const`: Update
* `bool UpdateObservation(vtkObject* prevObj, vtkObject* obj, const std::vector<unsigned long>& events) const`: Update
observer with multiple events.
* `bool UpdateObserver(vtkObject* prevObj, vtkObject* obj, unsigned long event = vtkCommand::ModifiedEvent) const`:
* `bool UpdateObservation(vtkObject* prevObj, vtkObject* obj, unsigned long event = vtkCommand::ModifiedEvent) const`:
Update observer with single event.
* `void RemoveObserver(vtkObject* prevObj) const`: Remove all observed events.
* `void RemoveObservations(vtkObject* prevObj)`: Remove all observed events.

```{warning}
UpdateObserver doesn't mutate the prevObj (for Python wrapping compatibility reasons). The object's value should be
UpdateObservation doesn't mutate the prevObj (for Python wrapping compatibility reasons). The object's value should be
updated manually after this update call.
```

Expand All @@ -142,8 +142,8 @@ event.
* `virtual void SetViewNode(vtkMRMLAbstractViewNode* viewNode)`: Called at initialization.
* `virtual void SetDisplayNode(vtkMRMLNode* displayNode)`: Called at initialization.

During the `OnUpdate` call if the display should be update, then the `ResetDisplay` method should be called. This method
will trigger the `UpdatePipeline` method which can be overridden to update display properties and will also trigger a
During the `OnUpdate` call if the display should be update, then the `UpdateDisplay` method should be called. This method
will trigger the `UpdateFromMRML` method which can be overridden to update display properties and will also trigger a
request render.

```python
Expand All @@ -161,14 +161,14 @@ class MyPipeline(vtkMRMLLayerDMScriptedPipeline):
# The two attributes below are used to connect observers on the modelNode and the modelTransform ModifiedEvent
# The vtkMRMLLayerDMScriptedPipeline base class provides convenience methods to simply observers
# See also: OnUpdate
# See also: UpdateObserver
# See also: UpdateObservation
self._modelNode = None
self._modelTransform = None

def OnUpdate(self, obj, eventId, callData):
"""
Observer update callback.
Triggered when any object & events observed using UpdateObserver is triggered.
Triggered when any object & events observed using UpdateObservation is triggered.

:param obj: vtkObject instance which triggered the callback
:param eventId: Event id which triggered the callback
Expand All @@ -178,7 +178,7 @@ class MyPipeline(vtkMRMLLayerDMScriptedPipeline):
if obj == self._modelNode:
self._ObserveModelTransformNode()

self.ResetDisplay()
self.UpdateDisplay()

def _ObserveModelTransformNode(self):
"""
Expand All @@ -191,7 +191,7 @@ class MyPipeline(vtkMRMLLayerDMScriptedPipeline):
if self._modelTransform == transformNode:
return

self.UpdateObserver(self._modelTransform, transformNode, vtkMRMLTransformNode.TransformModifiedEvent)
self.UpdateObservation(self._modelTransform, transformNode, vtkMRMLTransformNode.TransformModifiedEvent)
self._modelTransform = transformNode
```

Expand Down Expand Up @@ -332,7 +332,7 @@ Example of registration for one view type with multiple display node / display p

void vtkMRMLCPRPipelineCreatorLogic::RegisterPipelines()
{
static vtkSmartPointer<vtkMRMLLayerDMPipelineCreatorI> creator{ nullptr };
static vtkSmartPointer<vtkMRMLLayerDMPipelineCreator> creator{ nullptr };

if (!creator)
{
Expand Down Expand Up @@ -380,7 +380,7 @@ vtkMRMLLayerDMPipelineFactory.GetInstance().AddPipelineCreator(pipeline_creator)
```

```cpp
static vtkSmartPointer<vtkMRMLLayerDMPipelineCreatorI> creator{ nullptr };
static vtkSmartPointer<vtkMRMLLayerDMPipelineCreator> creator{ nullptr };

if (!creator)
{
Expand Down
8 changes: 4 additions & 4 deletions Examples/Cpp/ModelGlowDM/vtkMRMLModelGlowPipeline.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ void vtkMRMLModelGlowPipeline::OnRendererAdded(vtkRenderer* renderer)
renderer->SetPass(glowPass);
}

void vtkMRMLModelGlowPipeline::UpdatePipeline()
void vtkMRMLModelGlowPipeline::UpdateFromMRML()
{
if (this->GetDisplayNode() && this->ModelNode)
{
Expand All @@ -66,7 +66,7 @@ void vtkMRMLModelGlowPipeline::UpdatePipeline()

void vtkMRMLModelGlowPipeline::SetModelNode(vtkMRMLModelNode* node)
{
UpdateObserver(this->ModelNode, node);
UpdateObservation(this->ModelNode, node);
this->ModelNode = node;

if (!this->ModelNode)
Expand All @@ -78,7 +78,7 @@ void vtkMRMLModelGlowPipeline::SetModelNode(vtkMRMLModelNode* node)
mapper->SetInputData(this->ModelNode->GetPolyData());
this->GlowActor->SetMapper(mapper);

// UpdateObserver(this->ModelNode, node);
// UpdateObservation(this->ModelNode, node);

auto transformNode = this->ModelNode->GetParentTransformNode();
if (transformNode)
Expand All @@ -101,7 +101,7 @@ void vtkMRMLModelGlowPipeline::OnUpdate(vtkObject* node, unsigned long eventId,
SetDisplayNode(displayNode);
}

ResetDisplay();
UpdateDisplay();
}

bool vtkMRMLModelGlowPipeline::CanProcessInteractionEvent(vtkMRMLInteractionEventData* eventData, double& distance2)
Expand Down
8 changes: 4 additions & 4 deletions Examples/Cpp/ModelGlowDM/vtkMRMLModelGlowPipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#include "vtkSlicerModelGlowModuleMRMLExport.h"

// Slicer includes
#include "vtkMRMLLayerDMPipelineI.h"
#include "vtkMRMLLayerDMPipeline.h"

// VTK includes
#include <vtkSmartPointer.h>
Expand All @@ -15,17 +15,17 @@ class vtkMRMLInteractionEventData;
class vtkActor;
class vtkRenderer;

class VTK_SLICER_MODEL_GLOW_MODULE_MRML_EXPORT vtkMRMLModelGlowPipeline : public vtkMRMLLayerDMPipelineI
class VTK_SLICER_MODEL_GLOW_MODULE_MRML_EXPORT vtkMRMLModelGlowPipeline : public vtkMRMLLayerDMPipeline
{
public:
static vtkMRMLModelGlowPipeline* New();
vtkTypeMacro(vtkMRMLModelGlowPipeline, vtkMRMLLayerDMPipelineI);
vtkTypeMacro(vtkMRMLModelGlowPipeline, vtkMRMLLayerDMPipeline);

void SetDisplayNode(vtkMRMLNode* displayNode) override;
void OnRendererRemoved(vtkRenderer* renderer) override;
void OnRendererAdded(vtkRenderer* renderer) override;
unsigned int GetRenderOrder() const override;
void UpdatePipeline() override;
void UpdateFromMRML() override;
// void SetViewNode(vtkMRMLAbstractViewNode* viewNode) override;
// void SetScene(vtkMRMLScene* scene) override;

Expand Down
Loading
Loading