Primitives

Math types every other API is built on: Vector, Color3, CFrame, and Dim. All immutable, arithmetic returns new instances, never mutates in place.

local Primitives = import("Primitives")
local Vector  = Primitives.Vector
local Color3  = Primitives.Color3
local CFrame  = Primitives.CFrame
local Dim     = Primitives.Dim
Immutable, value-typed. All four types compare by value and never alias. Adding two Vectors allocates a new one; mutating the original is impossible. Internally every value is a small Rust Copy struct, so passing them around is cheap.

Vector

Three-component vector used for positions, directions, sizes, velocities, anywhere a 3D quantity makes sense. Coordinate convention is right-handed: +X right, +Y up, +Z toward the camera.

Native vector interop. Every Ruzit API that accepts a Vector also accepts a Luau native vector (the built-in primitive returned by vector(x, y, z)), so these are interchangeable:
part.Size = Vector.new(1, 2, 3)
part.Size = vector(1, 2, 3)
part:LookAt(vector(0, 5, 0))
Pass whichever feels natural. Use Vector when you want the named methods (:Lerp, :Cross, etc.) or component getters (.X, .Magnitude); reach for native vector when you're hot-path reading components in a tight loop, since native vector reads happen entirely inside the VM (~5-10× faster than crossing the FFI boundary every time).

Constructors

Vector.new(x, y, z) static

Construct a new vector. Each argument is optional; omitted axes default to 0.

Vector.new(1, 2, 3)
Vector.new(5)             -- (5, 0, 0)
Vector.new()              -- (0, 0, 0)
Vector.zero() static

Shorthand for Vector.new(0, 0, 0).

Vector.one() static

Shorthand for Vector.new(1, 1, 1).

Vector.FromNative(native) -> Vector static

Convert a Luau native vector (the built-in primitive returned by vector(x, y, z) and the vector.* library) into a Ruzit Vector userdata. Useful when you've got a native vector from a math helper or external module and need it in the form Ruzit's APIs (BasePart.Size, CFrame.new, etc.) accept.

Vector.FromNative(vector(1, 2, 3))
-- -> Vector(1, 2, 3)

Properties

.X number read-only

Right-axis component.

.Y number read-only

Up-axis component.

.Z number read-only

Forward-axis component (toward the camera in the engine's right-handed convention).

.Magnitude number read-only

Cached Euclidean length, sqrt(X² + Y² + Z²). Computed once at construction; reads are free.

Methods & operators

v:Lerp(other, t) -> Vector method

Linear interpolation. t = 0 returns self, t = 1 returns other. Values outside [0, 1] extrapolate.

v:Dot(other) -> number method

Dot product. Positive when the vectors face roughly the same direction, negative when opposite, zero when perpendicular.

v:Cross(other) -> Vector method

Right-handed cross product, perpendicular to both inputs.

v:Normalized() -> Vector method

Returns a unit-length copy. If the magnitude is effectively zero the original is returned (rather than NaN-ing).

v:Distance(other) -> number method

Euclidean distance between two points. Equivalent to (v - other).Magnitude.

v:ToNative() -> vector method

Convert to a Luau native vector. Use this in hot paths where you're reading components repeatedly — native vector reads happen inside the VM without crossing into Rust, which is roughly 5-10× faster than reading v.X / v.Y / v.Z on a userdata per access.

local nat = part.Size:ToNative()
-- nat.x, nat.y, nat.z are pure Lua reads from here on,
-- and you can pass `nat` back into any API that takes a Vector.
a + b -> Vector

Component-wise addition.

a - b -> Vector

Component-wise subtraction.

v * scalar -> Vector

Scalar multiply. The scalar must be a number.

v / scalar -> Vector

Scalar divide.

-v -> Vector

Negation. Equivalent to v * -1.

a == b, a < b, a <= b -> boolean

Component-wise comparisons (true only when ALL THREE axes match). Note < is partial-order, not magnitude-based — for length comparisons read .Magnitude directly.

Example

local from = Vector.new(0, 0, 0)
local to   = Vector.new(10, 5, 0)

-- Halfway point.
local mid = from:Lerp(to, 0.5)

-- Direction + distance.
local delta    = to - from
local distance = delta.Magnitude
local dir      = delta / distance     -- normalised

Color3

RGB color, channels normalised to 0 .. 1. Three constructors cover the common input formats: linear floats, 8-bit integers, and CSS hex literals.

Constructors

Color3.new(r, g, b) static

Linear 0 .. 1 channels. Out-of-range values are clamped.

Color3.new(0.18, 0.55, 0.28)  -- forest green
Color3.FromRGB(r, g, b) static

8-bit (0 .. 255) channels. Convenient for colors copied from a paint program. Internally divides by 255. Color3.fromRGB is an alias.

Color3.FromRGB(46, 140, 71)
Color3.FromHex(hex) static

CSS-style hex literal. Accepts "#RRGGBB", "RRGGBB", "#RGB" (each digit doubled), or "RGB". Throws on bad lengths or non-hex characters. Color3.fromHex is an alias.

Color3.FromHex("#2e8c47")
Color3.FromHex("ff0")        -- expands to "ffff00"

Properties

.R number read-only

Red channel, 0 .. 1.

.G number read-only

Green channel, 0 .. 1.

.B number read-only

Blue channel, 0 .. 1.

Methods & operators

c:Lerp(other, t) -> Color3 method

Component-wise interpolation. Useful for fades and day/night cycles.

a + b -> Color3

Channel-wise add. Result is clamped to 0 .. 1.

a - b -> Color3

Channel-wise subtract. Clamped at 0.

a == b, a < b, a <= b -> boolean

Component-wise comparisons (true only when ALL THREE channels match the relation).

Example

local day   = Color3.FromHex("#fdf6e3")
local night = Color3.new(0.05, 0.07, 0.13)

local Process = import("Process")
Process.Heartbeat:Connect(function(_dt)
    local t   = (os.clock() % 60) / 60
    local sky = day:Lerp(night, t)
    import("Renderable").SetAmbient(sky)
end)

CFrame

A "Coordinate Frame", the engine's standard transform: a 3D position plus an orientation. Anything that lives in the world (parts, cameras, controllers, attachments) carries a CFrame.

Orientation is stored as Euler angles in radians, applied X -> Y -> Z. For controlled rotations CFrame.Angles(rx, ry, rz) is the canonical builder.

Constructors

CFrame.new(position?, rotation?) static

Construct from a position Vector and (optional) rotation Vector. Both arguments are optional; either defaults to zero.

CFrame.new(Vector.new(0, 5, 0))
CFrame.new(Vector.new(), Vector.new(0, math.pi, 0))
CFrame.Angles(rx, ry, rz) static

Rotation-only CFrame from three Euler angles in radians. Equivalent to CFrame.new(Vector.new(), Vector.new(rx, ry, rz)) but reads more clearly at the call site.

CFrame.Angles(0, math.pi / 4, 0)   -- 45° yaw
CFrame.LookAt(eye, target, up?) static

Build a CFrame at eye oriented so its forward axis points at target. up defaults to Vector.new(0, 1, 0). The returned rotation is in Euler form, ready to drop into a part's CFrame or a camera.

-- Camera looks from (5, 5, 10) at the origin.
camera.CFrame = CFrame.LookAt(
    Vector.new(5, 5, 10),
    Vector.new(0, 0, 0)
)

Properties

.Position Vector read-only

World-space position.

.Rotation Vector read-only

Euler-angle orientation, radians. X is pitch, Y is yaw, Z is roll.

Methods & operators

cf:Lerp(other, t) -> CFrame method

Position lerps linearly; rotation lerps component-wise. Adequate for short-arc animations, use spherical interpolation if you need a full half-turn between keyframes.

a * b (CFrame * CFrame) -> CFrame

Compose poses. parent * child gives the child's world transform when the child is described in the parent's local space.

a * v (CFrame * Vector) -> CFrame

Transforms a point from the CFrame's local space into world space.

a + b, a - b -> CFrame

Component-wise add / subtract. Position and rotation each blend independently.

cf:FuzzyEq(other, epsilon?) -> boolean method

true if every component (3 position + 3 rotation) is within epsilon of the matching component on other. Default epsilon is 1e-5. Prefer this over == for "is the part roughly at this pose?" checks — direct equality on floats is brittle.

Caveat: rotation is compared as raw Euler radians, not angular distance, so two visually identical rotations differing by a multiple of 2π will not FuzzyEq. Wrap your bounds yourself if that matters.

-- Snap an animated part once it's settled near the target pose.
if part.CFrame:FuzzyEq(targetCF, 0.01) then
    part.CFrame = targetCF
    stop_animating()
end

Example

local Renderable = import("Renderable")
local Vector = import("Primitives").Vector
local CFrame = import("Primitives").CFrame

local part = Renderable.BasePart("Cube")
part.Size   = Vector.new(1, 1, 1)
part.CFrame = CFrame.new(Vector.new(0, 2, -5))
              * CFrame.Angles(0, math.pi / 4, 0)

Dim

Two-dimensional position / size, used everywhere screen-space matters: GUI element positions, mouse cursor coords, viewport sizes.

Convention follows pixel coordinates: +X is right, +Y is down (origin at the top-left of the window, opposite to math-class Y).

Constructors

Dim.new(x, y) static

Construct a 2D component.

Dim.new(800, 600)

Properties

.X number read-only

Horizontal component.

.Y number read-only

Vertical component (down-positive).

Methods & operators

d:Lerp(other, t) -> Dim method

Linear interpolation, same shape as Vector.

d:Scale(reference, target, maintainRatio?) -> Dim method new in 1.2

Rescale this Dim from one reference size to another. Designed for prebuilt UI: lay your panels out against a fixed reference (say Dim.new(400, 400)) at design time, then at runtime call :Scale(reference, Window.GetSize()) to map them onto the actual window.

  • reference — the design-time size the dim was authored against.
  • target — the runtime size to map into (e.g. Window.GetSize()).
  • maintainRatio — when true, both axes use the smaller of the two scale factors so the aspect ratio is preserved (good for letter-boxed UI). Default false.
a + b, a - b -> Dim

Component-wise add / subtract.

d * scalar, d / scalar, -d -> Dim

Scalar multiply / divide / negate.

a == b, a < b, a <= b -> boolean

Component-wise comparisons (true only when BOTH axes match the relation).

Example

local GUI = import("GUI")
local Dim = import("Primitives").Dim

local hp = GUI.Basic.Square()
hp.Size     = Dim.new(200, 12)
hp.Position = Dim.new(24, 24)

-- Centre on the window.
local Window = import("Window")
local centre = Window:GetSize() / 2
hp.Position = centre - hp.Size / 2
Next up: Architecture overview covers where these types fit. The other API tabs, Renderable, GUI, and friends, are coming soon.

UDim

Scale-based 2D component, the partner type to Dim. Each axis is a fraction (typically 0..1) of a parent dimension. Use it whenever you want a position or size to track its container (centered button = UDim.new(0.5, 0.5)) instead of living at fixed pixel coordinates.

Constructors

UDim.new(x?, y?) static

Both arguments default to 0.

UDim.zero() static

Shorthand for UDim.new(0, 0).

UDim.one() static

Shorthand for UDim.new(1, 1) — full size of the parent.

UDim.FromDim(scaleX, scaleY, parent) -> Dim static

One-shot scale-to-pixels. Equivalent to UDim.new(scaleX, scaleY):ToDim(parent) but reads more naturally when the scale values are constants. Use it for sizing a button or tile to a fraction of a container without first constructing a UDim value.

-- 20% × 20% of the parent.
btn.Size = UDim.FromDim(0.2, 0.2, parentSize)

Methods & operators

u:ToDim(parent) -> Dim method

Resolve to absolute pixels by multiplying each axis by the corresponding component of parent.

UDim.new(0.5, 0.25):ToDim(Dim.new(800, 600))
-- -> Dim(400, 150)
u:Lerp(other, t) -> UDim method
a + b, a - b -> UDim

Component-wise addition / subtraction (combine offsets).

u * scalar, u / scalar, -u -> UDim

Scalar arithmetic and negation.

a == b, a < b, a <= b -> boolean

Component-wise comparisons (true only when BOTH axes match).

local UDim = Primitives.UDim
local Dim  = Primitives.Dim

-- A button anchored to the right edge, 20% wide.
local winSize  = Dim.new(win:Width(), win:Height())
local btnScale = UDim.new(0.2, 0.08)
btn.Size = btnScale:ToDim(winSize)