"Great customer service. The folks at Novedge were super helpful in navigating a somewhat complicated order including software upgrades and serial numbers in various stages of inactivity. They were friendly and helpful throughout the process.."
Ruben Ruckmark
"Quick & very helpful. We have been using Novedge for years and are very happy with their quick service when we need to make a purchase and excellent support resolving any issues."
Will Woodson
"Scott is the best. He reminds me about subscriptions dates, guides me in the correct direction for updates. He always responds promptly to me. He is literally the reason I continue to work with Novedge and will do so in the future."
Edward Mchugh
"Calvin Lok is “the man”. After my purchase of Sketchup 2021, he called me and provided step-by-step instructions to ease me through difficulties I was having with the setup of my new software."
Mike Borzage
November 17, 2025 2 min read

Rhino.Python lets you build lightweight tools that remove repetitive clicks and enforce your team’s standards. Here’s how to start quickly and a practical script you can adopt today.
Sample tool: batch rename and colorize layers with persistent options (great for project standards). Paste into the editor, save, and run.
import rhinoscriptsyntax as rs
import scriptcontext as sc
import System.Drawing as sd
def main():
layers = rs.LayerNames() or []
if not layers:
rs.MessageBox("No layers in this document.", 48, "Rhino.Python")
return
# Sticky options persist between runs
prefix = rs.GetString("Prefix (Enter for none)", sc.sticky.get("rpy_prefix", "PRJ_"))
if prefix is None: return
suffix = rs.GetString("Suffix (Enter for none)", sc.sticky.get("rpy_suffix", ""))
if suffix is None: return
colorize = rs.GetBoolean(
"Apply colors to layers?",
("Colorize", "No", "Yes"),
sc.sticky.get("rpy_colorize", True)
)
if colorize is None: return
purge = rs.GetBoolean(
"Purge empty layers after rename?",
("Purge", "No", "Yes"),
sc.sticky.get("rpy_purge", True)
)
if purge is None: return
sc.sticky["rpy_prefix"] = prefix
sc.sticky["rpy_suffix"] = suffix
sc.sticky["rpy_colorize"] = colorize[0]
sc.sticky["rpy_purge"] = purge[0]
palette = [
sd.Color.FromArgb(230,57,70),
sd.Color.FromArgb(29,53,87),
sd.Color.FromArgb(69,123,157),
sd.Color.FromArgb(42,157,143),
sd.Color.FromArgb(233,196,106),
sd.Color.FromArgb(244,162,97),
sd.Color.FromArgb(231,111,81),
sd.Color.FromArgb(168,218,220),
]
renamed = 0
i = 0
for old in layers:
if not rs.IsLayer(old):
continue
base = old.split("::")[-1] # keep leaf names tidy
newname = "{}{}{}".format(prefix or "", base, suffix or "")
target = newname
if rs.IsLayer(target) and rs.LayerId(target) != rs.LayerId(old):
k = 1
while rs.IsLayer(target):
target = "{}_{}".format(newname, k)
k += 1
if target != old:
rs.RenameLayer(old, target)
renamed += 1
if colorize[0]:
rs.LayerColor(target, palette[i % len(palette)])
i += 1
if purge[0]:
for lname in (rs.LayerNames() or []):
objs = rs.ObjectsByLayer(lname, select=False)
if not objs:
try: rs.DeleteLayer(lname)
except: pass
rs.StatusBarMessage("{} layers processed.".format(renamed))
if __name__ == "__main__":
main()
Need Rhino licenses, upgrades, or expert advice? Visit NOVEDGE at novedge.com and explore Rhino solutions at NOVEDGE | Rhinoceros. Their team can help you standardize your scripting workflow across your studio.
You can find all the Rhino products on the NOVEDGE web site at this page.

November 17, 2025 13 min read
Read MoreSign up to get the latest on sales, new releases and more …