Touch and pen painting app¶
Time: 60 minutes. Difficulty: Advanced.
Author a full painting application as a single .esk: canvas,
brush picker, color swatch, undo / redo, save as PNG. Ships with
the user's tablet pressure / tilt mapped to the painted strokes.
Prerequisites¶
- Designer installed.
- A pen tablet (Wacom, Apple Pencil, Surface Pen, Huion, XP-Pen).
- Familiarity with the Brush quick start.
The window¶
File > New Skin, 1024 x 720. Default rectangular window with
a title bar: this is a real app, not a widget. Window > Toggle
Title Bar if you want chrome-less.
Layout¶
Author with the three columns common in painting apps:
| Region | Size | Contents |
|---|---|---|
| Left toolbox | 80 wide | Brush, Erase, Fill, Eyedrop buttons |
| Center canvas | 700 x 700 | The paint surface |
| Right panel | 240 wide | Brush size / opacity sliders, color picker, layer list |
Use the Designer's Row + Col + Stack containers (or hand-place each placement).
The canvas¶
The center is one big image placement with a writable
PaintMask. Set kind = "image", width = height = 700,
paint_mask = true.
The framework's brush system writes strokes into this mask layer when the Brush tool is active.
Wire the toolbox buttons¶
Each button switches the active tool:
(api.set_tool is the Designer's tool-switch API; in your runtime
app, simulate via the framework's Tool registry.)
Brush size + opacity sliders¶
Slider bindings in the document:
{ "id": "size_slider", "kind": "slider",
"x": 16, "y": 64, "width": 200, "height": 24,
"min": 1, "max": 200, "value": 24, "label": "Size" }
Tap the slider; the brush size updates live. Same for opacity.
Color picker¶
Drop a kind: "color_picker" placement with width: 200, height:
200. The picker exposes a change hook with the new color.
Layers¶
The user wants per-layer painting. Use the framework's per- placement layer model:
- "Layer 1" is the canvas's default layer.
- "Add Layer" button creates a new transparent layer on top.
- Toggle visibility and reorder in the right-panel layer list.
For v1 simplicity, support 4 layers; expand later.
Undo / redo¶
The framework's stroke history is per-placement. Bind:
@window.on("undo.click")
def undo(event):
window.canvas.undo_stroke()
@window.on("redo.click")
def redo(event):
window.canvas.redo_stroke()
Cmd+Z / Ctrl+Z are handled by the framework automatically
when the canvas has focus.
Save as PNG¶
The export captures every visible layer composited into one PNG.
Tablet calibration¶
First-run flow: Preferences > Tablet > Calibrate Pressure.
Three test strokes; the Designer remaps pressure to your hand's
typical range.
Test¶
Run > Preview Skin. Paint with the pen. The strokes should
respond to pressure (size + opacity) and tilt (Bristle / Pattern
engines).
Ship¶
What you exercised¶
- Three-column app layout in the Designer.
kind: "image"withpaint_mask.- Brush + Erase + Fill + Eyedrop tool integration.
- Slider + color_picker components.
- Layer list.
- Per-placement stroke history (undo / redo).
export_pngfor saving.