Skip to content

Scripting API

The gem handle

from ArtisanPlugin.Scripting import GemApi as gem, Transaction

Everything GemApi.Create, Find, All, Selected, ByLayer and ByMaterial hand back is an IGem. A handle is not a copy of the stone: it holds nothing but the object’s Guid and re-reads the document every time you touch it, so it always tells you the truth about the gem as it stands right now.

Usage

g = gem.Selected()[0]
print(g.Shape, g.Material, g.CaratWeight, g.SizeX, g.LayerName)

with Transaction.Begin("Enlarge the centre stone"):
    g.SetCaratWeight(1.25)
    g.Rotate(45)

Read-only properties

No licence check, no undo record, no transaction needed.

MemberMeaning
IdThe Rhino object Guid backing the handle
ShapeCut name, e.g. ROUND, PRINCESS, MARQUISE
MaterialCompound name, e.g. Diamond, Ruby
CaratWeightWeight in carats
SizeX / SizeY / SizeZDimensions in mm
PositionOrigin of the gem’s plane, on the girdle
PlaneThe gem’s full placement plane - origin and orientation
LayerNameFull path of the layer the gem sits on

Position and Plane report the gem’s live plane, kept in the object’s user dictionary and updated on every transform. Only if that entry is missing do they fall back to the plane captured when the gem was created.

Mutations

Each one calls LicenseGate.RequireValid() before touching the document and ends with a viewport redraw. All of them belong inside a Transaction if you want the script to undo as a single step.

MemberMeaning
SetMaterial(materialName)Change the compound; the display material is reapplied
SetCaratWeight(caratWeight)Resize by carat, keeping shape, material, plane and layer
SetSize(sizeX, sizeY, sizeZ)Resize to explicit mm dimensions
Scale(factor)Uniform scale of the current size (factor > 0)
Move(translation)Translate by a Vector3d
SetPlane(plane)Re-place the gem: move and orient so its plane coincides with plane
Rotate(degrees)Spin around the gem’s own Z axis through its plane origin; positive is counter-clockwise
Flip()Turn upside down - 180 degrees around its own X axis, in place
Copy() / Copy(translation)Duplicate in place or displaced; returns the new gem’s handle
Delete()Remove the gem from the document

Select(on) toggles the gem’s selection in the viewport and redraws. It is not a document mutation: no undo record, no licence gate. Use it to highlight what a script produced.

Handle semantics

Guids are stable across every mutation but Copy. Move, SetPlane, Rotate and Flip transform the object in place with deleteOriginal: true, which preserves the Guid. SetMaterial only edits attributes. The three resizers - SetCaratWeight, SetSize and Scale - regenerate the gem mesh at the new proportions and swap it in with Replace rather than add-and-delete, deliberately so the object keeps its Guid and its attributes (layer, material, name). A handle you took before a resize is still valid afterwards. Only Copy produces a new object, and it hands you a fresh handle to it; the source handle is untouched.

Handles are live, never cached. Neither the Rhino object nor the underlying gem is held on to: every property read and every mutation resolves the Guid against the active document first. Two handles to the same gem therefore always agree, and a handle picks up changes made by other scripts, by commands or by the user in between calls.

Touching a deleted gem throws. Once the object is gone - or was never an Artisan gemstone - resolving fails with an InvalidOperationException:

Gem 4a1f… no longer exists in the document.

That applies to reads as much as to mutations, so a stale handle fails loudly rather than silently doing nothing. Delete() does not invalidate the variable in Python; it invalidates the object, and the next access raises.

Copy keeps the source’s layer; Create does not. A copy is rebuilt through the same generator as a new gem, then explicitly moved onto the source gem’s layer, so duplicating a stone that lives on a custom layer keeps it there. GemApi.Create, by contrast, always drops new gems on the primary gems layer. Copy also carries over shape, material, size and orientation, and reapplies the gemstone material.

Validation happens before anything is written. Arguments are checked first, so a rejected call leaves the document untouched:

CallRejected whenMessage
SetMaterial(name)Empty or whitespaceMaterial name is required.
SetMaterial(name)Not a known compoundUnknown gem material ‘xxx’.
SetCaratWeight(ct)ct <= 0Carat weight must be > 0.
SetSize(x, y, z)Any dimension <= 0Gem dimensions must be > 0.
Scale(factor)factor <= 0Scale factor must be > 0.
SetPlane(plane)Plane is not validTarget plane is not valid.

Material names are normalised before parsing: trimmed, with dashes and spaces turned into underscores, matched case-insensitively. "pink sapphire", "Pink-Sapphire" and "PINK_SAPPHIRE" all reach the same compound. Use GemApi.Materials() when in doubt.

Two further failures come from the document rather than from your arguments: No active document. when there is no open RhinoDoc, and Failed to replace gem … while resizing. if the rebuild cannot be swapped in.

The complete interface, member by member, is on the IGem page.