A proper way to automatically generate GH components

Hi there! We have a component that takes two buttons as inputs. The nature of this component is such that there aren’t really any other params that would make sense to connect to it aside from the buttons, which is why we want to save the users 2 seconds of their time and create the buttons automatically when the component is dropped onto the canvas.

The issue is that when the component is dropped, it turns orange and complains about both inputs being unable to collect data even though the buttons are there and are in fact connected. Pressing the buttons does nothing until you manually reconnect both wires. Once that’s done, the component turns gray and works as expected.

This is what we have so far:

    public override void AddedToDocument(GHK.GH_Document document)
    {
        
        base.AddedToDocument(document);

        
        this.doc = this.OnPingDocument();

        // First button
        var inputButton = new GHK.Special.GH_ButtonObject();
        inputButton.Attributes = new GHK.Special.GH_ButtonObjectAttributes(inputButton);
        inputButton.Attributes.Pivot = new System.Drawing.PointF(this.Attributes.Pivot.X - 300, this.Attributes.Pivot.Y - 10);

        // Second button
        var outputButton = new GHK.Special.GH_ButtonObject();
        outputButton.Attributes = new GHK.Special.GH_ButtonObjectAttributes(outputButton);
        outputButton.Attributes.Pivot = new System.Drawing.PointF(this.Attributes.Pivot.X - 300, this.Attributes.Pivot.Y + 10);
        
        // Add buttons to Doc
        this.doc.AddObject(inputButton, true);
        this.doc.AddObject(outputButton, true);

        // Connect buttons to inputs
        this.Params.Input[0].Sources.Add(inputButton);
        this.Params.Input[1].Sources.Add(outputButton);

        // And here we go trying to refresh the solution with every trick in the book...
        // However nothing works

        // Expire components?
        inputButton.ExpireSolution(true);
        outputButton.ExpireSolution(true);
        Component.ExpireSolution(true);
 
        // Collect and compute data?
        this.Params.Input[0].CollectData();
        this.Params.Input[0].ComputeData();

        this.Params.Input[1].CollectData();
        this.Params.Input[1].ComputeData();
        
        // Expire everything?
        Params.OnParametersChanged();
        ExpireSolution(true);
        ExpirePreview(true);
        
    }

So what’s the proper sequence of refreshing / expiring the solution that lets the component know that its inputs have valid sources that are ready to supply data? @DavidRutten, @stevebaer? Thanks in advance!

I would use Param.AddSource() rather than Param.Sources.Add() - this handles some cleanup as well.

2 Likes

@andheum Magic! Thank you!

Here some old code that I used to reverse engineer a Raytraced material I had created, but lost the GH definition of. The component code starts at this location, and this is the SolveInstance.

I hope you don’t mind the F# code :slight_smile:

Some further highlights:

It helped me get back a very complex setup that was properly wired up and all that. These days it looks much tidier than the random mess it was after the reverse process :slight_smile:

2 Likes