719 lines
15 KiB
Plaintext
719 lines
15 KiB
Plaintext
# System library
|
|
|
|
haku comes with a set of built-in functions, called the _system library._
|
|
This is a reference for these functions.
|
|
|
|
## Preamble: how to read this reference
|
|
|
|
Each function comes with a _signature description_.
|
|
These descriptions read like this:
|
|
|
|
```haku
|
|
stroke
|
|
thickness : number
|
|
color : rgba
|
|
position : vec
|
|
-> scribble
|
|
```
|
|
|
|
The first element is always the function's name - in this case `stroke`.
|
|
Following this are `argumentName : argumentType` pairs, which describe the arguments that need to be passed to the function.
|
|
The last element is always the type of data this function produces.
|
|
|
|
Function names which are made up of symbols instead of letters are _operators_.
|
|
Operators may have one or two arguments, where one argument corresponds to a prefix form `-x`, and two arguments correspond to an infix form `x - y`.
|
|
Note that this documentation lists a unary and binary operator of the same spelling as _two separate functions_, not overloads of a single function.
|
|
|
|
The argument name usually does not matter when calling the function - it is only used for documentation purposes.
|
|
The one exception is arguments called `...`, which signify that zero or more arguments can be passed to the function at that position.
|
|
(Currently there are no functions that accept any number of arguments, though.)
|
|
|
|
The argument _type_ however is important.
|
|
If you try to use a function with the wrong type of value as its argument, it will fail with an error.
|
|
For example, consider a brush where we pass a number as `stroke`'s `color` and `position` arguments.
|
|
|
|
```haku
|
|
stroke 1 1 1
|
|
```
|
|
|
|
This brush will fail to render, since `stroke` expects an `rgba` as its 2nd argument.
|
|
|
|
With that said, there are several types of values in haku that can be passed into, and returned by functions.
|
|
|
|
- `_` - special type used to signify that any value may be passed into the function.
|
|
- `()` - also known as _nil_, means _no value._
|
|
- `boolean` - either `False` or `True`. Indicates truth or falsehood, used in `if` conditions.
|
|
- `number` - a real number, with 32 bits of precision.
|
|
- `vec` - a 4-dimensional vector, composed of four `number`s.
|
|
- `rgba` - an RGBA color, composed of four `number`s.
|
|
- `\a -> r` - a function taking in the parameter `a` and returning `r`, as returned by `\x -> x` literals.
|
|
- `list t` - a list of values, where each value is of the type `t`.
|
|
- `shape` - a mathematical shape.
|
|
|
|
- `shapeLike` - anything that can be turned into a `shape` using `toShape`.
|
|
|
|
- `scribble` - something that can be drawn on the wall.
|
|
- `reticle` - an interaction the user can make with the wall.
|
|
|
|
The syntax `a | b` may be used to signify that one of the listed types is accepted or returned.
|
|
|
|
The following syntax:
|
|
|
|
```haku
|
|
{
|
|
A : t
|
|
B : u
|
|
}
|
|
```
|
|
|
|
is used for _records_---functions which take in a tag as a parameter, and return a value depending on what tag was passed.
|
|
In the case above, if `A` is passed in a value of type `t` is returned, and if `B` is passed in a value of type `u` is returned.
|
|
Passing in any other tag is an error.
|
|
|
|
|
|
## Math
|
|
|
|
```haku
|
|
-
|
|
a : number
|
|
-> number
|
|
|
|
-
|
|
a : vector
|
|
-> vector
|
|
```
|
|
|
|
`-`, when used in its unary form `-x`, returns the number `x` with the opposite sign.
|
|
When used on vectors, returns the same vector facing the reverse direction (the individual components are negated.)
|
|
|
|
This operation is not defined for colors, because it doesn't make sense to have a color with negative RGBA values.
|
|
|
|
```haku
|
|
+
|
|
a : number
|
|
b : number
|
|
-> number
|
|
|
|
+
|
|
a : vector
|
|
b : vector
|
|
-> vector
|
|
|
|
+
|
|
a : rgba
|
|
b : rgba
|
|
-> rgba
|
|
```
|
|
|
|
`+` adds two numbers, vectors, or colors together.
|
|
|
|
```haku
|
|
-
|
|
a : number
|
|
b : number
|
|
-> number
|
|
|
|
-
|
|
a : vector
|
|
b : vector
|
|
-> vector
|
|
|
|
-
|
|
a : rgba
|
|
b : rgba
|
|
-> rgba
|
|
```
|
|
|
|
`-`, when used in its binary form `x - y`, subtracts two numbers, vectors, or colors from one another.
|
|
|
|
```haku
|
|
*
|
|
a : number
|
|
b : number
|
|
-> number
|
|
|
|
*
|
|
a : vector
|
|
b : vector
|
|
-> vector
|
|
|
|
*
|
|
a : rgba
|
|
b : rgba
|
|
-> rgba
|
|
```
|
|
|
|
`*` multiplies two numbers together.
|
|
When used on vectors, it scales them component-wise.
|
|
Likewise for colors.
|
|
|
|
```haku
|
|
/
|
|
a : number
|
|
b : number
|
|
-> number
|
|
|
|
/
|
|
a : vector
|
|
b : vector
|
|
-> vector
|
|
|
|
/
|
|
a : rgba
|
|
b : rgba
|
|
-> rgba
|
|
```
|
|
|
|
`/` divides a number by another number.
|
|
When used on vectors, it divides them component-wise.
|
|
Likewise for colors.
|
|
|
|
```haku
|
|
floor
|
|
x : number
|
|
-> number
|
|
|
|
ceil
|
|
x : number
|
|
-> number
|
|
|
|
round
|
|
x : number
|
|
-> number
|
|
```
|
|
|
|
`floor`, `ceil`, and `round` are rounding functions.
|
|
Each of them rounds a little differently:
|
|
|
|
- `floor` rounds towards -∞.
|
|
- `ceil` rounds towards +∞.
|
|
- `round` rounds half towards +∞.
|
|
|
|
```haku
|
|
abs
|
|
x : number
|
|
-> number
|
|
```
|
|
|
|
`abs` returns the absolute value of the given number.
|
|
|
|
If `x` is less than zero, returns `-x`.
|
|
Otherwise returns `x`.
|
|
|
|
```haku
|
|
mod
|
|
x : number
|
|
y : number
|
|
-> number
|
|
```
|
|
|
|
`mod` is the modulo operation.
|
|
|
|
It returns the remainder of dividing `x` by `y`.
|
|
haku uses the Euclidean definition, which means the remainder returned by `mod` is _always non-negative_.
|
|
|
|
```haku
|
|
pow
|
|
base : number
|
|
exponent : number
|
|
-> number
|
|
```
|
|
|
|
`pow` raises `base` to the given `exponent`.
|
|
|
|
```haku
|
|
sqrt
|
|
x : number
|
|
-> number
|
|
|
|
cbrt
|
|
x : nunber
|
|
-> number
|
|
```
|
|
|
|
`sqrt` returns the square root of the given number.
|
|
|
|
`cbrt` returns the cubic root of the given number.
|
|
|
|
Other roots may be obtained using `pow x (1 / base)`.
|
|
|
|
```haku
|
|
exp
|
|
x : number
|
|
-> number
|
|
|
|
ln
|
|
x : number
|
|
-> number
|
|
```
|
|
|
|
In the following functions, `e` is the base of the natural logarithm (approximately `2.7128`.)
|
|
The `e` constant (Euler's number) is currently not exposed to haku source code; you have to define it yourself.
|
|
|
|
`exp` is the exponential function `pow e x`.
|
|
|
|
`ln` is the natural logarithm (logarithm base `e` of `x`.)
|
|
|
|
```haku
|
|
expMinus1
|
|
x : number
|
|
-> number
|
|
|
|
ln1Plus
|
|
x : number
|
|
-> number
|
|
```
|
|
|
|
`expMinus1` is `pow e x - 1`, but accurate even when `x` is close to zero.
|
|
|
|
`ln1Plus` is `ln (1 + x)`, but more accurate than if the operations are performed separately.
|
|
|
|
```haku
|
|
exp2
|
|
x : number
|
|
-> number
|
|
```
|
|
|
|
`exp2` is the exponential function `pow 2 x`.
|
|
|
|
```haku
|
|
log2
|
|
x : number
|
|
-> number
|
|
|
|
log10
|
|
x : number
|
|
-> number
|
|
```
|
|
|
|
`log2` is the logarithm base `2` of `x`.
|
|
|
|
`log10` is the logarithm base `10` of `x`.
|
|
|
|
```haku
|
|
hypot
|
|
x : number
|
|
y : number
|
|
-> number
|
|
```
|
|
|
|
`hypot` is the hypotenuse of the Pythagorean triangle with right angle-adjacent sides `x` and `y`.
|
|
|
|
```haku
|
|
sin
|
|
x : number
|
|
-> number
|
|
|
|
cos
|
|
x : number
|
|
-> number
|
|
|
|
tan
|
|
x : number
|
|
-> number
|
|
```
|
|
|
|
`sin`, `cos`, and `tan` are the [trigonometric functions][] sine, cosine, and tangent.
|
|
Their argument `x` is counted in radians.
|
|
|
|
[trigonometric functions]: https://wikipedia.org/Trigonometric_functions
|
|
|
|
```haku
|
|
asin
|
|
x : number
|
|
-> number
|
|
|
|
acos
|
|
x : number
|
|
-> number
|
|
|
|
atan
|
|
x : number
|
|
-> number
|
|
```
|
|
|
|
`asin`, `acos`, and `atan` are the [inverse trigonometric functions][] arc sine, arc cosine, and arc tangent.
|
|
Their argument `x` is counted in radians.
|
|
|
|
[inverse trigonometric functions]: https://wikipedia.org/Inverse_trigonometric_functions
|
|
|
|
```haku
|
|
atan2
|
|
y : number
|
|
x : number
|
|
-> number
|
|
```
|
|
|
|
`atan2` is the angle between the positive X axis and a line that passes through `(0, 0)` and `(x, y)`.
|
|
|
|
Note the reverse argument order---`y` comes first, due to `atan2` being a convenience function over `atan (y / x)` that is defined for all arguments.
|
|
|
|
```haku
|
|
sinh
|
|
x : number
|
|
-> number
|
|
|
|
cosh
|
|
x : number
|
|
-> number
|
|
|
|
tanh
|
|
x : number
|
|
-> number
|
|
|
|
asinh
|
|
x : number
|
|
-> number
|
|
|
|
acosh
|
|
x : number
|
|
-> number
|
|
|
|
atanh
|
|
x : number
|
|
-> number
|
|
```
|
|
|
|
`sinh`, `cosh`, `tanh`, `asinh`, `acosh`, and `atanh`, are the six [hyperbolic functions][].
|
|
|
|
[hyperbolic functions]: https://en.wikipedia.org/wiki/Hyperbolic_functions
|
|
|
|
|
|
## Logic
|
|
|
|
The following functions are used to compare values and work with `boolean`s.
|
|
|
|
```haku
|
|
!
|
|
a : _
|
|
-> boolean
|
|
```
|
|
|
|
If `b` is `()` or `False`, `not` returns `True`.
|
|
Otherwise it returns `False`.
|
|
|
|
```haku
|
|
==
|
|
a : _
|
|
b : _
|
|
-> boolean
|
|
|
|
!=
|
|
a : _
|
|
b : _
|
|
-> boolean
|
|
```
|
|
|
|
`==` returns `True` if `a` and `b` are equal.
|
|
Whether two values are considered equal depends on their type:
|
|
|
|
- If the type of the two values differs, `False` is returned.
|
|
- If the two values are `number`s:
|
|
|
|
- If any of the values are `NaN`, `False` is returned.
|
|
- Otherwise `True` is returned if the two numbers have the exact same bit representation.
|
|
|
|
- If the two values are `vec`s, `True` is returned if each of their `number` components is equal to each other using the rules above.
|
|
- Likewise with `rgba`s.
|
|
- All other types of values use _reference_ equality - `True` is returned only if `a` and `b` are located in the same place in memory.
|
|
This more or less means that the values are considered equal if they are produced by the same call to a system function, in time.
|
|
|
|
`!=` returns `!(a == b)`.
|
|
|
|
```haku
|
|
<
|
|
a : _
|
|
b : _
|
|
-> boolean
|
|
|
|
<=
|
|
a : _
|
|
b : _
|
|
-> boolean
|
|
|
|
>
|
|
a : _
|
|
b : _
|
|
-> boolean
|
|
|
|
>=
|
|
a : _
|
|
b : _
|
|
-> boolean
|
|
```
|
|
|
|
`<` returns `True` if `a` is less than `b`, and `<=` returns `True` if `a` is less than _or_ equal to `b`.
|
|
|
|
Order is only well-defined for numbers.
|
|
Other types may assume an arbitrary but consistent ordering - `()` may be less than `True`, or it may not be less than `True`, but this will not change between executions of the program.
|
|
|
|
`a > b` is the same as `b < a`.
|
|
`a >= b` is the same as `b <= a`.
|
|
|
|
---
|
|
|
|
Note that `and` and `or` are currently missing from this list, but are reserved keywords.
|
|
You can implement them using regular functions as a replacement.
|
|
|
|
```haku
|
|
boolAnd = \a, b ->
|
|
if (a)
|
|
if (b) True
|
|
else False
|
|
else False
|
|
|
|
boolOr = \a, b ->
|
|
if (a)
|
|
True
|
|
else
|
|
if (b) True
|
|
else False
|
|
```
|
|
|
|
|
|
## Vectors
|
|
|
|
```haku
|
|
vec
|
|
x : number
|
|
-> vec
|
|
|
|
vec
|
|
x : number
|
|
y : number
|
|
-> vec
|
|
|
|
vec
|
|
x : number
|
|
y : number
|
|
z : number
|
|
-> vec
|
|
|
|
vec
|
|
x : number
|
|
y : number
|
|
z : number
|
|
w : number
|
|
-> vec
|
|
```
|
|
|
|
Creates a new `vec` from one to four number values.
|
|
|
|
A `vec` always has four dimensions.
|
|
If any of the arguments are omitted, its corresponding dimension is initialized to zero.
|
|
|
|
```haku
|
|
vecX
|
|
v : vec
|
|
-> number
|
|
|
|
vecY
|
|
v : vec
|
|
-> number
|
|
|
|
vecZ
|
|
v : vec
|
|
-> number
|
|
|
|
vecW
|
|
v : vec
|
|
-> number
|
|
```
|
|
|
|
`vecX`, `vecY`, `vecZ`, and `vecW` extract the individual components of a `vec`.
|
|
|
|
---
|
|
|
|
## Colors
|
|
|
|
```haku
|
|
rgba
|
|
r : number
|
|
g : number
|
|
b : number
|
|
a : number
|
|
-> rgba
|
|
```
|
|
|
|
Creates a new `rgba` with the given color channels.
|
|
Note that unlike `vec`, all color channels have to be provided to form an `rgba`.
|
|
|
|
```haku
|
|
rgbaR
|
|
color : rgba
|
|
-> number
|
|
|
|
rgbaG
|
|
color : rgba
|
|
-> number
|
|
|
|
rgbaB
|
|
color : rgba
|
|
-> number
|
|
|
|
rgbaA
|
|
color : rgba
|
|
-> number
|
|
```
|
|
|
|
`rgbaR`, `rgbaG`, `rgbaB`, `rgbaA` extract color channels out of an `rgba`.
|
|
|
|
---
|
|
|
|
haku uses RGBA values in a normalized `0` to `1` range rather than `0` to `255`, which may be unfamiliar if you're coming from other image editing software.
|
|
This is because it's easier to do math on normalized colors.
|
|
For example, consider multiplicatively blending two colors.
|
|
|
|
```haku
|
|
-- This is how you can multiply two colors together.
|
|
-- Note that the `*` operator works for colors, so you don't need to define this in your brushes.
|
|
mulRgba = \a, b ->
|
|
rgba (rgbaR a * rgbaR b) (rgbaG a * rgbaG b) (rgbaB a * rgbaB b) (rgbaA a * rgbaA b)
|
|
```
|
|
|
|
If haku represented colors using an 8-bit `0` to `255` range instead, to multiply two colors together, you would have to divide them by `255` to get them back into the correct range.
|
|
|
|
```haku
|
|
-- NOTE: This example does NOT work correctly.
|
|
mulRgba = \a, b ->
|
|
let red = (rgbaR a * rgbaR b) / 255
|
|
let green = (rgbaG a * rgbaG b) / 255
|
|
let blue = (rgbaB a * rgbaB b) / 255
|
|
let alpha = (rgbaA a * rgbaA b) / 255
|
|
rgba red green blue alpha
|
|
```
|
|
|
|
Note that haku does not clamp colors to the `0` to `1` range.
|
|
It is perfectly valid to have a color that is out of range or even `NaN`, but when drawing scribbles:
|
|
|
|
- any number less than `0` is clamped to `0`.
|
|
- any number greater than `1` is clamped to `1`.
|
|
- `∞` is clamped back to `1`.
|
|
- `-∞` is clamped back to `0`.
|
|
- any scribble with a `NaN` color is ignored.
|
|
|
|
Before scribbles are drawn to the wall, colors are converted to 8-bit integers for more efficient rasterization and storage.
|
|
This means some loss of precision will happen, which may cause issues with brushes like this one:
|
|
|
|
```haku
|
|
stroke 128 #00000004 (vec 0 0)
|
|
```
|
|
|
|
If you try to to use this brush to fill up a single spot with black, you will notice that despite all the math suggesting so, the color will end up gray instead.
|
|
|
|
|
|
## Shapes
|
|
|
|
```haku
|
|
toShape
|
|
value : _
|
|
-> () | shape
|
|
```
|
|
|
|
Converts the given value to a shape.
|
|
|
|
- For `shape`, clones the shape that was passed in.
|
|
- For `vec`, returns a point `shape`.
|
|
- For anything else, returns `()`.
|
|
|
|
```haku
|
|
line
|
|
start : vec
|
|
end : vec
|
|
-> shape
|
|
```
|
|
|
|
Creates a line segment shape with the provided `start` and `end` points.
|
|
|
|
```haku
|
|
rect
|
|
position : vec
|
|
size : vec
|
|
-> shape
|
|
|
|
rect
|
|
x : number
|
|
y : number
|
|
width : number
|
|
height : number
|
|
-> shape
|
|
```
|
|
|
|
Creates a rectangle shape with its top-left corner at `position`, with a given `size` stretching from the top-left corner.
|
|
|
|
The alternative 4-argument version takes in the rectangle's X/Y coordinates, width, and height as separate arguments instead of aggregating them into a `vec`.
|
|
|
|
```haku
|
|
circle
|
|
center : vec
|
|
radius : number
|
|
-> shape
|
|
|
|
circle
|
|
x : number
|
|
y : number
|
|
radius : number
|
|
-> shape
|
|
```
|
|
|
|
Creates a circle shape, with its center at `center`, with the provided radius.
|
|
|
|
The alternative 3-argument version takes in the circle's center X/Y coordinates as separate arguments instead of aggregating them into a `vec`.
|
|
|
|
## Scribbles
|
|
|
|
```haku
|
|
stroke
|
|
thickness : number
|
|
color : rgba
|
|
shape : shapeLike
|
|
-> scribble
|
|
```
|
|
|
|
Creates a stroke scribble, which outlines the provided shape with a stroke of the given thickness and color.
|
|
|
|
Point shapes are drawn as circles, and `line` shapes have round caps at the line's endpoints.
|
|
|
|
```haku
|
|
fill
|
|
color : rgba
|
|
shape : shapeLike
|
|
-> scribble
|
|
```
|
|
|
|
Creates a fill scribble, which fills in the entire area of the provided shape with a solid color.
|
|
|
|
Since this requires the shape to have a surface area, this does not do anything when point and `line` shapes are passed in.
|
|
|
|
|
|
## Reticles
|
|
|
|
```haku
|
|
withDotter
|
|
cont : \{
|
|
To : vec
|
|
From : vec
|
|
Num : number
|
|
} -> scribble
|
|
-> reticle
|
|
```
|
|
|
|
The dotter is a reticle that allows the user to draw things on the wall directly under the mouse cursor.
|
|
Once the user makes the interaction (presses the left mouse button), `cont` is called repeatedly with every movement of the mouse cursor, until the mouse button is released.
|
|
|
|
::: aside
|
|
|
|
It's not called a _plotter_ since the dotter does not plot lines or curves; it only places dots under the mouse cursor.
|
|
|
|
:::
|
|
|
|
During the interaction, `cont` is called with a record containing the following fields:
|
|
|
|
- `To` - the current position of the mouse cursor
|
|
- `From` - the previous position of the mouse cursor. May be equal to `To` if the user just pressed the mouse button.
|
|
- `Num` - the number of times `cont` has been called since the mouse cursor was pressed. Always greater or equal to `0`.
|
|
|
|
Since the dotter reticle finishes immediately (there is no extra interaction the user needs to take after pressing the mouse button for the action to be taken,) `cont` may only return a scribble; never another reticle.
|
|
|
|
The drawing area is a large, square, chunk-aligned perimeter around `To`.
|