Grasshopper

algorithmic modeling for Rhino

Displaying geometry in a custom component, which is not an output

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

Views: 2223

Replies to This Discussion

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

RSS

About

Translate

Search

Videos

  • Add Videos
  • View All

© 2024   Created by Scott Davidson.   Powered by

Badges  |  Report an Issue  |  Terms of Service