algorithmic modeling for Rhino
Hi everyone,
the standard behavior of a custom component is to display the output geometry of the component.
I was wondering if this behavior could be altered. In my case a custom component output geometry is a bunch of polylines. However they are categorized in X different categories and I would like to fill the colored polylines with a mesh colored according to the categories. The mesh however is just for "display" and should not be available as an output.
How would I do that?
Thanks
Martin
Tags:
Hallo Martin,
du kannst das interface IGH_PreviewObject ... implementieren, normalerweise wird das bei neuen Parametern implemetiert ... das geht aber bei allen Klassen die du in deinenen plugin hast... ein beispiel für Blöcke.... [leider kein Python]
IGH_PreviewObject.DrawViewportMeshes(IGH_PreviewArgs args){
hau rein was du immer vor hast. wichtig ist dass du den custompreview disposed(hat keinen garbage collector sonst hast du deine geometrie bis zur Beendigung von Rhino immer am Bildschirm.....oder bastel dir einen eigenen preview....
}
internal class GH_blockParameter : GH_PersistentParam<GH_blocks>, IGH_PreviewObject, IGH_BakeAwareObject
{
private bool m_hidden;
public override System.Guid ComponentGuid
{
get
{
return new System.Guid("{2d3d1810-bbc4-46f4-92fb-e6769e823255}");
}
}
BoundingBox IGH_PreviewObject.ClippingBox
{
get
{
return base.Preview_ComputeClippingBox();
}
}
bool IGH_PreviewObject.Hidden
{
get
{
return this.m_hidden;
}
set
{
this.m_hidden = value;
}
}
bool IGH_PreviewObject.IsPreviewCapable
{
get
{
return true;
}
}
bool IGH_BakeAwareObject.IsBakeCapable
{
get
{
return true;
}
}
public GH_blockParameter() : base("GH_block", "GH_block", "Represents a collection of all kinds of data", "Params", "Primitive")
{
this.m_hidden = false;
}
protected override GH_GetterResult Prompt_Singular(ref GH_blocks value)
{
return GH_GetterResult.success;
}
protected override GH_GetterResult Prompt_Plural(ref System.Collections.Generic.List/span>GH_blocks> values)
{
return GH_GetterResult.success;
}
void IGH_PreviewObject.DrawViewportMeshes(IGH_PreviewArgs args)
{
base.Preview_DrawWires(args);
}
void IGH_PreviewObject.DrawViewportWires(IGH_PreviewArgs args)
{
base.Preview_DrawWires(args);
}
void IGH_BakeAwareObject.BakeGeometry(RhinoDoc doc, ObjectAttributes att, System.Collections.Generic.List/span>System.Guid> obj_ids)
{
if (att == null)
{
att = doc.CreateDefaultAttributes();
}
try
{
System.Collections.IEnumerator enumerator = this.m_data.GetEnumerator();
while (enumerator.MoveNext())
{
IGH_BakeAwareData item = (IGH_BakeAwareData)enumerator.Current;
if (item != null)
{
System.Guid id;
if (item.BakeGeometry(doc, att, out id))
{
obj_ids.Add(id);
}
}
}
if (enumerator is System.IDisposable)
{
(enumerator as System.IDisposable).Dispose();
}
}
finally
{
}
}
void IGH_BakeAwareObject.BakeGeometry(RhinoDoc doc, System.Collections.Generic.List<System.Guid> obj_ids)
{
ObjectAttributes att = new ObjectAttributes();
att.set_LayerIndex(doc.get_Layers().get_CurrentLayer().get_LayerIndex());
try
{
System.Collections.IEnumerator enumerator = this.m_data.GetEnumerator();
while (enumerator.MoveNext())
{
IGH_BakeAwareData item = (IGH_BakeAwareData)enumerator.Current;
if (item != null)
{
System.Guid id;
if (item.BakeGeometry(doc, att, out id))
{
obj_ids.Add(id);
}
}
}
if (enumerator is System.IDisposable)
{
(enumerator as System.IDisposable).Dispose();
}
}
finally
{
}
}
}
}
GH_Component already implements that interface. You just need to override the DrawViewportMeshes already on GH_Component, call the base class method and then draw your meshes on top. Since you're outputting polylines, you shouldn't have to worry about the clipping boxes since your polylines will already make sure that your meshes are within the clipping planes.
--
David Rutten
david@mcneel.com
Poprad, Slovakia
Ahhh ok i got it IGH_Component Interface has IGH_PreviewObject implemented.
what helps...
Thanks,
I got this far. Most of the work was actually done by VS :-)
public override void DrawViewportMeshes(IGH_PreviewArgs args)
{
base.DrawViewportMeshes(args);
}
The question to me is: How do I "draw my meshes on top".
I have the meshes ( List<Mesh> myMeshes = new List<Mesh>(); )
calculated in "protected override void SolveInstance(IGH_DataAccess DA)"
How do I access the data from "SolveInstance" in "DrawViewportMeshes"?
How do I tell "DrawViewportMeshes" to actually draw these meshes?
- Martin
Hi Martin,
you can't. Variables declared inside a method are not visible from outside. You need to declare your meshes on the class level, i.e. not inside a method:
private List<Mesh> m_meshes;
Then you fill up this list inside SolveInstance:
if (DA.Iteration == 0)
m_meshes = new List<Mesh>();
//blah blah, yada yada yada
m_meshes.Add(someMesh);
Since m_meshes is declared at class level, it will be accessible to both SolveInstance and your DrawViewportMeshes method:
public override void DrawViewportMeshes(IGH_PreviewArgs args)
{
base.DrawViewportMeshes(args);if (m_meshes != null)
{
foreach (Mesh mesh in m_meshes)
{
//Draw the mesh any way you like using the args.Display field
}
}
}
--
David Rutten
david@mcneel.com
Poprad, Slovakia
Hm, I will look into my ILspy to give you the right answer. So far you can make your own class personalconduit : displayconduit {} ?!!? and then add the meshwire in the different drawingstages of the rhinodisplay, so you can draw over other stuff. Usally the order you put your geo to the display is the order it is shown. You also get by doing his kind of technic extra funky abilitys which you can not get by just using customconduit and it is straight forward...
or maybe...
1. put a List<Mesh> my_mesh field in your GH_Component
2. initalize it in the Constructor with this.my_mesh = new List<Mesh>();
3. in the SolveInstance you can simply access your global variable with this.my_mesh
4. now you can access the mesh in the DrawViewportMeshes with this.my_mesh
no magic attached to this you are just having a outside parameter for all your functions. It can also be your own displaysolver if you like.
the best is to use Ilspy (its for free) and then look into Grasshopper.dll hope david doesnot hate this too much... and look to the base.DrawViewportMeshes(args) this is a really good starting point to know how the mechanic works for displaypreviews... Hope David is not using some scrambler for his code in the future.. much better than looking to the sdk
Thank you,
this is very helpful. Using a private field is probably the best solution.
(I wasn't sure if there already was a property or method of some sort to store on the display geometry in the GH_Component Class)
Thanks again for your help.
- Martin
Welcome to
Grasshopper
Added by Parametric House 0 Comments 0 Likes
Added by Parametric House 0 Comments 0 Likes
Added by Parametric House 0 Comments 0 Likes
Added by Parametric House 0 Comments 0 Likes
Added by Parametric House 0 Comments 0 Likes
© 2024 Created by Scott Davidson. Powered by