Dot Pyjea

The Dot Pyjea file format (.pyjea) combines our custom Nodes Macro Language with Python. To load a standalone .pyjea file just drag and drop it onto the nodes workspace. If your .pyjea depends on files in the same directory, like audio files that use the naming syntax FILE(#N=VALUE).mp3, then drop the folder onto the nodes workspace.

Example1

			{cube(location@myfunction)}
			
@input(1.1) @input(2.2) @input(3.3) def myfunction(x,y,z): return vector(x,y,z)
The example above creates a new cube primitive and sets its location using the output of myfunction a Python-Function-Node. The function decorators (@input...) are subnodes that will be automatically connected to the input sockets of myfunction.

Example2

			{cube(location@myfunction)}
			
@vector(1.1, 2.2, 3.3) @vector(4,5,6) def myfunction(v1, v2): return v1 ❌ v2
Above two vector input nodes are created and connected to myfunction. Note the use of `❌`, this can be used instead of `*`.

Abstractions

Abstraction symbols are the latin symbols: ƂƆƱƋƎƏƔƕƢƧΩƸ
They are more flexible than regular function arguments or variables because they can be defined at the function or object levels, more on that concept later.
			{cube(logic@animate)}
			
with bpy: Ƃ:input(0.1) Ɔ:sine def animate: self.rotate.x += Ƃ mod = self.modify('BEVEL') mod.width = Ɔ
Above is a simple example using abstraction symbols that are connected to input nodes. Using abstraction symbols allows the coder to clearly define what should be edited at the node level by a game designer, this also avoids having hard coded values in a script.
Note: functions under `with bpy:` can use the bpy API.
bpy functions are called each frame by the runtime inside of the blender process, these functions do not take any arguments, to make that more clear the syntax def NAME: is allowed, note that it is also valid to write def NAME():.

Object-Level Abstractions

			{cube(logic@animate,Ƃ@input=0.1)}
			{cube(logic@animate,Ƃ@input=0.2)}
			with bpy:
				Ɔ:sine
				def animate:
					self.rotate.x += Ƃ
					mod = self.modify('BEVEL')
					mod.width = Ɔ
			
Using abstraction symbols at the object-level overrides any inputs defined at the script-level, this allows you to defined variables per-object, while the objects share the same script node. You define object-level symbols in the object macro, like the example above: {cube(logic@animate,Ƃ@input=0.1)}

Macro Generator Syntax

			for $ in range(1,40):
				{mball(color@#7,scale@foo$,location@bar$)}
			
@sine(0.1, 1, $*0.1) def foo$(s): if $==1: return 1 else: return vector(s,s,s)
@sine(0.1, 1, $*0.1) @cosine(0.1, 1, $*0.1) def bar$(s, c): return vector(s*4,0,c*4)
You can use a for loop to generate multiple primitive nodes, note the use of `$` the generator iterator.

Global Input Variables

			a = 0.1
			b = 4.0
			c = 1
			d = 1
			e = 1
			
for $ in range(1,40): {mball(color@#7,scale@foo$,location@bar$)}
@sine(0.1, c, $*a) def foo$(s): if $==1: return 1 else: return vector(s,s,s)
@sine(0.1, d, $*a) @cosine(0.1, e, $*a) def bar$(s, c): return vector(s*b,0,c*b)
Global level input variables allow you to create input nodes that are referenced by variable name from other nodes and logic.

Macro Generator and Text

			phase = 0.2
			radius = 4.0
			scale_amp = 1
			sin_amp = 1
			cos_amp = 1
			speed = -0.03
			ext = 0.5
			
for $,¢ in enumerate('panjea plugin'): {text(text@input=¢,extrude@input=ext,color@anim_color$,scale@foo$,location@bar$)}
@random @random @random def anim_color$(r,g,b): return color(r,g,b)
@sine(speed, scale_amp, $❌phase) def foo$(s): return vector(s,s,s)
@sine(speed, sin_amp, $❌phase) @cosine(speed, cos_amp, $❌phase) def bar$(s, c): return vector(s❌radius,0,c❌radius)
Note the use of `¢` for the generator iterator value.