def _draw_jig(self, glpane, color, highlighted = False): """ [overrides superclass method] """ del color self._update_props() if not self._should_draw(): return drawrad = 0.1 posns = [a.posn() for a in self.atoms] normcolor = self._drawing_color() # russ 080530: Support for patterned highlighting drawing modes. selected = self.picked patterned = isPatternedDrawing(select = selected, highlight = highlighted) if patterned: # Patterned selection drawing needs the normal drawing first. drawcylinder( normcolor, posns[0], posns[1], drawrad) startPatternedDrawing(select = selected, highlight = highlighted) pass # Draw solid color, or overlay pattern in highlight or selection color. drawcylinder( (highlighted and env.prefs[hoverHighlightingColor_prefs_key] or selected and env.prefs[selectionColor_prefs_key] or normcolor), posns[0], posns[1], drawrad) if patterned: # Reset from patterned drawing mode. endPatternedDrawing(select = selected, highlight = highlighted) pass return
def _draw_jig(self, glpane, color, highlighted=False): """ [overrides superclass method] """ del color self._update_props() if not self._should_draw(): return drawrad = 0.1 posns = [a.posn() for a in self.atoms] normcolor = self._drawing_color() # russ 080530: Support for patterned highlighting drawing modes. selected = self.picked patterned = isPatternedDrawing(select=selected, highlight=highlighted) if patterned: # Patterned selection drawing needs the normal drawing first. drawcylinder(normcolor, posns[0], posns[1], drawrad) startPatternedDrawing(select=selected, highlight=highlighted) pass # Draw solid color, or overlay pattern in highlight or selection color. drawcylinder( (highlighted and env.prefs[hoverHighlightingColor_prefs_key] or selected and env.prefs[selectionColor_prefs_key] or normcolor), posns[0], posns[1], drawrad) if patterned: # Reset from patterned drawing mode. endPatternedDrawing(select=selected, highlight=highlighted) pass return
def draw( self, highlighted=False, selected=False, patterning=True, highlight_color=None, draw_shader_primitives=True, #bruce 090312 renamed from draw_primitives transform_nonshaders=True, #bruce 090312 renamed from transform_DLs ): """ 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_shader_primitives: Whether to draw our shader primitives. Defaults to True. @param transform_nonshaders: Whether to apply self.transformControl to our non-shader drawing (such as DLs). 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) # KLUGES which should be replaced by our having suitable new attrs, # such as glpane or glprefs or glresourcecontext (replacing drawing_globals): drawing_phase = drawing_globals.drawing_phase # kluge in CSDL.draw # (the other kluge is not having glpane.glprefs to pass to apply_material, # in draw; we do have glpane in finish but no point in using it there # until we have it in .draw too, preferably by attr rather than arg # (should review that opinion).) # Russ 081128 (clarified, bruce 090218): # # GLPrimitiveSet.draw() calls this method (CSDL.draw) on the CSDLs # in its _CSDLs_with_nonshader_drawing attribute (a list of CSDLs), # passing draw_shader_primitives = False to only draw the DLs, and # transform_nonshaders = False to avoid redundantly applying their # TransformControls. # # It gathers the shader 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_phase != "glselect" and draw_shader_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_primitive_lists(): self.drawIndices[shader] = shader.makeDrawIndex(primitives) continue pass pass if self._drawing_funcs and drawing_phase != "glselect_glname_color": #bruce 090312 # These ignore our drawing-style args; # they also are cleared independently of start/finish, # and changing them doesn't set our last-changed timestamp. # All this is intentional. (Though we might decide to add a kind # which does participate in patterned drawing; this might require # supplying more than one func, or a dict of colors and nocolor # funcs....) if self.transformControl and transform_nonshaders: glPushMatrix() self.transformControl.applyTransform() for func in self._drawing_funcs: try: func() except: msg = "bug: exception in drawing_func %r in %r, skipping it" % ( func, self) print_compact_traceback(msg + ": ") pass continue if self.transformControl and transform_nonshaders: glPopMatrix() 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_phase != "glselect_glname_color" and self.has_nonempty_DLs()) # the following might be changed, then are used repeatedly below; # this simplifies the various ways we can handle transforms [bruce 090224] callList = glCallList # how to call a DL, perhaps inside our transform transform_once = False # whether to transform exactly once around the # following code (as opposed to not at all, or once per callList) if self.transformControl and transform_nonshaders: if prims_to_do and DLs_to_do: # shader primitives have transform built in, but DLs don't, # so we need to get in and out of local coords repeatedly # (once for each callList) during the following # (note similar code in DrawingSet.draw): [bruce 090224] callList = self._callList_inside_transformControl elif DLs_to_do: # we need to get into and out of local coords just once transform_once = True else: pass # nothing special needed for just shader prims (or nothing) pass if transform_once: glPushMatrix() self.transformControl.applyTransform() 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. callList(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: callList(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.) if highlight_color is not None: hcolor = highlight_color else: hcolor = env.prefs[hoverHighlightingColor_prefs_key] apply_material(hcolor) callList(self.nocolor_dl) if patterned_highlighting: # Reset from a patterned drawing mode set up above. endPatternedDrawing(highlight=highlighted) pass pass pass if transform_once: glPopMatrix() return
def finish(self, sorted_by_color): #bruce 090224 split this out of caller """ Finish collecting new primitives for use in self, and store them all in self, ready to be drawn in various ways. [meant to be called only by ColorSorter.start, for now] """ ## self._reset() ## # (note: this deallocates any existing display lists) if self.transformControl and (self.spheres or self.cylinders): self.updateTransform() # needed to do the transform for the first time, # even if it didn't change. Review: refactor to # whereever we first compile these down? That # might be a different place in self.draw vs. # draw from DrawingSet. selColor = env.prefs[selectionColor_prefs_key] # Note: if sorted_by_color is empty, current code still builds all # toplevel display lists, though they are noops. This may be needed # by some client code which uses those dls directly. Client code # wanting to know if it needs to draw our dls should test # self.has_nonempty_DLs(), which tests self._per_color_dls, # or self.has_nonshader_drawing(), which reports on that or any # other kind of nonshader (immediate mode opengl) drawing we might # have. [bruce 090225/090312 comment] # First build the lower level per-color sublists of primitives. for color, funcs in sorted_by_color.iteritems(): sublists = [glGenLists(1), 0] # Remember the display list ID for this color. self._per_color_dls.append([color, sublists]) glNewList(sublists[0], GL_COMPILE) opacity = color[3] if opacity == -1: #russ 080306: "Unshaded colors" for lines are signaled # by an opacity of -1 (4th component of the color.) glDisable(GL_LIGHTING) # Don't forget to re-enable it! pass for func, params, name in funcs: if name: glPushName(name) else: pass ## print "bug_2: attempt to push non-glname", name func(params) # Call the draw worker function. if name: glPopName() pass continue if opacity == -1: # Enable lighting after drawing "unshaded" objects. glEnable(GL_LIGHTING) pass glEndList() if opacity == -2: # piotr 080419: Special case for drawpolycone_multicolor # create another display list that ignores # the contents of color_array. # Remember the display list ID for this color. sublists[1] = glGenLists(1) glNewList(sublists[1], GL_COMPILE) for func, params, name in funcs: if name: glPushName(name) else: pass ## print "bug_3: attempt to push non-glname", name if func == drawpolycone_multicolor_worker: # Just to be sure, check if the func # is drawpolycone_multicolor_worker # and call drawpolycone_worker instead. # I think in the future we can figure out # a more general way of handling the # GL_COLOR_MATERIAL objects. piotr 080420 pos_array, color_array_junk, rad_array = params drawpolycone_worker((pos_array, rad_array)) elif func == drawtriangle_strip_worker: # piotr 080710: Multi-color modification # for triangle_strip primitive (used by # reduced protein style). pos_array, normal_array, color_array_junk = params drawtriangle_strip_worker( (pos_array, normal_array, None)) if name: glPopName() pass continue glEndList() continue # Now the upper-level lists call all of the per-color sublists. #### REVIEW: these are created even when empty. Is that necessary? # [bruce 090224 Q] # One with colors. color_dl = self.color_dl = glGenLists(1) glNewList(color_dl, GL_COMPILE) for color, dls in self._per_color_dls: opacity = color[3] if opacity < 0: #russ 080306: "Unshaded colors" for lines are signaled # by a negative alpha. glColor3fv(color[:3]) # piotr 080417: for opacity == -2, i.e. if # GL_COLOR_MATERIAL is enabled, the color is going # to be ignored, anyway, so it is not necessary # to be tested here else: apply_material(color) glCallList(dls[0]) continue glEndList() # A second one without any colors. nocolor_dl = self.nocolor_dl = glGenLists(1) glNewList(nocolor_dl, GL_COMPILE) for color, dls in self._per_color_dls: opacity = color[3] if opacity == -2 \ and dls[1] > 0: # piotr 080420: If GL_COLOR_MATERIAL is enabled, # use a regular, single color dl rather than the # multicolor one. Btw, dls[1] == 0 should never # happen. glCallList(dls[1]) else: glCallList(dls[0]) glEndList() # A third DL implements the selected appearance. selected_dl = self.selected_dl = glGenLists(1) glNewList(selected_dl, GL_COMPILE) # russ 080530: Support for patterned selection drawing modes. patterned = isPatternedDrawing(select=True) if patterned: # Patterned drawing needs the colored dl drawn first. glCallList(color_dl) startPatternedDrawing(select=True) pass # Draw solid color (unpatterned) or an overlay pattern, in the # selection color. apply_material(selColor) glCallList(nocolor_dl) if patterned: # Reset from patterning drawing mode. endPatternedDrawing(select=True) glEndList() pass
def draw( self, highlighted=False, selected=False, patterning=True, highlight_color=None, draw_shader_primitives=True, # bruce 090312 renamed from draw_primitives transform_nonshaders=True, # bruce 090312 renamed from transform_DLs ): """ 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_shader_primitives: Whether to draw our shader primitives. Defaults to True. @param transform_nonshaders: Whether to apply self.transformControl to our non-shader drawing (such as DLs). 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 # KLUGES which should be replaced by our having suitable new attrs, # such as glpane or glprefs or glresourcecontext (replacing drawing_globals): drawing_phase = drawing_globals.drawing_phase # kluge in CSDL.draw # (the other kluge is not having glpane.glprefs to pass to apply_material, # in draw; we do have glpane in finish but no point in using it there # until we have it in .draw too, preferably by attr rather than arg # (should review that opinion).) # Russ 081128 (clarified, bruce 090218): # # GLPrimitiveSet.draw() calls this method (CSDL.draw) on the CSDLs # in its _CSDLs_with_nonshader_drawing attribute (a list of CSDLs), # passing draw_shader_primitives = False to only draw the DLs, and # transform_nonshaders = False to avoid redundantly applying their # TransformControls. # # It gathers the shader 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_phase != "glselect" and draw_shader_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_primitive_lists(): self.drawIndices[shader] = shader.makeDrawIndex(primitives) continue pass pass if self._drawing_funcs and drawing_phase != "glselect_glname_color": # bruce 090312 # These ignore our drawing-style args; # they also are cleared independently of start/finish, # and changing them doesn't set our last-changed timestamp. # All this is intentional. (Though we might decide to add a kind # which does participate in patterned drawing; this might require # supplying more than one func, or a dict of colors and nocolor # funcs....) if self.transformControl and transform_nonshaders: glPushMatrix() self.transformControl.applyTransform() for func in self._drawing_funcs: try: func() except: msg = "bug: exception in drawing_func %r in %r, skipping it" % (func, self) print_compact_traceback(msg + ": ") pass continue if self.transformControl and transform_nonshaders: glPopMatrix() 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_phase != "glselect_glname_color" and self.has_nonempty_DLs() # the following might be changed, then are used repeatedly below; # this simplifies the various ways we can handle transforms [bruce 090224] callList = glCallList # how to call a DL, perhaps inside our transform transform_once = False # whether to transform exactly once around the # following code (as opposed to not at all, or once per callList) if self.transformControl and transform_nonshaders: if prims_to_do and DLs_to_do: # shader primitives have transform built in, but DLs don't, # so we need to get in and out of local coords repeatedly # (once for each callList) during the following # (note similar code in DrawingSet.draw): [bruce 090224] callList = self._callList_inside_transformControl elif DLs_to_do: # we need to get into and out of local coords just once transform_once = True else: pass # nothing special needed for just shader prims (or nothing) pass if transform_once: glPushMatrix() self.transformControl.applyTransform() 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. callList(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: callList(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.) if highlight_color is not None: hcolor = highlight_color else: hcolor = env.prefs[hoverHighlightingColor_prefs_key] apply_material(hcolor) callList(self.nocolor_dl) if patterned_highlighting: # Reset from a patterned drawing mode set up above. endPatternedDrawing(highlight=highlighted) pass pass pass if transform_once: glPopMatrix() return
def finish(self, sorted_by_color): # bruce 090224 split this out of caller """ Finish collecting new primitives for use in self, and store them all in self, ready to be drawn in various ways. [meant to be called only by ColorSorter.start, for now] """ ## self._reset() ## # (note: this deallocates any existing display lists) if self.transformControl and (self.spheres or self.cylinders): self.updateTransform() # needed to do the transform for the first time, # even if it didn't change. Review: refactor to # whereever we first compile these down? That # might be a different place in self.draw vs. # draw from DrawingSet. selColor = env.prefs[selectionColor_prefs_key] # Note: if sorted_by_color is empty, current code still builds all # toplevel display lists, though they are noops. This may be needed # by some client code which uses those dls directly. Client code # wanting to know if it needs to draw our dls should test # self.has_nonempty_DLs(), which tests self._per_color_dls, # or self.has_nonshader_drawing(), which reports on that or any # other kind of nonshader (immediate mode opengl) drawing we might # have. [bruce 090225/090312 comment] # First build the lower level per-color sublists of primitives. for color, funcs in sorted_by_color.iteritems(): sublists = [glGenLists(1), 0] # Remember the display list ID for this color. self._per_color_dls.append([color, sublists]) glNewList(sublists[0], GL_COMPILE) opacity = color[3] if opacity == -1: # russ 080306: "Unshaded colors" for lines are signaled # by an opacity of -1 (4th component of the color.) glDisable(GL_LIGHTING) # Don't forget to re-enable it! pass for func, params, name in funcs: if name: glPushName(name) else: pass ## print "bug_2: attempt to push non-glname", name func(params) # Call the draw worker function. if name: glPopName() pass continue if opacity == -1: # Enable lighting after drawing "unshaded" objects. glEnable(GL_LIGHTING) pass glEndList() if opacity == -2: # piotr 080419: Special case for drawpolycone_multicolor # create another display list that ignores # the contents of color_array. # Remember the display list ID for this color. sublists[1] = glGenLists(1) glNewList(sublists[1], GL_COMPILE) for func, params, name in funcs: if name: glPushName(name) else: pass ## print "bug_3: attempt to push non-glname", name if func == drawpolycone_multicolor_worker: # Just to be sure, check if the func # is drawpolycone_multicolor_worker # and call drawpolycone_worker instead. # I think in the future we can figure out # a more general way of handling the # GL_COLOR_MATERIAL objects. piotr 080420 pos_array, color_array_junk, rad_array = params drawpolycone_worker((pos_array, rad_array)) elif func == drawtriangle_strip_worker: # piotr 080710: Multi-color modification # for triangle_strip primitive (used by # reduced protein style). pos_array, normal_array, color_array_junk = params drawtriangle_strip_worker((pos_array, normal_array, None)) if name: glPopName() pass continue glEndList() continue # Now the upper-level lists call all of the per-color sublists. #### REVIEW: these are created even when empty. Is that necessary? # [bruce 090224 Q] # One with colors. color_dl = self.color_dl = glGenLists(1) glNewList(color_dl, GL_COMPILE) for color, dls in self._per_color_dls: opacity = color[3] if opacity < 0: # russ 080306: "Unshaded colors" for lines are signaled # by a negative alpha. glColor3fv(color[:3]) # piotr 080417: for opacity == -2, i.e. if # GL_COLOR_MATERIAL is enabled, the color is going # to be ignored, anyway, so it is not necessary # to be tested here else: apply_material(color) glCallList(dls[0]) continue glEndList() # A second one without any colors. nocolor_dl = self.nocolor_dl = glGenLists(1) glNewList(nocolor_dl, GL_COMPILE) for color, dls in self._per_color_dls: opacity = color[3] if opacity == -2 and dls[1] > 0: # piotr 080420: If GL_COLOR_MATERIAL is enabled, # use a regular, single color dl rather than the # multicolor one. Btw, dls[1] == 0 should never # happen. glCallList(dls[1]) else: glCallList(dls[0]) glEndList() # A third DL implements the selected appearance. selected_dl = self.selected_dl = glGenLists(1) glNewList(selected_dl, GL_COMPILE) # russ 080530: Support for patterned selection drawing modes. patterned = isPatternedDrawing(select=True) if patterned: # Patterned drawing needs the colored dl drawn first. glCallList(color_dl) startPatternedDrawing(select=True) pass # Draw solid color (unpatterned) or an overlay pattern, in the # selection color. apply_material(selColor) glCallList(nocolor_dl) if patterned: # Reset from patterning drawing mode. endPatternedDrawing(select=True) glEndList() pass