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.
| Category | Color | Preview |
|---|---|---|
| Achromatic | WHITE | #FFFFFF |
| BLACK | #000000 | |
| GRAY_A → GRAY_E | ||
| Blue | BLUE_A → BLUE_E | |
| Teal | TEAL_A → TEAL_E | |
| Green | GREEN_A → GREEN_E | |
| Yellow | YELLOW_A → YELLOW_E | |
| Gold | GOLD_A → GOLD_E | |
| Orange | ORANGE_A → ORANGE_E | |
| Red | RED_A → RED_E | |
| Maroon | MAROON_A → MAROON_E | |
| Purple | PURPLE_A → PURPLE_E | |
| Pink | PINK_A → PINK_E | |
| Pure | PURE_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→ downz→ 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
| Name | Vector | Meaning | Visual |
|---|---|---|---|
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
- Create a
themes/folder next to yourmurali.toml - Add a file (e.g.
sesh.toml) - Define the required fields
- 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
- Create a
palettes/folder next to yourmurali.toml - Add a file (e.g.
my_palette.toml) - Define your colors inside
- 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