# Scripting fundamentals

## **Graphic primitives**

All of the primitive shapes that can be exported in Cuttle are called `Graphic`s. There are four `Graphic` classes:

-   An `Anchor` represents an anchor point of a `Path`. It has a `.position`, `.handleIn`, and `.handleOut` property (all `Vec`s).
-   A `Path` represents an arbitrary closed or open path. It has an `.anchors` property which is an array of `Anchor`s and a `.closed` property which is `true` or `false`. It also has Style properties `.fill` and `.stroke`.
-   A `CompoundPath` represents a collection of paths. These are used to create shapes with holes. You can also use these to “bundle” together multiple paths which can be useful in certain export situations (e.g. to force certain machines to trace those paths in order). A `CompoundPath` has a `.paths` property. It also has Style properties `.fill` and `.stroke`.
-   A `Group` is an organizational unit. It has an `.items` property which is an array of other `Graphic`s.

## **Constructors**

Here’s an example showing how to create each primitive. You can try pasting this code as a new [Code Component](https://cuttle.xyz/learn/scripting/code-components).

// Anchors created with position, handleIn, and handleOut. // Note: handleIn and handleOut are relative values from position. const a1 = Anchor(Vec(2, 0), Vec(0, 0), Vec(0.5, 0)); const a2 = Anchor(Vec(3, 1), Vec(-0.5, 0), Vec(0, 0)); // Creating a Path from the above anchors. By default Paths are // not closed. const path1 = Path(\[a1, a2\]); // Putting \`true\` as the second argument to Path() makes a closed // path. const path2 = Path( \[Anchor(Vec(2, 2)), Anchor(Vec(2, 5)), Anchor(Vec(5, 5)), Anchor(Vec(5, 2))\], true ); // Using Path.fromPoints(...) is another way to create a Path from // straight segments. const path3 = Path.fromPoints(\[Vec(3, 3), Vec(3, 4), Vec(4, 4)\], true); // Creating a CompoundPath const compoundPath = CompoundPath(\[path2, path3\]); // Creating a Group const group = Group(\[path1, compoundPath\]); return group;

Note that typing `new` before the constructors is optional.

The code above also demonstrates `Path.fromPoints(...)` to construct a `Path` of straight segments. You can find more convenience methods for creating `Anchor`s, `Path`s, `CompoundPath`s, and `Group`s in the reference documentation.

## **Navigating the scene hierarchy**

`Graphic`s form a tree and that tree can be arbitrarily nested — `Group`s can contain other `Group`s. When writing modifiers, it’s often handy to just work with all the `Anchor`s or all the `Path`s. Thus there are convenience methods that will traverse through the tree of a `Graphic` and return all the objects you’re looking for.

-   `.allAnchors()` returns an array of all the `Anchor` objects.
-   `.allPaths()` returns an array of all the `Path` objects.
-   `.allCompoundPaths()` returns an array of all the `CompoundPath` objects.
-   `.allPathsAndCompoundPaths()` returns an array of all `CompoundPath`s and all top-level `Path`s (meaning the `Path` is not contained within a `CompoundPath`). This is all the objects that can be styled.

## **Transforming Graphics**

All of the `Graphic`s have a `.transform(...)` method which is analogous to the Transform modifier in Cuttle.

![](https://cuttle-content.imgix.net/learn/scripting-fundamentals/944ad77e225be8a9fc026ebd443e1b721a3acf843f88917fbcf5184577a926dd.png?auto=compress,format&q=60&fit=max&w=720&h=720&dpr=2)

To perform the above transform you could write:

input.transform({ position: Vec(3, 0), rotation: 30, });

That is, the `transform` method takes an object with the following properties, all optional:

-   `position`: a `Vec`
-   `rotation`: a`number` in degrees
-   `scale`: a `Vec` for non-uniform scale or `number` for uniform scale
-   `skew`: a `number` in degrees
-   `origin`: a `Vec` for where the center of rotation and scale should be
-   `Group`s, `Path`s, and `CompoundPath`s do not have transformations.
    
    Note that unlike some other graphics frameworks that have a “scene graph” — a hierarchy of shapes — parent shapes in Cuttle do _not_ have transformations. When you call `.transform(...)` on a parent shape, it will mutate the positions and handles of the `Anchor`s (the leaf nodes of the tree).
    

## **Mutating methods and** `**.clone()**`

You can make a copy of any `Graphic` object with the `.clone()` method. This will return a deep copy of the object. “Deep” means that children will also be copied recursively — for example if you `.clone()` a `Path` then all the child `Anchor`s will also be cloned.

Note that most of the methods (e.g. `.transform(...)`) that you can call on a `Graphic` will mutate the object or its children. So if you don’t want to mutate your `Graphic`, you’ll want to first copy it with `.clone()`.

For example, here is a simple modifier that returns the original input along with a copy of the input moved one unit to the right.

return \[input, input.clone().transform({ position: Vec(1, 0) })\];

## **The** `**return**` **value**

All modifiers and code components need to return a `Graphic`. As a convenience, you can also return an array of `Graphic`s which Cuttle will turn into a `Group`.