summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Smith <bruce@nanorex.com>2009-02-21 00:03:08 +0000
committerBruce Smith <bruce@nanorex.com>2009-02-21 00:03:08 +0000
commit785402ce730379d9700bc0f6868f028159587498 (patch)
tree2b0b38c461cc06be81f5a8747a344988dfd3d802
parent3a4954668b12d58b1eb47649d74b0940efcfcc17 (diff)
downloadnanoengineer-785402ce730379d9700bc0f6868f028159587498.tar.gz
nanoengineer-785402ce730379d9700bc0f6868f028159587498.zip
ColorSorter.start & chunk.*Matrix want glpane arg, track transforms
-rwxr-xr-xcad/src/commands/BuildCrystal/CrystalShape.py12
-rw-r--r--cad/src/commands/TestGraphics/test_selection_redraw.py2
-rwxr-xr-xcad/src/graphics/drawing/ColorSorter.py91
-rw-r--r--cad/src/graphics/model_drawing/ChunkDrawer.py16
-rw-r--r--cad/src/graphics/model_drawing/ExternalBondSetDrawer.py4
-rw-r--r--cad/src/graphics/model_drawing/special_drawing.py2
-rw-r--r--cad/src/graphics/widgets/GLPane_csdl_collector.py10
-rw-r--r--cad/src/graphics/widgets/GLPane_drawingset_methods.py26
-rw-r--r--cad/src/graphics/widgets/GLPane_minimal.py14
-rwxr-xr-xcad/src/model/bonds.py4
-rwxr-xr-xcad/src/model/chem.py4
-rwxr-xr-xcad/src/model/chunk.py44
-rw-r--r--cad/src/prototype/test_drawing.py4
13 files changed, 189 insertions, 44 deletions
diff --git a/cad/src/commands/BuildCrystal/CrystalShape.py b/cad/src/commands/BuildCrystal/CrystalShape.py
index 6ba231ac8..9abd3d68e 100755
--- a/cad/src/commands/BuildCrystal/CrystalShape.py
+++ b/cad/src/commands/BuildCrystal/CrystalShape.py
@@ -778,19 +778,19 @@ class CrystalShape(shape):
drawline(white, p0, p1)
- def draw(self, win, layerColor):
+ def draw(self, glpane, layerColor):
"""
- Draw the shape. win, not used, is for consistency among
- drawing functions (and may be used if drawing logic gets
- more sophisticated.
+ Draw the shape.
- Find the bounding box for the curve and check the position of each
+ Find the bounding box for the curve and check the position of each
carbon atom in a lattice would occupy for being 'in'
the shape. A tube representation of the atoms thus selected is
saved as a GL call list for fast drawing.
This method is only for crystal-cutter mode. --Huaicai
"""
+ #bruce 090220 renamed first arg from win to glpane (which is what
+ # was actually passed) and used it in ColorSorter.start (required now).
if 0:
self._anotherDraw(layerColor)
return
@@ -802,7 +802,7 @@ class CrystalShape(shape):
return
#russ 080225: Moved glNewList into ColorSorter.start for displist re-org.
#russ 080225: displist side effect allocates a ColorSortedDisplayList.
- ColorSorter.start(self.displist) # grantham 20051205
+ ColorSorter.start(glpane, self.displist) # grantham 20051205
try:
for layer, bonds in self.bondLayers.items():
color = layerColor[layer]
diff --git a/cad/src/commands/TestGraphics/test_selection_redraw.py b/cad/src/commands/TestGraphics/test_selection_redraw.py
index 4405c71ce..6f07002f4 100644
--- a/cad/src/commands/TestGraphics/test_selection_redraw.py
+++ b/cad/src/commands/TestGraphics/test_selection_redraw.py
@@ -64,7 +64,7 @@ class CSDL_holder(object):
def __init__(self, x, y, n):
self.csdl = ColorSortedDisplayList()
# draw into it, based on x, y, n
- ColorSorter.start(self.csdl)
+ ColorSorter.start(None, self.csdl)
for i in range(n):
z = i - (_NUM_SPHERES_PER_CSDL - 1) / 2.0
color = (random.uniform(0.2, 0.8),
diff --git a/cad/src/graphics/drawing/ColorSorter.py b/cad/src/graphics/drawing/ColorSorter.py
index 03a5747e6..7d125b7b6 100755
--- a/cad/src/graphics/drawing/ColorSorter.py
+++ b/cad/src/graphics/drawing/ColorSorter.py
@@ -124,6 +124,10 @@ 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
@@ -350,7 +354,7 @@ class ColorSortedDisplayList: #Russ 080225: Added.
Allocate a CSDL in the parent class and fill it with the ColorSorter:
self.csdl = ColorSortedDisplayList()
- ColorSorter.start(self.csdl)
+ ColorSorter.start(glpane, self.csdl)
drawsphere(...), drawcylinder(...), drawpolycone(...), and so on.
ColorSorter.finish()
@@ -565,6 +569,12 @@ class ColorSortedDisplayList: #Russ 080225: Added.
# ==
+class _fake_GLPane: #bruce 090220
+ transforms = () # or make this [] if necessary, but value should never change
+ pass
+
+_the_fake_GLPane = _fake_GLPane()
+
class ColorSorter:
"""
State Sorter specializing in color (really any object that can be
@@ -628,6 +638,10 @@ class ColorSorter:
ColorSorter._parent_csdl = None # Passed from start() to finish()
+ ColorSorter.glpane = None #bruce 090220
+
+ ColorSorter._initial_transforms = None #bruce 090220
+
# following are guesses by bruce 090220:
ColorSorter.sorted_by_color = None
ColorSorter._cur_shapelist = None
@@ -645,12 +659,17 @@ class ColorSorter:
class _attrholder:
pass
state = _attrholder()
+
+ if len(ColorSorter._gl_name_stack) > 1:
+ print "fyi: name stack is non-null when suspended -- bug?", ColorSorter._gl_name_stack #####
state.sorting = ColorSorter.sorting
state._sorted = ColorSorter._sorted
state._immediate = ColorSorter._immediate
state._gl_name_stack = ColorSorter._gl_name_stack
state._parent_csdl = ColorSorter._parent_csdl
+ state.glpane = ColorSorter.glpane
+ state._initial_transforms = ColorSorter._initial_transforms
state.sorted_by_color = ColorSorter.sorted_by_color
state._cur_shapelist = ColorSorter._cur_shapelist
state.sphereLevel = ColorSorter.sphereLevel
@@ -664,6 +683,7 @@ class ColorSorter:
def _unsuspend_if_needed(): # staticmethod
"""
If we're suspended, unsuspend.
+ Otherwise, reinit state as a precaution.
"""
if ColorSorter._suspended_states:
state = ColorSorter._suspended_states.pop()
@@ -673,16 +693,53 @@ class ColorSorter:
ColorSorter._immediate = state._immediate
ColorSorter._gl_name_stack = state._gl_name_stack
ColorSorter._parent_csdl = state._parent_csdl
+ ColorSorter.glpane = state.glpane
+ ColorSorter._initial_transforms = state._initial_transforms
ColorSorter.sorted_by_color = state.sorted_by_color
ColorSorter._cur_shapelist = state._cur_shapelist
ColorSorter.sphereLevel = state.sphereLevel
pass
+ else:
+ #bruce 090220 guess precaution
+ assert len(ColorSorter._gl_name_stack) == 1
+ ColorSorter._init_state()
return
_unsuspend_if_needed = staticmethod(_unsuspend_if_needed)
# ==
+
+ def _relative_transforms(): # staticmethod #bruce 090220
+ """
+ Return a list or tuple (owned by caller) of the additional transforms
+ we're presently inside, relative to when start() was called.
+
+ Also do related sanity checks (as assertions).
+ """
+ t1 = ColorSorter._initial_transforms
+ n1 = len(t1)
+
+ t2 = ColorSorter.glpane.transforms # should be same or more
+ n2 = len(t2)
+
+ if n1 < n2:
+ assert t1 == t2[:n1]
+ return tuple(t2[n1:])
+ else:
+ assert n1 <= n2
+ return ()
+ pass
+
+ _relative_transforms = staticmethod(_relative_transforms)
+
+ def _debug_transforms(): # staticmethod #bruce 090220
+ return [ColorSorter._initial_transforms,
+ ColorSorter._relative_transforms()]
+
+ _debug_transforms = staticmethod(_debug_transforms)
+
+ # ==
def pushName(glname):
"""
@@ -794,6 +851,10 @@ class ColorSorter:
Schedule a sphere for rendering whenever ColorSorter thinks is
appropriate.
"""
+ if _DEBUG and ColorSorter._parent_csdl and ColorSorter._parent_csdl.reentrant:
+ print "bare_prim sphere:", ColorSorter._gl_name_stack[-1], \
+ color, pos, radius, ColorSorter._debug_transforms() #####
+
if drawing_globals.use_c_renderer and ColorSorter.sorting:
if len(color) == 3:
lcolor = (color[0], color[1], color[2], opacity)
@@ -850,6 +911,10 @@ class ColorSorter:
Schedule a wiresphere for rendering whenever ColorSorter thinks is
appropriate.
"""
+ if _DEBUG and ColorSorter._parent_csdl and ColorSorter._parent_csdl.reentrant:
+ print "bare_prim wiresphere:", ColorSorter._gl_name_stack[-1], \
+ color, pos, radius, ColorSorter._debug_transforms() #####
+
if drawing_globals.use_c_renderer and ColorSorter.sorting:
if len(color) == 3:
lcolor = (color[0], color[1], color[2], 1.0)
@@ -876,6 +941,10 @@ class ColorSorter:
Schedule a cylinder for rendering whenever ColorSorter thinks is
appropriate.
"""
+ if _DEBUG and ColorSorter._parent_csdl and ColorSorter._parent_csdl.reentrant:
+ print "bare_prim cylinder:", ColorSorter._gl_name_stack[-1], \
+ color, pos1, pos2, radius, capped, ColorSorter._debug_transforms() #####
+
if drawing_globals.use_c_renderer and ColorSorter.sorting:
if len(color) == 3:
lcolor = (color[0], color[1], color[2], 1.0)
@@ -1009,12 +1078,16 @@ class ColorSorter:
# ==
- def start(csdl, pickstate = None): # staticmethod
+ def start(glpane, csdl, pickstate = None): # staticmethod
"""
Start sorting - objects provided to "schedule" and primitives such as
"schedule_sphere" and "schedule_cylinder" will be stored for a sort at
the time "finish" is called.
+ glpane is used for its transform stack. It can be None, but then
+ we will not notice whether primitives we collect are inside
+ any transforms beyond the ones current when we start.
+
csdl is a ColorSortedDisplayList or None, in which case immediate
drawing is done.
@@ -1023,6 +1096,7 @@ class ColorSorter:
#russ 080225: Moved glNewList here for displist re-org.
# (bruce 090114: removed support for use_color_sorted_vbos)
#bruce 090220: support _parent_csdl.reentrant
+ #bruce 090220: added new required first argument glpane
if ColorSorter._parent_csdl and ColorSorter._parent_csdl.reentrant:
assert ColorSorter.sorting
@@ -1035,6 +1109,15 @@ class ColorSorter:
assert ColorSorter._parent_csdl is None #bruce 090105
ColorSorter._parent_csdl = csdl # used by finish()
+ assert ColorSorter.glpane is None
+ if glpane is None:
+ glpane = _the_fake_GLPane
+ assert not glpane.transforms
+ ColorSorter.glpane = glpane
+ ColorSorter._initial_transforms = list(glpane.transforms)
+ if _DEBUG:
+ print "CS.initial transforms:", ColorSorter._debug_transforms() #####
+
if pickstate is not None:
csdl.selectPick(pickstate)
pass
@@ -1090,6 +1173,7 @@ class ColorSorter:
to not draw (the drawing has already happened).
"""
assert ColorSorter.sorting #bruce 090220, appears to be true from this code
+ assert ColorSorter.glpane #bruce 090220
if not ColorSorter._parent_csdl:
#bruce 090220 revised, check _parent_csdl rather than sorting
@@ -1098,6 +1182,7 @@ class ColorSorter:
### WARNING: DUPLICATE CODE with end of this method
# (todo: split out some submethods to clean up)
ColorSorter.sorting = False
+ ColorSorter.glpane = None
ColorSorter._unsuspend_if_needed()
return # Plain immediate-mode, nothing to do.
@@ -1336,6 +1421,8 @@ class ColorSorter:
# Use either the normal-color display list or the selected one.
selected = parent_csdl.selected)
+ ColorSorter.glpane = None
+
ColorSorter._unsuspend_if_needed()
return
diff --git a/cad/src/graphics/model_drawing/ChunkDrawer.py b/cad/src/graphics/model_drawing/ChunkDrawer.py
index 7af2b5160..39daf9e29 100644
--- a/cad/src/graphics/model_drawing/ChunkDrawer.py
+++ b/cad/src/graphics/model_drawing/ChunkDrawer.py
@@ -348,8 +348,8 @@ class ChunkDrawer(TransformedDisplayListsDrawer):
# put it in its place
glPushMatrix()
- try: # do our glPopMatrix no matter what
- self._chunk.applyMatrix()
+ try: # do our popMatrix no matter what
+ self._chunk.applyMatrix(glpane)
##delegate_selection_wireframe = False
delegate_draw_atoms = False
@@ -442,7 +442,7 @@ class ChunkDrawer(TransformedDisplayListsDrawer):
if wantlist:
##print "Regenerating display list for %s" % self.name
match_checking_code = self.begin_tracking_usage()
- ColorSorter.start(self.displist)
+ ColorSorter.start(glpane, self.displist)
# Note: passing self._chunk.picked was needed
# when ColorSorter.finish (below) got
# draw_now = True, but is not needed now
@@ -524,7 +524,7 @@ class ChunkDrawer(TransformedDisplayListsDrawer):
except:
print_compact_traceback("exception in Chunk.draw, continuing: ")
- glPopMatrix()
+ self._chunk.popMatrix(glpane)
glPopName() # pops self._chunk.glname
@@ -698,7 +698,7 @@ class ChunkDrawer(TransformedDisplayListsDrawer):
if use_outer_colorsorter:
# note: not used with ExternalBondSets
- ColorSorter.start(None)
+ ColorSorter.start(glpane, None)
# [why is this needed? bruce 080707 question]
for bond in objects_to_draw:
@@ -900,11 +900,11 @@ class ChunkDrawer(TransformedDisplayListsDrawer):
##### TODO: use glpane.draw_csdl.
if self._has_displist():
apply_material(color) ### REVIEW: still needed?
- self._chunk.pushMatrix()
+ self._chunk.pushMatrix(glpane)
for csdl in ([self.displist] +
[ed.csdl for ed in self.extra_displists.values()]):
csdl.draw(highlighted = True, highlight_color = color)
- self._chunk.popMatrix()
+ self._chunk.popMatrix(glpane)
pass
# piotr 080521: Get display mode for drawing external bonds and/or
@@ -921,7 +921,7 @@ class ChunkDrawer(TransformedDisplayListsDrawer):
# (as was done in older code). (Note that there will soon be
# objects containing display lists for them, and our job will
# be to not draw *those objects* twice, in any one frame.)
- ColorSorter.start(None)
+ ColorSorter.start(glpane, None)
for bond in self._chunk.externs:
bond.draw(glpane, disp, color, drawLevel)
continue
diff --git a/cad/src/graphics/model_drawing/ExternalBondSetDrawer.py b/cad/src/graphics/model_drawing/ExternalBondSetDrawer.py
index 43583e2e8..64564a7a7 100644
--- a/cad/src/graphics/model_drawing/ExternalBondSetDrawer.py
+++ b/cad/src/graphics/model_drawing/ExternalBondSetDrawer.py
@@ -86,7 +86,7 @@ class ExternalBondSetDrawer(TransformedDisplayListsDrawer):
use_outer_colorsorter = True # not sure whether/why this is needed
if use_outer_colorsorter:
- ColorSorter.start(None)
+ ColorSorter.start(glpane, None)
for bond in self._ebset._bonds.itervalues():
bond.draw(glpane, disp, color, drawLevel)
@@ -232,7 +232,7 @@ class ExternalBondSetDrawer(TransformedDisplayListsDrawer):
# print "Regenerating display list for %r (%d)" % \
# (self, env.redraw_counter)
match_checking_code = self.begin_tracking_usage()
- ColorSorter.start(self.displist, c1.picked and c2.picked)
+ ColorSorter.start(glpane, self.displist, c1.picked and c2.picked)
# not sure whether picked arg needed
# protect against exceptions while making display list,
diff --git a/cad/src/graphics/model_drawing/special_drawing.py b/cad/src/graphics/model_drawing/special_drawing.py
index d0fa02d67..f92659a22 100644
--- a/cad/src/graphics/model_drawing/special_drawing.py
+++ b/cad/src/graphics/model_drawing/special_drawing.py
@@ -446,7 +446,7 @@ class ExtraChunkDisplayList(object, SubUsageTrackingMixin):
if wantlist:
match_checking_code = self.begin_tracking_usage()
# note: method defined in superclass, SubUsageTrackingMixin
- ColorSorter.start(self.csdl, selected)
+ ColorSorter.start(glpane, self.csdl, selected)
### REVIEW: is selected arg needed? guess yes,
# since .finish will draw it based on the csdl state
# which is determined by that arg. If so, this point needs
diff --git a/cad/src/graphics/widgets/GLPane_csdl_collector.py b/cad/src/graphics/widgets/GLPane_csdl_collector.py
index b04910186..1ab8379f5 100644
--- a/cad/src/graphics/widgets/GLPane_csdl_collector.py
+++ b/cad/src/graphics/widgets/GLPane_csdl_collector.py
@@ -42,7 +42,11 @@ class GLPane_csdl_collector(_GLPane_csdl_collector_superclass):
For more info, see docstring of GLPane.before_drawing_csdls.
"""
- def __init__(self):
+ def __init__(self, glpane):
+ ## print "\ninit GLPane_csdl_collector", glpane, glpane.drawing_phase
+ self._glpane = glpane
+ # note: this won't be a ref cycle once we're done with,
+ # since glpane won't refer to us anymore then
return
def setup_for_drawingsets(self):
@@ -56,7 +60,7 @@ class GLPane_csdl_collector(_GLPane_csdl_collector_superclass):
"""
"""
self.bare_primitives = ColorSortedDisplayList(reentrant = True)
- ColorSorter.start(self.bare_primitives)
+ ColorSorter.start(self._glpane, self.bare_primitives)
return
def draw_csdl_in_drawingset(self, csdl, intent):
@@ -118,7 +122,7 @@ class fake_GLPane_csdl_collector(_GLPane_csdl_collector_superclass):
"""
Use one of these "between draws" to avoid or mitigate bugs.
"""
- def __init__(self):
+ def __init__(self, glpane):
print_compact_stack(
"warning: fake_GLPane_csdl_collector is being instantiated: " )
return
diff --git a/cad/src/graphics/widgets/GLPane_drawingset_methods.py b/cad/src/graphics/widgets/GLPane_drawingset_methods.py
index f11d9928a..7aa559603 100644
--- a/cad/src/graphics/widgets/GLPane_drawingset_methods.py
+++ b/cad/src/graphics/widgets/GLPane_drawingset_methods.py
@@ -15,6 +15,8 @@ Part.after_drawing_model.
from utilities.debug_prefs import debug_pref
from utilities.debug_prefs import Choice_boolean_False
+from utilities.debug import print_compact_traceback
+
from graphics.drawing.DrawingSet import DrawingSet
from graphics.widgets.GLPane_csdl_collector import GLPane_csdl_collector
@@ -44,10 +46,25 @@ class GLPane_drawingset_methods(object):
Initialize self._csdl_collector if necessary, and return it.
"""
- if not self._csdl_collector:
- self._csdl_collector = self._csdl_collector_class()
- # note: self._csdl_collector_class changes dynamically
- return self._csdl_collector
+ try:
+ ## print "__get_csdl_collector", self
+ if not self._csdl_collector:
+ ## print "alloc in __get_csdl_collector", self
+ self._csdl_collector = self._csdl_collector_class( self)
+ # note: self._csdl_collector_class changes dynamically
+ return self._csdl_collector
+ except:
+ # without this try/except, python will report any exception in here
+ # (or at least any AttributeError) as if it was an AttributeError
+ # on self.csdl_collector, discarding all info about the nature
+ # and code location of the actual error! [bruce 090220]
+ ### TODO: flush all output streams in print_compact_traceback;
+ # in current code, the following prints before we finish printing
+ # whatever print statement had the exception partway through, if one did
+ print_compact_traceback("\nfollowing exception is *really* this one, inside __get_csdl_collector: ")
+ print
+ raise
+ pass
def __set_csdl_collector(self):
"""
@@ -59,6 +76,7 @@ class GLPane_drawingset_methods(object):
"""
del method for self.csdl_collector property
"""
+ ## print "\ndel csdl_collector", self
self._csdl_collector = None
csdl_collector = property(__get_csdl_collector, __set_csdl_collector, __del_csdl_collector)
diff --git a/cad/src/graphics/widgets/GLPane_minimal.py b/cad/src/graphics/widgets/GLPane_minimal.py
index 317482d13..f693ee583 100644
--- a/cad/src/graphics/widgets/GLPane_minimal.py
+++ b/cad/src/graphics/widgets/GLPane_minimal.py
@@ -142,6 +142,9 @@ class GLPane_minimal(QGLWidget, GLPane_drawingset_methods, object): #bruce 07091
_resize_counter = 0
+ drawing_phase = '?' # overridden in GLPane_rendering_methods, but needed for
+ # debug prints that might happen in any class of GLPane [bruce 090220]
+
# default values of subclass-specific constants
permit_draw_bond_letters = True #bruce 071023
@@ -193,6 +196,17 @@ class GLPane_minimal(QGLWidget, GLPane_drawingset_methods, object): #bruce 07091
# piotr 080807
# Most recent quaternion to be used in animation timer.
self.last_quat = None
+
+ self.transforms = [] ### TODO: clear this at start of frame, complain if not clear
+ # stack of current transforms (or Nodes that generate them)
+ # [bruce 090220]
+ # Note: this may be revised once we have TransformNode,
+ # e.g. we might push their dt and st separately;
+ # note we might need to push a "slot" for them if they might
+ # change before being popped, or perhaps even if they might
+ # change between the time pushed and the time later used
+ # (by something that collects them from here in association
+ # with a ColorSortedDisplayList).
return
diff --git a/cad/src/model/bonds.py b/cad/src/model/bonds.py
index 7538e75cd..276833b6b 100755
--- a/cad/src/model/bonds.py
+++ b/cad/src/model/bonds.py
@@ -2201,7 +2201,7 @@ class Bond(BondBase, StateMixin, Selobj_API): #bruce 041109 partial rewrite
if mol is mol2:
# internal bond; geometric info is stored in chunk-relative
# coords; we need mol's help to use those
- mol.pushMatrix()
+ mol.pushMatrix(glpane)
self.draw(glpane, mol.get_dispdef(glpane), color, mol.assy.drawLevel,
highlighted )
# sorry for all the kluges (e.g. 1 or 2 of those args) that beg for
@@ -2218,7 +2218,7 @@ class Bond(BondBase, StateMixin, Selobj_API): #bruce 041109 partial rewrite
#commit, same day, GLPane.py (sort selobj candidates) and this
#file (don't shorten_tubes next to singlets [later moved to
#bond_drawer.py]), this has been fixed.
- mol.popMatrix()
+ mol.popMatrix(glpane)
else:
# external bond -- draw it at max dispdef of those from its mols
disp = max( mol.get_dispdef(glpane), mol2.get_dispdef(glpane) )
diff --git a/cad/src/model/chem.py b/cad/src/model/chem.py
index d125e20e6..a63ff4614 100755
--- a/cad/src/model/chem.py
+++ b/cad/src/model/chem.py
@@ -2530,7 +2530,7 @@ class Atom( PAM_Atom_methods, AtomBase, InvalMixin, StateMixin, Selobj_API):
#does seem to work. Note that it needs testing for rotated chunks,
#since until you next modify them, the wirespheres are also drawn
#rotated.)
- self.molecule.pushMatrix()
+ self.molecule.pushMatrix(glpane)
try:
# note: the following inlines self.drawing_radius(picked_Radius = True),
# but makes further use of intermediate values which that method
@@ -2551,7 +2551,7 @@ class Atom( PAM_Atom_methods, AtomBase, InvalMixin, StateMixin, Selobj_API):
print_compact_traceback("exception in draw_wirespheres " \
"part of draw_in_abs_coords ignored: ")
pass
- self.molecule.popMatrix()
+ self.molecule.popMatrix(glpane)
return
def drawing_radius(self, picked_radius = False):
diff --git a/cad/src/model/chunk.py b/cad/src/model/chunk.py
index f9544bb43..068e6b8f0 100755
--- a/cad/src/model/chunk.py
+++ b/cad/src/model/chunk.py
@@ -566,36 +566,58 @@ class Chunk(Chunk_Dna_methods, Chunk_mmp_methods,
# [bruce 090212 moved all these back to class Chunk;
# they're often called externally]
- def pushMatrix(self):
+ def pushMatrix(self, glpane):
"""
- Do glPushMatrix(),
- then transform from (presumed) world coordinates
- to self's private coordinates.
+ Do glPushMatrix(), then transform from (presumed) world coordinates
+ to self's private coordinates. Also tell glpane this was done
+ (for more info and requirements see docstring of applyMatrix).
+
@see: self.applyMatrix()
@see: self.popMatrix()
"""
glPushMatrix()
- self.applyMatrix()
+ self.applyMatrix(glpane)
return
- def applyMatrix(self):
+ def applyMatrix(self, glpane):
"""
- Without doing glPushMatrix(),
- transform from (presumed) world coordinates
- to self's private coordinates.
+ Without doing glPushMatrix(), transform the current GL matrix state
+ from (presumed) world coordinates to self's private coordinates.
+
+ This is only permitted in 1-1 correspondence with a call
+ (just done by caller) of either self.pushMatrix(glpane)
+ or glPushMatrix(). I.e. two calls in a row of self.applyMatrix
+ are illegal. This is not checked; errors in this will
+ cause some things to be drawn in the wrong place.
+
+ glpane must correspond to the current GL context.
+
+ Also tell glpane that a push/apply of self's coordinate system has
+ just been done, in case deferred drawing done after this call
+ wants to know how to reproduce the current GL matrix state later
+ (or more precisely, the current *symbolic* state -- i.e. which local
+ coordinate systems are pushed, even if their value when used later
+ differs from their current value). (This is why we require 1-1
+ correspondence between push and apply.)
+
@see: self.pushMatrix()
"""
origin = self.basecenter
glTranslatef(origin[0], origin[1], origin[2])
q = self.quat
glRotatef(q.angle * 180.0 / math.pi, q.x, q.y, q.z)
+ glpane.transforms += [self]
return
- def popMatrix(self):
+ def popMatrix(self, glpane):
"""
- Undo the effect of self.pushMatrix().
+ Undo the effect of self.pushMatrix(glpane). Also tell glpane this was
+ done (for more info and requirements see docstring of applyMatrix).
"""
glPopMatrix()
+ assert glpane.transforms[-1] is self
+ glpane.transforms.pop()
+ return
# ==
diff --git a/cad/src/prototype/test_drawing.py b/cad/src/prototype/test_drawing.py
index 7b51fdcdd..f1e0d9b50 100644
--- a/cad/src/prototype/test_drawing.py
+++ b/cad/src/prototype/test_drawing.py
@@ -383,7 +383,7 @@ def test_drawing(glpane, initOnly = False):
(nSpheres, "ColorSorter"))
test_csdl = ColorSortedDisplayList()
- ColorSorter.start(test_csdl)
+ ColorSorter.start(None, test_csdl)
drawsphere([0.5, 0.5, 0.5], # color
[0.0, 0.0, 0.0], # pos
.5, # radius
@@ -986,7 +986,7 @@ def test_drawing(glpane, initOnly = False):
# Test selection using the CSDL glname.
ColorSorter.pushName(csdl.glname)
- ColorSorter.start(csdl)
+ ColorSorter.start(None, csdl)
for (color, center, radius) in zip(colors, centers, radii):
if not doCylinders:
# Through ColorSorter to the sphere primitive buffer...