Skip to main content

PML (Picture Markup Language) — A Lisp-style language for sprite asset generation

Project description

PML — Picture Markup Language

A Lisp-style DSL for sprite asset generation. Describe game sprites in S-expressions, compile to PNG/GIF via Pillow.

(sprite-canvas 128 256 :bg "transparent")
(add (character :expression "happy" :style 'cel))
(render "hero.png")

Quick Start

# Install
uv sync

# Run a file
uv run pml examples/hello.pml

# Start REPL
uv run pml

# Render a sprite (see examples/sprite.pml)
uv run pml examples/sprite.pml -o examples_output

# Render animation as GIF
uv run pml examples/animation.pml -o examples_output

# CLI options
uv run pml file.pml --json          # Structured JSON output
uv run pml file.pml -o ./output     # Set output directory
uv run pml file.pml --watch         # Auto-re-run on file change
uv run pml --help                   # All options

Examples

Basic Graphics

(canvas 300 200 :bg "#f5f5f5")
(add (rect 20 20 80 60 :fill "#3498db" :stroke "#2c3e50" :stroke-width 2))
(add (circle 180 60 35 :fill "#e74c3c"))
(add (ellipse 260 100 25 40 :fill "#2ecc71"))
(render "shapes.png")

Character Sprite

(sprite-canvas 128 256 :bg "transparent" :anchor 'center-bottom)

(define hero
  (character
    :outfit (outfit :top 'armor :bottom 'armor :shoes 'boots)
    :weapon (weapon :type 'sword :material 'crystal :element 'holy)
    :expression "happy"
    :style 'cel))

(add hero)
(render "hero.png")

Animation → GIF

(canvas 200 200 :bg "#1a1a2e")

(define ball (circle 30 30 20 :fill "#e74c3c"))

(animate ball 'x 30 170 1.0 :ease 'sine-in-out)
(animate ball 'y 30 170 0.4 :ease 'bounce-out)
(play)
(render "bounce.gif" :fps 30)

Skeleton & IK

(defskeleton arm (x y)
  (joint shoulder :pos (0 0)   :length 40.0 :angle 0.0 :min -120 :max 120)
  (joint elbow   :pos (0 40)  :length 35.0 :angle 0.0 :min -150 :max 0)
  (joint wrist   :pos (0 35)  :length 0.0  :angle 0.0))

(define arm-inst (instantiate-skeleton arm 50 180))
(ik-solve arm-inst 'wrist 95 125 :method 'fabrik :iterations 30)
(joint-position arm-inst 'elbow)   ; → (x y)

Spritesheet

(render-spritesheet "sprites.png"
  (character :expression "happy") (character :expression "angry")
  :cols 2 :cell-width 64 :cell-height 64)
; → spritesheet.png + spritesheet.spritesheet.json

UI Widgets

(sprite-canvas 256 192)
(define btn (button :label "Start" :width 100 :height 32 :style 'rounded))
(add (group :transform (translate 0 10) btn))
(render "ui.png")

More examples in examples/.


Features

  • Full Lisp dialect: S-expressions, closures, macros, lexical scoping
  • Graphics pipeline: primitives, transforms, canvas compositing
  • Sprite system: style engine, palette management, semantic components (character, body, eyes, hair, outfit, items, UI, scene elements)
  • Animation engine: property tweening, timeline, easing functions, GIF export
  • Inverse Kinematics: FABRIK and CCD solvers with angle constraints and skin binding
  • Module system: import/provide with caching and circular dependency detection
  • Standard library: math, color, easing, shapes
  • MCP server: expose as tools for AI agents (Claude, Cursor)
  • CLI: file execution, REPL, watch mode, JSON output, output directory control
  • Pillow backend: PNG, JPG, GIF output
  • LLM-friendly API: structured error hints for AI repair

Project Structure

pml/                          # Core interpreter
├── lexer.py → parser.py → expander.py → evaluator.py  # Pipeline
├── environment.py            # Lexical scoping
├── module_loader.py          # import/provide system
├── errors.py                 # Error types with repair hints
├── types.py                  # Symbol, Keyword, Procedure, Macro
├── repl.py                   # CLI + REPL entry
├── api.py                    # PMLRuntime — LLM-facing API
├── mcp_server.py             # MCP server for AI agents
├── transform.py              # AffineTransform
├── builtins/                 # Arithmetic, comparison, IO, list/string ops
├── graphics/                 # Primitives, canvas, render
├── sprites/                  # Style, palette, components
├── animation/                # Timeline, easing, interpolation
├── skeleton/                 # SkeletonTemplate, FABRIK/CCD IK
└── backend/                  # Pillow render backend
stdlib/                       # Standard library (.pml files)
├── math.pml, color.pml, easing.pml, shapes.pml
└── sprites/                  # Component API docs
examples/                     # Runnable .pml demos
tests/                        # pytest test suite (389 tests)
docs/
├── language.md               # Full language reference
└── README.zh.md              # Chinese guide

Documentation

Resource Link
Language Reference docs/language.md
Chinese Guide docs/README.zh.md
Examples examples/
API Reference pml/api.py

MCP Server

For AI agents (Claude Desktop, Cursor, etc.):

uv run pml-mcp

Exposes 5 tools: execute_pml, render_sprite, validate, list_components, preview_params.

Add to Claude Desktop config:

{
  "mcpServers": {
    "pml": {
      "command": "uv",
      "args": ["run", "pml-mcp"],
      "cwd": "/path/to/PML"
    }
  }
}

Requirements

  • Python ≥ 3.10
  • Pillow ≥ 12.2.0
  • uv package manager (install guide)

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

picmarkup-0.1.0.tar.gz (165.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

picmarkup-0.1.0-py3-none-any.whl (101.5 kB view details)

Uploaded Python 3

File details

Details for the file picmarkup-0.1.0.tar.gz.

File metadata

  • Download URL: picmarkup-0.1.0.tar.gz
  • Upload date:
  • Size: 165.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for picmarkup-0.1.0.tar.gz
Algorithm Hash digest
SHA256 dce7a465543d8d9765245ee07d5901d824fa29904e586172f112fae82d8fdedd
MD5 7f3ee375fbdcf5a09ce25f444961fd65
BLAKE2b-256 e4bd3823c8c3878a7737ac5d764b47120d75d5202ea0651af45582c62c6e0cfd

See more details on using hashes here.

File details

Details for the file picmarkup-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: picmarkup-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 101.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for picmarkup-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e3b08c95484b10db9ac587eb9fed89aeea8b569b4d7e90017e069d9a6813c9ae
MD5 d3b0279f371cb248a2cd6ed8c3676520
BLAKE2b-256 5130935ea996d2edf60fb52318fb6fada7a7baa7ce673959bf798e558b6e5224

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page