Writing a Useful Snippet
This article focuses on the ideation aspect of SketchUp Extension development. For the technical aspects of how to create a valid SketchUp Extension, see Creating a SketchUp Extension. If you've never written code before, you may want to start with Writing Your First Code.
When making a SketchUp extension, you first need an idea. The idea can be from your own modeling workflow, maybe a task you are currently doing manually but want to speed up with automation, or an idea from a customer or an investor. For beginners, something close to your own workflow is often easiest.
If you are new to coding and don't know the limitations, we'd recommend starting to automate some of the most dull mindless clicking in your workflow. Something with no creative input or decision making. Something that can be clearly defined in words and delegated to the least creative but most meticulous and tireless boring person you could think of. Or really, delegated to a machine.
It's also good to avoid something that requires a kind of visual intuition. Some tasks, like packing objects efficiently in a tight space can be easy for a human to just see the answer to, but it's trickier to write down the instructions as mathematical formulas.
Example Snippets
These snippets could be typed and worked on in the SketchUp Ruby Console (Extensions > Developers > Ruby Console) but as they get longer that gets inconvenient. You could also use a code editor, save them as an .rb file. You can use the load method followed by the file path (within quotes) in the Ruby Console to load and run the file. To later reload, you can simply press the up arrow key and Enter. You could also use Eneroth Script Runner to drag and drop the .rb file into SketchUp, or use Ruby Console+.
Randomize Colors
Maybe you've drawn a bookcase, a container terminal or a car park and want to apply a bunch of random colors to a large set of objects. For a small project you can easily click a bunch of times in the Materials panel to pick different colors but when the project grows we want a better solution.
Computers are great at iterating over objects and doing repetitive tasks to them, without getting bored or tired, like this:
Sketchup.active_model.start_operation("Paint Stuff", true)
Sketchup.active_model.selection.each do |entity|
entity.material = "red"
end
Sketchup.active_model.commit_operationstart_operation and commit_operation tells SketchUp that the code in between is a single action that should be possible to undo in just one step. If we don't do this, you may need to undo hundreds of times to go back to restore the previous colors. But if you accidentally undo one time too much, you instead revert the work you want to keep.
If used on groups and components as opposed to directly on faces, make sure the content is painted with the default material (aka no material) for the material of the container to be displayed on its content. (Learn more about material inheritance in SketchUp.)
But so far everything selected just turned red. This could just as well have been done with the Paint Bucket tool! Let's randomize the colors. For this it's easier to create a custom color, based on numbers, not named colors.
color = Sketchup::Color.new(255, 255, 0)Computers typically use RGB colors, colors defined as a mix of the three additive primary colors red, green and blue. The value of each channel can vary between 0 (darkness) and 255 (full light). Red and green combined makes yellow.
Computers can generate psuedo-random numbers. 256 here is for the 256 possible values from 0 to 255.
number = rand(256)You can combine this to generate a random color.
color = Sketchup::Color.new(rand(256), rand(256), rand(256))And plug it into the script above, to do it for each selected entity.
Sketchup.active_model.start_operation("Paint Stuff")
Sketchup.active_model.selection.each do |entity|
entity.material = Sketchup::Color.new(rand(256), rand(256), rand(256))
end
Sketchup.active_model.commit_operationThis is a tiny script of just a few lines that can add actual value to a SketchUp Project! But it's far from perfect. You may have noticed the In Model view in the Materials panel is now quickly flooded with materials, many of them being almost identical. Also, as a user you have no control what colors are used.
To avoid flooding the model with new materials, we can use existing materials within the model. This code gives us an array of all materials in the model.
materials = Sketchup.active_model.materialsThe sample method can be used to pick a random element from an array.
favorite_tool = ["Push Pull", "Orbit", "Swedish Key", "Line"].sampleWe can combine these to pick any random material from the model, and use it in our previous code.
Sketchup.active_model.start_operation("Paint Stuff")
Sketchup.active_model.selection.each do |entity|
entity.material = Sketchup.active_model.materials.sample
end
Sketchup.active_model.commit_operationThis solved the problem of flooding the model with new materials, but we still have little control of the materials assigned. In a simple model with just a scale figure, we may get a nice color distribution, but for an actual project we could now have cars made of carpet and shipping containers made out of leaves. That's not very good.
Another approach is to not pick any random color within the model, but pick a color already present in the selection set. For this we need to first collect the colors of the selection.
materials = []
Sketchup.active_model.selection.each do |entity|
materials << entity.material
end[] creates an empty array. << is used to append an element to the array.
A shorter way to do the same thing in Ruby is to use the map method.
materials = Sketchup.active_model.selection.map { |e| e.material }We can shorten the code even further with a handy Ruby idiom.
materials = Sketchup.active_model.selection.map(&:material)Then we can sample from this new list of materials.
Sketchup.active_model.start_operation("Paint Stuff")
Sketchup.active_model.selection.each do |entity|
entity.material = materials.sample
end
Sketchup.active_model.commit_operationThese could be combined to a single chunk of code, to redistribute the materials already used in that selection, but also kept separate if you want to sample from one selection and apply to another.
You can also use materials.uniq! to remove any duplicates from the array. This means all materials are equally likely to get used. Otherwise the likelihood is weighted by their original frequency in the selection.
You can also use materials.compact! to remove nil values, i.e. the absence of a material. This means every selected entity gets painted with a material and not reverted to the default (none-)material.
This code for randomly distributing existing materials can also be used in tandem with our previous code for randomly generating materials, with you the user manually picking out the colors you like in between. The possibilities are near endless!
With snippets you can quickly adjust and customize on the fly. Once you are happy with the functionality, you can wrap the chunks of code into methods, add menu entries or toolbar commands and properly package it as an extension.
If worked into an actual extension, you could have one button to generate random new materials, and another button to distribute the currently applied materials, with the user manually pruning their materials in between. There could also be separate buttons for sampling and applying. It takes a bit of testing and tweaking to see what makes the most sense for practical usage.
Book Titles

Another script useful for a bookcase is the book title script I made when moving in 2017. I wanted to plan my new bookcase in advance and naturally modeled my books in SketchUp. In practice, I modeled one generic book and scaled it to different sizes and applied different materials.
You could stop there but I also wanted to see the titles on the spines of all the books, to aid when categorizing them. For this I created a new component for each book, wrapping the sized and painted generic book component along with a 3D text on the spine. For a small set of books you could manually create the 3D text and position it on each spine, but for more than a handful this quickly gets tedious.
Instead I used a small little script to create the 3D text, based on the definition name of the component. Then the name can be controlled from Entity Info.
model = Sketchup.active_model
model.start_operation("Label Books", true)
model.selection.each do |entity|
label = entity.definition.entities.add_group
label.entities.add_3d_text(entity.definition.name, TextAlignLeft, "arial")
end
model.commit_operationThis first version iterates over the selected entities and adds a group with their definition name as text. The text is in the wrong place, with the wrong orientation and wrong size, but it is a start. To actually see the text, you may need to turn on Back Edges or X-Ray.

If the book components are not already unique (have individual definitions), this script can't add individual labels to them. To make them unique you can right click at each one and hit Make Unique. If you want to reuse the same generic book component between them to reduce the file size a bit, you can enter the component and make a generic component out of all its geometry, before making the individual instances unique.
Before adjusting the placement, we can change the script to purge any previously added text. This means we don't have to undo between iterations when developing. It also helps in actual usage, in case a book is renamed. In practice, to add a book to my collection, I make a copy of any nearby book, make it unique, change the size and material of its content, rename it and run the script again to add the new title.
For this, we can use a Tag (formerly called Layer) to differentiate what the script draws from what we draw manually as users.
model = Sketchup.active_model
model.start_operation("Label Books", true)
# layers.add either creates a new Tag or returns the existing one by that name.
tag = model.layers.add("Book labels")
model.selection.each do |entity|
entities = entity.definition.entities
old_label = entities.find
