Would anyone else be interested in the ability to set the Draw Order on the Custom Preview component?
I know we can set the draw order of objects with the new Drafting Attributes of the Model Object data type and this works great if the intention is to bake the geometry.
However, it would be very beneficial to expose this functionality extended to the Custom Preview component to create ease of use in highlighting objects without Z-Fighting, previewing Model Hatches or Surfaces acting as solid model hatches (by nature of having a draw order above the occluding geometry), and for many other debugging and diagrammatic purposes.
Currently my workflow entails creating and baking lots of geometry for “display/diagramming” purposes that has no Geometrical reason to exist outside of the Display Pipeline and is really only hogging resources and file space by being baked into the model to be “displayed”.
So of course the Custom Preview component works great for these elements but the ability to control draw order is still needed for said elements.
When you are previewing GH objects it actually works this way already, bringing the selected object to the foreground:
Here’s my attempt so far with a python component and while this does handle the solid fill portion, I can’t seem to get the draw order to bring itself to the foreground.
from ghpythonlib.componentbase import executingcomponent as component
import Grasshopper
import System
from System.Drawing import Color
import Rhino as rh
class CustomDisplayDrawOrder(component):
def RunScript(self, M, C):
self.meshes = M # M is a list of meshes
# Set Display Color
self.material = rh.Display.DisplayMaterial(Color.Black)
self.material.Emission = C
# Add event handlers for drawing
rh.Display.DisplayPipeline.CalculateBoundingBox += self.CalculateBoundingBox
rh.Display.DisplayPipeline.PostDrawObjects += self.DrawViewportMeshes
def CalculateBoundingBox(self, sender, e):
for mesh in self.meshes:
e.IncludeBoundingBox(mesh.GetBoundingBox(True))
def DrawViewportMeshes(self, sender, e):
for mesh in self.meshes:
e.Display.DrawMeshShaded(mesh, self.material)
def __del__(self):
# Remove event handlers when the component is deleted
rh.Display.DisplayPipeline.CalculateBoundingBox -= self.CalculateBoundingBox
rh.Display.DisplayPipeline.PostDrawObjects -= self.DrawViewportMeshes
def __exit__(self):
# Handle Draw Order
rh.Display.DisplayPipeline.DrawForeground -= self.DrawViewportMeshes
def __enter__(self):
# Handle Draw Order - Draw In Foreground
rh.Display.DisplayPipeline.DrawForeground += self.DrawViewportMeshes
@AndersDeleuran I cannibalized bits of your code from this post and then tried to utilize the draw foreground method you shared with me in this post here but can’t seem to get it to apply properly to this implementation above. I also attempted to clear the display with this method you shared but I think I’m just muddying the logic trying to combine everything…
Essentially I am looking to mimic the “shaded” functionality of a color input with a custom preview component while controlling the draw order to the foreground or background.
Okay, I went back to some previous posts @AndersDeleuran shared such as this one:
And figured it out.
Here’s the updated Python code if anyone is interested:
from ghpythonlib.componentbase import executingcomponent as component
import Grasshopper
import System
from System.Drawing import Color
import Rhino as rh
class CustomDisplayForeground(component):
def RunScript(self, O, M):
# M is a list of meshes
self.meshes = O
# Set Display Color
self.material = rh.Display.DisplayMaterial(Color.Black)
self.material.Emission = M
#Setup Objects To Be Drawn
def DrawForeground(self, sender, arg):
if self.drawingWires:
self.drawingWires = False
for mesh in self.meshes:
arg.Display.DrawMeshShaded(mesh, self.material)
def DrawViewportWires (self,arg):
self.drawingWires = True
#Handle Draw Foreground Events
def __exit__(self):
rh.Display.DisplayPipeline.DrawForeground -= self.DrawForeground
def __enter__(self):
rh.Display.DisplayPipeline.DrawForeground += self.DrawForeground
Just a quick sidenote/tip: When drawing 3D meshes with overlapping faces, I typically use Mesh.Offset to slightly offset them away from each other, like how the real world objects would stack to prevent Z-fighting. It’s a brute force solution, but it does the trick and is pretty fast to compute
Thanks @AndersDeleuran , this is the method I’ve been using for Floor Plan hatching and such prior to R8 Draw Order on the Drafting Attributes was implemented. And I still need this in cases like room diagram coloring where I want the colors “contained” in the rooms so I can’t draw to foreground but the offset is needed, as you mentioned, to prevent the Z-Fighting
With this drawForeground method it appears to have no Z-fighting since it’s layering itself Infront of the other objects in the display pipeline, is that correct?
Thanks for sharing! It seems that Display Conduits in general are where I need to spend time reading as there’s a lot of possibilities packed in there