hx-multianim
A Haxe library for creating animations and pixel art UI elements using the Heaps framework. Define state animations and programmable UI components with a custom .manim DSL.
Interactive Playground
Try it live: hx-multianim Playground
Edit .manim files in the browser and see results instantly. Source: hx-multianim-playground.
Visual Test Report
Browse all rendered examples: Visual Test Report
90+ visual tests covering UI components, layouts, filters, particles, animated paths, and more. Tests run automatically on every push via GitHub Actions.
Documentation
- .manim Format Reference — UI elements, programmables, layouts, graphics, particles, and data blocks
- .manim Quick Reference — Table-based lookup of all
.manimelements, properties, and operations - Animated Paths Guide — Paths, curves, easing, animated path traversal, projectiles, and examples
- Programmable Macros — Compile-time code generation tutorial and reference
- Data Blocks — Static typed data definitions with macro codegen
- .anim Format Reference — State animations with playlists and extra points
- .anim Quick Reference — Table-based lookup of all
.animdeclarations, filters, conditionals, and Haxe API
Getting Started
Prerequisites
Install Haxe
Download and install Haxe from haxe.org.
Install Lix (Recommended)
Lix is the modern package manager for Haxe projects:
npm install -g lix
Quick Start
-
Add to your project:
`hxml -lib hx-multianim -lib heaps` -
Create a UI element (
.manim):` version: 1.0
#textDemo programmable() {
text(dd, "Hello World", red, left, 200): 0, 0
text(m3x6, "Centered text", blue, center, 200): 0, 20
}
`
- Load and build in Haxe:
`haxe import bh.multianim.MultiAnimBuilder;
// Load the .manim file var fileContent = byte.ByteData.ofString(sys.io.File.getContent("ui.manim")); var builder = MultiAnimBuilder.load(fileContent, resourceLoader, "ui.manim");
// Build a programmable element
var result = builder.buildWithParameters("textDemo", new Map());
scene.addChild(result.object);
`
- Create a state animation (
.anim):` sheet: characters states: direction(l, r)
animation idle {
fps: 4
playlist {
sheet: "player_${direction}_idle"
}
}
`
- Load and use AnimationSM:
`haxe import bh.stateanim.AnimParser; import bh.stateanim.AnimationSM;
// Load and parse var parsed = resourceLoader.loadAnimParser("character.anim");
// Create state selector var stateSelector:AnimationStateSelector = ["direction" => "l"];
// Create animation state machine var animSM = parsed.createAnimSM(stateSelector); scene.addChild(animSM);
// Control animations
animSM.addCommand(SwitchState("idle"), ExecuteNow);
`
UIScreen System
The library provides a screen management system for building complete UI applications.
ScreenManager
ScreenManager handles screen lifecycle, resource loading, and hot-reloading:
import bh.ui.screens.ScreenManager;
class Main extends hxd.App {
var screenManager:ScreenManager;
override function init() {
screenManager = new ScreenManager(this);
screenManager.showScreen(new MainMenuScreen(screenManager));
}
override function update(dt:Float) {
screenManager.update(dt);
}
}
UIScreen
Extend UIScreenBase to create screens with UI elements:
import bh.ui.screens.UIScreen;
import bh.ui.screens.ScreenManager;
class MainMenuScreen extends UIScreenBase {
var builder:MultiAnimBuilder;
public function new(screenManager:ScreenManager) {
super(screenManager);
}
public override function load() {
// Load .manim file with hot-reload support
builder = screenManager.buildFromResourceName("ui/mainmenu.manim", true);
// Build and add UI elements
var panel = builder.buildWithParameters("mainPanel", []);
addBuilderResult(panel);
// Add interactive elements
var button = addButton(builder.createElementBuilder("button"), "Start Game", null);
addElementWithPos(button, 100, 200);
button.onClick = () -> onStartGame();
}
public override function onScreenEvent(event:UIScreenEvent, source:UIElement) {
// Handle UI events
}
}
Layers
Screens support multiple z-order layers for proper element stacking:
// Built-in layers (lowest to highest)
BackgroundLayer // Layer index 1
DefaultLayer // Layer index 3
ModalLayer // Layer index 5
// Add elements to specific layers
addElement(button, ModalLayer);
addObjectToLayer(sprite, BackgroundLayer);
UI Elements
UIScreenBase provides helper methods for common UI components. Settings are injected automatically via MacroUtils.macroBuildWithParameters or passed explicitly. See docs/manim.md for full component reference.
// Buttons
var btn = addButtonWithSingleBuilder(builder, "button", settings, "Click Me");
// or with explicit builder
var btn = addButton(builder.createElementBuilder("button"), "Click Me", settings);
// Checkboxes (buildName overridable via settings)
var cb = addCheckbox(builder, true);
// Sliders (supports custom range via min/max/step settings)
var slider = addSlider(builder, 50);
slider.min = 0;
slider.max = 1;
slider.step = 0.1;
// Progress bars (display-only, value 0-100)
var bar = addProgressBar(builder, settings, 75);
// Dropdowns (all sub-component names overridable via settings)
var dd = addDropdown(dropdownBuilder, panelBuilder, itemBuilder,
scrollbarBuilder, "scrollbar", items, settings);
// Scrollable lists
var list = addScrollableList(panelBuilder, itemBuilder, scrollbarBuilder,
"scrollbar", items, settings, 0, 200, 300);
// Radio buttons
var radio = addRadio(builder, items, true, 0); // vertical, initially selected index 0
Element Groups
Organize and manage related elements:
// Create a group
createGroup("menuButtons");
// Add elements to group
addElementToGroup("menuButtons", button1);
addElementToGroup("menuButtons", button2);
// Remove all elements in group
removeGroupElements("menuButtons");
Dialogs
Show modal dialogs over the current screen:
// Show dialog
screenManager.showDialog(new ConfirmDialog(screenManager), this, "confirm");
// Handle dialog result in onScreenEvent
public override function onScreenEvent(event:UIScreenEvent, source:UIElement) {
switch event {
case UIOnControllerEvent(OnDialogResult(dialogName, result)):
if (dialogName == "confirm") {
// Handle dialog result
}
default:
}
}
License
BSD 3-Clause — see LICENSE for details.