Skip to main content
Version: Next 🚧

Space and color

Murali is not pixel-based. Positions, radii, and type sizes are world units. That keeps layout predictable and export resolution-independent.

from murali_engine import Circle, Scene
from murali_kit.colors import BLUE_D, WHITE
from murali_kit.themes import DarkTheme

scene = Scene()
scene.apply_theme(DarkTheme())
scene.add(Circle(radius=1.0, color=BLUE_D).with_stroke(0.04, WHITE))

See Coordinate system for axes, frames, and to_edge.


Colors​

The engine accepts (r, g, b, a) tuples in 0.0…1.0. Named swatches are kit:

from murali_kit.colors import WHITE, BLUE_D, GOLD_C, GRAY_B

Unsuffixed names are the C step (BLUE is BLUE_C). A through E run light to dark.

CategoryColorPreview
AchromaticWHITE#FFFFFF
BLACK#000000
GRAY_A → GRAY_E
BlueBLUE_A → BLUE_E
TealTEAL_A → TEAL_E
GreenGREEN_A → GREEN_E
YellowYELLOW_A → YELLOW_E
GoldGOLD_A → GOLD_E
OrangeORANGE_A → ORANGE_E
RedRED_A → RED_E
MaroonMAROON_A → MAROON_E
PurplePURPLE_A → PURPLE_E
PinkPINK_A → PINK_E
PurePURE_RED / PURE_GREEN / PURE_BLUE

How to think about colors​

  • Use palette constants (e.g. BLUE_C, GREEN_E) for semantic meaning
  • Use raw colors (Vec4) for fine-tuned visuals (backgrounds, subtle tones)
  • Prefer consistency over variety
use murali::colors::*;

let circle_id = scene.add_tattva(
Circle::new(1.5, 48, GREEN_E),
ORIGIN,
);

Positions​

In Murali, the center of the screen is (0, 0, 0).

You define positions using:

Vec3::new(x, y, z)
  • +x → right
  • -x → left
  • +y → up
  • -y → down
  • z → depth (used for layering; higher values come closer to the camera)

In Murali, positions are absolute and deterministic — the same coordinates always produce the same visual result.

You can either use raw vectors:

Vec3::new(2.0, 1.0, 0.0)

Or use predefined constants from murali::positions.

use glam::Vec3;

pub const ORIGIN: Vec3 = Vec3::ZERO;
pub const CAMERA_DEFAULT_POS: Vec3 = Vec3::new(0.0, 0.0, 10.0);

pub const UP: Vec3 = Vec3::Y;
pub const DOWN: Vec3 = Vec3::NEG_Y;
pub const LEFT: Vec3 = Vec3::NEG_X;
pub const RIGHT: Vec3 = Vec3::X;

Common Position Constants​

NameVectorMeaningVisual
UP(0, 1, 0)Move upward⬆️
DOWN(0, -1, 0)Move downward⬇️
LEFT(-1, 0, 0)Move left⬅️
RIGHT(1, 0, 0)Move right➡️
ORIGIN(0, 0, 0)Center of screen🎯
CAMERA_DEFAULT_POS(0, 0, 10)Default camera position📷

Themes​

Murali provides two built-in themes:

  • dark (default)
  • light

Themes define:

  • background color
  • surface colors
  • text colors
  • accent colors

Once you're comfortable, you should create your own theme to define a consistent visual identity.

Creating a custom theme​

  1. Create a themes/ folder next to your murali.toml
  2. Add a file (e.g. sesh.toml)
  3. Define the required fields
  4. Activate it from murali.toml

Example:

name = "murali-dark"
background = "#0A121C"
surface = "#1C2E45"
surface_alt = "#2B405C"
text_primary = "#F2F7FC"
text_muted = "#BCCEE2"
accent = "#56C1F4"
accent_alt = "#AA8EF9"
positive = "#4FD193"
warning = "#F9B742"

Then point Murali at the theme from your project config:

theme = "sesh"

Murali will look for themes/sesh.toml next to your project murali.toml.


Palettes​

For advanced use cases, Murali supports custom palettes.

Palettes allow you to define your own color systems beyond the built-in constants.

How to create a palette​

  1. Create a palettes/ folder next to your murali.toml
  2. Add a file (e.g. my_palette.toml)
  3. Define your colors inside
  4. Load the palette by name in your scene code

Example palette file:

name = "my-palette"
primary = "#56C1F4"
secondary = "#AA8EF9"
highlight = "#F9B742"

Example usage:

use murali::Palette;

let palette = Palette::load("my_palette");
let primary = palette.require("primary");

This feature is evolving — examples will be added soon.


You now have the core mental model for how Murali represents visuals.

→ Continue to First Scene