Introduction

With Twikit Connect, a designer has the ability to expand the possibilities for product parametrization. As well as using the Twikit modifiers, one can also use Grasshopper's power to its advantage.

Designing for Twikit Create in Grasshopper does have some rules linked to it to ensure optimal compatibility. In this document, all the guidelines will be explained for a smooth integration in Twikit Create.

The use of in- and outputs

When connecting Grasshopper with Twikit Create, in- and outputs are needed to set up communication between the two. Twikit Connect supports a wide range of in- and outputs as long as they are configured properly. Everything should be configured the same, except for the mesh parameter, which is an exception to the rule.

Twikit Connect will, regardless of what is configured before, overwrite the input parameters with what comes from Twikit Create. So if a slider is for example connected to a number input param, the slider can be used for testing in Rhino/Grasshopper while designing, but once imported in Twikit Create, the value of the slider will play no further role as the number that gets input from Twikit Create, will overwrite this value.

Basic configuration

In order to expose an in- or output to Twikit Connect, the parameter of the corresponding item should be put in its own group with the name “RH_IN: [Unique name]” or “RH_OUT: [Unique name]” depending on if it is an in- or output.

A visual representation of what the in- and outputs should look like.

Mesh configuration

For meshes, a slightly different configuration is needed, especially for the input. It is driven by a text param and then converted into a C# modifier. While designing, it is advised to use the normal mesh param and switch just before exporting the script for implementation in Twikit Create. For the output, the only difference is the name of the group: “RH_OUT:mesh: [Unique name]”.

A mesh output should always be one joined, manifold mesh.

A visual representation of what the mesh in- and output should look like.


The code that should be put inside of the C# script:

using System;
using System.Collections;
using System.Collections.Generic;

using Rhino;
using Rhino.Geometry;

using Grasshopper;
using Grasshopper.Kernel;
using Grasshopper.Kernel.Data;
using Grasshopper.Kernel.Types;

using System.IO;
using System.Linq;

/// <summary>
/// This class will be instantiated on demand by the Script component.
/// </summary>
public class Script_Instance : GH_ScriptInstance
{
#region Utility functions
  /// <summary>Print a String to the [Out] Parameter of the Script component.</summary>
  /// <param name="text">String to print.</param>
  private void Print(string text) { /* Implementation hidden. */ }
  /// <summary>Print a formatted String to the [Out] Parameter of the Script component.</summary>
  /// <param name="format">String format.</param>
  /// <param name="args">Formatting parameters.</param>
  private void Print(string format, params object[] args) { /* Implementation hidden. */ }
  /// <summary>Print useful information about an object instance to the [Out] Parameter of the Script component. </summary>
  /// <param name="obj">Object instance to parse.</param>
  private void Reflect(object obj) { /* Implementation hidden. */ }
  /// <summary>Print the signatures of all the overloads of a specific method to the [Out] Parameter of the Script component. </summary>
  /// <param name="obj">Object instance to parse.</param>
  private void Reflect(object obj, string method_name) { /* Implementation hidden. */ }
#endregion

#region Members
  /// <summary>Gets the current Rhino document.</summary>
  private readonly RhinoDoc RhinoDocument;
  /// <summary>Gets the Grasshopper document that owns this script.</summary>
  private readonly GH_Document GrasshopperDocument;
  /// <summary>Gets the Grasshopper script component that owns this script.</summary>
  private readonly IGH_Component Component;
  /// <summary>
  /// Gets the current iteration count. The first call to RunScript() is associated with Iteration==0.
  /// Any subsequent call within the same solution will increment the Iteration count.
  /// </summary>
  private readonly int Iteration;
#endregion

  /// <summary>
  /// This procedure contains the user code. Input parameters are provided as regular arguments,
  /// Output parameters as ref arguments. You don't have to assign output parameters,
  /// they will have a default value.
  /// </summary>
  private void RunScript(string x, ref object A)
  {
    var decodedData = Convert.FromBase64String(x); //the obj file

    var filename = Path.GetTempFileName();
    filename = Path.ChangeExtension(filename, ".obj"); // the tmp obj file name on disk

    File.WriteAllBytes(filename, decodedData); //write the file to disk

    var doc = Rhino.RhinoDoc.CreateHeadless(null); // create a Rhino File
    doc.Import(filename); // import the obj into this file

    var objects = doc.Objects.GetObjectList(Rhino.DocObjects.ObjectType.Mesh); // get the imported meshes

    Mesh geometry = objects.SingleOrDefault().Geometry as Mesh; // get the mesh

    A = geometry; // return the mesh
  }

  // <Custom additional code> 

  // </Custom additional code> 
}
C

Best practices

In Grasshopper, one has an infinite amount of possibilities to get the same result. In this section, a few best practices are bundled that have been proven to work well with Twikit Create.

Clean file

By having a clean file, unwanted surprises should be kept to a minimum. It will also keep debugging time to a minimum as the file is easier to understand.

Keeping the file clean means:

  • No modifiers that are not in use (stray modifiers).
    These might lead to errors or warnings which leads to the script not being compatible.

  • Internalise all data that is otherwise linked to objects in Rhino.
    Not internalising this data will lead to the loss of the data when saving the Grasshopper file.

  • Group inputs and outputs.
    Having all input parameters together at the beginning of the script and all outputs together on the right side of the script will contribute to the readability of the script.

  • Working from left to right.
    Most people read from left to right. If this is incorporated into the script, it will again be much easier to debug it if needed.

Data Dams

Data dams can be very useful when working on the script, it stops data from flowing through the modifier unless it is opened. This will avoid the script recomputing fully when making a change at the beginning of the script.
With Twikit Connect, the script should fully recompute when one of its parameters change. Thus all data dams should be set to Always open before importing the script to Twikit Create.

Fast and full versions

A full grasshopper script might take a minute or more to recalculate fully. Having this reflect in the configurator is far from ideal. This is why it is advised to have a light or fast version of the script, where a simple representation is shown of the product. This could for example be a flat brace, without ribs, clips for closing or other details. This fast script should take 0-10 seconds to fully recalculate to have an acceptable user experience when implemented in the configurator.

The full script is then shown at the end of the configurator when everything is configured. This script will be a lot heavier but will show what the end product will look like.

If the full script is still too slow for a proper user experience, a differentiation can be made between a full visualization script and a full export script. The Full visualizations script will then be used for visualizing in the last step and the full export script will be used for exporting in the back-end after a configuration is saved and ordered.

Keep in mind that having more versions of one file (Fast, Full & Export) needs a good overview so all changes are always implemented in all applicable versions of said file.

Adding functional points

When multiple points are needed from TwikFit, it is advised to use one single point param that captures the whole list of points. In the example below, the “RH_IN: LOP” captures all points, the Partition List param divides the list into groups and the Explode Tree separates those groups into branches.

By partitioning and exploding the list of points, full control of the points can be gained.

The use of Grasshopper plugins

One of the powers of Grasshopper lies in the numerous available plugins. Whether it is for calculating complex lattices or remeshing an object according to a specific algorithm, there is a plugin for that.

It’s not all sunshine and rainbows though, while Twikit Connect supports a lot of plugins for Grasshopper already, they are not all supported. If a certain plugin is not found in the list of supported or unsupported plugins, one can always reach out to Twikit to check compatibility. If a plugin is in the unsupported list, it means it cannot be supported, either due to incompatibility or legal reasons.

Checking the plugins used

When designing in Grasshopper, it is not always easy to keep an overview of all the plugins used in a script. This can luckily, easily be checked with another plugin called MetaHopper. By using its Document Info component, The A param or “3rd Party Assemblies (A) as a list” will output all 3rd party plugins that can be found in the document (excluding the Document Info component itself).

Don’t forget to delete the component for checking the plugins before importing the script in Twikit Create.

The Document Info component is connected with a panel to see all 3rd party plugins in use.

Supported plugins

Name

Version

URL

Comments

4D Noise

1.0.0.0

https://www.food4rhino.com/en/app/4d-noise

 

Caterpillar

1.2.0

https://www.food4rhino.com/en/app/caterpillar

 

Clipper

0.3.2.0

https://www.food4rhino.com/en/app/clipper-grasshopper-and-rhino

 

Crystallon

2.0

https://www.food4rhino.com/en/app/crystallon

Components Only

CurveOffsetTools

1.0.0.0

 

 

Dendro

0.9.0.0

https://www.food4rhino.com/en/app/dendro

 

Engrave

1.2.0.0

 

 

Exoskeleton 2

1.0.0.0

https://www.grasshopper3d.com/group/exoskeleton

 

Fattener

0.0.0.1

https://discourse.mcneel.com/t/skeleton-fattener-mesh-cage-morph/74766

 

GENERATION

1.0.0.0

https://www.food4rhino.com/en/app/generation

 

BIM GeoGym IFC

1.9.4.0

https://www.food4rhino.com/en/app/bim-geomgym-ifc

Alias: ggRhinoIFC

Heteroptera

0.6.2.4

https://www.food4rhino.com/en/app/heteroptera

 

Human

1.2.0

https://www.food4rhino.com/en/app/human

 

Jackalope

1.0.0.3

https://www.food4rhino.com/en/app/jackalope

 

jSwan

1.2.0

https://www.food4rhino.com/en/app/jswan

 

Kangaroo 2

2.5.3

https://www.food4rhino.com/en/app/kangaroo-physics

 

LunchBox

2020.11.2.0

https://www.food4rhino.com/en/app/lunchbox

 

LunchBoxML

2020.10.13.0

https://www.food4rhino.com/en/app/lunchbox

Included in LunchBox installer

MarchingCubes

1.0.0.0

 

 

Mesh+

2.1.03

https://www.food4rhino.com/en/app/mesh

Components Only

Mesh Pipe

1.0.0.0

https://www.grasshopper3d.com/forum/topics/mesh-pipe

 

OpenNest

1.3.3

https://www.food4rhino.com/en/app/opennest

 

Plankton

0.3.0.0

https://github.com/meshmash/Plankton/releases

 

Python Interpreter

0.6.0.3

https://www.food4rhino.com/en/app/ghpython

Pufferfish

3.0.0.0

https://www.food4rhino.com/en/app/pufferfish

 

Room Surveyor

0.7.0.1

https://www.food4rhino.com/en/app/roomsurveyor

 

Rooster

1.1.0

https://www.food4rhino.com/en/app/rooster

Alias: GhPotrace

Shortest Walk

1.5.1.0

https://www.food4rhino.com/en/app/shortest-walk-gh

 

Weaverbird

0.9.0.1

https://www.grasshopper3d.com/group/weaverbird

 

XtreeE

1.0

 

 

Unsupported plugins

Name

Url

Reason

MeshEdit

https://www.food4rhino.com/app/meshedit

No commercial license