Sketch structure
Every sketch inherits from Sketch and implements Draw(). A host calls Setup() once, then Draw() on every frame, at the rate set by FrameRate().
On this page · 19 entries
SetupDrawSizeFrameRateNoLoopDelayThread[Tweak] · [Tweak(float min, float max)] · ShowTweaks · HideTweaksOnStopShade · CreateShader2D · LoadShader2DWindowResizedDisplayDensity · PixelDensityPixelWidth · PixelHeightSettingsFullScreen · WindowMove · WindowResize · WindowResizable · WindowTitle · WindowRatioRedrawExitPrint · Println · LogWarning · LogError- Runnable example
Setup
Setup() → void
Runs once before the first frame. Use it to set the canvas size and any one-time state.
Drawabstract
Draw() → void
Runs once per frame while IsLooping is true. The only member every sketch must implement.
Size
Size(int w, int h)
Sets the canvas dimensions. Call from Setup().
FrameRate
FrameRate(int fps)
Sets the target frame rate. Minimum 1.
NoLoop
NoLoop() / Loop()
Stops or resumes automatic per-frame redraw via IsLooping.
Delay
Delay(int ms)
Halts the calling thread for ms milliseconds. Since Draw() runs on whatever thread the host pumps its render loop on, a long Delay() blocks that same thread/frame — exactly like Processing blocking its own animation thread.
FrameRate() for smooth motion. Delay() is meant for sketches that only need to redraw occasionally and would rather sit idle than burn CPU on frames nobody will see change — a slow-updating clock, a sensor readout, an ambient display.Thread
Thread(string methodName)
Runs a no-argument method of this sketch on a background thread and returns immediately, like Processing's thread(functionName). Looks the method up by name via reflection (public or private, instance method) — same string-based API as Processing's own.
Draw() just read that field each frame. Keep the handoff to something simple (a single field write/read, or your own lock) to avoid tearing.[Tweak] · [Tweak(float min, float max)] · ShowTweaks · HideTweaks
[Tweak][Tweak(float min, float max)]ShowTweaks()HideTweaks()
Put [Tweak] above a float, double, int, bool or Color field and it gets a live control in a panel over the running sketch: a slider (a checkbox for bool, three R/G/B sliders for Color). Drag it and the field changes while the sketch keeps running — no Run, no restart. [Tweak(0, 20)] sets the range; plain [Tweak] goes from 0 to twice the starting value. Label = "..." changes the text. Click the panel's header to fold it; HideTweaks() hides it (before SaveFrame(), say) and ShowTweaks() brings it back.
MousePressed()/MouseClicked(), so dragging a slider doesn't also paint on your canvas. The values live in your own fields, so ⚡ Hot Reload keeps whatever you tuned.GetTweakValues() returns each [Tweak] field's current value already written as C#.OnStopvirtual
OnStop() → void
Override to let go of anything the sketch opened outside the engine — a camera, a serial port, a MIDI or audio device, a socket — like Processing's dispose(). Called once, when the sketch stops for good: ■ Stop (the Run switch) in the IDE, another Run replaces it, or its window closes. Not called on ⚡ Hot Reload, where those same objects carry over to the new code. Without it, a device opened by the previous Run stays busy until the IDE closes.
Shade · CreateShader2D · LoadShader2D
Shade(string sksl)Shade(PShader2D shader, x?, y?, w?, h?)CreateShader2D(sksl)LoadShader2D(path)
Fills the canvas (or a rectangle) with a fragment shader written in SkSL — Skia's shading language: GLSL with half4/float2 instead of vec4/vec2 and a half4 main(float2 fragCoord). Runs in the plain 2D renderer on every OS. When declared, these uniforms are filled in for you: iTime, iResolution, iMouse (x, y, pressed), iFrame, iAmplitude and iSpectrum[8|16|32|64]; set your own with shader.Set("name", ...). fragCoord is in sketch pixels with y pointing down.
Shade(source) compiles once and caches by the text, so editing the shader and pressing ⚡ Hot Reload swaps it in without restarting time or music. If the new code doesn't compile, the last good shader keeps running and the error shows bottom-left. It runs on the CPU: keep the canvas modest.WindowResizedvirtual
WindowResized() → void
Called when the canvas size changes after the first frame.
DisplayDensity · PixelDensity
DisplayDensity() → intPixelDensity(int density)
HiDPI helpers kept for API parity. DisplayDensity() always returns 1 — DanaProcessing draws everything at logical-pixel resolution and leaves any HiDPI scaling to the host. PixelDensity() only validates its argument (1 or 2, like Processing) and otherwise has no effect.
PixelWidth · PixelHeight
PixelWidthPixelHeight → int
Width/height of the sketch's backing buffer in actual pixels, like Processing's pixelWidth/pixelHeight. Since DanaProcessing always draws at 1:1 (see PixelDensity() above), these are always equal to Width/Height — kept so sketches ported from Processing that read them directly (e.g. when indexing LoadPixels()'s array by hand) keep working unchanged.
Settingsvirtual
Settings() → void
Runs once, before Setup(), like Processing's settings(). The host is responsible for calling it immediately before Setup().
size() is special-cased by the preprocessor and can't take a variable inside setup(). Plain C# has no such restriction — Size() works fine called directly inside Setup() too. Overriding Settings() is provided purely so sketches ported from Processing that rely on the setup-order guarantee (settings() strictly before setup()) keep behaving the same way.FullScreen · WindowMove · WindowResize · WindowResizable · WindowTitle · WindowRatio
FullScreen(bool fullScreen = true)WindowMove(x, y)WindowResize(w, h)WindowResizable(bool)WindowTitle(string)WindowRatio(w, h)
Window-management requests, each backed by an event a host can subscribe to and act on — the same pattern RedrawRequested/ExitRequested already use. SetLocation(), SetResizable(), and SetTitle() are classic-API aliases for WindowMove(), WindowResizable(), and WindowTitle() respectively.
| call | event raised | readable state |
|---|---|---|
| FullScreen(bool) | FullScreenRequested | IsFullScreen |
| WindowMove(x, y) | WindowMoveRequested | — |
| WindowResize(w, h) | WindowResizeRequested | — |
| WindowResizable(bool) | WindowResizableChanged | IsWindowResizable |
| WindowTitle(string) | WindowTitleChanged | WindowTitleText |
| WindowRatio(w, h) | WindowRatioRequested | — |
Redraw
Redraw() → void
Requests a single extra frame while NoLoop() is in effect, raising the RedrawRequested event. Looping sketches don't need this — they're already rendering continuously.
Exit
Exit() → void
Raises the ExitRequested event. DanaProcessing doesn't own a process to terminate — whatever hosts the sketch (a window, a canvas control) should subscribe and close/stop accordingly.
Print · Println · LogWarning · LogError
Print(object message)Println(message)LogWarning(message)LogError(message)
Print writes with no trailing newline and no timestamp/coloring — meant for building a line piece by piece across calls, finished off with a Println. Println/LogWarning/LogError go through DanaLogger, timestamped and color-coded by level.
| property | type | meaning |
|---|---|---|
| FrameCount | int | Frames drawn so far. |
| Width / Height | int | Current canvas size. |
| TargetFrameRate | int | Set via FrameRate(). |
| IsLooping | bool | Whether the host should keep calling Draw(). |
| DisplayWidth / DisplayHeight | int | Size of the screen the sketch runs on. 0 until the host sets it. |
Runnable example
A complete sketch using this section. Test in Dana opens it in the IDE, or paste it into a new tab and press Run.
// Setup() runs once, Draw() every frame. NoLoop()/Loop() pause and resume. public class Structure : Sketch { float angle; public override void Setup() { Size(500, 300); FrameRate(60); } public override void Draw() { Background(30, 32, 40); angle += 0.05f; Fill(255, 180, 120); NoStroke(); Circle(Width / 2 + Cos(angle) * 150, Height / 2, 40); Fill(255); Text($"frame {FrameCount} · click to {(IsLooping ? "pause" : "resume")}", 12, 20); } public override void MousePressed() { if (IsLooping) NoLoop(); else Loop(); } }