SkillAgentSearch skills...

Rhino.Scripting

A complete reimplementation of the Rhino-Script-Syntax in F#

Install / Use

/learn @goswinr/Rhino.Scripting
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

logo

Rhino.Scripting

Rhino.Scripting on nuget.org Build Status Docs Build Status

<!-- [![Check dotnet tools](https://github.com/goswinr/Rhino.Scripting/actions/workflows/outdatedDotnetTool.yml/badge.svg)](https://github.com/goswinr/Rhino.Scripting/actions/workflows/outdatedDotnetTool.yml) -->

license code size

Rhino.Scripting is a complete re-implementation of the original RhinoScript syntax in and for F# (and C#).<br> Before this repo, the high-level RhinoScript API was only available for VBScript and (Iron-)Python.<br> This repo enables the use of the RhinoScriptSyntax in F# and C#<br> together with all the great coding experience and editor tooling that come with F# and C#, like:<br>

  • automatic code completion while typing.<br>
  • automatic error checking and highlighting in the background.<br>
  • type info on mouse over.<br>
  • type safety even without type annotation (= type inference in F#).<br>

What is RhinoScript?

RhinoScript provides application scripting for the Rhino3D CAD app.<br> RhinoScript has more than 900 functions to control all kinds of aspects of automating Rhino3D.<br> It was originally implemented in 2002 in VBScript.<br> Extensive documentation on the original VBScript-based version is available here.

In 2010, all functions from RhinoScript were reimplemented in IronPython (Python running on .NET).<br> This allowed the use of a modern, rich, and dynamically typed programming language with a huge standard library and <br> also access to all functions of the underlying .NET Framework as well as the RhinoCommon SDK.

What is this repo?

This repo has all original RhinoScript functions reimplemented in F#.<br> It is literally a translation of the open-source IronPython rhinoscriptsyntax implementation to F#.<br> You can see all 900+ methods in this repo in the docs.

A few minor bugs from the Python implementation are fixed and a few extra methods and optional parameters were added.<br> I have been using this library extensively for my own professional scripting needs since 2019.<br> If you have problems, questions, or find a bug, please open an issue.

Get started

The recommended scripting use case is via Fesh, the dedicated F# scripting editor for Rhino.<br> However, you can use this library just as well in the new Rhino 8 ScriptEditor with C# or in independently compiled F#, C#, or VB.net projects.

Get started in F#

First reference the assemblies.

#r "nuget: Rhino.Scripting"

The main namespace is Rhino.Scripting.<br> The main class of this library is called RhinoScriptSyntax it has all ~900 functions as static methods.<br> In F# you can create an alias like this:

open Rhino.Scripting
type rs = RhinoScriptSyntax

then use any of the RhinoScript functions like you would in Python or VBScript.<br> The CoerceXXXX functions will help you create types if you are too lazy to fully specify them.

let pl = rs.CoercePlane(0 , 80 , 0) // makes World XY plane at point
rs.AddText("Hello, Fesh", pl, height = 50.)

For F# scripting the Rhino.Scripting.Fsharp provides useful extensions and curried functions for piping and partial application.

Get started in C#

You can use it via the new Rhino 8 ScriptEditor. First reference the assemblies.

#r "nuget: Rhino.Scripting"

The main namespace is Rhino.Scripting.<br> The main class of this library is called RhinoScriptSyntax it has all ~900 functions as static methods.<br> In C# you can create an alias like this:

using rs = Rhino.Scripting.RhinoScriptSyntax;

then you can use it like the RhinoScriptSyntax in Python:

var pt = rs.GetObject("Select an Object");
rs.ObjectColor(pt, System.Drawing.Color.Blue);

How about the dynamic types and optional parameters from VBScript and Python?

Many RhinoScript functions take variable types of input parameters.<br> This is implemented with method overloads.<br> Many RhinoScript functions have optional parameters.<br> These are also implemented as optional method parameters.<br> Many RhinoScript functions are getters and setters at the same time.<br> Depending on if an argument is provided or not, the function acts as a getter or setter.<br> This is also implemented with method overloads.

Example

For example rs.ObjectLayer can be called in several ways:

To get the layer of one object, returns a string:<br>

rs.ObjectLayer(guid)

To set the layer of one object (fails if layer does not exist), no return value:<br>

rs.ObjectLayer(guid, string)

To set the layer of one object, and create the layer if it does not exist yet, no return value:<br>

rs.ObjectLayer(guid, string, createLayerIfMissing = true )

To set the layer of several objects (fails if layer does not exist), no return value:<br>

rs.ObjectLayer(list of guids, string)

To set the layer of several objects, and create the layer if it does not exist yet, no return value:<br>

rs.ObjectLayer(list of guids, string, createLayerIfMissing = true )

These are implemented with 3 overloads and Optional and DefaultParameterValue parameters:

    ///<summary>Returns the full layer name of an object.
    /// parent layers are separated by <c>::</c>.</summary>
    ///<param name="objectId">(Guid) The identifier of the object</param>
    ///<returns>(string) The object's current layer.</returns>
    static member ObjectLayer(objectId:Guid) : string = //GET
        let obj = RhinoScriptSyntax.CoerceRhinoObject(objectId)
        let index = obj.Attributes.LayerIndex
        State.Doc.Layers.[index].FullPath

    ///<summary>Modifies the layer of an object ,
    ///     optionally creates layer if it does not exist yet.</summary>
    ///<param name="objectId">(Guid) The identifier of the object</param>
    ///<param name="layer">(string) Name of an existing layer</param>
    ///<param name="createLayerIfMissing">(bool) Optional,
    ///     Default Value: <c>false</c> Set true to create Layer
    ///     if it does not exist yet.</param>
    ///<param name="allowAllUnicode">(bool) Optional,
    ///     Allow Ambiguous Unicode characters too </param>
    ///<param name="collapseParents">(bool) Optional,
    ///     Collapse parent layers in Layer UI </param>
    ///<returns>(unit) void, nothing.</returns>
    static member ObjectLayer( objectId:Guid
                             , layer:string
                             ,[<OPT;DEF(false)>]createLayerIfMissing:bool
                             ,[<OPT;DEF(false:bool)>]allowAllUnicode:bool
                             ,[<OPT;DEF(false:bool)>]collapseParents:bool) : unit = //SET
        let obj = RhinoScriptSyntax.CoerceRhinoObject(objectId)
        let layerIndex =
            if createLayerIfMissing then
                UtilLayer.getOrCreateLayer(
                    layer,
                    UtilLayer.randomLayerColor,
                    UtilLayer.ByParent,
                    UtilLayer.ByParent,
                    allowAllUnicode,
                    collapseParents
                    ).Index
            else
                RhinoScriptSyntax.CoerceLayer(layer).Index
        obj.Attributes.LayerIndex <- layerIndex
        obj.CommitChanges() |> ignore
        State.Doc.Views.Redraw()

    ///<summary>Modifies the layer of multiple objects, optionally creates
    ///     layer if it does not exist yet.</summary>
    ///<param name="objectIds">(Guid seq) The identifiers of the objects</param>
    ///<param name="layer">(string) Name of an existing layer</param>
    ///<param name="createLayerIfMissing">(bool) Optional,
    ///     Default Value: <c>false</c> Set true to create Layer
    ///     if it does not exist yet.</param>
    ///<param name="allowUnicode">(bool) Optional,
    ///     Allow Ambiguous Unicode characters too </param>
    ///<param name="collapseParents">(bool) Optional,
    ///     Collapse parent layers in Layer UI </param>
    ///<returns>(unit) void, nothing.</returns>
    static member ObjectLayer( objectIds:Guid seq
                             , layer:string
                             , [<OPT;DEF(false)>]createLayerIfMissing:bool
                             , [<OPT;DEF(false:bool)>]allowUnicode:bool
                             , [<OPT;DEF(false:bool)>]collapseParents:bool) : unit = //MULTISET
        let layerIndex =
            if createLayerIfMissing then
                UtilLayer.getOrCreateLayer(
                    layer,
                    UtilLayer.randomLayerColor,
View on GitHub
GitHub Stars7
CategoryDevelopment
Updated1d ago
Forks1

Languages

F#

Security Score

90/100

Audited on Apr 6, 2026

No findings