How to I make options for commands using RhinoCommon (C#)

I am reading this code snippet and trying to understand.
Rhino - Add Command Line Options (rhino3d.com)

My goal is after an object is selected, the user selects a material from a list in the command line, with letters underlined to select. How do I implement this?

This is my toy script. Something isn’t right with the integer selection, the current integer isn’t changing after the Get. I don’t know what is going on with the option select and I am not sure how to implement it.

    {
        public TestCommand()
        {
            // Rhino only creates one instance of each command class defined in a
            // plug-in, so it is safe to store a refence in a static property.
            Instance = this;
        }

        ///<summary>The only instance of this command.</summary>
        public static TestCommand Instance { get; private set; }

        ///<returns>The command name as it appears on the Rhino command line.</returns>
        public override string EnglishName => "TestCommand";

        protected override Result RunCommand(RhinoDoc doc, RunMode mode)
        {

            RhinoApp.WriteLine("Select a volume");
            
            //get an object
            GetObject getObject = new GetObject();
            getObject.SetCommandPrompt("Select an object.");
            var result = getObject.Get();
            Rhino.Input.Custom.OptionInteger optInteger = new Rhino.Input.Custom.OptionInteger(1, -1, 100);
            //selects an object
                
            //get an integer
            GetInteger getInteger = new GetInteger();
            getInteger.SetCommandPrompt("Please select an integer.");
            result = getInteger.Get();
            Rhino.RhinoApp.WriteLine(" Integer = {0}", optInteger.CurrentValue);
            //always prints "Integer = 1" no matter the integer I select.

            //get an option
            GetOption getOption = new GetOption();
            string[] listValues = new string[] { "Sterling Silver", "Brass", "Bronze", "14K Gold", "18K Gold", "24K Gold", "Platinum", "Paladium" };
            int listIndex = 0;
            getOption.AddOptionList("Material", listValues, listIndex);
            getOption.SetCommandPrompt("select option");
            getOption.Get();
            Rhino.RhinoApp.WriteLine("material selected is {0}", listValues[getOption.OptionIndex()]);
            //always says invalid selection for any number or string. Does not display options.
            //Throws an exception when I hit escape.
            return Result.Success;
        }
    }

Hi @stevescott517,

Maybe something more like this?

protected override Result RunCommand(RhinoDoc doc, RunMode mode)
{
  const string materialKey = "Material";
  var materialList = new string[] { "Brass", "Bronze", "Gold_14k", "Gold_18K", "Gold_24K", "Platinum", "Paladium", "SterlingSilver" };

  // Get persistent settings
  var materialIndex = Settings.GetInteger(materialKey, 0);

  var getOption = new GetOption();
  getOption.SetCommandPrompt("Choose command option");
  getOption.AcceptNothing(true);
  while (true)
  {
    getOption.ClearCommandOptions();
    var materialOption = getOption.AddOptionList(materialKey, materialList, materialIndex);
    var res = getOption.Get();
    if (res == GetResult.Option)
    {
      var option = getOption.Option();
      if (option.Index == materialOption)
        materialIndex = option.CurrentListOptionIndex;
      continue;
    }
    else if (res == GetResult.Nothing)
    {
      break;
    }
    else
    {
      return Result.Cancel;
    }
  }

  // Set persistent settings
  Settings.SetInteger(materialKey, materialIndex);

  return Result.Success;
}

– Dale

Hi @stevescott517

Your integer selection isn’t working because you didn’t add optInteger to the Get object you are calling. GetInteger expects the user to type in an integer then you can get it with Number() method. If you want integer input as an option, then you have to use OptionInteger like in my example below.

OptionInteger optInteger = new OptionInteger(1, -1, 100);
GetOption getIntOption = new GetOption();
getIntOption.AddOptionInteger("optionInteger", ref optInteger); 
getIntOption.SetCommandPrompt("Please select an integer");
getIntOption.Get();
RhinoApp.WriteLine($"Integer = {optInteger.CurrentValue}");

For option list @dale gave you a nice example about how to handle it. Also mind the strings in the example, they don’t contain any whitespace (e.g. “Gold_14K” instead of “14K Gold”).

Thanks Dale this is very helpful. Just one problem I am having. When I select a material it changes the materialIndex, good, but when I hit space to approve, it is returning a cancel result while I was expecting a nothing result and breaking the loop and continuing. Whether I hit the spacebar or hit escape, both result in a cancel. Would you be able to explain this? My intent is for the space bar to set the GetResult to Nothing so it will break the loop, and escape sending a result of Cancel.

this is my revised code


            //get a material
            const string materialKey = "Material";
            string[] materialList = new string[] { "SterlingSilver", "Brass", "Bronze", "Gold_14K", "Gold_18K", "Gold_24K", "Platinum", "Paladium" };
            var materialIndex = Settings.GetInteger(materialKey, 0);
            var getOption = new GetOption();
            getOption.SetCommandPrompt("select option");
            while (true)
            {
                getOption.ClearCommandOptions();
                var materialOption = getOption.AddOptionList(materialKey, materialList, materialIndex);
                var res = getOption.Get();
                if (res == GetResult.Option)
                {
                    Rhino.RhinoApp.WriteLine("result was an option. Continuing.");
                    var option = getOption.Option();
                    if (option.Index == materialOption)
                    {
                        materialIndex = option.CurrentListOptionIndex;
                    }
                    continue;
                }
                else if (res == GetResult.Nothing)
                {
                    Rhino.RhinoApp.WriteLine("result was nothing.");
                    break;
                }
                else if (res == GetResult.Cancel)
                {
                    Rhino.RhinoApp.WriteLine("result was cancel");
                    return Result.Cancel;
                }
                else
                {
                    Rhino.RhinoApp.Write("the result fell through and was a {0}.", res);
                    return Result.Cancel;
                }

            }
           // This code is not reachable.
            Settings.SetInteger(materialKey, materialIndex);
            Rhino.RhinoApp.WriteLine("material selected is {0}", materialList[materialIndex]);
            return Result.Success;

Thank you so much. Adding the AddOptionInteger method got it the integer option working.

Hi @stevescott517,

Make sure to add:

getOption.AcceptNothing(true);

Otherwise, GetOption.Get will never return GetResult.Nothing.

– Dale