p5nim is a gate in the Nimπ universe that leads you to the magical world of Processing and p5.jsπΈ. Or, conversely, a potentially gateway drug from Processing/p5.js to the thoroughly enjoyable, dangerously addictive and sort of universal programming language Nim.
More prosaically p5nim provides Nim bindings for the p5.js library, some syntactic sugar and convenience functions to use it with nimibπ³. In p5nim example gallery you can also see live a number of p5.js examples and openprocessing artwork ported to Nim. Documentation is built with nimib, a library to publish nim code to the web.
Processing is language, a graphical library and IDE for artists and designers with the purpose of teaching non-programmers the fundamentals of programming in a visual context. The project was initiated in 2001 and it was built in Java, one of the reason being that java applets were a common technology at the time to show interactive applications on the web. p5.js was started in 2013 to reinterpret Processing for the modern web. From its website:
p5.js is a JavaScript library for creative coding, with a focus on making coding accessible and inclusive for artists, designers, educators, beginners, and anyone else! p5.js is free and open-source because we believe software, and the tools to learn it, should be accessible to everyone.
Note that there is also an alternative pure nim implementation inspired by p5js (which also works for native target): https://github.com/GabrielLasso/drawim
This project started as a fork of https://github.com/Foldover/nim-p5/, to fix some bugs.
It has been renamed as p5nim
, the goal is to clean more the api to make it more Nim idiomatic,
port more examples, fix more stuff and add more convenience functions
to use it with nimib.
Also in scope are additional p5js libraries such as p5sound (see below).
I will add stuff as I need it but you are more than welcome to jump in and help out (check issues)!
It is available on nimble (replaced nimp5) and you can install it using:
nimble install https://github.com/pietroppeter/p5nim/
You might want instead to clone it, in order to contribute fixing stuff and adding more ported examples:
git clone https://github.com/pietroppeter/p5nim/
cd p5nim
nimble develop
import p5
setup:
createCanvas(400, 400)
background(200)
draw:
if mouseIsPressed:
fill(0)
else:
fill(255)
ellipse(mouseX, mouseY, 40, 40)
As you see from the code above (live), using p5nim is almost identical to using p5.js, save for the syntax. To learn how to use this the best way is to use p5.js documentation and port examples.
p5sound is an additional library from p5js which extends p5 with sound functionalities. A work-in-progress wrapper is available, see doorbell for example of usage.
import nimib
import p5 # only imports nimib utilities when not using js backend
nbInit
nbUseP5 # adds p5 js and imports p5 in JsGlobal
nbUseP5Sound # optional in case you want also p5sound
nbCodeDisplay(nbJsFromCode): # if you want to display the js code
const nimColor = "#ffc200"
var doorbell: SoundFile
preload:
doorbell = loadSound("assets/doorbell.mp3")
setup:
createCanvas(200, 100)
background(nimColor)
text("click to play the doorbell ποΈ", 10, 20)
mousePressed:
play(doorbell)
nbSave
Instance mode allows to place a p5 instance into a specific <div>
and to have multiple p5 canvas in the same document.
Thanks to nim metaprogramming capabilities (and mostly thanks to @Vindaar),
we do not need
to have a different api for instance mode, we can have the same api
we use for global mode, we only need to wrap it in a instance
call.
See instances for an example.
Note: this feature is not yet complete, see #8
There are a number of javascript procedures that p5js needs to know about (like setup
and draw
) and they have to be declared with the {.exportc.} pragma.
In p5nim we provide templates that remove the necessity to declare procs with {.exportc.}. The full list is in src/p5/p5sugar.nim.
Since Number in javascript
is actually a float, in p5nim all procedures are defined with input a float
.
For convenience p5nim
exports
lenientops
from standard library
and a converter from int to float
(in the original bindings PNumber
- the generic number used by all functions -
is defined as int or float
;
this behavior is currently still available under the compile time switch p5IntOrFloat
;
it will likely be removed at some point).
When converting examples from p5js there are some common pitfalls:
- some variables (e.g.
key
) arecstring
(backend compatible strings) and you might need to convert them with$
before using them - when porting an example containing objects you will need to change more stuff, see example okazz_220919a:
- nim support for forward declaration is experimental, better to define your object before its usage in setup and draw.
- you will need to declare the type of object. You can pick it to be a
ref object
or a plainobject
(in the examples currently I am mostly usingref object
, see this commit for an example of changes between the two approaches)
- some math/random functions that seem to be available in
p5js
(such asfloor
,random
which are defined in the bindings) do not actually work, so code compiles but the canvas is not shown (you can see an error in the console). In those cases it is better to importmath
andrandom
from stdlib (but you might run in conflicts, e.g. when usingsqrt
which is also defined inp5js
) For an example see okazz_221026a and try removing the imports ofmath
andrandom
, usefloor
instead ofmath.floor
orrandom(1.0)
instead ofrandom.rand(1.0)
. This is actually something for which a solution should be found in this library (remove them from bindings?).
- go through the examples on p5js site, pick one that you like and convert it to nim. You might want to copy and adapt last example from
docsrc
(look at the index to find out what is the last one). You will need to increment the example number, add a title and a description. It is pretty fun!- you will have to commit the html in docs, and rerun also
nim r index
(which uses data fromdocs\index.json
) - as you find out new conversion pitfalls update the readme up there
- you will have to commit the html in docs, and rerun also
- an excellent source of open art is openprocessing