Custom colors

How to run that script in Rhino? :slight_smile:

Currently, that’s about the only alternative. You don’t need sixteen scripts, only one in which you change the RGB values for each color. Instead of toolbar buttons, it’s also possible to create a drop-down list box with color names to choose from - and I guess with ETO you might even be able to add a color swatch for each - that part is beyond my current scripting skillset.

I have the basic colors set up in a flyout toolbar:


LMB changes selected objects’ color to desired color, RMB changes all selectable objects having the same color as selected object(s) to desired color.

Here is a python code sample for a drop-down list color picker. It uses a dictionary structure to associate each color name with its RGB value. The dictionary keys (names) are first recalled to constitute the list of names to show in the drop-down picker box, then the chosen name is used to query the dictionary for the color RGB value associated with the name to apply to the selected objects.
(the same can be done with layer colors)

import rhinoscriptsyntax as rs

def CustomColorDict():
    #create a dictionary of keys (color names) and values (R,G,B)
    color_dict={}
    color_dict["White"]=(255,255,555)
    color_dict["Light Gray"]=(230,230,230)
    color_dict["Medium Gray"]=(190,190,190)
    color_dict["Dark Gray"]=(105,105,105)
    color_dict["Black"]=(0,0,0)
    color_dict["Fire"]=(255,0,0)
    color_dict["Earth"]=(0,127,0)
    color_dict["Air"]=(63,63,255)
    color_dict["Water"]=(0,127,255)
    color_dict["Berry"]=(235,0,117)
    color_dict["Orange"]=(237,118,48)
    color_dict["Lemon"]=(253,208,28)
    color_dict["Lime"]=(111,202,33)
    color_dict["Turquoise"]=(13,160,209)
    color_dict["Grape"]=(127,127,255)
    color_dict["Eggplant"]=(73,73,165)
    return color_dict

def CustomColorListPicker():
    obj_ids=rs.GetObjects("Select objects to change color",preselect=True)
    if not obj_ids: return
    
    #import the dictionary
    custom_colors=CustomColorDict()
    
    #list box with dictionary keys (color names) to choose from
    choice=rs.ListBox(custom_colors.keys(),"New color for objects")
    if not choice: return
    
    #apply chosen color key's value (RGB) to the selected objects
    for obj_id in obj_ids: rs.ObjectColor(obj_id,custom_colors[choice])
    rs.UnselectObjects(obj_ids)

CustomColorListPicker()
1 Like

I’m currently running it from here, although I’ll share whem I figure out how to bind it to a button.

Ah yes, it occurs to me now that I can pass a color name as a variable to the python script. I’ve said it before, but it’s really time for me to go through the Python training materials. Your flyout menu is a nice solution.

Here is a python code sample for a drop-down list color picker. It uses a dictionary structure to associate each color name with its RGB value. The dictionary keys (names) are first recalled to constitute the list of names to show in the drop-down picker box, then the chosen name is used to query the dictionary for the color RGB value associated with the name to apply to the selected objects.
(the same can be done with layer colors)

You’re too kind, thank you for this.

Before:

After:

Just one more question please, then I promise that I’ll put this tired old thread back to bed:

The list comes up in no apparent order, is there a way to keep the order of the Dictionary intact as it was declared in the script?

1 Like

Hi all,

I have an idea on this problem.
It is quite possible to use the palette from the Materials.
The result data to copy and past into Object Properties or in the Layer Color.

To do this need to do a little preparation.
First, copy the Shaded mode in order to copy all the lighting settings.
Light scheme and light method.

In the new Copy of Shaded need to change the Shaded settings.
Replace the “Custom material for all objects” to “Rendering material”

In the Material Editor create new material (custom). And give a new name. For example “Shaded Mode”.
And set up material setting from the Shaded Mode to Custom Material.

Gloss Finish 50
Enviroument: rhino_shhed_mode_emap_beckground.png, and set 30%.

Render material is ready to use. It is fully consistent with the material to which we are accustomed to Shaded Mode.

Now sellect the object which we want to assign an individual color.

_-SetObjectDisplayMode _Pause “Copy of Shaded”

Open the layers and open the Layer Material panel.
Open the palette and configure the color. It works interactive.
This palette from Materials has all “Custom colors”.

Interactive

Copy Hex Code.
Past Hex In Layer or Display Color.

_SetObjectDisplayMode _Pause _Mode=_UseView

I don’t know how to write macro or script. I do not have enough knowledge. But the algorithm is like that.

Put the object into Copy of Shaded
Open the palette of materials
Create new Custom material
Copy the hex
Insert the hex into the layer or properties of the object.
Change the Object DisplayMode to UseView.

If someone writes a script using this algorithm, then it will be very cool. In one script two tasks will be resolved. Custom Colors and Interactive Color Settings.

Recently I made a request related to the problem of interactive mode for color settings:

Yes, I wasn’t really thinking about that at the time. The problem is dictionary objects in IronPython 2.7 are actually unordered key-value pairs, you could sort them alphabetically, but keeping them in the same order as originally listed is not easily possible. Later versions of CPython can preserve dictionary order apparently.

So, another way to do this is to just create a nested list or two parallel lists with color names and color RGB values. That way they will stay in list order.

import rhinoscriptsyntax as rs

def CustomColorList():
    #create a nested list of tuples of (color name,(r,g,b))
    color_list=[]
    color_list.append(("White",(255,255,555)))
    color_list.append(("Light Gray",(230,230,230)))
    color_list.append(("Medium Gray",(190,190,190)))
    color_list.append(("Dark Gray",(105,105,105)))
    color_list.append(("Black",(0,0,0)))
    color_list.append(("Fire",(255,0,0)))
    color_list.append(("Earth",(0,127,0)))
    color_list.append(("Air",(63,63,255)))
    color_list.append(("Water",(0,127,255)))
    color_list.append(("Berry",(235,0,117)))
    color_list.append(("Orange",(237,118,48)))
    color_list.append(("Lemon",(253,208,28)))
    color_list.append(("Lime",(111,202,33)))
    color_list.append(("Turquoise",(13,160,209)))
    color_list.append(("Grape",(127,127,255)))
    color_list.append(("Eggplant",(73,73,165)))
    return color_list

def CustomColorListPicker():
    obj_ids=rs.GetObjects("Select objects to change color",preselect=True)
    if not obj_ids: return
    
    #import the color list, and "unzip" it into two parallel lists (python trick)
    color_names,colors=zip(*CustomColorList())
    
    #list box with color names to choose from
    choice=rs.ListBox(color_names,"New color for objects")
    if not choice: return
    
    #get index of chosen name in color list names
    idx=color_names.index(choice)
    
    #apply chosen color names' associated value (RGB) to the selected objects
    for obj_id in obj_ids: rs.ObjectColor(obj_id,colors[idx])
    rs.UnselectObjects(obj_ids)

CustomColorListPicker()
3 Likes

That’s perfect!

Here’s a (very) slightly modified script, to change the selected object’s layer color. I put both versions on a button.

import rhinoscriptsyntax as rs

def CustomColorList():
   #create a nested list of tuples of (color name,(r,g,b))
   color_list={}
   color_list.append(("White",(255,255,555)))
   color_list.append(("Light Gray",(230,230,230)))
   color_list.append(("Medium Gray",(190,190,190)))
   color_list.append(("Dark Gray",(105,105,105)))
   color_list.append(("Black",(0,0,0)))
   color_list.append(("Fire",(255,0,0)))
   color_list.append(("Earth",(0,127,0)))
   color_list.append(("Air",(63,63,255)))
   color_list.append(("Water",(0,127,255)))
   color_list.append(("Berry",(235,0,117)))
   color_list.append(("Orange",(237,118,48)))
   color_list.append(("Lemon",(253,208,28)))
   color_list.append(("Lime",(111,202,33)))
   color_list.append(("Turquoise",(13,160,209)))
   color_list.append(("Grape",(127,127,255)))
   color_list.append(("Eggplant",(73,73,165)))
   return color_list

def CustomColorListPicker():
   obj_ids=rs.GetObjects("Select objects to change the color of their layer(s)",preselect=True)
   if not obj_ids: return

   #import the color list, and "unzip" it into two parallel lists (python trick)
   color_names,colors=zip(*CustomColorList())

   #list box with color names to choose from
   choice=rs.ListBox(color_names,"New color for object layer")
   if not choice: return

   #get index of chosen name in color list names
   idx=color_names.index(choice)

   #apply chosen color names' associated value (RGB) to the selected objects' layer(s)
   for obj_id in obj_ids:
      obj_layer=rs.ObjectLayer(obj_id)
      rs.LayerColor(obj_layer,colors[idx])
   rs.UnselectObjects(obj_ids)

CustomColorListPicker()

Thanks for the code!

1 Like

It gives the following error message on my Rhino 7:

File "C:\Users\Bobi\AppData\Local\Temp\TempScript.py", line 3
    import rhinoscriptsyntax as rs
    ^
SyntaxError: unexpected indent

You need to be careful when copying and pasting Python code, the code flow is based on indents. You might have accidentally inserted a tab or a space at the top line.

Edit - I copied out @hanscad 's code above and pasted it into a text editor, and there are only 3 spaces used as an indent, not the usual four… It still will work if the indents are the same everywhere, but that might be causing the problem.

1 Like

Note that in addition to the indent problem mentioned above, you have color_list={} on line 6 with curly brackets which defines an empty dictionary… they should be square brackets to define an empty list.

Here is my version of the code, the main difference is that above, if you have many selected objects on the same layer, it will reassign the color to the layer as many times as there are selected objects on that layer. I used instead a set object to create a set of unique layer names from the selected objects, and then assigned the color only once to each of those layers.

import rhinoscriptsyntax as rs

def CustomColorList():
    #create a nested list of tuples of (color name,(r,g,b))
    color_list=[]
    color_list.append(("White",(255,255,555)))
    color_list.append(("Light Gray",(230,230,230)))
    color_list.append(("Medium Gray",(190,190,190)))
    color_list.append(("Dark Gray",(105,105,105)))
    color_list.append(("Black",(0,0,0)))
    color_list.append(("Fire",(255,0,0)))
    color_list.append(("Earth",(0,127,0)))
    color_list.append(("Air",(63,63,255)))
    color_list.append(("Water",(0,127,255)))
    color_list.append(("Berry",(235,0,117)))
    color_list.append(("Orange",(237,118,48)))
    color_list.append(("Lemon",(253,208,28)))
    color_list.append(("Lime",(111,202,33)))
    color_list.append(("Turquoise",(13,160,209)))
    color_list.append(("Grape",(127,127,255)))
    color_list.append(("Eggplant",(73,73,165)))
    return color_list

def ObjsLayerColorsFromList():
    msg="Select objects to change the color of their layer(s)"
    obj_ids=rs.GetObjects(msg,preselect=True)
    if not obj_ids: return
    rs.UnselectObjects(obj_ids)
    
    #create a set of unique layer names of selected objects
    obj_layers=set()
    for obj_id in obj_ids: obj_layers.add(rs.ObjectLayer(obj_id))

    #import the color list, and "unzip" it into two parallel lists (python trick)
    color_names,colors=zip(*CustomColorList())

    #list box with color names to choose from
    choice=rs.ListBox(color_names,"New color for object layer")
    if not choice: return

    #get index of chosen name in color list names
    idx=color_names.index(choice)

    #apply chosen color names' RGB value to the selected objects' layer(s)
    for obj_layer in obj_layers: rs.LayerColor(obj_layer,colors[idx])

ObjsLayerColorsFromList()
4 Likes

All my python has been in mu editor until now, but I was a little surprised the python editor in Rhino doesn’t seem to really care much about spacing, nor does it appear to have an auto-format function.

I put the curlies because when I used brackets it made a .

Auto format no, but the tab key indents 4 spaces. I haven’t tried the new editor for V8 yet.

Curly brackets in Python make a completely different object, they are not interchangeable with square brackets.

You might implement OrderedDict, it’s available in IronPython 2.7. I’ve had some performance issues with it on a large dictionaries, but for this case it’ll likely not be a concern.

https://docs.python.org/2.7/library/collections.html#collections.OrderedDict

1 Like