How to keep Custom Attributes when restarting a file?

Hello.

I made a component that changes the value of Input depending on the button placed at the bottom.
This basically works fine, but when I save the file and restart it, the Input value is initialized.
If you press the button again after startup, it will work properly, but it is inconvenient.
Is there a solution?

Thank you.


ExtendGUI.gha (10 KB)
ExtendGUIComponent.cs (10.5 KB)

I guess this helps : C# numericUpDown & button Issue

using Grasshopper.GUI;
using Grasshopper.GUI.Canvas;
using Grasshopper.Kernel;
using Grasshopper.Kernel.Attributes;
using System;
using System.Drawing;
using System.Globalization;
using System.Windows.Forms;
namespace ExtendGUI
{
    public class ExtendGuiComponent : GH_Component
    {
        public int Num;
        public ExtendGuiComponent() : base("ExtendGUI", "ExGUI", "test", "User", "tests") { }
        public override void CreateAttributes()
        {
            m_attributes = new AttributesCustom(this);
        }
        protected override void RegisterInputParams(GH_InputParamManager pManager)
        {
            var name = Num == 0 ? "*" : " / ";
            pManager.AddNumberParameter("0", "0", "0", GH_ParamAccess.item, 0);
            pManager.AddNumberParameter(name, name, "", GH_ParamAccess.item, 0);
        }
        protected override void RegisterOutputParams(GH_OutputParamManager pManager)
        {
            pManager.AddNumberParameter("Num", "N", "Number.", GH_ParamAccess.item);
        }
        protected override void BeforeSolveInstance()
        {
            var input = 0.0;
            var name = "x";
            if (!Params.Input[0].VolatileData.IsEmpty)
            {
                foreach (var item in Params.Input[0].VolatileData.AllData(false))
                    item.CastTo(out input);
                name = input.ToString(CultureInfo.InvariantCulture);
            }
            Params.Input[0].Name = name;
            Params.Input[0].NickName = name;
        }
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            var num0 = 0.0;
            if (!DA.GetData(0, ref num0)) return;
            if (Params.Input.Count < 2) return;
            switch (Num)
            {
                case 0:
                    {
                        var num1 = 0.0;
                        if (!DA.GetData(1, ref num1)) return;
                        DA.SetData(0, num0 * num1);
                        break;
                    }
                case 1:
                    {
                        var num1 = 0.0;
                        if (!DA.GetData(1, ref num1)) return;
                        DA.SetData(0, num0 / num1);
                        break;
                    }
                default:
                    DA.SetData(0, 0);
                    break;
            }
        }
        public override bool Write(GH_IO.Serialization.GH_IWriter writer)
        {
            writer.SetInt32("Num", Num);
            return base.Write(writer);
        }
        public override bool Read(GH_IO.Serialization.GH_IReader reader)
        {
            Num = reader.GetInt32("Num");
            return base.Read(reader);
        }
        protected override Bitmap Icon => null;
        public override Guid ComponentGuid => new Guid("90194116-a86f-4ef8-84e2-e480b3000c5b");
    }
    public class AttributesCustom : GH_ComponentAttributes
    {
        private Rectangle _buttonBounds0;
        private Rectangle _buttonBounds1;
        private GH_Capsule _button0;
        private GH_Capsule _button1;
        public AttributesCustom(IGH_Component owner) : base(owner) { }
        protected override void Layout()
        {
            base.Layout();
            var rec0 = GH_Convert.ToRectangle(Bounds);
            rec0.Height += 44;
            var rec1 = rec0;
            rec1.Y = rec0.Bottom - 44;
            rec1.Height = 22;
            rec1.Inflate(-2, -2);
            var rec2 = rec0;
            rec2.Y = rec0.Bottom - 22;
            rec2.Height = 22;
            rec2.Inflate(-2, -2);
            Bounds = rec0;
            _buttonBounds0 = rec1;
            _buttonBounds1 = rec2;
        }
        protected override void Render(GH_Canvas canvas, Graphics graphics, GH_CanvasChannel channel)
        {
            var extendGui = (ExtendGuiComponent)Owner;
            switch (channel)
            {
                case GH_CanvasChannel.Objects:
                    RenderComponentCapsule(canvas, graphics, true, false, false, true, true, true);
                    _button0 = GH_Capsule.CreateTextCapsule(_buttonBounds0, _buttonBounds0, extendGui.Num == 0 ? GH_Palette.Black : GH_Palette.White, "Multiplied", 5, 0);
                    _button0.Render(graphics, this.Selected, Owner.Locked, Owner.Hidden);
                    _button0.Dispose();
                    _button1 = GH_Capsule.CreateTextCapsule(_buttonBounds1, _buttonBounds1, extendGui.Num == 1 ? GH_Palette.Black : GH_Palette.White, "Divided", 5, 0);
                    _button1.Render(graphics, this.Selected, Owner.Locked, Owner.Hidden);
                    _button1.Dispose();
                    break;
                default:
                    base.Render(canvas, graphics, channel);
                    break;
            }
        }
        public override GH_ObjectResponse RespondToMouseDown(GH_Canvas sender, GH_CanvasMouseEvent e)
        {
            if (e.Button != MouseButtons.Left) return base.RespondToMouseDown(sender, e);
            var extendGui = (ExtendGuiComponent)Owner;
            var button = ((RectangleF)_buttonBounds0).Contains(e.CanvasLocation) ? 0 :
                ((RectangleF)_buttonBounds1).Contains(e.CanvasLocation) ? 1 : -1;
            if (button == -1) return base.RespondToMouseDown(sender, e);
            if (extendGui.Num == button)
                return GH_ObjectResponse.Handled;
            var name = button == 0 ? "*" : " / ";
            extendGui.Params.Input[1].Name = name;
            extendGui.Params.Input[1].NickName = name;
            extendGui.RecordUndoEvent("button");
            extendGui.Num = button;
            extendGui.ExpireSolution(true);
            return GH_ObjectResponse.Handled;
        }
    }
}

ExtendGUI.zip (30.3 KB)

1 Like

Thank you for your reply.

I’m very sorry, but this problem was embarrassingly due to my rudimentary mistake.
I solved it by changing the definition of the initial input of this component as in the attached file.

Thanks to your post, I am grateful to know the meaning of the Read and Write methods.

ExtendGUIComponent.cs (10.8 KB)

Thank you!

It looks like you had to register the initial inputs :upside_down_face:

Let me ask you another question.

I added a new feature to the Component I made yesterday.
Like the Gif image, we are increasing the number of values to import.
At first glance it looks like it’s working, but when I save the file and restart it, the number of imports is incorrect.
The same thing happens when I copy the Component.
Do you know what is causing this problem?


ExtendGUIComponent.cs (14.5 KB)

Try implementing IGH_VariableParameterComponent in your class. It does some extra bookkeeping for a variable amount of inputs and outputs during file saving.

Sorry for the late reply.

It started working well!
Thank you :joy:


ExtendGUIComponent.cs (15.2 KB)