trame icon indicating copy to clipboard operation
trame copied to clipboard

RemoveActor does not remove last actor from a scene

Open spookylukey opened this issue 1 year ago • 2 comments

Describe the bug

If I have a set of actors added to a renderer, and I attempt to remove them all, all but the last of them is removed. This is different from normal VTK behaviour, which allows all to be removed.

To Reproduce

Using the RemoveActor.py script below, do:

python RemoveActor.py

You can use a and r to add and remove actors. With the normal VTK rendering, note how you can remove the last one.

Then, do

python RemoveActor.py --use-trame

Use the "Add" and "Remove" buttons. Here, when you attempt to remove the last actor, it does not. Interestingly, the display also seems to freeze at this point - dragging with the mouse does not cause rotation, almost as if it thinks there is nothing to update. However, on adding another actor again, you will now have two items than can be rotated as normal.

Code

#!/usr/bin/env python

import random
import argparse
from trame.app import get_server
from trame.ui.vuetify import SinglePageLayout
from trame.widgets import vtk, vuetify
from vtkmodules.vtkCommonTransforms import vtkTransform

from vtkmodules.vtkFiltersSources import vtkConeSource
from vtkmodules.vtkRenderingCore import (
    vtkActor,
    vtkPolyDataMapper,
    vtkRenderer,
    vtkRenderWindow,
    vtkRenderWindowInteractor,
)

# Required for interactor initialization
from vtkmodules.vtkInteractionStyle import vtkInteractorStyleSwitch, vtkInteractorStyleTrackballCamera  # noqa

# Required for rendering initialization, not necessary for
# local rendering, but doesn't hurt to include it
import vtkmodules.vtkRenderingOpenGL2  # noqa


# -----------------------------------------------------------------------------
# VTK pipeline
# -----------------------------------------------------------------------------

renderer = vtkRenderer()
renderWindow = vtkRenderWindow()
renderWindow.AddRenderer(renderer)

renderWindowInteractor = vtkRenderWindowInteractor()
renderWindowInteractor.SetRenderWindow(renderWindow)

cone_source = vtkConeSource()
mapper = vtkPolyDataMapper()
mapper.SetInputConnection(cone_source.GetOutputPort())


actors = []

def add_actor():
    actor = vtkActor()
    actor.SetMapper(mapper)
    transform = vtkTransform()
    transform.PostMultiply()
    transform.RotateZ(random.randint(0, 180))
    transform.RotateX(random.randint(0, 180))
    actor.SetUserTransform(transform)
    actors.append(actor)
    renderer.AddActor(actor)


add_actor()
renderer.ResetCamera()


def run_normal():

    class MyKeyPressInteractorStyle(vtkInteractorStyleTrackballCamera):
        def __init__(self):
            super().__init__()
            self.AddObserver("KeyPressEvent", self.my_KeyPressEvent_observer)

        def my_KeyPressEvent_observer(self , obj, event):
            keysym = self.GetInteractor().GetKeySym()
            print(len(actors))
            if keysym == 'r':
                print("r pressed")
                if actors:
                    renderer.RemoveActor(actors.pop())
                    renderer.Modified()
                    renderWindow.Render()
            elif keysym == 'a':
                print("a pressed")
                add_actor()
                renderer.Modified()
                renderWindow.Render()

    renderWindowInteractor.SetInteractorStyle(MyKeyPressInteractorStyle())
    renderWindow.Render()
    renderWindowInteractor.Start()

def run_trame():
    server = get_server(client_type = "vue2")
    ctrl = server.controller

    def add_clicked(**kwargs):
        print("add clicked")
        add_actor()
        ctrl.view_update()

    def remove_clicked(**kwargs):
        print("remove clicked")
        if actors:
            renderer.RemoveActor(actors.pop())
        ctrl.view_update()

    with SinglePageLayout(server) as layout:
        with layout.toolbar:
            vuetify.VSpacer()
            vuetify.VBtn("Add", click=add_clicked)
            vuetify.VBtn("Remove", click=remove_clicked)

        with layout.content:
            with vuetify.VContainer(
                fluid=True,
                classes="pa-0 fill-height",
            ):
                view = vtk.VtkLocalView(renderWindow)
                ctrl.view_update = view.update

    server.start()

# -----------------------------------------------------------------------------
# Main
# -----------------------------------------------------------------------------

parser = argparse.ArgumentParser()
parser.add_argument('--use-trame', action='store_true')

if __name__ == "__main__":

    if parser.parse_args().use_trame:
        run_trame()
    else:
        run_normal()

Expected behavior

The code should behave the same under trame as normally.

Platform:

I assuming all platforms are affected.

Device:

  • [X] Desktop
  • [ ] Mobile

OS:

  • [ ] Windows
  • [ ] MacOS
  • [X] Linux
  • [ ] Android
  • [ ] iOS

Browsers Affected:

  • [X] Chrome
  • [X] Firefox
  • [ ] Microsoft Edge
  • [ ] Safari
  • [ ] Opera
  • [ ] Brave
  • [ ] IE 11

spookylukey avatar Jan 15 '24 13:01 spookylukey