Wish: More UserData like SetUserText(): SetUserBool() and SetUserList()

@dale Would it be possible to add more user data types ala rs.setUserText()?

I use rs.SetUserText() to add configurable values to the objects we make.
(And then run an update script that reads these values, regenerates the geometry and replaces the original)

I would love to have a rs.SetUserBool() and rs.SetUserList() where:
rs.SetUserBool() would give us a toggle button and where
rs.SetUserList() would give us the option to choose from a list of predefined values.

Or a simpler version:
Let rs.SetUserText() accept True and False and if those are present show a toggle instead of text:

Instead of sticking to rhinoscriptsyntax you could venture into directly using the UserDictionary property on GeometryBase Class, which is essentially what setting a user text will be using.

The UserDictionary will give you an instance of ArchivableDictionary Class which has a method ArchivableDictionary.Set Method (String, Boolean) with which you already can set the boolean to your geometry.

Check ArchivableDictionary.Set Method to see what you can set to your geometry.

obj.Geometry.UserDictionary.Set("Feature", True)
1 Like

Thanks for trying Nathan, but I am afraid I am way to low level for this… I don’t understand how to use obj.Geometry.UserDictionary.Set(“Feature”, True)

Here is what I tried, and from here I don’t know how to search for a solution.

import rhinoscriptsyntax as rs
import Rhino
import scriptcontext as sc

# Select object
go = Rhino.Input.Custom.GetObject()
go.SetCommandPrompt("Select object")
go.SubObjectSelect = False
go.GroupSelect = False
go.GetMultiple(1, 1)

if go.CommandResult() == Rhino.Commands.Result.Success:
    print go.CommandResult()
    obj = go.Object(0)
    ### Here is where I fail...
    obj.Geometry.UserDictionary.Set("Feature", True)

I find Python so much easier for my brain to use, so could you please try to explain why setting up obj the way I did was wrong?

What is the error you get? At first glance it looks ok.

Wait, try this:

if go.CommandResult() == Rhino.Commands.Result.Object:

Or use the “simple” object getter, RhinoGet.GetOneObject(…)
https://developer.rhino3d.com/api/RhinoCommon/html/Overload_Rhino_Input_RhinoGet_GetOneObject.htm

1 Like

Hi Menno, I still don’t get results, here is the latest test, but I get the error:

Message: ‘builtin_function_or_method’ object has no attribute ‘UserDictionary’

Traceback:
line 5, in , “…\Temp\TempScript.py”

import Rhino
filter = Rhino.DocObjects.ObjectType.Brep
rc, objref = Rhino.Input.RhinoGet.GetOneObject("Select brep", False, filter)
if objref:
    objref.Geometry.UserDictionary.Set("Feature", True)

I presume I should venture into the GeometryBase Class somehow, but this is too abstract for me to understand :slight_smile: (And I must admit that I fear that if I start making too complex stuff I will suffer when maintaining it in the future, as using the tools are my main focus, not programming… :sweat_smile:)

Geometry is a method, not a property, on the ObjRef class. I understand it may be confusing, as it is a property on the RhinoObject class.

objref.Geometry().UserDictionary.Set("Feature", true);
# or
objRef.Object().Geometry.UserDictionary.Set("Feature", true);

All RhinoCommon classes are documented, e.g. ObjRef is documented here:

OK, that was a long way to a destination unknown :slight_smile:
I didn’t get results I understood with TryGetBool so I used a Try Except solution instead. This now works:

import Rhino
filter = Rhino.DocObjects.ObjectType.Brep
rc, objref = Rhino.Input.RhinoGet.GetOneObject("Select brep", False, filter)

### Toggle the bool
if objref:
    try:
        if objref.Geometry().UserDictionary.GetBool("Feature") == False:
            objref.Geometry().UserDictionary.Set("Feature", True)
        else:
            objref.Geometry().UserDictionary.Set("Feature", False)
    except:
        objref.Geometry().UserDictionary.Set("Feature", True)
    print objref.Geometry().UserDictionary.GetBool("Feature")

But it doesn’t show up in the userText panel in Rhino, so I am kind of back where I started, unless there is something else I don’t understand yet (frankly I must say I don’t understand what I have done so far either :wink: )

To recap the initial question:
Is it possible to add a True/False toggle to UserText?

The way I understand it is, user text is set on the object attributes (not geometry) like so

Obj.Attributes.SetUserString(string key, string value)

This you will see in the user text panel, as string pairs. As this only supports strings as values, you won’t be able to get a toggle/checkbox.

1 Like

You are assigning the UserText to the geometry not the object.

see also: Difference between Attribute user text and Geometry user text?

Try

objref.Object().Attributes.UserDictionary.Set("Feature", True)

cant test it right now, but if objref is an object not an objectreference

objref.Attributes.UserDictionary.Set("Feature", True)

Thanks Roger!
That works fine, it toggles as it should now. But (sorry for the noob question) but this attribute isn’t available through any standard panels like UserText is it? I understand I can make my own GUI though, but I would prefer not to if I can avoid it.

I think the way you want it is not possible. If you look inside the “SetUserText” code, it’s simply:

obj = rhutil.coercerhinoobject(object_id, True, True)
    if type(key) is not str: key = str(key)
    if value and type(value) is not str: value = str(value)
    if attach_to_geometry: return obj.Geometry.SetUserString(key, value)
    return obj.Attributes.SetUserString(key, value)

Note the last line, obj.Attributes.SetUserString(key,value). Again, adding the data to the attributes of the object(note that object and geometry in rhino is not the same).
Now if you look into the rhino common namespace/object attributes class you can see that there exist a seperate method “setusertext” to explicitly set user text. Meaning, the userdictionary where you can add your bool types and the usertext are different(otherwise why not use the set method of the user dictionary).
Also, if you look into the python method above, you can see that in the second line the code checks if the value to be entered into the value-field is a string(text object) - if not, it will convert it.

So, what you want is not possible in that way, you have to use your own panel.

1 Like