Repository navigation
Track Processing API coverage in libprocessing/mewnala #153
Description
This issue tracks progress toward implementing the Processing API in libprocessing/mewnala.
The goal is to reach broad compatibility with the existing Processing API so that sketches can be ported with minimal friction.
Guidelines
Keywords below are listed using the original Java syntax. Some differences are expected due to the specifics of Python.
Breaking changes should be intentional, and their motivation should be documented in the corresponding issues or PRs.
Definition of done
Mark items as done only once they:
- match the original Processing behavior (see the linked reference page)
- have been validated with example sketches (e.g. in Processing examples, Nature of Code, or the
examplesdirectory) - are included in the latest mewnala release (https://pypi.org/project/mewnala/)
Progress Tracker
Important
The list is based on the official Processing reference. This is NOT an exhaustive list of every class, method, or keyword in Processing. Parts of the API are undocumented or listed in individual class pages, see the Methods section of PVector or PImage for example. For a more complete API overview, see the Processing 4 Javadoc.
Data
Composite
- Array
- ArrayList
- FloatDict
- FloatList
- HashMap
- IntDict
- IntList
- JSONArray
- JSONObject
- Object
- String
- StringDict
- StringList
- Table
- TableRow
- XML
Array Functions
Conversion
Primitive
String Functions
Input
Files
- BufferedReader
- createInput()
- createReader()
- launch()
- loadBytes()
- loadJSONArray()
- loadJSONObject()
- loadStrings()
- loadXML()
- parseJSONArray()
- parseJSONObject()
- parseXML()
- selectFolder()
- selectInput()
- loadTable()
Time & Date
Keyboard
Mouse
- mouseButton
- mouseClicked()
- mouseDragged()
- mouseMoved()
- mousePressed
- mousePressed()
- mouseReleased()
- mouseWheel()
- mouseX
- mouseY
- pmouseX
- pmouseY
Constants
Typography
Loading & Displaying
Attributes
Metrics
Rendering
Shaders
Image
Pixels
Loading & Displaying
Textures
Shape
2d primitives
Vertex
- beginContour()
- beginShape()
- bezierVertex()
- curveVertex()
- endContour()
- endShape()
- quadraticVertex()
- vertex()
Curves
- bezierDetail()
- bezierPoint()
- bezierTangent()
- bezier()
- curveDetail()
- curvePoint()
- curveTangent()
- curveTightness()
- curve()
3D Primitives
Attributes
Loading & Displaying
Math
Calculation
- abs()
- ceil()
- constrain()
- dist()
- exp()
- floor()
- lerp()
- log()
- mag()
- map()
- max()
- min()
- norm()
- pow()
- round()
- sq()
- sqrt()
Trigonometry
Operators
- += (add assign)
- + (addition)
- -- (decrement)
- / (divide)
- /= (divide assign)
- ++ (increment)
- - (minus)
- % (modulo)
- * (multiply)
- *= (multiply assign)
- -= (subtract assign)
Bitwise Operators
Random
Output
Files
- PrintWriter
- beginRaw()
- beginRecord()
- createOutput()
- createWriter()
- endRaw()
- endRecord()
- saveBytes()
- saveJSONArray()
- saveJSONObject()
- saveStream()
- saveStrings()
- saveTable()
- saveXML()
- selectOutput()
Text Area
Image
Color
Creating & Reading
Setting
Lights Camera
Lights
- ambientLight()
- directionalLight()
- lightFalloff()
- lightSpecular()
- lights()
- noLights()
- normal()
- pointLight()
- spotLight()
Material Properties
Camera
Coordinates
Transform
- applyMatrix()
- popMatrix()
- printMatrix()
- pushMatrix()
- resetMatrix()
- rotateX()
- rotateY()
- rotateZ()
- rotate()
- scale()
- shearX()
- shearY()
- translate()
Structure
- [] (array access)
- = (assign)
- catch
- class
- , (comma)
- // (comment)
- {} (curly braces)
- /** */ (doc comment)
- . (dot)
- draw()
- exit()
- extends
- false
- final
- implements
- import
- loop()
- /* */ (multiline comment)
- new
- noLoop()
- null
- () (parentheses)
- popStyle()
- pop()
- private
- public
- pushStyle()
- push()
- redraw()
- return
- ; (semicolon)
- setLocation()
- setResizable()
- setTitle()
- setup()
- static
- super
- this
- thread()
- true
- try
- void
Control
Conditionals
Relational Operators
- == (equality)
- > (greater than)
- >= (greater than or equal to)
- != (inequality)
- < (less than)
- <= (less than or equal to)
Iteration
Logical Operators
Environment
- cursor()
- delay()
- displayDensity()
- displayHeight
- displayWidth
- focused
- frameCount
- frameRate
- frameRate()
- fullScreen()
- height
- noCursor()
- noSmooth()
- pixelDensity()
- pixelHeight
- pixelWidth
- settings()
- size()
- smooth()
- width
- windowMove()
- windowMoved()
- windowRatio()
- windowResizable()
- windowResize()
- windowResized()
- windowTitle()
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsTodo
Activity
Gmin2 commentedon May 29, 2026
hey @SableRaf , i was just experimenting with this and managed to get the math ones working (map, constrain, lerp, norm, dist, mag, radians, degrees, plus random and noise ported from processing so the output matches). should i just open the pr for those and then move on to color reading next (red, green, blue, alpha, brightness, lerp_color)?
one small thing i wanted to flag, the list here uses the java camelCase names but mewnala already uses snake_case (stroke_weight, no_fill etc), so im matching behaviour with pythonic names rather than the exact names. shout if youd rather i do it differently.
cc @catilac @tychedelia
catilac commentedon Jun 4, 2026
@Gmin2 hi! i think for python we should do what is pythonic. there is also a discussion to be had around processing APIs potentially getting in the way of what is best practice in python.
antiboredom commentedon Jun 4, 2026
Hi all, I've been playing around with mewnala and it's really great! So excited to see this happening.
To echo @catilac's comment, I was thinking this might be a good opportunity to have a conversation about how "pythony" to make the library and the example sketches. One thing that I noticed in the examples, that I think should be changed, is the use of the star import (
from mewnala import *). I realize this makes things feel easier for beginners because it makes calling methods less verbose, but it's considered a bad practice in python.The second issue I'm seeing in the examples is the use of the
globalkeyword, another pattern that's generally frowned upon. This is a bit trickier to deal with. There would in my mind be 2 alternative patterns to look into.Option 1: store sketch state in a top level object. This would work with the existing codebase, but I still don't think is ideal or very ergonomic:
Option 2: remove
setupanddraw. Put setupy stuff at the top level, and replace the draw function with a while loop. I think this is the strongest option, and the most "pythony". It's also closer to how other similar libraries like pygame work.These are just my initial thoughts after playing around a bit. I'm very curious to hear what other people think!
catilac commentedon Jun 30, 2026
Hi @antiboredom thanks so much for your input here! These are really great ideas. The departure from
setup()anddraw()is something i definitely haven't considered. It also feels like a really clean approach that would cut out a lot of tricky engineering.I also think this would make our lives easier in jupyter notebook and google collab because we'd be very "pythony"
Since we would just be writing regular python, someone could always go and write the fancy thing on top to create the setup() and draw() stuff if they really wanted.
catilac commentedon Jun 30, 2026
@SableRaf I would like to turn this page into a bunch of issues for the Full Processing API Coverage Milestone could we discuss this?
hx2A commentedon Jul 1, 2026
I'm also opposed to writing
import *in Python, I think it is a bad practice. There are other ways to go about this though. For py5 I did create a custom Jupyter Notebook kernel that provides the sameimport *experience. This is also available to users in Thonny using what we call "imported mode". Educators who use py5 like this as it is better for beginners and reduces cognitive load and visual clutter. Maybe mewnala could explore other options besidesimport *that provide a similar result?I also don't like
globalstatements but they are necessary in py5 because of the dependence onsetup()anddraw()functions.This is an intriguing idea! I see how
m.draw()could set the pace of the rendering frame rate and there would be no need forglobalstatements. I'd really like using it this way. My only question is what would drive the animation thread? In Processing the animation thread is driven by Java code, or in the case of the OpenGL renderers, it is driven by the JOGL code (at least I think they are, that part of the code is opaque to me). Anyhow, the above while loop suggests Python is controlling the animation thread. But libprocessing is a Rust library, and some folks might want to code with it in pure Rust with Rust driving the animation. I suppose things could be engineered such that both are possible, but that might add unwanted complexity. I know from py5 that having multiple ways of using it is great but it also makes things harder to maintain. But if it can be done cleanly, I think providing options like this are great idea.SableRaf commentedon Jul 2, 2026
Yes, let's chat. I DM'd you.
We could re-use the same script I used to generate the task-tracker sub-issues in the
processing-examples-mewnalarepo.Also this is important to consider when looking at the todos above: