mirror of
https://github.com/github/awesome-copilot.git
synced 2026-05-30 02:21:46 +00:00
new skill rhino3d-scripts (#1705)
* resolve readme validate * Apply suggestions from code review Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: John Haugabook <johnhaugabook@gmail.com> * rhino3d-scripts: rm reference to deprecated VBScript --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
# Macros, Loading, and Running Scripts
|
||||
|
||||
## Command Macros (no script needed)
|
||||
|
||||
A macro is a string of command-line input. Anywhere Rhino accepts a command (alias, toolbar button, `_ReadCommandFile`), you can place a macro.
|
||||
|
||||
### Syntax rules
|
||||
|
||||
| Token | Meaning |
|
||||
|---|---|
|
||||
| `!` | **Cancel** any currently running command before this one starts. Always start macros with `!`. |
|
||||
| `_` | Use the **English** (invariant) command name, so the macro works in any locale. |
|
||||
| `-` | Run the command in **script mode** — suppress dialogs, accept input from the macro string. |
|
||||
| `_Enter` | Press Enter at the current prompt. |
|
||||
| `Pause` | Stop and wait for the user to supply this input interactively. |
|
||||
| `;` | Comment to end of line. |
|
||||
| Newline | Same as a space — a separator between tokens, not a command terminator. |
|
||||
|
||||
### Example macros
|
||||
|
||||
```text
|
||||
! _-Line 0,0,0 10,0,0
|
||||
! _-Circle 0,0,0 5 _Enter
|
||||
! _SelAll _Delete
|
||||
! _-Properties _Object _Name "MyObject" _EnterEnd _Enter
|
||||
! _-RunPythonScript "MyScript.py"
|
||||
```
|
||||
|
||||
## Running Saved Scripts
|
||||
|
||||
### Python (`.py`)
|
||||
|
||||
```text
|
||||
_-RunPythonScript "C:\Users\example\Scripts\MyScript.py"
|
||||
```
|
||||
|
||||
Or, with the script folder on the search path:
|
||||
|
||||
```text
|
||||
_-RunPythonScript "MyScript.py"
|
||||
```
|
||||
|
||||
`_EditPythonScript` opens the legacy editor; `_ScriptEditor` (Rhino 8) opens the unified editor with Python 3, VB, and C#.
|
||||
|
||||
### RhinoScript (`.rvb`, `.vbs`)
|
||||
|
||||
Two steps: **load** the file (registers its subs/functions), then **run** a named sub.
|
||||
|
||||
```text
|
||||
_-LoadScript "MyScript.rvb"
|
||||
_-RunScript MyMainSub
|
||||
```
|
||||
|
||||
A single `.rvb` can hold many subs; `_RunScript` chooses which to invoke.
|
||||
|
||||
### Search Paths
|
||||
|
||||
`Options → Files → Search paths` — folders listed here are scanned when you reference a script by bare filename. Without this, you must give a full path.
|
||||
|
||||
### Startup Scripts
|
||||
|
||||
`Options → RhinoScript → Startup` (and `Options → Python → Startup`) — files in these lists run once when Rhino opens. Useful for registering custom commands or aliases.
|
||||
|
||||
**Guard against missing document** in startup code:
|
||||
|
||||
```python
|
||||
import scriptcontext as sc
|
||||
|
||||
def startup():
|
||||
if sc.doc is None:
|
||||
return
|
||||
|
||||
startup()
|
||||
```
|
||||
|
||||
## Toolbar Buttons & Aliases
|
||||
|
||||
A toolbar button’s **Command** field is just a macro. To make a button that runs your script:
|
||||
|
||||
```text
|
||||
! _-RunPythonScript "MyScript.py"
|
||||
```
|
||||
|
||||
Set the **Tooltip** to a short description; set the icon via the button editor.
|
||||
|
||||
To create an alias: `Options → Aliases → New`. The alias name becomes a typed command; its value is the macro.
|
||||
|
||||
## Invoking Macros From a Script
|
||||
|
||||
```python
|
||||
import rhinoscriptsyntax as rs
|
||||
rs.Command("! _-Line 0,0,0 10,0,0", echo=False)
|
||||
```
|
||||
|
||||
`echo=False` suppresses command-history output but does **not** suppress prompts — always use `-` and complete every prompt within the macro string.
|
||||
@@ -0,0 +1,90 @@
|
||||
# RhinoCommon Namespace Map
|
||||
|
||||
Use this to decide which `Rhino.*` namespace to import for a task. All of these are accessible from Python with `import Rhino`.
|
||||
|
||||
## Document & Object Model
|
||||
|
||||
| Need | Namespace | Key types |
|
||||
|---|---|---|
|
||||
| The active document, units, tolerances, undo | `Rhino` | `RhinoDoc`, `RhinoApp` |
|
||||
| Reading/writing objects in the doc | `Rhino.DocObjects` | `RhinoObject`, `ObjectAttributes`, `Layer`, `ObjectType` |
|
||||
| Tables (layers, materials, blocks, dim styles) | `Rhino.DocObjects.Tables` | `LayerTable`, `InstanceDefinitionTable`, `MaterialTable` |
|
||||
| Custom per-object user data | `Rhino.DocObjects.Custom` | `UserData` |
|
||||
| File I/O (.3dm, import/export) | `Rhino.FileIO` | `File3dm`, `File3dmObject` |
|
||||
|
||||
## Geometry
|
||||
|
||||
| Need | Namespace | Key types |
|
||||
|---|---|---|
|
||||
| Points, vectors, transforms | `Rhino.Geometry` | `Point3d`, `Vector3d`, `Transform`, `Plane`, `BoundingBox` |
|
||||
| Curves | `Rhino.Geometry` | `Curve`, `NurbsCurve`, `PolylineCurve`, `LineCurve`, `ArcCurve` |
|
||||
| Surfaces & breps | `Rhino.Geometry` | `Surface`, `NurbsSurface`, `Brep`, `BrepFace`, `Extrusion` |
|
||||
| Meshes | `Rhino.Geometry` | `Mesh`, `MeshFace`, `MeshNgon` |
|
||||
| SubD | `Rhino.Geometry` | `SubD`, `SubDFace`, `SubDEdge` |
|
||||
| Geometry collections (vertices, edges, faces lists) | `Rhino.Geometry.Collections` | `MeshVertexList`, `BrepEdgeList` |
|
||||
| Intersections | `Rhino.Geometry.Intersect` | `Intersection`, `CurveIntersections` |
|
||||
| Mesh refinement | `Rhino.Geometry.MeshRefinements` | |
|
||||
| Space morphs (bend, twist, etc.) | `Rhino.Geometry.Morphs` | `BendSpaceMorph`, `TwistSpaceMorph` |
|
||||
|
||||
## User Interaction
|
||||
|
||||
| Need | Namespace | Key types |
|
||||
|---|---|---|
|
||||
| Prompts, getters, command results | `Rhino.Input` / `Rhino.Input.Custom` | `RhinoGet`, `GetObject`, `GetPoint`, `GetOption` |
|
||||
| Commands (when building a plugin) | `Rhino.Commands` | `Command`, `Result` |
|
||||
| Forms, dialogs, panels | `Rhino.UI` | `Dialog`, `Panels`, `RhinoEtoExtensions` |
|
||||
| UI controls / data sources | `Rhino.UI.Controls` | |
|
||||
| Gumball | `Rhino.UI.Gumball` | |
|
||||
|
||||
## Display & Rendering
|
||||
|
||||
| Need | Namespace | Key types |
|
||||
|---|---|---|
|
||||
| Viewports, display conduits, draw overlays | `Rhino.Display` | `DisplayPipeline`, `DisplayConduit`, `RhinoViewport` |
|
||||
| Render content (materials, environments) | `Rhino.Render` | `RenderContent`, `RenderMaterial`, `RenderTexture` |
|
||||
| Render mesh customization | `Rhino.Render.CustomRenderMeshes` | |
|
||||
| Post effects | `Rhino.Render.PostEffects` | |
|
||||
|
||||
## Runtime & Plugins
|
||||
|
||||
| Need | Namespace | Key types |
|
||||
|---|---|---|
|
||||
| Plugin lifecycle, settings | `Rhino.PlugIns` | `PlugIn`, `FileImportPlugIn`, `FileExportPlugIn` |
|
||||
| In-process Rhino (run Rhino from external .NET) | `Rhino.Runtime.InProcess` | `RhinoCore` |
|
||||
| Native interop (pointers, marshalling) | `Rhino.Runtime.InteropWrappers` | |
|
||||
| User notifications (toasts) | `Rhino.Runtime.Notifications` | |
|
||||
|
||||
## Common Patterns
|
||||
|
||||
```python
|
||||
import Rhino
|
||||
import scriptcontext as sc
|
||||
import System.Drawing
|
||||
|
||||
doc = sc.doc # Rhino.RhinoDoc
|
||||
tol = doc.ModelAbsoluteTolerance # float
|
||||
view = doc.Views.ActiveView # Rhino.Display.RhinoView
|
||||
layer_index = doc.Layers.Add("MyLayer", System.Drawing.Color.Red)
|
||||
|
||||
# Find a Rhino object from a rhinoscriptsyntax GUID
|
||||
rhobj = doc.Objects.Find(guid) # Rhino.DocObjects.RhinoObject
|
||||
geom = rhobj.Geometry # Rhino.Geometry.GeometryBase
|
||||
|
||||
# Add geometry with attributes
|
||||
attrs = Rhino.DocObjects.ObjectAttributes()
|
||||
attrs.LayerIndex = layer_index
|
||||
attrs.Name = "example"
|
||||
new_id = doc.Objects.AddCurve(curve, attrs)
|
||||
```
|
||||
|
||||
## Undo
|
||||
|
||||
```python
|
||||
undo_serial = doc.BeginUndoRecord("Batch Op")
|
||||
try:
|
||||
# ... many doc.Objects.* calls ...
|
||||
pass
|
||||
finally:
|
||||
doc.EndUndoRecord(undo_serial)
|
||||
doc.Views.Redraw()
|
||||
```
|
||||
@@ -0,0 +1,108 @@
|
||||
# `rhinoscriptsyntax` Cheatsheet
|
||||
|
||||
```python
|
||||
import rhinoscriptsyntax as rs
|
||||
```
|
||||
|
||||
## User Input
|
||||
|
||||
| Function | Returns |
|
||||
|---|---|
|
||||
| `rs.GetObject(message, filter, preselect, select)` | GUID or `None` |
|
||||
| `rs.GetObjects(message, filter)` | list of GUIDs |
|
||||
| `rs.GetPoint(message, base_point)` | `Point3d` or `None` |
|
||||
| `rs.GetString(message, default, strings)` | str |
|
||||
| `rs.GetInteger`, `rs.GetReal` | int / float |
|
||||
| `rs.GetBoolean(message, items, defaults)` | list of bools |
|
||||
|
||||
Common `rs.filter.*` flags (OR them together):
|
||||
|
||||
```
|
||||
point=1, point_cloud=2, curve=4, surface=8, polysurface=16,
|
||||
mesh=32, light=256, annotation=512, instance_reference=4096,
|
||||
text_dot=8192, grip=16384, detail=32768, hatch=65536,
|
||||
morph_control=131072, sub_d=262144
|
||||
```
|
||||
|
||||
## Creating Geometry
|
||||
|
||||
| Function | Notes |
|
||||
|---|---|
|
||||
| `rs.AddPoint(point)` | |
|
||||
| `rs.AddLine(start, end)` | |
|
||||
| `rs.AddPolyline(points)` | `points` is a list of 3-tuples |
|
||||
| `rs.AddCircle(plane_or_center, radius)` | |
|
||||
| `rs.AddArc(plane, radius, angle_deg)` | angle in **degrees** |
|
||||
| `rs.AddCurve(points, degree=3)` | NURBS through control points |
|
||||
| `rs.AddInterpCurve(points, degree=3)` | NURBS through points |
|
||||
| `rs.AddSphere(center, radius)` | |
|
||||
| `rs.AddBox(corners)` | `corners` = 8 points |
|
||||
| `rs.AddPlanarSrf(curves)` | returns list |
|
||||
| `rs.AddLoftSrf(curves, ...)` | returns list of GUIDs |
|
||||
| `rs.AddExtrusion(profile, path)` / `rs.ExtrudeCurveStraight` | |
|
||||
|
||||
## Object Properties
|
||||
|
||||
| Function | Purpose |
|
||||
|---|---|
|
||||
| `rs.ObjectLayer(id [, layer])` | get/set |
|
||||
| `rs.ObjectColor(id [, color])` | RGB tuple |
|
||||
| `rs.ObjectName(id [, name])` | |
|
||||
| `rs.ObjectType(id)` | int matching `rs.filter.*` |
|
||||
| `rs.IsCurve / IsSurface / IsBrep / IsMesh / IsPoint(id)` | |
|
||||
| `rs.DeleteObject(id)` / `rs.DeleteObjects(ids)` | |
|
||||
| `rs.CopyObject(id, translation)` | |
|
||||
| `rs.MoveObject(id, translation)` | |
|
||||
| `rs.RotateObject(id, center, angle, axis=None, copy=False)` | angle in degrees |
|
||||
| `rs.ScaleObject(id, origin, scale)` | scale is a 3-tuple |
|
||||
|
||||
## Curves
|
||||
|
||||
| Function | |
|
||||
|---|---|
|
||||
| `rs.CurveLength(id)` | |
|
||||
| `rs.CurveDomain(id)` | `(t0, t1)` |
|
||||
| `rs.EvaluateCurve(id, t)` | `Point3d` |
|
||||
| `rs.CurveStartPoint / CurveEndPoint(id)` | |
|
||||
| `rs.CurveClosestPoint(id, point)` | parameter `t` |
|
||||
| `rs.DivideCurve(id, segments, create_points=False, return_points=True)` | |
|
||||
| `rs.IsCurveClosed / IsCurvePlanar(id)` | |
|
||||
|
||||
## Layers
|
||||
|
||||
| Function | |
|
||||
|---|---|
|
||||
| `rs.AddLayer(name, color=None, visible=True, locked=False, parent=None)` | |
|
||||
| `rs.CurrentLayer([layer])` | |
|
||||
| `rs.LayerNames()` | list |
|
||||
| `rs.LayerVisible(name [, visible])` | |
|
||||
| `rs.DeleteLayer(name)` | |
|
||||
| `rs.ObjectsByLayer(name)` | list of GUIDs |
|
||||
|
||||
## Document & View
|
||||
|
||||
| Function | |
|
||||
|---|---|
|
||||
| `rs.UnitAbsoluteTolerance()` | |
|
||||
| `rs.UnitSystem()` | int (`rs.unit_system_*`) |
|
||||
| `rs.EnableRedraw(enable)` | **toggle this around bulk ops** |
|
||||
| `rs.Redraw()` | force one redraw |
|
||||
| `rs.ViewNames()` / `rs.CurrentView([name])` | |
|
||||
| `rs.ZoomExtents(view=None, all=False)` | |
|
||||
|
||||
## Selection
|
||||
|
||||
| Function | |
|
||||
|---|---|
|
||||
| `rs.SelectedObjects()` | list |
|
||||
| `rs.SelectObject(id)` / `rs.SelectObjects(ids)` | |
|
||||
| `rs.UnselectAllObjects()` | |
|
||||
| `rs.InvertSelectedObjects()` | |
|
||||
|
||||
## Macros from Script
|
||||
|
||||
`rs.Command(command_string, echo=True)` runs a macro exactly as if typed at the command line. Always prefix `!` (cancel) and `-` (no dialog):
|
||||
|
||||
```python
|
||||
rs.Command("! _-Line 0,0,0 10,0,0", echo=False)
|
||||
```
|
||||
@@ -0,0 +1,112 @@
|
||||
# VBScript Quirks for RhinoScript
|
||||
|
||||
Things that bite when writing `.rvb` / `.vbs` files and aren’t obvious to anyone whose mental model is C-family or Python.
|
||||
|
||||
## Always Start With `Option Explicit`
|
||||
|
||||
Without it, mistyping a variable name silently creates a new `Variant` set to `Empty`. Every `.rvb` file should begin:
|
||||
|
||||
```vbscript
|
||||
Option Explicit
|
||||
```
|
||||
|
||||
## No Block Scope
|
||||
|
||||
All `Dim` declarations inside a `Sub`/`Function` are hoisted to the top. A `Dim` inside an `If` block is visible after the `If` ends. Loop counters survive the loop.
|
||||
|
||||
## `Nothing` vs `Empty` vs `Null`
|
||||
|
||||
| Sentinel | Test with | Meaning |
|
||||
|---|---|---|
|
||||
| `Empty` | `IsEmpty(x)` | `Dim`’d but never assigned |
|
||||
| `Null` | `IsNull(x)` | Explicit “no value” — what `Rhino.GetObject` returns on cancel |
|
||||
| `Nothing` | `x Is Nothing` | An **object** reference that points to nothing — only for `Set` variables |
|
||||
|
||||
Wrong sentinel → silently false.
|
||||
|
||||
## Parentheses Change Semantics
|
||||
|
||||
```vbscript
|
||||
Foo a, b ' Call a Sub or Function (return value discarded)
|
||||
Call Foo(a, b) ' Call a Sub or Function (return value discarded)
|
||||
x = Foo(a, b) ' Call a Function and capture the return
|
||||
Foo(a, b) ' SYNTAX ERROR for multi-arg subs
|
||||
|
||||
Foo(x) ' Calls Foo passing x BY VALUE, even if Foo declares ByRef
|
||||
Foo x ' Honors Foo's ByRef declaration
|
||||
```
|
||||
|
||||
If a Sub modifies its argument and your change isn’t taking effect — you wrapped the argument in parentheses.
|
||||
|
||||
## `ByRef` Is the Default
|
||||
|
||||
Unlike most languages, VBScript passes arguments **by reference by default**. Functions can mutate their callers’ variables. Be explicit:
|
||||
|
||||
```vbscript
|
||||
Sub Increment(ByRef n)
|
||||
n = n + 1
|
||||
End Sub
|
||||
```
|
||||
|
||||
## Arrays Are 0-Based But Have `UBound`, Not `Length`
|
||||
|
||||
```vbscript
|
||||
Dim arr(2) ' Three elements: arr(0), arr(1), arr(2)
|
||||
For i = 0 To UBound(arr)
|
||||
arr(i) = i * 10
|
||||
Next
|
||||
```
|
||||
|
||||
`Dim arr(n)` creates `n+1` elements. `ReDim Preserve arr(newSize)` resizes (only the last dimension of a multi-dim array).
|
||||
|
||||
## `Set` Is Required for Object Assignment
|
||||
|
||||
```vbscript
|
||||
Set fso = CreateObject("Scripting.FileSystemObject") ' correct
|
||||
fso = CreateObject("Scripting.FileSystemObject") ' RUNTIME ERROR
|
||||
```
|
||||
|
||||
Any time the right-hand side is an object (COM object, RegExp, Dictionary), you must use `Set`.
|
||||
|
||||
## Error Handling Is Manual
|
||||
|
||||
```vbscript
|
||||
On Error Resume Next
|
||||
Rhino.AddCircle Array(0,0,0), -1
|
||||
If Err.Number <> 0 Then
|
||||
Rhino.Print "Failed: " & Err.Description
|
||||
Err.Clear
|
||||
End If
|
||||
On Error GoTo 0 ' Restore normal error behavior
|
||||
```
|
||||
|
||||
`On Error Resume Next` suppresses **all** errors until `On Error GoTo 0`. Forgetting to restore is a common bug.
|
||||
|
||||
## Points Are 3-Element Arrays
|
||||
|
||||
Rhino expects `Array(x, y, z)`. A 2-element array (`Array(x, y)`) raises a type-mismatch error.
|
||||
|
||||
```vbscript
|
||||
Dim pt
|
||||
pt = Array(1.0, 2.0, 3.0)
|
||||
Rhino.AddPoint pt
|
||||
```
|
||||
|
||||
## String Concatenation Uses `&`, Not `+`
|
||||
|
||||
`+` on strings works only if **both** sides are strings. If one side is a number, `+` does numeric addition and throws a type-mismatch. Always use `&`:
|
||||
|
||||
```vbscript
|
||||
Rhino.Print "Count: " & n
|
||||
```
|
||||
|
||||
## `For Each` Needs a `Variant`
|
||||
|
||||
```vbscript
|
||||
Dim item
|
||||
For Each item In someCollection
|
||||
' ...
|
||||
Next
|
||||
```
|
||||
|
||||
The loop variable must be `Variant`. You cannot `Dim item As Long` (VBScript has no typed `Dim`).
|
||||
Reference in New Issue
Block a user