C# creating automatic sliders

Hey !
I am trying to create multiple sliders based based upon an integer input. I have modified James -ramden code:.
The problem is it works fine on the first attempt, but the number of sliders increases exponentially , I want them to erase the old sliders and generate new ones according to the integer input.
Here is my modified code.
private void RunScript(bool x, object y, int z, ref object A)
{

Random rnd = new Random();
int i = 0;

if(x)
{
  for(i = 0;i < z;i++)
  {
    //instantiate  new slider
    Grasshopper.Kernel.Special.GH_NumberSlider slid = new Grasshopper.Kernel.Special.GH_NumberSlider();
    slid.CreateAttributes(); //sets up default values, and makes sure your slider doesn't crash rhino

    //customise slider (position, ranges etc)
    int inputcount = this.Component.Params.Input[1].SourceCount;
    slid.Attributes.Pivot = new System.Drawing.PointF((float) this.Component.Attributes.DocObject.Attributes.Bounds.Left - slid.Attributes.Bounds.Width - 30, (float) this.Component.Params.Input[1].Attributes.Bounds.Y + inputcount * 30);
    slid.Slider.Maximum = 10;
    slid.Slider.Minimum = 0;
    slid.Slider.DecimalPlaces = 2;
    slid.SetSliderValue((decimal) (rnd.Next(1000) * 0.01));

    //Until now, the slider is a hypothetical object.
    // This command makes it 'real' and adds it to the canvas.
    GrasshopperDocument.AddObject(slid, false);

    //Connect the new slider to this component
    this.Component.Params.Input[1].AddSource(slid);
  }
}

}

Any help will be much appreciated

Guys any luck?

Shout out the dark lord.

In addition to this, lets say I have a component that has 3 inputs and input 2 has two sliders connected to it. I want to delete these sliders when solution is generated. I want to do this because so that I can add new sliders to input 2 for another solution- i will plugin the code for generating new sliders which would get connected to input 2 automatically.

You can use IGH_Param.Sources to get a list of source parameters and then GH_Document.RemoveObjects Method to remove them:
aditya

  private void RunScript(bool x, List<object> y, int z)
  {
    Random rnd = new Random();
    if(x)
    {
      if(this.Component.Params.Input[1].SourceCount > 0)
      {
        List<IGH_Param> sources = new List<IGH_Param>(this.Component.Params.Input[1].Sources);
        GrasshopperDocument.RemoveObjects(sources, false);
      }
      for(int i = 0;i < z;i++)
      {
        //instantiate  new slider
        Grasshopper.Kernel.Special.GH_NumberSlider slid = new Grasshopper.Kernel.Special.GH_NumberSlider();
        slid.CreateAttributes(); //sets up default values, and makes sure your slider doesn't crash rhino

        //customise slider (position, ranges etc)
        int inputcount = this.Component.Params.Input[1].SourceCount;
        slid.Attributes.Pivot = new System.Drawing.PointF((float) this.Component.Attributes.DocObject.Attributes.Bounds.Left - slid.Attributes.Bounds.Width - 30, (float) this.Component.Params.Input[1].Attributes.Bounds.Y + inputcount * 30);
        slid.Slider.Maximum = 10;
        slid.Slider.Minimum = 0;
        slid.Slider.DecimalPlaces = 2;
        slid.SetSliderValue((decimal) (rnd.Next(1000) * 0.01));

        //Until now, the slider is a hypothetical object.
        // This command makes it 'real' and adds it to the canvas.
        GrasshopperDocument.AddObject(slid, false);

        //Connect the new slider to this component
        this.Component.Params.Input[1].AddSource(slid);
      }
    }
  }

tognatta.aditya.gh (14.9 KB)

3 Likes

@Mahdiyar this works, but I’am afraid gives me this error. Appreciate the quick response. Refer image below


Furthermore, If I want to connect this to another component Input(x), How do I go about this.
Rationally, I should try and find the component first and use <input .AddSource(myslid); >on that component. But how do I find that component through component name or ID? I could use FInd component from NodeinCode but the I’am afraid it will find similar components on the canvas.
Any suggestions.

You can get rid of this error by scheduling a new solution and registering a callback:

private void RunScript(bool x, List<object> y, int z)
  {
    if(x && z != _z)
      GrasshopperDocument.ScheduleSolution(5, SolutionCallback);
    _z = z;
  }

  // <Custom additional code> 
  private int _z;
  private void SolutionCallback(GH_Document doc)
  {
    Random rnd = new Random();
    if(this.Component.Params.Input[1].SourceCount > 0)
    {
      List<IGH_Param> sources = new List<IGH_Param>(this.Component.Params.Input[1].Sources);
      GrasshopperDocument.RemoveObjects(sources, false);
    }
    for(int i = 0;i < _z;i++)
    {
      //instantiate  new slider
      Grasshopper.Kernel.Special.GH_NumberSlider slid = new Grasshopper.Kernel.Special.GH_NumberSlider();
      slid.CreateAttributes(); //sets up default values, and makes sure your slider doesn't crash rhino

      //customise slider (position, ranges etc)
      int inputcount = this.Component.Params.Input[1].SourceCount;
      slid.Attributes.Pivot = new System.Drawing.PointF((float) this.Component.Attributes.DocObject.Attributes.Bounds.Left - slid.Attributes.Bounds.Width - 30, (float) this.Component.Params.Input[1].Attributes.Bounds.Y + inputcount * 30);
      slid.Slider.Maximum = 10;
      slid.Slider.Minimum = 0;
      slid.Slider.DecimalPlaces = 2;
      slid.SetSliderValue((decimal) (rnd.Next(1000) * 0.01));

      //Until now, the slider is a hypothetical object.
      // This command makes it 'real' and adds it to the canvas.
      GrasshopperDocument.AddObject(slid, false);

      //Connect the new slider to this component
      this.Component.Params.Input[1].AddSource(slid);
    }
  }

tognatta.aditya (new solution).gh (13.8 KB)
P.S. Obviously you can also get rid of this error by activating Do not show this message again check box.
If you want to know why you get this message, you need to read @DavidRutten explanation here.

1 Like

Got that! Appreciate the prompt response.
Did you read the text below the image on my previous reply?Any suggestions or insight on it will be helpful

aditya%202

private void RunScript(bool reset, string compoentnName, int n)
  {
    if(reset)
    {
      _n = n;
      _compoentnName = compoentnName;
      GrasshopperDocument.ScheduleSolution(5, SolutionCallback);
    }
  }

  // <Custom additional code> 
  private int _n;
  private string _compoentnName;
  private void SolutionCallback(GH_Document doc)
  {
    foreach(IGH_DocumentObject obj in GrasshopperDocument.Objects)
    {
      if (obj.NickName == _compoentnName)
      {
        IGH_Component targetComponent = obj as IGH_Component;
        Random rnd = new Random();
        if(targetComponent.Params.Input[1].SourceCount > 0)
        {
          List<IGH_Param> sources = new List<IGH_Param>(targetComponent.Params.Input[1].Sources);
          GrasshopperDocument.RemoveObjects(sources, false);
        }
        for(int i = 0;i < _n;i++)
        {
          //instantiate  new slider
          Grasshopper.Kernel.Special.GH_NumberSlider slid = new Grasshopper.Kernel.Special.GH_NumberSlider();
          slid.CreateAttributes(); //sets up default values, and makes sure your slider doesn't crash rhino

          //customise slider (position, ranges etc)
          int inputcount = targetComponent.Params.Input[1].SourceCount;
          slid.Attributes.Pivot = new System.Drawing.PointF((float) targetComponent.Attributes.DocObject.Attributes.Bounds.Left - slid.Attributes.Bounds.Width - 30, (float) targetComponent.Params.Input[1].Attributes.Bounds.Y + inputcount * 30);
          slid.Slider.Maximum = 10;
          slid.Slider.Minimum = 0;
          slid.Slider.DecimalPlaces = 2;
          slid.SetSliderValue((decimal) (rnd.Next(1000) * 0.01));

          //Until now, the slider is a hypothetical object.
          // This command makes it 'real' and adds it to the canvas.
          GrasshopperDocument.AddObject(slid, false);

          //Connect the new slider to this component
          targetComponent.Params.Input[1].AddSource(slid);
        }
        break;
      }
    }
  }

tognatta.aditya (Another Component).gh (15.1 KB)

3 Likes

@Mahdiyar thanks a ton, this works like a charm.

Further taking this discussion, is there a way to name them?

@Mahdiyar Using the code above can i do custom nicknames with a list of string input?

Hi @Mahdiyar If we want to determine which slides are added to which component input code? For example, in the example below, I want to add to the second input, the Radius(Gh_input.(index))


tognatta-select hh input(index).gh (8.2 KB)

1 Like

hi @Mahdiyar
I succeeded to solve myself to answer the problem above :innocent:


add slider advance.gh (10.5 KB)

  private void RunScript(bool reset, string compoentnName, int n, int a, int b, int @Decimal, int indexInput)
  {
  if(reset)
  {
  _n = n;
  _a = a;
  _b = b;
  _Decimal = Decimal;
  _indexInput=indexInput;
  _compoentnName = compoentnName;
  GrasshopperDocument.ScheduleSolution(5, SolutionCallback);
}
  }

  // <Custom additional code> 
private int _n;
private int _a = 0;
private int _b = 10;
private int _Decimal ;
private int _indexInput;
private string _compoentnName;
private void SolutionCallback(GH_Document doc)
{
  foreach(IGH_DocumentObject obj in GrasshopperDocument.Objects)
  {
    if (obj.NickName == _compoentnName)
    {
      IGH_Component targetComponent = obj as IGH_Component;
      Random rnd = new Random();
      if(targetComponent.Params.Input[_indexInput].SourceCount > 0)
      {
        List<IGH_Param> sources = new List<IGH_Param>(targetComponent.Params.Input[_indexInput].Sources);
        GrasshopperDocument.RemoveObjects(sources, false);
      }
      for(int i = 0;i < _n;i++)
      {
        //instantiate  new slider
        Grasshopper.Kernel.Special.GH_NumberSlider slid = new Grasshopper.Kernel.Special.GH_NumberSlider();
        slid.CreateAttributes(); //sets up default values, and makes sure your slider doesn't crash rhino

        //customise slider (position, ranges etc)
        int inputcount = targetComponent.Params.Input[_indexInput].SourceCount;
        slid.Attributes.Pivot = new System.Drawing.PointF((float) targetComponent.Attributes.DocObject.Attributes.Bounds.Left - slid.Attributes.Bounds.Width - 30, (float) targetComponent.Params.Input[_indexInput].Attributes.Bounds.Y + inputcount * 30);
        slid.Slider.Maximum = _b;
        slid.Slider.Minimum = _a;
        slid.Slider.DecimalPlaces = _Decimal;
        slid.SetSliderValue((decimal) (rnd.Next(1000 * _b / 10) * 0.01));

        //Until now, the slider is a hypothetical object.
        // This command makes it 'real' and adds it to the canvas.
        GrasshopperDocument.AddObject(slid, false);

        //Connect the new slider to this component
        targetComponent.Params.Input[_indexInput].AddSource(slid);
      }
      break;
    }
  }
}

thanks

1 Like

Hi, is there a simple solution to access and remotely control also the ToolStripDropDown menu of a component via a C# or Python script? I fould only a old thread set input parameter from a pop-up menu (VB) - Grasshopper (grasshopper3d.com). Any ideas @Mahdiyar,@DavidRutten,@andheum, @garciadelcastillo? Thank you.

Hi, @matous.stieber
I’m converting to c#, but I’m not sure if this code will run in a c# component outside of Visual Studio

Maybe another way!

 protected override void AppendAdditionalComponentMenuItems(ToolStripDropDown menu)
  {
    // First, see if there's a single value already stored in the parameter.
    // If there isn't, cv will have a value of Int32.MinValue.
    int cv = int.MinValue;
    Parameters.Param_Integer param = (Parameters.Param_Integer) Params.Input[1];

    if (param.PersistentDataCount == 1)
    {
      cv = param.PersistentData[0].Value;
    }

    Menu_AppendGenericMenuItem(menu, "First", Menu_SetFirstDefault, null, null, null, cv == 1);
    Menu_AppendGenericMenuItem(menu, "Second", Menu_SetSecondDefault, null, null, null, cv == 2);
    Menu_AppendGenericMenuItem(menu, "Third", Menu_SetThirdDefault, null, null, null, cv == 3);
    Menu_AppendGenericMenuItem(menu, "Fourth", Menu_SetFourthDefault, null, null, null, cv == 4);
  }

  private void Menu_SetFirstDefault(object sender, EventArgs e)
  {
    RecordUndoEvent("Constant changed");
    Parameters.Param_Integer param = (Parameters.Param_Integer) Params.Input[1];
    param.ClearPersistentData();
    param.AddPersistentData(1);
    param.ExpireSolution(true);
  }

ToolStripDropDown menu.gh (8.0 KB)رر

Unfortunatly it does not help, @Rh-3d-p.

my understanding is that the ToolStripMenuItems are only instantiated at right-clicks. don’t think you can find it outside the event.

you may be able to access the values or properties those ToolStripMenuItems modify. i suspect those are what you’re really after, although they may be private

Thank you @Will_Wang but the issue has been already solved https://discourse.mcneel.com/t/remotely-control-toolstripdropdown-menu/ by @sebastian.lindholm