summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Smith <bruce@nanorex.com>2009-02-21 05:39:00 +0000
committerBruce Smith <bruce@nanorex.com>2009-02-21 05:39:00 +0000
commit11c54020481eaa7bf763c39ede420e4befa5ca6b (patch)
tree1ef76c8101617dfed31b5ecca2e7706cade60cee
parent785402ce730379d9700bc0f6868f028159587498 (diff)
downloadnanoengineer-theirix-11c54020481eaa7bf763c39ede420e4befa5ca6b.tar.gz
nanoengineer-theirix-11c54020481eaa7bf763c39ede420e4befa5ca6b.zip
split ColorSortedDisplayList into its own file
-rwxr-xr-xcad/src/commands/BuildCrystal/CrystalShape.py2
-rw-r--r--cad/src/commands/TestGraphics/test_selection_redraw.py2
-rwxr-xr-xcad/src/graphics/drawing/ColorSortedDisplayList.py493
-rwxr-xr-xcad/src/graphics/drawing/ColorSorter.py470
-rw-r--r--cad/src/graphics/drawing/DrawingSet.py2
-rw-r--r--cad/src/graphics/drawing/GLPrimitiveSet.py2
-rw-r--r--cad/src/graphics/model_drawing/TransformedDisplayListsDrawer.py2
-rw-r--r--cad/src/graphics/model_drawing/special_drawing.py2
-rw-r--r--cad/src/graphics/widgets/GLPane_csdl_collector.py2
-rw-r--r--cad/src/prototype/test_drawing.py2
10 files changed, 512 insertions, 467 deletions
diff --git a/cad/src/commands/BuildCrystal/CrystalShape.py b/cad/src/commands/BuildCrystal/CrystalShape.py
index 9abd3d68e..cbd2d0b11 100755
--- a/cad/src/commands/BuildCrystal/CrystalShape.py
+++ b/cad/src/commands/BuildCrystal/CrystalShape.py
@@ -51,7 +51,7 @@ from graphics.drawing.CS_draw_primitives import drawcylinder
from graphics.drawing.CS_draw_primitives import drawsphere
from graphics.drawing.CS_draw_primitives import drawline
from graphics.drawing.ColorSorter import ColorSorter
-from graphics.drawing.ColorSorter import ColorSortedDisplayList
+from graphics.drawing.ColorSortedDisplayList import ColorSortedDisplayList
from utilities.constants import SUBTRACT_FROM_SELECTION
from utilities.constants import OUTSIDE_SUBTRACT_FROM_SELECTION
diff --git a/cad/src/commands/TestGraphics/test_selection_redraw.py b/cad/src/commands/TestGraphics/test_selection_redraw.py
index 6f07002f4..27ca172be 100644
--- a/cad/src/commands/TestGraphics/test_selection_redraw.py
+++ b/cad/src/commands/TestGraphics/test_selection_redraw.py
@@ -33,7 +33,7 @@ import foundation.env as env
from graphics.drawing.DrawingSet import DrawingSet
## from graphics.drawing.TransformControl import TransformControl
from graphics.drawing.ColorSorter import ColorSorter
-from graphics.drawing.ColorSorter import ColorSortedDisplayList
+from graphics.drawing.ColorSortedDisplayList import ColorSortedDisplayList
from graphics.drawing.CS_draw_primitives import drawsphere
from commands.TestGraphics.GraphicsTestCase import GraphicsTestCase
diff --git a/cad/src/graphics/drawing/ColorSortedDisplayList.py b/cad/src/graphics/drawing/ColorSortedDisplayList.py
new file mode 100755
index 000000000..7e6f15ed0
--- /dev/null
+++ b/cad/src/graphics/drawing/ColorSortedDisplayList.py
@@ -0,0 +1,493 @@
+# Copyright 2004-2009 Nanorex, Inc. See LICENSE file for details.
+"""
+ColorSortedDisplayList.py - A set of primitives to be drawn as a unit,
+under runtime-determined drawing styles
+
+@author: Russ
+@version: $Id$
+@copyright: 2004-2009 Nanorex, Inc. See LICENSE file for details.
+
+History:
+
+This was originally written by Russ in ColorSorter.py.
+See that file for its pre-090220 history.
+
+bruce 090220 added reentrancy, split it into this file.
+
+TODO:
+
+Change ColorSorter into a normal class with distinct instances.
+Give it a stack of instances rather than its current _suspend system.
+Refactor some things between ColorSorter and ColorSortedDisplayList
+(which needs renaming). [bruce 090220 comment]
+"""
+
+from OpenGL.GL import glCallList
+from OpenGL.GL import glDeleteLists
+from OpenGL.GL import glGenLists
+
+import foundation.env as env
+
+from graphics.drawing.gl_lighting import isPatternedDrawing
+from graphics.drawing.gl_lighting import startPatternedDrawing
+from graphics.drawing.gl_lighting import endPatternedDrawing
+
+from utilities.prefs_constants import hoverHighlightingColor_prefs_key
+from utilities.prefs_constants import hoverHighlightingColorStyle_prefs_key
+from utilities.prefs_constants import HHS_HALO
+from utilities.prefs_constants import selectionColorStyle_prefs_key
+from utilities.prefs_constants import SS_HALO
+
+from utilities.debug import print_compact_traceback
+
+import graphics.drawing.drawing_globals as drawing_globals
+
+from graphics.drawing.gl_lighting import apply_material
+
+# ==
+
+_csdl_id_counter = 0
+_warned_del = False
+
+# ==
+
+class ColorSortedDisplayList: #Russ 080225: Added.
+ """
+ The ColorSorter's parent uses one of these to store color-sorted display
+ list state. It's passed in to ColorSorter.start() .
+
+ CSDLs are now created with a TransformControl reference as an argument (and
+ are internally listed in it while they exist). This TransformControl
+ reference is constant (although the transform in the TransformControl is
+ mutable).
+
+ For convenience, the TransformControl argument can be left out if you don't
+ want to use a TransformControl to move the CSDL. This has the same effect as
+ giving a TransformControl whose transform remains as the identity matrix.
+ """
+
+ # default values of instance variables
+ transformControl = None
+ reentrant = False #bruce 090220
+
+ def __init__(self, transformControl = None, reentrant = False):
+ """
+ """
+ if reentrant:
+ self.reentrant = True # permits reentrant ColorSorter.start
+
+ # [Russ 080915: Added.
+ # A unique integer ID for each CSDL.
+ global _csdl_id_counter
+ _csdl_id_counter += 1
+ self.csdl_id = _csdl_id_counter
+
+ # Support for lazily updating drawing caches, namely a
+ # timestamp showing when this CSDL was last changed.
+ self.changed = drawing_globals.eventStamp()
+
+ # Included drawing-primitive IDs.
+ self.spheres = []
+ self.cylinders = []
+
+ # Russ 081128: A cached primitives drawing index. This is only used
+ # when drawing individual CSDLs for hover-highlighting, for testing,
+ # and during development. Normally,
+ # primitives from a number of CSDLs are collected into a GLPrimitiveSet
+ # with a drawing index covering all of them.
+ #bruce 090218: corrected above comment, and changed drawIndex ->
+ # drawIndices so it can support more than one primitive type.
+ self.drawIndices = {}
+
+ if transformControl is not None:
+ self.transformControl = transformControl
+ # Note: this requires the csdlID to be already set!
+ self.transformControl.addCSDL(self)
+ pass
+
+ # Russ 081122: Mark CSDLs with a glname for selection.
+ self.glname = env._shared_glselect_name_dict.\
+ alloc_my_glselect_name(self)
+ ###self.glname = 0x12345678 ### For testing.
+
+ self.clear()
+
+ # Whether to draw in the selection over-ride color.
+ self.selected = False
+
+ ### TODO [bruce 090114 comment]: a near-term goal is to remove
+ # self.selected and self.dl, so that self only knows
+ # how to draw either way, but always finds out as-needed
+ # (from client state) which way to actually draw.
+ # Reviewing the current code, I think the only remaining
+ # essential use of self.dl is in CrystalShape.py
+ # (see new comment in its docstring for how to clean that up),
+ # and the only remaining essential use of self.selected
+ # (aside from maintaining self.dl, no longer needed if it's removed)
+ # is in ColorSorter.finish (which should be replaced by
+ # passing finish the same drawing-style arguments that
+ # CSDL.draw accepts).
+
+ return
+
+ # Russ 080925: Added.
+ def transform_id(self):
+ """
+ Return the transform_id of the CSDL, or None if there is no associated
+ TransformControl.
+ """
+ if self.transformControl is None:
+ return None
+ return self.transformControl.transform_id
+
+ # Russ 080915: Added.
+ def __del__(self): # Called by Python when an object is being freed.
+ self.destroy()
+ return
+
+ def destroy(self): # Called by us to break cyclic reference loops.
+ # Free any OpenGL resources.
+ ### REVIEW: Need to wait for our OpenGL context to become current when
+ # GLPane calls its method saying it's current again. See chunk dealloc
+ # code for details. This hangs NE1 now, so it's commented out.
+ ## self.deallocate_displists()
+
+ # Unregister self from its TransformControl, breaking the Python
+ # reference cycle so the CSDL can be reclaimed.
+ if self.transformControl is not None:
+ try:
+ self.transformControl.removeCSDL(self)
+ #bruce 090218 fixed two bugs in this line; untested either way
+ except:
+ global _warned_del
+ if not _warned_del:
+ print_compact_traceback(
+ "bug (printed only once per session): "
+ "exception in ColorSortedDisplayList.destroy ignored: ")
+ _warned_del = True
+ pass
+ pass
+ pass
+ return
+
+ # ==
+
+ # Russ 080925: For batched primitive drawing, drawing-primitive functions
+ # conditionally collect lists of primitive IDs here in the CSDL, rather than
+ # sending them down through the ColorSorter schedule methods into the DL
+ # layer. Later, those primitive lists are collected across the CSDLs in
+ # a DrawingSet, into the per-primitive-type VBO caches and MultiDraw indices
+ # managed by its GLPrimitiveSet. Most of the intermediate stuff will be
+ # cached in the underlying GLPrimitiveBuffer, since GLPrimitiveSet is meant
+ # to be very transient.
+ #
+ # This can be factored when we get a lot of primitive shaders. For now,
+ # simply cache the drawing-primitive IDs at the top level of CSDL.
+ def clearPrimitives(self):
+ # Free them in the GLPrimitiveBuffers.
+ if drawing_globals.use_batched_primitive_shaders:
+ drawing_globals.spherePrimitives.releasePrimitives(self.spheres)
+
+ if drawing_globals.use_cylinder_shaders:
+ drawing_globals.cylinderPrimitives.releasePrimitives(
+ self.cylinders)
+ pass
+ pass
+ self.spheres = []
+ self.cylinders = []
+ self.drawIndices = {}
+ return
+
+ def addSphere(self, center, radius, color, glname):
+ """
+ Allocate a sphere primitive and add its ID to the sphere list.
+ . center is a VQT point.
+ . radius is a number.
+ . color is a list of components: [R, G, B].
+ . glname comes from the _gl_name_stack.
+ """
+ self.spheres += drawing_globals.spherePrimitives.addSpheres(
+ [center], radius, color, self.transform_id(), glname)
+ self.drawIndices = {}
+ return
+
+ # Russ 090119: Added.
+ def addCylinder(self, endpts, radii, color, glname):
+ """
+ Allocate a cylinder primitive and add its ID to the cylinder list.
+ . endpts is a tuple of two VQT points.
+ . radii may be a single number, or a tuple of two radii for taper.
+ . color is a list of components: [R, G, B] or [R, G, B, A].
+ . glname comes from the _gl_name_stack.
+ """
+ self.cylinders += drawing_globals.cylinderPrimitives.addCylinders(
+ [endpts], radii, color, self.transform_id(), glname)
+ self.drawIndices = {}
+ return
+
+ # ==
+
+ ### REVIEW: the methods draw_in_abs_coords and nodes_containing_selobj
+ # don't make sense in this class in the long run, since it is not meant
+ # to be directly used as a "selobj" or as a Node. I presume they are
+ # only needed by temporary testing and debugging code, and they should be
+ # removed when no longer needed. [bruce 090114 comment]
+
+ # Russ 081128: Used by preDraw_glselect_dict() in standard_repaint_0(), and
+ # draw_highlighted_objectUnderMouse() in _do_other_drawing_inside_stereo().
+ def draw_in_abs_coords(self, glpane, color):
+ self.draw(highlighted = True, highlight_color = color)
+ return
+
+ # Russ 081128: Used by GLPane._update_nodes_containing_selobj().
+ def nodes_containing_selobj(self):
+ # XXX Only TestGraphics_GraphicsMode selects CSDL's now, so no
+ # XXX connection to the Model Tree.
+ return []
+
+ # ==
+
+ def shaders_and_primitives(self): #bruce 090218, needed only for CSDL.draw
+ """
+ Yield each pair of (shader, primitive-list) which we need to draw.
+ """
+ if self.spheres:
+ assert drawing_globals.spherePrimitives
+ yield drawing_globals.spherePrimitives, self.spheres
+ if self.cylinders:
+ assert drawing_globals.cylinderPrimitives
+ yield drawing_globals.cylinderPrimitives, self.cylinders
+ return
+
+ def draw_shader_primitives(self, *args): #bruce 090218, needed only for CSDL.draw
+ for shader, primitives in self.shaders_and_primitives():
+ index = self.drawIndices[shader]
+ shader.draw(index, *args)
+ continue
+ return
+
+ def draw(self,
+ highlighted = False,
+ selected = False,
+ patterning = True,
+ highlight_color = None,
+ draw_primitives = True ):
+ """
+ Simple all-in-one interface to CSDL drawing.
+
+ Allocate a CSDL in the parent class and fill it with the ColorSorter:
+ self.csdl = ColorSortedDisplayList()
+ ColorSorter.start(glpane, self.csdl)
+ drawsphere(...), drawcylinder(...), drawpolycone(...), and so on.
+ ColorSorter.finish()
+
+ Then when you want to draw the display lists call csdl.draw() with the
+ desired options:
+
+ @param highlighted: Whether to draw highlighted.
+
+ @param selected: Whether to draw selected.
+
+ @param patterning: Whether to apply patterned drawing styles for
+ highlighting and selection, according to the prefs settings.
+ If not set, it's as if the solid-color prefs are chosen.
+
+ @param highlight_color: Option to over-ride the highlight color set in
+ the color scheme preferences.
+
+ @param draw_primitives: Whether to draw shader primitives in the CSDL.
+ Defaults to True.
+ """
+
+ patterned_highlighting = (patterning and
+ isPatternedDrawing(highlight = highlighted))
+ halo_selection = (selected and
+ env.prefs[selectionColorStyle_prefs_key] == SS_HALO)
+ halo_highlighting = (highlighted and
+ env.prefs[hoverHighlightingColorStyle_prefs_key] ==
+ HHS_HALO)
+
+ # Russ 081128 (clarified, bruce 090218):
+ # GLPrimitiveSet.draw() calls this method (CSDL.draw) on CSDLs_with_DLs,
+ # passing draw_primitives = False to only draw the DLs.
+ # It gathers the primitives in a set of CSDLs into one big drawIndex
+ # per primitive type, and draws each drawIndex in a big batch.
+ #
+ # This method (CSDL.draw) is also called to
+ # draw *both* DLs and primitives in a CSDL, e.g. for hover-highlighting.
+ #
+ # Russ 081208: Skip drawing shader primitives while in GL_SELECT.
+ #
+ # Bruce 090218: support cylinders too.
+ prims_to_do = (drawing_globals.drawing_phase != "glselect" and
+ draw_primitives and (self.spheres or self.cylinders))
+ if prims_to_do:
+ # Cache drawing indices for just the primitives in this CSDL,
+ # in self.drawIndices, used in self.draw_shader_primitives below.
+ if not self.drawIndices:
+ for shader, primitives in self.shaders_and_primitives():
+ self.drawIndices[shader] = shader.makeDrawIndex(primitives)
+ continue
+ pass
+ pass
+
+ # Normal or selected drawing are done before a patterned highlight
+ # overlay, and also when not highlighting at all. You'd think that when
+ # we're drawing a solid highlight appearance, there'd be no need to draw
+ # the normal appearance first, because it will be obscured by the
+ # highlight. But halo selection extends beyond the object and is only
+ # obscured by halo highlighting. [russ 080610]
+ # Russ 081208: Skip DLs when drawing shader-prims with glnames-as-color.
+ DLs_to_do = (drawing_globals.drawing_phase != "glselect_glname_color"
+ and len(self.per_color_dls) > 0)
+ if (patterned_highlighting or not highlighted or
+ (halo_selection and not halo_highlighting)) :
+ if selected:
+ # Draw the selected appearance.
+ if prims_to_do: # Shader primitives.
+ self.draw_shader_primitives( highlighted, selected,
+ patterning, highlight_color)
+ pass
+
+ if DLs_to_do: # Display lists.
+ # If the selection mode is patterned, the selected_dl does
+ # first normal drawing and then draws an overlay.
+ glCallList(self.selected_dl)
+ pass
+ pass
+ else:
+ # Plain, old, solid drawing of the base object appearance.
+ if prims_to_do:
+ self.draw_shader_primitives() # Shader primitives.
+ pass
+
+ if DLs_to_do:
+ glCallList(self.color_dl) # Display lists.
+ pass
+ pass
+ pass
+
+ if highlighted:
+
+ if prims_to_do: # Shader primitives.
+ self.draw_shader_primitives( highlighted, selected,
+ patterning, highlight_color)
+ pass
+
+ if DLs_to_do: # Display lists.
+ if patterned_highlighting:
+ # Set up a patterned drawing mode for the following draw.
+ startPatternedDrawing(highlight = highlighted)
+ pass
+
+ # Draw a highlight overlay (solid, or in an overlay pattern.)
+ apply_material(highlight_color is not None and highlight_color
+ or env.prefs[hoverHighlightingColor_prefs_key])
+ glCallList(self.nocolor_dl)
+
+ if patterned_highlighting:
+ # Reset from a patterned drawing mode set up above.
+ endPatternedDrawing(highlight = highlighted)
+ pass
+ pass
+
+ pass
+ return
+
+ # ==
+ # CSDL state maintenance.
+
+ def clear(self):
+ """
+ Empty state.
+ """
+ self.dl = 0 # Current display list (color or selected.)
+ self.color_dl = 0 # DL to set colors, call each lower level list.
+ self.selected_dl = 0 # DL with a single (selected) over-ride color.
+ self.nocolor_dl = 0 # DL of lower-level calls for color over-rides.
+ self.per_color_dls = [] # Lower level, per-color primitive sublists.
+ return
+
+ def not_clear(self):
+ """
+ Check for empty state.
+ """
+ return (self.dl or self.color_dl or self.nocolor_dl or
+ self.selected_dl or
+ self.per_color_dls and len(self.per_color_dls))
+
+ def activate(self):
+ """
+ Make a top-level display list id ready, but don't fill it in.
+ """
+ ### REVIEW: after today's cleanup, I think this can no longer be called.
+ # (Though it may be a logic bug that CrystalShape.py never calls it.)
+ # [bruce 090114 comment]
+
+ # Display list id for the current appearance.
+ if not self.selected:
+ self.color_dl = glGenLists(1)
+ else:
+ self.selected_dl = glGenLists(1)
+ pass
+ self.selectDl()
+ #bruce 070521 added these two asserts
+ assert type(self.dl) in (type(1), type(1L))
+ assert self.dl != 0 # This failed on Linux, keep checking. (bug 2042)
+ return
+
+ def selectPick(self, boolVal):
+ """
+ Remember whether we're selected or not.
+ """
+ self.selected = boolVal
+ self.selectDl()
+ return
+
+ def selectDl(self):
+ """
+ Change to either the normal-color display list or the selected one.
+ """
+ self.dl = self.selected and self.selected_dl or self.color_dl
+ return
+
+ def reset(self):
+ """
+ Return to initialized state.
+ """
+ if self.not_clear():
+ # deallocate leaves it clear.
+ self.deallocate_displists()
+ pass
+ return
+
+ def deallocate_displists(self):
+ """
+ Free any allocated display lists.
+ """
+ # With CSDL active, self.dl duplicates either selected_dl or color_dl.
+ if (self.dl != self.color_dl and
+ self.dl != self.selected_dl):
+ glDeleteLists(self.dl, 1)
+ for dl in [self.color_dl, self.nocolor_dl, self.selected_dl]:
+ if dl != 0:
+ glDeleteLists(dl, 1)
+ pass
+ continue
+ # piotr 080420: The second level dl's are 2-element lists of DL ids
+ # rather than just a list of ids. The second DL is used in case
+ # of multi-color objects and is required for highlighting
+ # and selection (not in rc1)
+ for clr, dls in self.per_color_dls: # Second-level dl's.
+ for dl in dls: # iterate over DL pairs.
+ if dl != 0:
+ glDeleteLists(dl, 1)
+ pass
+ continue
+ continue
+ self.clear()
+ return
+
+ pass # end of class ColorSortedDisplayList
+
+# end
diff --git a/cad/src/graphics/drawing/ColorSorter.py b/cad/src/graphics/drawing/ColorSorter.py
index 7d125b7b6..e912a2c4e 100755
--- a/cad/src/graphics/drawing/ColorSorter.py
+++ b/cad/src/graphics/drawing/ColorSorter.py
@@ -1,7 +1,6 @@
# Copyright 2004-2009 Nanorex, Inc. See LICENSE file for details.
"""
-ColorSorter.py - A set of primitives to be drawn as a unit,
-under runtime-determined drawing styles
+ColorSorter.py - sort primitives and store them in a ColorSortedDisplayList
@author: Grantham, Russ
@version: $Id$
@@ -42,9 +41,11 @@ gl_lighting.py gl_buffers.py
081126 russ Added CSDL shader hover-highlight support, including glname drawing.
-REVIEW:
+090119 russ Added cylinder shader-primitive support.
-bruce 090114:
+090220 bruce split class ColorSortedDisplayList into its own file
+
+REVIEW [bruce 090114]:
* there are a lot of calls of glGenLists(1) that would be VRAM memory leaks
if they didn't deallocate any prior display list being stored in the same attribute
@@ -57,14 +58,12 @@ to make this very clear.
* see my comments dated 090114 about cleaning up .dl, .selected, .selectPick,
and activate (and related comments in CrystalShape.py and chunk.py).
-russ 090119 Added cylinder shader-primitive support.
-
TODO:
Change ColorSorter into a normal class with distinct instances.
Give it a stack of instances rather than its current _suspend system.
Refactor some things between ColorSorter and ColorSortedDisplayList
-(which needs renaming). Split them into separate files. [bruce 090220 comment]
+(which also needs renaming). [bruce 090220 comment]
"""
from OpenGL.GL import GL_BLEND
@@ -72,7 +71,6 @@ from OpenGL.GL import glBlendFunc
from OpenGL.GL import glCallList
from OpenGL.GL import glColor3fv
from OpenGL.GL import GL_COMPILE
-from OpenGL.GL import glDeleteLists
from OpenGL.GL import glDepthMask
from OpenGL.GL import glDisable
from OpenGL.GL import glEnable
@@ -95,19 +93,16 @@ from graphics.drawing.gl_lighting import startPatternedDrawing
from graphics.drawing.gl_lighting import endPatternedDrawing
from utilities.prefs_constants import selectionColor_prefs_key
-from utilities.prefs_constants import hoverHighlightingColor_prefs_key
-from utilities.prefs_constants import hoverHighlightingColorStyle_prefs_key
-from utilities.prefs_constants import HHS_HALO
-from utilities.prefs_constants import selectionColorStyle_prefs_key
-from utilities.prefs_constants import SS_HALO
-from utilities.debug import print_compact_traceback
+from utilities.debug import print_compact_stack
import graphics.drawing.drawing_globals as drawing_globals
+
if drawing_globals.quux_module_import_succeeded:
import quux
from graphics.drawing.CS_ShapeList import ShapeList_inplace
+
from graphics.drawing.CS_workers import drawcylinder_worker
from graphics.drawing.CS_workers import drawline_worker
from graphics.drawing.CS_workers import drawpolycone_multicolor_worker
@@ -117,458 +112,15 @@ from graphics.drawing.CS_workers import drawsphere_worker_loop
from graphics.drawing.CS_workers import drawsurface_worker
from graphics.drawing.CS_workers import drawwiresphere_worker
from graphics.drawing.CS_workers import drawtriangle_strip_worker
+
from graphics.drawing.gl_lighting import apply_material
# ==
-_csdl_id_counter = 0
-_warned_del = False
-
_DEBUG = False
# ==
-class ColorSortedDisplayList: #Russ 080225: Added.
- """
- The ColorSorter's parent uses one of these to store color-sorted display
- list state. It's passed in to ColorSorter.start() .
-
- CSDLs are now created with a TransformControl reference as an argument (and
- are internally listed in it while they exist). This TransformControl
- reference is constant (although the transform in the TransformControl is
- mutable).
-
- For convenience, the TransformControl argument can be left out if you don't
- want to use a TransformControl to move the CSDL. This has the same effect as
- giving a TransformControl whose transform remains as the identity matrix.
- """
-
- # default values of instance variables
- transformControl = None
- reentrant = False #bruce 090220
-
- def __init__(self, transformControl = None, reentrant = False):
- """
- """
- if reentrant:
- self.reentrant = True # permits reentrant ColorSorter.start
-
- # [Russ 080915: Added.
- # A unique integer ID for each CSDL.
- global _csdl_id_counter
- _csdl_id_counter += 1
- self.csdl_id = _csdl_id_counter
-
- # Support for lazily updating drawing caches, namely a
- # timestamp showing when this CSDL was last changed.
- self.changed = drawing_globals.eventStamp()
-
- # Included drawing-primitive IDs.
- self.spheres = []
- self.cylinders = []
-
- # Russ 081128: A cached primitives drawing index. This is only used
- # when drawing individual CSDLs for hover-highlighting, for testing,
- # and during development. Normally,
- # primitives from a number of CSDLs are collected into a GLPrimitiveSet
- # with a drawing index covering all of them.
- #bruce 090218: corrected above comment, and changed drawIndex ->
- # drawIndices so it can support more than one primitive type.
- self.drawIndices = {}
-
- if transformControl is not None:
- self.transformControl = transformControl
- # Note: this requires the csdlID to be already set!
- self.transformControl.addCSDL(self)
- pass
-
- # Russ 081122: Mark CSDLs with a glname for selection.
- self.glname = env._shared_glselect_name_dict.\
- alloc_my_glselect_name(self)
- ###self.glname = 0x12345678 ### For testing.
-
- self.clear()
-
- # Whether to draw in the selection over-ride color.
- self.selected = False
-
- ### TODO [bruce 090114 comment]: a near-term goal is to remove
- # self.selected and self.dl, so that self only knows
- # how to draw either way, but always finds out as-needed
- # (from client state) which way to actually draw.
- # Reviewing the current code, I think the only remaining
- # essential use of self.dl is in CrystalShape.py
- # (see new comment in its docstring for how to clean that up),
- # and the only remaining essential use of self.selected
- # (aside from maintaining self.dl, no longer needed if it's removed)
- # is in ColorSorter.finish (which should be replaced by
- # passing finish the same drawing-style arguments that
- # CSDL.draw accepts).
-
- return
-
- # Russ 080925: Added.
- def transform_id(self):
- """
- Return the transform_id of the CSDL, or None if there is no associated
- TransformControl.
- """
- if self.transformControl is None:
- return None
- return self.transformControl.transform_id
-
- # Russ 080915: Added.
- def __del__(self): # Called by Python when an object is being freed.
- self.destroy()
- return
-
- def destroy(self): # Called by us to break cyclic reference loops.
- # Free any OpenGL resources.
- ### REVIEW: Need to wait for our OpenGL context to become current when
- # GLPane calls its method saying it's current again. See chunk dealloc
- # code for details. This hangs NE1 now, so it's commented out.
- ## self.deallocate_displists()
-
- # Unregister self from its TransformControl, breaking the Python
- # reference cycle so the CSDL can be reclaimed.
- if self.transformControl is not None:
- try:
- self.transformControl.removeCSDL(self)
- #bruce 090218 fixed two bugs in this line; untested either way
- except:
- global _warned_del
- if not _warned_del:
- print_compact_traceback(
- "bug (printed only once per session): "
- "exception in ColorSortedDisplayList.destroy ignored: ")
- _warned_del = True
- pass
- pass
- pass
- return
-
- # ==
-
- # Russ 080925: For batched primitive drawing, drawing-primitive functions
- # conditionally collect lists of primitive IDs here in the CSDL, rather than
- # sending them down through the ColorSorter schedule methods into the DL
- # layer. Later, those primitive lists are collected across the CSDLs in
- # a DrawingSet, into the per-primitive-type VBO caches and MultiDraw indices
- # managed by its GLPrimitiveSet. Most of the intermediate stuff will be
- # cached in the underlying GLPrimitiveBuffer, since GLPrimitiveSet is meant
- # to be very transient.
- #
- # This can be factored when we get a lot of primitive shaders. For now,
- # simply cache the drawing-primitive IDs at the top level of CSDL.
- def clearPrimitives(self):
- # Free them in the GLPrimitiveBuffers.
- if drawing_globals.use_batched_primitive_shaders:
- drawing_globals.spherePrimitives.releasePrimitives(self.spheres)
-
- if drawing_globals.use_cylinder_shaders:
- drawing_globals.cylinderPrimitives.releasePrimitives(
- self.cylinders)
- pass
- pass
- self.spheres = []
- self.cylinders = []
- self.drawIndices = {}
- return
-
- def addSphere(self, center, radius, color, glname):
- """
- Allocate a sphere primitive and add its ID to the sphere list.
- . center is a VQT point.
- . radius is a number.
- . color is a list of components: [R, G, B].
- . glname comes from the _gl_name_stack.
- """
- self.spheres += drawing_globals.spherePrimitives.addSpheres(
- [center], radius, color, self.transform_id(), glname)
- self.drawIndices = {}
- return
-
- # Russ 090119: Added.
- def addCylinder(self, endpts, radii, color, glname):
- """
- Allocate a cylinder primitive and add its ID to the cylinder list.
- . endpts is a tuple of two VQT points.
- . radii may be a single number, or a tuple of two radii for taper.
- . color is a list of components: [R, G, B] or [R, G, B, A].
- . glname comes from the _gl_name_stack.
- """
- self.cylinders += drawing_globals.cylinderPrimitives.addCylinders(
- [endpts], radii, color, self.transform_id(), glname)
- self.drawIndices = {}
- return
-
- # ==
-
- ### REVIEW: the methods draw_in_abs_coords and nodes_containing_selobj
- # don't make sense in this class in the long run, since it is not meant
- # to be directly used as a "selobj" or as a Node. I presume they are
- # only needed by temporary testing and debugging code, and they should be
- # removed when no longer needed. [bruce 090114 comment]
-
- # Russ 081128: Used by preDraw_glselect_dict() in standard_repaint_0(), and
- # draw_highlighted_objectUnderMouse() in _do_other_drawing_inside_stereo().
- def draw_in_abs_coords(self, glpane, color):
- self.draw(highlighted = True, highlight_color = color)
- return
-
- # Russ 081128: Used by GLPane._update_nodes_containing_selobj().
- def nodes_containing_selobj(self):
- # XXX Only TestGraphics_GraphicsMode selects CSDL's now, so no
- # XXX connection to the Model Tree.
- return []
-
- # ==
-
- def shaders_and_primitives(self): #bruce 090218, needed only for CSDL.draw
- """
- Yield each pair of (shader, primitive-list) which we need to draw.
- """
- if self.spheres:
- assert drawing_globals.spherePrimitives
- yield drawing_globals.spherePrimitives, self.spheres
- if self.cylinders:
- assert drawing_globals.cylinderPrimitives
- yield drawing_globals.cylinderPrimitives, self.cylinders
- return
-
- def draw_shader_primitives(self, *args): #bruce 090218, needed only for CSDL.draw
- for shader, primitives in self.shaders_and_primitives():
- index = self.drawIndices[shader]
- shader.draw(index, *args)
- continue
- return
-
- def draw(self,
- highlighted = False,
- selected = False,
- patterning = True,
- highlight_color = None,
- draw_primitives = True ):
- """
- Simple all-in-one interface to CSDL drawing.
-
- Allocate a CSDL in the parent class and fill it with the ColorSorter:
- self.csdl = ColorSortedDisplayList()
- ColorSorter.start(glpane, self.csdl)
- drawsphere(...), drawcylinder(...), drawpolycone(...), and so on.
- ColorSorter.finish()
-
- Then when you want to draw the display lists call csdl.draw() with the
- desired options:
-
- @param highlighted: Whether to draw highlighted.
-
- @param selected: Whether to draw selected.
-
- @param patterning: Whether to apply patterned drawing styles for
- highlighting and selection, according to the prefs settings.
- If not set, it's as if the solid-color prefs are chosen.
-
- @param highlight_color: Option to over-ride the highlight color set in
- the color scheme preferences.
-
- @param draw_primitives: Whether to draw shader primitives in the CSDL.
- Defaults to True.
- """
-
- patterned_highlighting = (patterning and
- isPatternedDrawing(highlight = highlighted))
- halo_selection = (selected and
- env.prefs[selectionColorStyle_prefs_key] == SS_HALO)
- halo_highlighting = (highlighted and
- env.prefs[hoverHighlightingColorStyle_prefs_key] ==
- HHS_HALO)
-
- # Russ 081128 (clarified, bruce 090218):
- # GLPrimitiveSet.draw() calls this method (CSDL.draw) on CSDLs_with_DLs,
- # passing draw_primitives = False to only draw the DLs.
- # It gathers the primitives in a set of CSDLs into one big drawIndex
- # per primitive type, and draws each drawIndex in a big batch.
- #
- # This method (CSDL.draw) is also called to
- # draw *both* DLs and primitives in a CSDL, e.g. for hover-highlighting.
- #
- # Russ 081208: Skip drawing shader primitives while in GL_SELECT.
- #
- # Bruce 090218: support cylinders too.
- prims_to_do = (drawing_globals.drawing_phase != "glselect" and
- draw_primitives and (self.spheres or self.cylinders))
- if prims_to_do:
- # Cache drawing indices for just the primitives in this CSDL,
- # in self.drawIndices, used in self.draw_shader_primitives below.
- if not self.drawIndices:
- for shader, primitives in self.shaders_and_primitives():
- self.drawIndices[shader] = shader.makeDrawIndex(primitives)
- continue
- pass
- pass
-
- # Normal or selected drawing are done before a patterned highlight
- # overlay, and also when not highlighting at all. You'd think that when
- # we're drawing a solid highlight appearance, there'd be no need to draw
- # the normal appearance first, because it will be obscured by the
- # highlight. But halo selection extends beyond the object and is only
- # obscured by halo highlighting. [russ 080610]
- # Russ 081208: Skip DLs when drawing shader-prims with glnames-as-color.
- DLs_to_do = (drawing_globals.drawing_phase != "glselect_glname_color"
- and len(self.per_color_dls) > 0)
- if (patterned_highlighting or not highlighted or
- (halo_selection and not halo_highlighting)) :
- if selected:
- # Draw the selected appearance.
- if prims_to_do: # Shader primitives.
- self.draw_shader_primitives( highlighted, selected,
- patterning, highlight_color)
- pass
-
- if DLs_to_do: # Display lists.
- # If the selection mode is patterned, the selected_dl does
- # first normal drawing and then draws an overlay.
- glCallList(self.selected_dl)
- pass
- pass
- else:
- # Plain, old, solid drawing of the base object appearance.
- if prims_to_do:
- self.draw_shader_primitives() # Shader primitives.
- pass
-
- if DLs_to_do:
- glCallList(self.color_dl) # Display lists.
- pass
- pass
- pass
-
- if highlighted:
-
- if prims_to_do: # Shader primitives.
- self.draw_shader_primitives( highlighted, selected,
- patterning, highlight_color)
- pass
-
- if DLs_to_do: # Display lists.
- if patterned_highlighting:
- # Set up a patterned drawing mode for the following draw.
- startPatternedDrawing(highlight = highlighted)
- pass
-
- # Draw a highlight overlay (solid, or in an overlay pattern.)
- apply_material(highlight_color is not None and highlight_color
- or env.prefs[hoverHighlightingColor_prefs_key])
- glCallList(self.nocolor_dl)
-
- if patterned_highlighting:
- # Reset from a patterned drawing mode set up above.
- endPatternedDrawing(highlight = highlighted)
- pass
- pass
-
- pass
- return
-
- # ==
- # CSDL state maintenance.
-
- def clear(self):
- """
- Empty state.
- """
- self.dl = 0 # Current display list (color or selected.)
- self.color_dl = 0 # DL to set colors, call each lower level list.
- self.selected_dl = 0 # DL with a single (selected) over-ride color.
- self.nocolor_dl = 0 # DL of lower-level calls for color over-rides.
- self.per_color_dls = [] # Lower level, per-color primitive sublists.
- return
-
- def not_clear(self):
- """
- Check for empty state.
- """
- return (self.dl or self.color_dl or self.nocolor_dl or
- self.selected_dl or
- self.per_color_dls and len(self.per_color_dls))
-
- def activate(self):
- """
- Make a top-level display list id ready, but don't fill it in.
- """
- ### REVIEW: after today's cleanup, I think this can no longer be called.
- # (Though it may be a logic bug that CrystalShape.py never calls it.)
- # [bruce 090114 comment]
-
- # Display list id for the current appearance.
- if not self.selected:
- self.color_dl = glGenLists(1)
- else:
- self.selected_dl = glGenLists(1)
- pass
- self.selectDl()
- #bruce 070521 added these two asserts
- assert type(self.dl) in (type(1), type(1L))
- assert self.dl != 0 # This failed on Linux, keep checking. (bug 2042)
- return
-
- def selectPick(self, boolVal):
- """
- Remember whether we're selected or not.
- """
- self.selected = boolVal
- self.selectDl()
- return
-
- def selectDl(self):
- """
- Change to either the normal-color display list or the selected one.
- """
- self.dl = self.selected and self.selected_dl or self.color_dl
- return
-
- def reset(self):
- """
- Return to initialized state.
- """
- if self.not_clear():
- # deallocate leaves it clear.
- self.deallocate_displists()
- pass
- return
-
- def deallocate_displists(self):
- """
- Free any allocated display lists.
- """
- # With CSDL active, self.dl duplicates either selected_dl or color_dl.
- if (self.dl != self.color_dl and
- self.dl != self.selected_dl):
- glDeleteLists(self.dl, 1)
- for dl in [self.color_dl, self.nocolor_dl, self.selected_dl]:
- if dl != 0:
- glDeleteLists(dl, 1)
- pass
- continue
- # piotr 080420: The second level dl's are 2-element lists of DL ids
- # rather than just a list of ids. The second DL is used in case
- # of multi-color objects and is required for highlighting
- # and selection (not in rc1)
- for clr, dls in self.per_color_dls: # Second-level dl's.
- for dl in dls: # iterate over DL pairs.
- if dl != 0:
- glDeleteLists(dl, 1)
- pass
- continue
- continue
- self.clear()
- return
-
- pass # End of ColorSortedDisplayList.
-
-# ==
-
class _fake_GLPane: #bruce 090220
transforms = () # or make this [] if necessary, but value should never change
pass
@@ -1468,7 +1020,7 @@ class ColorSorter:
_draw_sorted = staticmethod(_draw_sorted)
- pass # End of class ColorSorter
+ pass # end of class ColorSorter
ColorSorter._init_state()
# (this would be called in __init__ if ColorSorter was a normal class.)
diff --git a/cad/src/graphics/drawing/DrawingSet.py b/cad/src/graphics/drawing/DrawingSet.py
index f7480c93f..0e5f1c8fa 100644
--- a/cad/src/graphics/drawing/DrawingSet.py
+++ b/cad/src/graphics/drawing/DrawingSet.py
@@ -75,7 +75,7 @@ has no name in this proposal.
import graphics.drawing.drawing_globals as drawing_globals
from graphics.drawing.GLPrimitiveSet import GLPrimitiveSet
-from graphics.drawing.ColorSorter import ColorSortedDisplayList
+from graphics.drawing.ColorSortedDisplayList import ColorSortedDisplayList
class DrawingSet:
"""
diff --git a/cad/src/graphics/drawing/GLPrimitiveSet.py b/cad/src/graphics/drawing/GLPrimitiveSet.py
index 9c92c0072..c964fa9c3 100644
--- a/cad/src/graphics/drawing/GLPrimitiveSet.py
+++ b/cad/src/graphics/drawing/GLPrimitiveSet.py
@@ -47,7 +47,7 @@ See design comments on:
"""
import graphics.drawing.drawing_globals as drawing_globals
-from graphics.drawing.ColorSorter import ColorSortedDisplayList
+from graphics.drawing.ColorSortedDisplayList import ColorSortedDisplayList
from graphics.drawing.GLPrimitiveBuffer import GLPrimitiveBuffer
from graphics.drawing.TransformControl import TransformControl
diff --git a/cad/src/graphics/model_drawing/TransformedDisplayListsDrawer.py b/cad/src/graphics/model_drawing/TransformedDisplayListsDrawer.py
index 4aec19b6b..2128637fd 100644
--- a/cad/src/graphics/model_drawing/TransformedDisplayListsDrawer.py
+++ b/cad/src/graphics/model_drawing/TransformedDisplayListsDrawer.py
@@ -31,7 +31,7 @@ from foundation.changes import SelfUsageTrackingMixin, SubUsageTrackingMixin
# and chunks can know when they need to inval that because something drawn into it
# would draw differently due to a change in some graphics pref it used
-from graphics.drawing.ColorSorter import ColorSortedDisplayList # not yet used?
+from graphics.drawing.ColorSortedDisplayList import ColorSortedDisplayList # not yet used?
# ==
diff --git a/cad/src/graphics/model_drawing/special_drawing.py b/cad/src/graphics/model_drawing/special_drawing.py
index f92659a22..58d760fa7 100644
--- a/cad/src/graphics/model_drawing/special_drawing.py
+++ b/cad/src/graphics/model_drawing/special_drawing.py
@@ -13,7 +13,7 @@ with some parts refiled into foundations.
"""
from graphics.drawing.ColorSorter import ColorSorter
-from graphics.drawing.ColorSorter import ColorSortedDisplayList
+from graphics.drawing.ColorSortedDisplayList import ColorSortedDisplayList
from utilities.Comparison import same_vals
diff --git a/cad/src/graphics/widgets/GLPane_csdl_collector.py b/cad/src/graphics/widgets/GLPane_csdl_collector.py
index 1ab8379f5..5a59760bd 100644
--- a/cad/src/graphics/widgets/GLPane_csdl_collector.py
+++ b/cad/src/graphics/widgets/GLPane_csdl_collector.py
@@ -15,7 +15,7 @@ a separate object on 090219
from utilities.debug import print_compact_stack
-from graphics.drawing.ColorSorter import ColorSortedDisplayList
+from graphics.drawing.ColorSortedDisplayList import ColorSortedDisplayList
from graphics.drawing.ColorSorter import ColorSorter
# ==
diff --git a/cad/src/prototype/test_drawing.py b/cad/src/prototype/test_drawing.py
index f1e0d9b50..aa1073528 100644
--- a/cad/src/prototype/test_drawing.py
+++ b/cad/src/prototype/test_drawing.py
@@ -200,7 +200,7 @@ from graphics.drawing.GLSphereBuffer import GLSphereBuffer
from graphics.drawing.DrawingSet import DrawingSet
from graphics.drawing.TransformControl import TransformControl
from graphics.drawing.ColorSorter import ColorSorter
-from graphics.drawing.ColorSorter import ColorSortedDisplayList
+from graphics.drawing.ColorSortedDisplayList import ColorSortedDisplayList
from graphics.drawing.CS_draw_primitives import drawsphere, drawcylinder
from graphics.drawing.CS_workers import drawsphere_worker_loop
from graphics.drawing.gl_buffers import GLBufferObject