C# Hide profiler overlay for certain components

Dear GH folks, dear David,

I’ve implemented a couple of custom component attributes to have sliders, buttons and other controls on top of Grasshopper components.

With my dropdown I’m running into trouble if the profiler widget is activated and the expanded dropdown exceeds the component bounds at the bottom.

Afaik the profiler boxes are not drawn by the components but by the profiler widget. The widgets are pretty far to the end of the drawing pipeline so the profiler boxes will always be on top of the components.

I have two ideas:

  • subclass Grasshopper.GUI.Widgets.GH_ProfilerWidget and redo it’s render method so it will not render the profiler box for components that have some special flag set (e.g. false if they have a dropdown and it is expanded, true otherwise). However, how can I tell GH to load my modified profiler widget instead of the original one?
  • Expand the bounds of my component to include the expanded dropdown. This has to be done after its own Render method was called because otherwise I’m messing up my component capsule. This feels pretty hacky but might be the way to go if the other way does not work…

Are there any other ways to tackle this problem? Which is more doable / elegant?

Thanks in advance!
Best,
Paul

1 Like

Expand you “drop down” box upwards? ( “Raise up” box that is. :slight_smile: )

// Rolf

1 Like

Excellent idea, this really didn’t come to my mind. Thanks :slight_smile:
However, I’d like to keep that as a last resort and see if hiding the profiler is possible…

@DavidRutten do you have any further hints on where to look / which path to go?
Many thanks!
Paul

Override the ProcessorTime property on your component and return a zero timespan. It’s not ideal, but if your component never takes long to complete anyway it shouldn’t mess too much with the bookkeeping.

Hello @PaulBomke
Nice example of the Custom component.
Have you used any guide for creating it? I only recall a guide with extending of the ContextMenu of the component.

Thanks,
Dmitriy

The Grasshopper SDK docs contain an example for extending the attributes of objects, although note that it is much harder to do it for aggregate objects like Components than it is for individual objects like floating parameters. Almost all custom attribute objects in Grasshopper core are individual parameters, with the only exceptions being Gradient, Legend, Data Dam, Expression, Make2D, and Galapagos.

@DavidRutten
Unfortunately the ProcessorTime property seems to be read-only. At least that’s the error I get for
ProcessorTime = TimeSpan.Zero;
Is there a way around this? In principle I like the idea and it would be easy to implement…

@Dmitriy
I’ve based this on the instruction you can find here:
http://developer.rhino3d.com/wip/api/grasshopper/html/8a7974ab-7b2b-4f48-84d0-6e81b184e6b0.htm
In principle all of it is in there…

Ah, now I get it, you wrote override.

It works :slight_smile:

In my component I’m doing this:

public override TimeSpan ProcessorTime
{
    get
    {
	if (HideProfiler)
	{
		return TimeSpan.Zero;
	}
	else
	{
		return base.ProcessorTime;
	}
    }
}

where HideProfiler is a bool that I set if one of the dropdowns is expanded and extends over the bounds of the component.

Thanks for the help :slight_smile:

4 Likes

Thanks guys.

@PaulBomke, are you adding all elements (Buttons, Combos, Dropdowns) inside Render Sub?

Edit: Ok, yes. I found it out.

Thanks,
Dmitriy

Very neat, I figured you’d always return zero, but this is a much nicer solution.

Hi @DavidRutten

In the overridden Render Sub I am calling RenderIncomingWires(canvas.Painter, Owner.Sources, Owner.WireDisplay), however its says that Sources and WireDisplay are not the members of my GH component.
Others properties from below work fine.

Owner.RuntimeMessageLevel
Owner.Locked
Owner.NickName

Where can be the problem?

Thanks,
Dmitriy

@Dmitriy If you only want to paint stuff on top of your component it might be much easier to expand its Bounds in your Layout override to make it a little bigger and then simply call this in your Render override:

// Draw the component. This is a convenience function that draws all of the
// specified items at once.
// Set the flags to omit drawing specific items:
// drawComponentBaseBox, drawComponentNameBox, drawJaggedEdges, drawParameterGrips, drawParameterNames, drawZuiElements
base.RenderComponentCapsule(canvas, graphics, true, false, false, true, true, true);

This will draw the larger component with all the incoming wires, name box and so on and you can then paint some custom stuff in top of it within the free space you have…

Thanks @PaulBomke,
I found the problem: it was related to the inheritance of wrong type.

As for my goal - I need sometimes extend functionality of my Custom components with elements such as drop-downs, Combos, Checkboxes and others.
I as learned - all this needs to be added manually: graphics + event handling, but seems not a big issue in comparison to the additional functionality it can provide.

Thanks,
Dmitriy

Hello @DavidRutten, @PaulBomke and others.

I have a small question: I am changing layout content of the custom component (adding extra button) inside RespondToMouseDown function but seems that Render sub is not called automatically.
Only after zooming in/out component view is updated as I need it.
How to handle it? Should I extra call Render sub within RespondToMouseDown?

Thanks in advance,
Dmitriy

I think that

GH_Component_Extended comp = Owner as GH_Component_Extended;

followed by

comp.OnDisplayExpired(true);

should do it. (GH_Component_Extended is the name of you component class)

You can also do

sender.Refresh();

I guess…

Thanks, will try it out…

Hello @PaulBomke,
I managed to get call of Render sub.
I also resizing component in Layout sub. But seems Layout is not being called unless I drag component.
Any way to make Layout sub called?

Thanks,
Dmitriy

Try calling ExpireLayout() on the attributes. That should trigger a call to Layout() during the next canvas paint operation.

1 Like