Is something like "AddOptionString" possible?

Hi.

Is it possible to add a user input string to the options as in the image?
The user would take the following steps:

  1. Press “String=default value”
  2. Type a custom string as input
  3. Press enter
  4. Automatically go back to the same menu as in the image
  5. Press enter and continue the command

image

The situation in the image comes from this code example: https://developer.rhino3d.com/samples/rhinocommon/add-command-line-options/

Your answers would be greatly appreciated.

Josien

I think what you want is found in AddOption see
https://developer.rhino3d.com/api/RhinoCommon/html/M_Rhino_Input_Custom_GetBaseClass_AddOption_3.htm

You can add a OptionName=String Value on the command line.

1 Like

Actually, I don’t think this solves my problem. What I want, is that the user can then type his/her own string.

Hold my beer… I know this can be done.

public Result RunCommand(RhinoDoc doc, RunMode mode)
{
  GetPoint gp = new GetPoint();
  string chosenString = "default value";
  Point3d chosen;
  while (true)
  {
    gp.ClearCommandOptions();
    int stringOption = gp.AddOption("String", chosenString);
    GetResult gr = gp.Get();
    if (gr == GetResult.Point)
    {
      chosen = gp.Point();
      break;
    }

    if (gr == GetResult.Option)
    {
      if (gp.OptionIndex() == stringOption)
      {
        GetString gs = new GetString();
        gs.SetCommandPrompt("Type your string");
        GetResult stringGetResult = gs.GetLiteralString();
        if (stringGetResult == GetResult.String)
        {
          chosenString = gs.StringResult();
        }
      }
    }
  }

  RhinoApp.WriteLine("Chosen string: " + chosenString);

  return Result.Success;
}

Wow, that works! Thanks a lot. I will be working a bit more on what I want to achieve and then post the end result here.

I also have a follow up question: what if you actually don’t want a GetPoint?
What I want to achieve is that the user can choose some options from the same menu, then press enter and continue (without getting a point).

To clear up, the user would type the command, then enter a menu like this:
nlsfb_code = 22.23 building_part_id = FA simple_element_name = Roof Beam
(In this menu the user can click an option, then type his/her alternative string, press enter and go back to the menu)
Then, the user presses enter, the command continues and the values are used later in the code.

Long story short, is something like a GetNothing :slight_smile: possible ?

Yes, instead of GetPoint use GetOption. Of course, it will never return GetResult.Point, so you should do the following with AcceptNothing(true):

GetOption go = new GetOption();

// this will return GetResult.Nothing if the user presses Enter:
go.AcceptNothing(true); 
while(true)
{
  go.ClearCommandOptions();
  // build your options with currently defined values
  // ...
  // ...

  // get the current state from the user
  GetResult gr = go.Get();
  if (gr == GetResult.Nothing) break;
  if (gr == GetResult.Option) 
  {
    // process option that was changed
  }
}

@menno Firstly, I found a small mistake in your code. I couldn’t cancel the command, it would just stay in the loop forever unless you actually drew a point / chose an option.

As promised, here is my finished code :slight_smile: :

OptionToggle newOverwriteToggle = new OptionToggle(true, "Overwrite", "New");
            OptionDouble manuAreaOption = new OptionDouble(manuArea);
            OptionDouble manuMaterialPriceOption = new OptionDouble(manuMaterialPrice);
            OptionDouble labourHoursOption = new OptionDouble(labourHours);
            OptionDouble toolsPriceOption = new OptionDouble(toolsPrice);

            GetOption go = new GetOption();
            go.SetCommandPrompt("Settings");
            go.AcceptNothing(true);
            while (true)
            {
                go.ClearCommandOptions();
                if (!newElement) go.AddOptionToggle("Mode", ref newOverwriteToggle);
                int plateOptIndex = go.AddOptionList("Plate", plateNames, plateIndex);
                int buildingPartOptIndex = go.AddOptionList("BuildingPart", buildingPartNames, buildingPartIndex);
                int nlsfbOptIndex = go.AddOptionList("NLSFB", nlsfbRegCodes, nlsfbIndex);
                int ifcEntityOptIndex = go.AddOptionList("IfcEntity", ifcEntities, ifcEntityIndex);
                int elementSimpleOptIndex = go.AddOption("SimpleElementName", elementNameSimple);
                go.AddOptionDouble("ManualAreaM2", ref manuAreaOption);
                go.AddOptionDouble("ManualMaterialPrice", ref manuMaterialPriceOption);
                go.AddOptionDouble("LabourHours", ref labourHoursOption);
                go.AddOptionDouble("ToolsCost", ref toolsPriceOption);
                
                RhinoApp.WriteLine("Element size is {0} mm x {1} mm.", width, length);

                GetResult gr = go.Get();
                if (go.CommandResult() != Rhino.Commands.Result.Success)
                    return go.CommandResult();

                if (gr == GetResult.Nothing)
                {
                    if(!newElement) newVersion = newOverwriteToggle.CurrentValue;
                    manuArea = manuAreaOption.CurrentValue;
                    manuMaterialPrice = manuMaterialPriceOption.CurrentValue;
                    labourHours = labourHoursOption.CurrentValue;
                    toolsPrice = toolsPriceOption.CurrentValue;
                    buildingPartID = buildingPartIDs[buildingPartIndex];
                    plateID = plateIDs[plateIndex];
                    nlsfb = nlsfbCodes[nlsfbIndex];
                    ifcEntity = ifcEntities[ifcEntityIndex];
                    if(plateID == 0 || buildingPartIndex == 0 || nlsfbIndex == 0 || ifcEntityIndex == 0)
                    {
                        RhinoApp.WriteLine("Plate, Building part, NLSFB and IFCentity cannot be NULL.");
                        continue;
                    }
                    break;
                }
                if (gr == GetResult.Option)
                {
                    if (go.OptionIndex() == buildingPartOptIndex)
                    {
                        buildingPartIndex = go.Option().CurrentListOptionIndex;
                    }
                    else if (go.OptionIndex() == plateOptIndex)
                    {
                        plateIndex = go.Option().CurrentListOptionIndex;
                    }
                    else if (go.OptionIndex() == ifcEntityOptIndex)
                    {
                        ifcEntityIndex = go.Option().CurrentListOptionIndex;
                    }
                    else if (go.OptionIndex() == nlsfbOptIndex)
                    {
                        nlsfbIndex = go.Option().CurrentListOptionIndex;
                    }
                    else if (go.OptionIndex() == elementSimpleOptIndex)
                    {
                        GetString gst = new GetString();
                        gst.SetCommandPrompt("Simple Element Name");
                        if (gst.GetLiteralString() == GetResult.String)
                        {
                            elementNameSimple = gst.StringResult();
                        }
                    }
                }
            }

The code will not work directly if you copy paste it into your own visual studio, because there is some lists (like plateNames) and indexes (like plateIndex) that I initialized and assigned earlier in the code and it is too complex to put it here. But you can adapt the code to make it work!

1 Like