File: scene.py

package info (click to toggle)
mayavi2 4.8.3-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 21,892 kB
  • sloc: python: 49,447; javascript: 32,885; makefile: 129; fortran: 60
file content (241 lines) | stat: -rw-r--r-- 8,461 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
"""A scene object manages a TVTK scene and objects in it.
"""
# Author: Prabhu Ramachandran <prabhu_r@users.sf.net>
# Copyright (c) 2005,  Enthought, Inc.
# License: BSD Style.

# Enthought library imports.
from traits.api import Event, List, Str, Instance
from traitsui.api import View, Group, Item
from apptools.persistence.state_pickler import set_state

# Local imports.
from tvtk.pyface.tvtk_scene import TVTKScene
from mayavi.core.base import Base
from mayavi.core.source import Source
from mayavi.core.common import handle_children_state, exception
from mayavi.core.adder_node import SourceAdderNode

######################################################################
# `Scene` class.
######################################################################
class Scene(Base):
    """ The Mayavi scene class.
    """

    # The version of this class.  Used for persistence.
    __version__ = 0

    # The scene (RenderWindow) associated with this component -- we
    # redeclare it here just to be able to record this scene, we don't
    # want it recorded on all objects since the scene is shared
    # (although it isn't an error to register an object twice with the
    # recorder).
    scene = Instance(TVTKScene, record=True)

    # The source objects associated with this object.
    children = List(Source, record=True)

    # The name of this scene.
    name = Str('TVTK Scene')

    # The icon
    icon = Str('scene.ico')

    # The human-readable type for this object
    type = Str(' scene')

    # The objects view.
    view = View(Group(Item(name='scene', style='custom'),
                           show_labels=False)
               )

    # The adder node dialog class
    _adder_node_class = SourceAdderNode

    # The dispatch, to register callbacks on mouse pick
    _mouse_pick_dispatcher = Instance(
        'mayavi.core.mouse_pick_dispatcher.MousePickDispatcher',
        record=False)

    ######################################################################
    # `object` interface
    ######################################################################
    def __get_pure_state__(self):
        # Base removes the scene, but we need to save it!
        d = super(Scene, self).__get_pure_state__()
        d['scene'] = self.scene
        d.pop('_mouse_pick_dispatcher', None)
        return d

    def __set_pure_state__(self, state):
        handle_children_state(self.children, state.children)

        # As `camera.distance` is derived from other camera parameters
        # if camera is defined, we should skip restoring "distance"
        if state.scene and state.scene.camera:
            state.scene.camera.pop("distance", None)

        # Now set our complete state.  Doing the scene last ensures
        # that the camera view is set right.  Before doing this though,
        # if the light_manager is None, the scene hasn't been painted,
        # in that case save the light manager state and set the state later.
        # All we do is set the _saved_light_manager_state and the scene
        # will take care of the rest.
        if self.scene is not None and self.scene.light_manager is None:
            lm_state = state['scene'].pop('light_manager', None)
            self.scene._saved_light_manager_state = lm_state

        set_state(self, state, last=['scene'])

    ######################################################################
    # `Scene` interface
    ######################################################################

    def on_mouse_pick(self, callback, type='point', button='Left',
                            remove=False):
        """ Add a picking callback on mouse click.

            When the mouse button is press, object picking is called, and
            the given callback is invoked with the resulting pick
            as an argument.

            **Keyword arguments**

            :type: 'point', 'cell', or 'world'
                The picker type used for picking.
            :button: 'Left', 'Middle', or 'Right'
                The mouse button triggering the picking event.
            :remove: boolean
                If remove is True, the callback is removed from the
                list of callbacks.

            **Returns**
            picker: a tvtk picker
                The picker that will be used to do the picking.

            **Notes**

            The callback must accept one argument: the TVTK picker.

            The same callback can be added multiple times.
        """
        key = (callback, type, button)
        if remove:
            self._mouse_pick_dispatcher.callbacks.remove(key)
        else:
            self._mouse_pick_dispatcher.callbacks.append(key)
        return self._mouse_pick_dispatcher._active_pickers[type]


    ######################################################################
    # `Base` interface
    ######################################################################
    def start(self):
        """This is invoked when this object is added to the mayavi
        pipeline.
        """
        # Do nothing if we are already running.
        if self.running:
            return

        # Start all our children.
        for obj in self.children:
            obj.start()

        # Disallow the hide action in the context menu
        self._HideShowAction.enabled = False

        super(Scene, self).start()

    def stop(self):
        """Invoked when this object is removed from the mayavi
        pipeline.
        """
        if not self.running:
            return

        # Disable rendering to accelerate shutting down.
        scene = self.scene
        if scene is not None:
            status = scene.disable_render
            scene.disable_render = True
        try:
            # Stop all our children.
            for obj in self.children:
                obj.stop()
        finally:
            # Re-enable rendering.
            if scene is not None:
                scene.disable_render = status
                self.scene = None
        super(Scene, self).stop()

    def add_child(self, child):
        """This method intelligently adds a child to this object in
        the MayaVi pipeline.
        """
        self.children.append(child)

    def remove_child(self, child):
        """Remove specified child from our children.
        """
        self.children.remove(child)

    def remove(self):
        """Remove ourselves from the mayavi pipeline.
        """
        if self.parent is not None:
            self.stop()
            self.parent.close_scene(self)

    ######################################################################
    # `TreeNodeObject` interface
    ######################################################################
    def tno_can_add(self, node, add_object):
        """ Returns whether a given object is droppable on the node.
        """
        try:
            if issubclass(add_object, Source):
                return True
        except TypeError:
            if isinstance(add_object, Source):
                return True
        return False

    def tno_drop_object(self, node, dropped_object):
        """ Returns a droppable version of a specified object.
        """
        if isinstance(dropped_object, Source):
            return dropped_object

    ######################################################################
    # Non-public interface
    ######################################################################
    def _children_changed(self, old, new):
        self._handle_children(old, new)

    def _children_items_changed(self, list_event):
        self._handle_children(list_event.removed, list_event.added)

    def _handle_children(self, removed, added):
        for obj in removed:
            obj.stop()
        for obj in added:
            obj.trait_set(scene=self.scene, parent=self)
            if self.running:
                # It makes sense to start children only if we are running.
                # If not, the children will be started when we start.
                try:
                    obj.start()
                except:
                    exception()

    def _menu_helper_default(self):
        from mayavi.core.traits_menu import SourceMenuHelper
        return SourceMenuHelper(object=self)

    def __mouse_pick_dispatcher_default(self):
        from mayavi.core.mouse_pick_dispatcher import \
                        MousePickDispatcher
        return MousePickDispatcher(scene=self)