def __init__(self, parent, overlayList, displayCtx, frame): """Create a ``Scene3dPanel``. :arg parent: A :mod:`wx` parent object. :arg overlayList: A :class:`.OverlayList` instance. :arg displayCtx: A :class:`.DisplayContext` instance. :arg frame: The :class:`.FSLeyesFrame` instance. """ sceneOpts = scene3dopts.Scene3DOpts(self) canvaspanel.CanvasPanel.__init__(self, parent, overlayList, displayCtx, frame, sceneOpts) # In 3D, the displaySpace must always be # set to world, regardless of the parent # DC value. This can be overridden manually # however (e.g. through the python shell) displayCtx.detachDisplaySpace() displayCtx.defaultDisplaySpace = 'world' displayCtx.displaySpace = 'world' contentPanel = self.contentPanel self.__canvas = scene3dcanvas.WXGLScene3DCanvas(contentPanel, overlayList, displayCtx) opts = self.__canvas.opts opts.bindProps('pos', displayCtx, 'location') opts.bindProps('showCursor', sceneOpts) opts.bindProps('cursorColour', sceneOpts) opts.bindProps('bgColour', sceneOpts) opts.bindProps('showLegend', sceneOpts) opts.bindProps('legendColour', sceneOpts, 'fgColour') opts.bindProps('occlusion', sceneOpts) opts.bindProps('light', sceneOpts) opts.bindProps('lightPos', sceneOpts) opts.bindProps('zoom', sceneOpts) opts.bindProps('offset', sceneOpts) opts.bindProps('rotation', sceneOpts) opts.bindProps('highDpi', sceneOpts) sizer = wx.BoxSizer(wx.HORIZONTAL) sizer.Add(self.__canvas, flag=wx.EXPAND, proportion=1) contentPanel.SetSizer(sizer) self.centrePanelLayout() self.initProfile() self.syncLocation = True
def makeDisplayContext(namespace): """Creates :class:`.OverlayList`, :class:`.DisplayContext``, and :class:`.SceneOpts` instances which represent the scene to be rendered, as described by the arguments in the given ``namespace`` object. """ # Create an overlay list and display context. # The DisplayContext, Display and DisplayOpts # classes are designed to be created in a # parent-child hierarchy. So we need to create # a 'dummy' master display context to make # things work properly. overlayList = fsloverlay.OverlayList() masterDisplayCtx = displaycontext.DisplayContext(overlayList) childDisplayCtx = displaycontext.DisplayContext(overlayList, parent=masterDisplayCtx) # We have to artificially create a ref to the # master display context, otherwise it may get # gc'd arbitrarily. The parent reference in the # child creation above is ultimately stored as # a weakref, so we need to create a real one. childDisplayCtx.masterDisplayCtx = masterDisplayCtx # The handleOverlayArgs function uses the # fsleyes.overlay.loadOverlays function, # which will call these functions as it # goes through the list of overlay to be # loaded. def load(ovl): log.info('Loading overlay {} ...'.format(ovl)) def error(ovl, error): log.info('Error loading overlay {}: '.format(ovl, error)) # Load the overlays specified on the command # line, and configure their display properties parseargs.applyOverlayArgs(namespace, overlayList, masterDisplayCtx, loadFunc=load, errorFunc=error) # Create a SceneOpts instance describing # the scene to be rendered. The parseargs # module assumes that GL canvases have # already been created, so we use mock # objects to trick it. The options applied # to these mock objects are applied to the # real canvases later on, in the render # function below. if namespace.scene == 'ortho': sceneOpts = orthoopts.OrthoOpts(MockCanvasPanel(3)) elif namespace.scene == 'lightbox': sceneOpts = lightboxopts.LightBoxOpts(MockCanvasPanel(1)) elif namespace.scene == '3d': sceneOpts = scene3dopts.Scene3DOpts(MockCanvasPanel(1)) # 3D views default to # world display space if namespace.scene == '3d': childDisplayCtx.displaySpace = 'world' parseargs.applySceneArgs(namespace, overlayList, childDisplayCtx, sceneOpts) # Centre the location. The DisplayContext # will typically centre its location on # initialisation, but this may not work # if any overlay arguments change the bounds # of an overlay (e.g. mesh reference image) if namespace.worldLoc is None and namespace.voxelLoc is None: b = childDisplayCtx.bounds childDisplayCtx.location = [ b.xlo + 0.5 * b.xlen, b.ylo + 0.5 * b.ylen, b.zlo + 0.5 * b.zlen ] # This has to be applied after applySceneArgs, # in case the user used the '-std'/'-std1mm' # options. if namespace.selectedOverlay is not None: masterDisplayCtx.selectedOverlay = namespace.selectedOverlay if len(overlayList) == 0: raise RuntimeError('At least one overlay must be specified') return overlayList, childDisplayCtx, sceneOpts