Pass Custom Class as a DataTree to input/output

Hi all,

I am new to Grasshopper SDK and plugin development generally and I am struggling for some time to understand how I can pass a custom class as a Grasshopper tree to the output of the component.

I have made a class called “Apple” and when in “Solve Instance” I create several of these apples and pass them to the output as DataTree as result I get only results from ToString() method. Why ToString() method is called and why instead I don’t get DataTree

Does someone know what is my mistake in the code? Thanks a lot for any of your help

Below is my code

namespace MyApplePlugin
{
    public class MyApplePluginComponent : GH_Component
    {

        public MyApplePluginComponent()
          : base("MyApplePlugin", "MyApplePlugin",
            "MyApplePlugin",
            "MyPlugins", "Apple")
        {
        }

        protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
        {
            pManager.AddTextParameter("Names", "Names", "Names", GH_ParamAccess.tree);
        }

        protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
        {
            pManager.AddGenericParameter("Apples", "Apples", "Apples", GH_ParamAccess.tree);
        }

        protected override void SolveInstance(IGH_DataAccess DA)
        {
            GH_Structure<GH_String> names = new GH_Structure<GH_String>();
            if (!DA.GetDataTree(0, out names)) return;
          
            GH_Structure<Apple> appleTree = new GH_Structure<Apple>();

            for (int i = 0; i < names.PathCount; i++)
            {
                GH_Path path = names.get_Path(i);

                foreach (GH_String name in names.get_Branch(path))
                {
                    Apple a = new Apple(name.ToString());
                    appleTree.Append(a, path);
                }
            }
            DA.SetDataTree(0, appleTree);
        }

        public class Apple : GH_Goo<Apple>
        {
            private string _name;

            public Apple(string name)
            {
                _name = name;
            }

            public override bool IsValid
            {
                get { return true; }
            }
            public override string TypeName
            {
                get { return "Apple Tree"; }
            }
            public override string TypeDescription
            {
                get { return "Custom Apple Tree"; }
            }
            public override IGH_Goo Duplicate()
            {
                throw new NotImplementedException();
            }

            public override string ToString()
            {
                return "Apple as a String";
            }
        }


        protected override System.Drawing.Bitmap Icon => null;


        public override Guid ComponentGuid => new Guid("aab6994a-7b47-4c8a-adb4-66198301630a");
    }
}

Hello,

The Panel can only show text, so it always calls .ToString().
This doesn’t say your component doesn’t actually retrieves a DataTree.

If you want to mimic native parameters, you need to implement the GH_Param or GH_PersistentParam associated to this type.

And then use the .AddParameter method in your RegisterOutputParams.
The AddGenericParameter adds a “Data” parameter (native GH type).

Also : your code seems to be looping through all branches and items of the tree, only to convert each element to an Apple. I’d strongly recommend you switch your inputs and outputs do a GH_ParamAccess.item, and let Grasshopper handle the trees as almost every component does.

Edited because I completely mis-interpretated the problem…

Hi, thanks a lot for the explanation. By implementing GH_Param I was able to get the wanted results on the output of the component. Also as you said is not necessary that I loop through all branches and elements when component is doing that by default.

Thanks again and best regards