> ## Documentation Index
> Fetch the complete documentation index at: https://docs.spurdoverse.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Color

> 8-bit RGBA color with hex, packed, HSV and HSL forms.

export const like_0 = "ColorLike"

export const name_0 = "Color"

An 8-bit RGBA color, channels `0`–`255`. Global class, no import.

```ts theme={null}
const orange = new Color(255, 128, 0);            // alpha defaults to 255
const faded = orange.lerp("#ffffff", 0.5);        // any ColorLike works where a color is expected
const glass = Color.from([255, 255, 255, 64]);
```

<Note>
  A plain number is always packed `0xAABBGGRR`, red in the low byte.
  Fields `r`, `g`, `b`, `a` take integers `0`–`255`, anything else throws.
</Note>

`ColorLike` is a `Color`, a packed number, `"#rgb"`, `"#rgba"`, `"#rrggbb"`, `"#rrggbbaa"`, `[r, g, b, a?]` or `{ r, g, b, a? }`.

## Overview

<CardGroup cols={2}>
  <Card title="Common" icon="layer-group" href="#common">
    `from`, `set`, `add`, `lerp`…
  </Card>

  <Card title="Creating" icon="plus" href="#creating">
    `fromHex`, `fromRGB`, `fromHSV`, `red()`…
  </Card>

  <Card title="Adjusting" icon="sliders" href="#adjusting">
    `scale`, `withAlpha`, `withAlphaF`, `lerp`.
  </Card>

  <Card title="Converting" icon="right-left" href="#converting">
    `toHex`, `toABGR`, `toHSV`…
  </Card>
</CardGroup>

***

## Common

Every argument takes any <code>{like_0}</code>, not just a <code>{name_0}</code>.

| Member | Does |
| :- | :- |
| <code>new {name_0}(value)</code>, <code>{name_0}.from(value)</code> | Copy from any <code>{like_0}</code>. |
| `set(...)` | Replaces every component in place, returns `this`. Same arguments as the constructor. |
| `clone()` | A copy. |
| `equals(other, epsilon?)` | Every component within `epsilon`. Default `0`, exact. |
| `toArray()`, `toJSON()` | Plain array, plain object. |
| `toString()` | <code>"{name_0}(…)"</code> |
| `add(other)`, `sub(other)` | Component-wise. |
| `scale(factor)` | Every component times `factor`. |
| `mul(x)`, `div(x)` | By a number, or component-wise by another value. Dividing by zero throws `RangeError`. |
| `lerp(other, t)` | Linear blend, `t` not clamped. |
| `normalize()`, `normalized()` | The first changes the value and returns `this`, the second returns a copy. |

Only `set()` and `normalize()` change the value. Nothing changes its arguments.

Color has no `mul`, `div` or `normalize`. Channel math clamps instead of wrapping, and `lerp` clamps `t` to `0`–`1`.

***

## Creating

The constructor with no arguments is opaque white.

<Warning>
  `new Color(255)` is not grey or white. One number is the packed form, so it's red with alpha `0`.
</Warning>

| Static | From |
| :- | :- |
| `Color.fromABGR(value)` | `0xAABBGGRR`, same as passing the number |
| `Color.fromRGBA(value)` | `0xRRGGBBAA` |
| `Color.fromARGB(value)` | `0xAARRGGBB` |
| `Color.fromRGB(value)` | `0xRRGGBB`, alpha 255, top byte ignored |
| `Color.fromFloat(r, g, b, a?)` | Channels `0`–`1`, clamped, alpha defaults to `1` |
| `Color.white()`, `black()`, `red()`, `green()`, `blue()` | Opaque |
| `Color.transparent()` | `(0, 0, 0, 0)` |

```ts theme={null}
Color.fromRGBA(0xff8800ff);   // opaque orange
Color.fromRGB(0x008080);      // teal
```

### fromHex

<br />

```ts theme={null}
Color.fromHex(hex: string): Color
```

Parses `rgb`, `rgba`, `rrggbb` or `rrggbbaa`, with or without `#`. Anything else throws `TypeError`.

```ts theme={null}
Color.fromHex("#00ff0080");   // half-transparent green
Color.fromHex(userInput);     // plain strings too, unlike ColorLike
```

### fromHSV

<br />

```ts theme={null}
Color.fromHSV(h: number, s: number, v: number, a?: number): Color
Color.fromHSL(h: number, s: number, l: number, a?: number): Color
```

Hue in degrees, any value (wrapped). Saturation, value, lightness and alpha are `0`–`1`, alpha defaults to `1`.

```ts theme={null}
const rainbow = Color.fromHSV((Date.now() / 10) % 360, 1, 1);
const pastel = Color.fromHSL(200, 0.6, 0.8);
```

***

## Adjusting

| Method | Returns |
| :- | :- |
| `add(other)`, `sub(other)` | Channel-wise including alpha, saturating at `255` / `0` |
| `scale(factor)` | Brightness: `r`, `g`, `b` times `factor`, alpha unchanged |
| `lerp(other, t)` | All four channels towards `other`, `t` clamped to `0`–`1` |

### withAlpha

<br />

```ts theme={null}
withAlpha(alpha: number): Color
withAlphaF(alpha: number): Color
```

The same color with a new alpha. `withAlpha` takes `0`–`255`, `withAlphaF` takes `0`–`1`. Both clamp.

```ts theme={null}
Color.red().withAlpha(128);    // half transparent
Color.red().withAlphaF(0.5);   // same
```

***

## Converting

| Method | Returns |
| :- | :- |
| `toABGR()` | `0xAABBGGRR`, the ColorLike number form |
| `toRGBA()` | `0xRRGGBBAA` |
| `toARGB()` | `0xAARRGGBB` |
| `toHex()` | `"#rrggbbaa"`, lowercase |
| `toHSV()` | `{ h, s, v, a }`, hue in degrees `0`–`360` (`0` for greys), the rest `0`–`1` |
| `toHSL()` | `{ h, s, l, a }`, same ranges |

```ts theme={null}
Color.red().toHex();   // "#ff0000ff"

localStorage.setItem("accent", accent.toHex());
const saved = Color.fromHex(localStorage.getItem<string>("accent") ?? "#fff");
```

***

## Example

Health bar color from green to red, faded by distance.

```ts theme={null}
import entities from "@native/entities";
import render from "@native/render";

const full = Color.fromHex("#40ff40");
const empty = Color.fromHex("#ff4040");

on("render", () => {
    const myPos = entities.getLocalPlayer()?.getOrigin();
    if (!myPos) return;

    for (const player of entities.getPlayers({ skipLocal: true })) {
        const pos = player.getOrigin();
        const screen = pos && render.worldToScreen(pos);
        if (!pos || !screen) continue;

        const color = empty
            .lerp(full, player.m_iHealth / 100)
            .withAlphaF(Math.remap(myPos.distTo(pos), 500, 4000, 1, 0.3));

        render.rectFilled(screen.sub([20, 2]), screen.add([20, 2]), color);
    }
});
```
