Skip to content

Instantly share code, notes, and snippets.

@jesterKing
Created June 1, 2016 21:56
Show Gist options
  • Save jesterKing/3e53f3def639ca249e3a11eb777add5f to your computer and use it in GitHub Desktop.
Save jesterKing/3e53f3def639ca249e3a11eb777add5f to your computer and use it in GitHub Desktop.
Grasshopper F# sample code. Note that the code in this gist isn't complete - it probably won't compile. But it should show the basic idea of what goes in a F# component for Grasshopper.
namespace CommonStuff
open Microsoft.FSharp.Reflection
open System
open System.Text
open System.Collections.Generic
open System.Linq
open System.Drawing
open System.Windows.Forms
open Grasshopper.Kernel
open Grasshopper.Kernel.Attributes
open Grasshopper.Kernel.Types
open Grasshopper.Kernel.Special
open ShaderGraphResources
open System.Diagnostics
/// participate in shader XML generation.
type ICyclesNode =
/// Get the XML name of the node tag.
abstract member NodeName : string
/// Simple color representation with ints (R, G, B)
type IntColor = int * int * int
module Utils =
let toString (x:'a) =
match FSharpValue.GetUnionFields(x, typeof<'a>) with
| case, _ -> case.Name
let fromString<'a> (s:string) =
match FSharpType.GetUnionCases typeof<'a> |> Array.filter (fun case -> case.Name = s) with
|[|case|] -> Some(FSharpValue.MakeUnion(case,[||]) :?> 'a)
|_ -> None
/// Give first (R) component of triplet (IntColor)
let R (_r:int, _:int, _:int) = _r
/// Give second (G) component of triplet (IntColor)
let G (_:int, _g:int, _:int) = _g
/// Give third (B) component of triplet (IntColor)
let B (_:int, _:int, _b:int) = _b
/// Create a GH_Colour from given IntColor
let createColor c = new GH_Colour(Color.FromArgb((R c), (G c), (B c)))
/// Give message if true, else empty string ""
let SetMessage t m = match t with true -> m | _ -> ""
let IntColorFromColor (c:Color) =
((int c.R), (int c.G), (int c.B))
/// Read color from given component data access at index idx. component
/// message will be set to msg if reading the data failed.
/// Returns an IntColor.
let readColor(u:GH_Component, DA:IGH_DataAccess, idx:int, msg) : IntColor =
let mutable c = new GH_Colour()
let r = DA.GetData(idx, &c)
u.Message <- SetMessage (not r) msg
IntColorFromColor(c.Value)
/// Distributions used in several nodes: Glass, Glossy, Refraction
type Distribution = Sharp | Beckmann | GGX | Asihkmin_Shirley with
member u.toString = Utils.toString u
member u.toStringR = (u.toString).Replace("_", "-")
static member fromString s = Utils.fromString<Distribution> s
namespace SampleNode
open System
open System.Drawing
open System.Windows.Forms
open Grasshopper.Kernel
open Rhino.Geometry
open CommonStuff
open ShaderGraphResources
type AnisotropicBsdf() =
inherit GH_Component("Anisotropic BSDF", "anisotropic", "Anisotropic BSDF node for shader graph", "Shader", "BSDF")
member val Distribution = GGX with get, set
override u.RegisterInputParams(mgr : GH_Component.GH_InputParamManager) =
mgr.AddColourParameter("Color", "C", "anisotropic color", GH_ParamAccess.item, Color.DarkBlue) |> ignore
mgr.AddNumberParameter("Roughness", "Rgh", "Roughness of anisotropic bsdf", GH_ParamAccess.item, 0.0) |> ignore
mgr.AddNumberParameter("Rotation", "R", "Rotation", GH_ParamAccess.item, 1.4) |> ignore
mgr.AddVectorParameter("Normal", "N", "Normal", GH_ParamAccess.item, Vector3d.Zero) |> ignore
mgr.AddVectorParameter("Tangent", "T", "Tangent", GH_ParamAccess.item, Vector3d.Zero) |> ignore
override u.RegisterOutputParams(mgr : GH_Component.GH_OutputParamManager) =
mgr.AddColourParameter("BSDF", "BSDF", "Anisotropic BSDF", GH_ParamAccess.item) |> ignore
override u.ComponentGuid = new Guid("bab1082a-4c74-4d07-9c63-d3f40a178c6a")
override u.Icon = Icons.Glossy
override u.SolveInstance(DA: IGH_DataAccess) =
u.Message <- ""
let c = Utils.readColor(u, DA, 0, "Couldn't read anisotropic color")
u.Message <- u.Distribution.toStringR
DA.SetData(0, Utils.createColor c) |> ignore
override u.Write(writer:GH_IO.Serialization.GH_IWriter) =
writer.SetString("Distribution", u.Distribution.toString) |> ignore
base.Write(writer)
override u.Read(reader:GH_IO.Serialization.GH_IReader) =
if reader.ItemExists("Distribution") then
u.Distribution <-
let d = Distribution.fromString (reader.GetString "Distribution")
match d with | None -> GGX | _ -> d.Value
base.Read(reader)
override u.AppendAdditionalComponentMenuItems(menu:ToolStripDropDown) =
let append_menu (it:Distribution) =
GH_DocumentObject.Menu_AppendItem(menu, it.toStringR, (fun _ _ -> u.Distribution <- it; u.ExpireSolution true), true, u.Distribution = it) |> ignore
append_menu Beckmann
append_menu GGX
append_menu Asihkmin_Shirley
interface ICyclesNode with
member u.NodeName = "anisotropic_bsdf"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment