From ccee4d15328184140359d8ae76ac613528d8c3f3 Mon Sep 17 00:00:00 2001
From: Paul McCarthy <pauld.mccarthy@gmail.com>
Date: Sat, 16 Jan 2016 18:42:18 +0000
Subject: [PATCH] Render.py creates a master and child display context. I think
 I'm stuck with this parent-child DCTX requirement, as otherwise the
 DisplayOpts classes will be too complicated/flaky.

---
 fsl/fsleyes/fsleyes_parseargs.py |  8 +++----
 fsl/fsleyes/gl/lightboxcanvas.py |  2 +-
 fsl/fsleyes/gl/slicecanvas.py    |  4 +++-
 fsl/tools/render.py              | 37 ++++++++++++++++++++++++++------
 4 files changed, 38 insertions(+), 13 deletions(-)

diff --git a/fsl/fsleyes/fsleyes_parseargs.py b/fsl/fsleyes/fsleyes_parseargs.py
index 362f2e569..66927581d 100644
--- a/fsl/fsleyes/fsleyes_parseargs.py
+++ b/fsl/fsleyes/fsleyes_parseargs.py
@@ -496,7 +496,7 @@ ARGUMENTS = td.TypeDict({
     'VolumeOpts.displayRange'    : ('dr', 'displayRange'),
     'VolumeOpts.clippingRange'   : ('cr', 'clippingRange'),
     'VolumeOpts.invertClipping'  : ('ic', 'invertClipping'),
-    'VolumeOpts.clipImage'       : ('ci', 'clipImage'),
+    'VolumeOpts.clipImage'       : ('cl', 'clipImage'),
     'VolumeOpts.cmap'            : ('cm', 'cmap'),
     'VolumeOpts.negativeCmap'    : ('nc', 'negativeCmap'),
     'VolumeOpts.useNegativeCmap' : ('un', 'useNegativeCmap'),
@@ -516,8 +516,8 @@ ARGUMENTS = td.TypeDict({
     'VectorOpts.suppressY'     : ('ys', 'suppressY'),
     'VectorOpts.suppressZ'     : ('zs', 'suppressZ'),
     'VectorOpts.cmap'          : ('cm', 'cmap'),
-    'VectorOpts.colourImage'   : ('ci', 'colourImage'),
-    'VectorOpts.modulateImage' : ('mi', 'modulateImage'),
+    'VectorOpts.colourImage'   : ('co', 'colourImage'),
+    'VectorOpts.modulateImage' : ('mo', 'modulateImage'),
     'VectorOpts.clipImage'     : ('cl', 'clipImage'),
     'VectorOpts.clippingRange' : ('cr', 'clippingRange'),
 
@@ -1519,7 +1519,7 @@ def applyOverlayArgs(args, overlayList, displayCtx, **kwargs):
             fileOpts = FILE_OPTIONS.get(opts, [])
 
             for fileOpt in fileOpts:
-                value = getattr(opts, fileOpt) 
+                value = getattr(optArgs, fileOpt)
                 if value is not None:
 
                     image = _findOrLoad(overlayList,
diff --git a/fsl/fsleyes/gl/lightboxcanvas.py b/fsl/fsleyes/gl/lightboxcanvas.py
index 86b48e697..353da3612 100644
--- a/fsl/fsleyes/gl/lightboxcanvas.py
+++ b/fsl/fsleyes/gl/lightboxcanvas.py
@@ -746,7 +746,7 @@ class LightBoxCanvas(slicecanvas.SliceCanvas):
             display = self.displayCtx.getDisplay(overlay)
             globj   = self._glObjects.get(overlay, None)
 
-            if (globj is None) or (not display.enabled):
+            if (globj is None) or (not globj.ready()) or (not display.enabled):
                 continue
 
             log.debug('Drawing {} slices ({} - {}) for '
diff --git a/fsl/fsleyes/gl/slicecanvas.py b/fsl/fsleyes/gl/slicecanvas.py
index 9488327d4..25b142571 100644
--- a/fsl/fsleyes/gl/slicecanvas.py
+++ b/fsl/fsleyes/gl/slicecanvas.py
@@ -520,7 +520,9 @@ class SliceCanvas(props.HasProperties):
         # But if any display/opts properties
         # are not synchronised, we'll use our
         # own texture stack. 
-        if not (display.allSyncedToParent() and 
+        if not (display.getParent()         and
+                display.allSyncedToParent() and 
+                opts   .getParent()         and
                 opts   .allSyncedToParent()):
 
             name = '{}_{}'.format(id(self.displayCtx), name)
diff --git a/fsl/tools/render.py b/fsl/tools/render.py
index 79795bfbd..9e3881611 100644
--- a/fsl/tools/render.py
+++ b/fsl/tools/render.py
@@ -339,6 +339,18 @@ def run(args, context):
             width=width,
             height=height)
 
+        c.showCursor      = sceneOpts.showCursor
+        c.cursorColour    = sceneOpts.cursorColour
+        c.bgColour        = sceneOpts.bgColour
+        c.renderMode      = sceneOpts.renderMode
+        c.resolutionLimit = sceneOpts.resolutionLimit
+        c.sliceSpacing    = sceneOpts.sliceSpacing
+        c.nrows           = sceneOpts.nrows
+        c.ncols           = sceneOpts.ncols
+        c.zrange          = sceneOpts.zrange
+        c.showGridLines   = sceneOpts.showGridLines
+        c.highlightSlice  = sceneOpts.highlightSlice
+
         props.applyArguments(c, args)
         canvases.append(c)
 
@@ -397,6 +409,12 @@ def run(args, context):
                 zax=zax,
                 width=int(width),
                 height=int(height))
+
+            c.showCursor      = sceneOpts.showCursor
+            c.cursorColour    = sceneOpts.cursorColour
+            c.bgColour        = sceneOpts.bgColour
+            c.renderMode      = sceneOpts.renderMode
+            c.resolutionLimit = sceneOpts.resolutionLimit
             
             if zoom is not None: c.zoom = zoom
             c.centreDisplayAt(*centre)
@@ -407,8 +425,6 @@ def run(args, context):
     # lightbox canvases) and render them one by one
     for i, c in enumerate(canvases):
 
-        c.bgColour   = sceneOpts.bgColour
-        c.showCursor = sceneOpts.showCursor
         if   c.zax == 0: c.pos.xyz = displayCtx.location.yzx
         elif c.zax == 1: c.pos.xyz = displayCtx.location.xzy
         elif c.zax == 2: c.pos.xyz = displayCtx.location.xyz
@@ -511,9 +527,16 @@ def parseArgs(argv):
 
 def context(args):
 
-    # Create an image list and display context 
-    overlayList  = fsloverlay.OverlayList()
-    displayCtx = displaycontext.DisplayContext(overlayList)
+    # Create an image 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)
 
     # The handleOverlayArgs function uses the
     # fsl.fsleyes.overlay.loadOverlays function,
@@ -528,12 +551,12 @@ def context(args):
     # Load the overlays specified on the command
     # line, and configure their display properties
     fsleyes_parseargs.applyOverlayArgs(
-        args, overlayList, displayCtx, loadFunc=load, errorFunc=error)
+        args, overlayList, masterDisplayCtx, loadFunc=load, errorFunc=error)
 
     if len(overlayList) == 0:
         raise RuntimeError('At least one overlay must be specified')
 
-    return overlayList, displayCtx
+    return overlayList, childDisplayCtx
  
 
 FSL_TOOLNAME  = 'Render'
-- 
GitLab