Draw To Screen Space Foreground From DrawViewportWires

Any idea, why the code does not work in the new Script (neither CPython or Python 3) component of Rhino Beta?

There are no errors, but also no HUD…

That’s because the new script editor does not have a GHPython SDK mode equivalent yet:

See also this topic:

Note that you can still use the current GHPython component in Rhino 8. It’s been marked as deprecated and is therefore hidden. Here’s a how to find it:

2 Likes

Thank you for this excellent and helpful answer!

1 Like

Hey @AndersDeleuran, I did not quite understand. How would this solve the issue of the permanence of the 2D drawings? I am not so familiar with the software structure…

Btw thank you guys for your codes… Now made my own plot, super userful (and beautiful IMO hehe)
Thank you!

(although the plot still cant be deleted and for some reason the domain input does not update when changed, only the txt input… used the C# version, as I was too confused with Python…)

2 Likes

The GH_Component class currently has the DrawViewportMeshes and DrawViewportWires methods:

That we can override in both C# and GHPython scripting components. Giving us a simple and unified method for implementing all the fabulous drawing methods provided by the DisplayPipeline class. Because the DrawViewportMeshes and DrawViewportWires methods handle all the events etc. for us, which can otherwise be quite tricky and tedious. The proposal is then to expand this by also adding DrawForeground as a standard override, which would hopefully negate the issues you are seeing.

For posterity, I did a bit more testing and cobbled together what appears to resolve this. Basically, getting rid of the hack to pipe into DrawViewportWires and instead run a conditional statement in DrawForeground that checks if the component preview is on, that we are in the correct Grasshopper document (basically the same as Giulios original solution, doh!), and in the active Rhino view:


230927_ScreenLegendDebug_00.gh (8.0 KB)

Edit: Updated to also check if the component is locked before drawing, cheers @antoinemaes

8 Likes

Amazing and very straightforward solution. I am trying to implement it my C# script, but could not find the documentation for the ghenv. “methods” (is this even the correct term)
Tried to find it in the RhinoCommon API and the Grasshopper SDK…

I believe ghenv.Component would be this.Component in a C# scripting component.

1 Like

Thanks a lot, works perfect.

There are still some strange bugs:

  1. The title of the legend can be updated via the input
  2. The legend values not for some reason I do not understand

Ad. 2: They are only updated when the code is being rerun. However, it then overlaps the old inputs, as can be seen here.

i tried to implement sth like the Redraw method, but was not successful in calling it.

230927_HUD.gh (10.6 KB)

edit: i found the solution, the values have to be cleared whenever the RunScript is called with

plotValues.Clear();
plotColors.Clear();

@stevebaer, any ideas how the scaling issue with ViewCaptureToFile can be solved? Without this being resolved, one can really only take random screenshots. A fixed image size is impossible to achieve, as one always has to capture the current viewport dimensions…

Cheers,
Rudi

hi @rudolf.neumerkel
@Mahdiyar
i Developed this script but i want to use in Rhino7 c# also
do you Convert it to c# old Script ?
230927_HUD.-ver2gh.gh (24.1 KB)

Hey, I don’t really understand your question. If you want to make it work with the od script component, you basically have to copy/paste the code and just take care of the predefined code of the V7 script editor.

Sorry for goes away from original thread a bit.

I`m trying to duplicate this code in Rhino Python, but it shows nothing and no error info return. And strings from rc.RhinoApp.WriteLine are also not printed.

I think DrawForeground func may not registered to rc.Display.DisplayPipeline.DrawForeground, May I get some suggestion in this case? Here is the code:

import System
import Rhino as rc
import rhinoscriptsyntax as rs

def DrawForeground(sender,arg):
    rc.RhinoApp.WriteLine("A 3")
    
    # Check component preview/locked, active GH document and Rhino viewport
    if arg.Viewport.Id == arg.RhinoDoc.ActiveDoc.Views.ActiveView.ActiveViewportID:
        
        rc.RhinoApp.WriteLine("A 4")
        
        # Text is drawn in front of mesh
        txt = "a"
        pt = rc.Geometry.Point2d(180,100)
        arg.Display.Draw2dText(txt,System.Drawing.Color.Black,pt,False,100,"Consolas")
        
        # Rectangle is drawn in front of mesh
        rec2d = System.Drawing.Rectangle(50,100,100,100)
        arg.Display.Draw2dRectangle(rec2d,System.Drawing.Color.Black,10,System.Drawing.Color.Red)
     
rc.Display.DisplayPipeline.DrawForeground += DrawForeground
rs.GetString("listen to mouse down")
rc.Display.DisplayPipeline.DrawForeground -= DrawForeground

This has been solved by just adding redraw().

I added a
bool IsInTiledDraw(out System.Drawing.Size fullSize, out System.Drawing.Rectangle currentTile)
function to the DisplayPipeline class.

This will be available in Rhino 8.2

So this means, that the tiling error that occurred when changing the display resolution, is now fixed?

This means that people can now detect that tiled captures are occurring and take the appropriate action to avoid repeated output in every tile.

This code works great, thank you for sharing it!

1 Like

Hi Thomas,
To take a screenshot from the Grasshopper viewport, use the following Python code. By adding a Boolean toggle to the _capture input, only the active view will be captured. This approach ensures you won’t encounter the previous issue.

Inputs:

file_name
folder
viewport

width_
height_
mode_
transparent_
_capture

ghenv.Component.Name = 'LB Capture View'
ghenv.Component.NickName = 'CaptureView'
ghenv.Component.Message = '1.2.0'
ghenv.Component.Category = 'Ladybug'
ghenv.Component.SubCategory = '4 :: Extra'
ghenv.Component.AdditionalHelpFromDocStrings = '2'

import os

try:
    from ladybug.futil import preparedir
    from ladybug.config import folders
except ImportError as e:
    raise ImportError('\nFailed to import ladybug:\n\t{}'.format(e))

try:
    from ladybug_rhino.grasshopper import all_required_inputs, bring_to_front
    from ladybug_rhino.viewport import viewport_by_name, capture_view
except ImportError as e:
    raise ImportError('\nFailed to import ladybug_rhino:\n\t{}'.format(e))


if all_required_inputs(ghenv.Component) and _capture:
    # ensure the component runs last on the canvas
    bring_to_front(ghenv.Component)

    # prepare the folder
    folder = _folder_ if _folder_ is not None else \
        os.path.join(folders.ladybug_tools_folder, 'resources', 'captured_views')
    preparedir(folder, remove_content=False)

    # get the viewport objects
    vp_names = viewport_ if len(viewport_) != 0 else [None]
    viewports = [viewport_by_name(vp) for vp in vp_names]

    # save the viewports to images
    for i, view_p in enumerate(viewports):
        f_name = _file_name if len(viewports) == 1 else \
            '{}_{}'.format(_file_name, vp_names[i])
        file_p = os.path.join(folder, f_name)
        fp = capture_view(view_p, file_p, width_, height_, mode_, transparent_)
        print(fp)

hope it will work with you.
Ahmad