ffd8 / P5LIVE

p5.js collaborative live-coding vj environment!
https://p5live.org
GNU General Public License v3.0
226 stars 35 forks source link

feature: global variables that persist sketch recompiles #18

Closed osresearch closed 4 years ago

osresearch commented 5 years ago

It would be useful to be able to define variables that persist between sketch recompiles and calls to buildSketch(), similar to the way the p5vars.frameCount does. Some applications for this are to be able to have a countdown timer for the performance or to keep animations going non-stop rather than having to always restart from zero.

osresearch commented 5 years ago

It looks like parent.foo can be used to create a global variable. It can be initialized only once by checking in setup() if it exists:

function setup()
{
    if (!parent.time_left)
        parent.time_left = 600
}

void draw()
{
    text("TIME LEFT" + parent.time_left, 0, 0)
    if  (parent.time_left != 0)
        parent.time_left--;
}
osresearch commented 5 years ago

This works for simple variables, but objects that have their own draw() methods won't work since they don't have the right p5 graphics context (they have the old one from the previous sketch). This might be fixable if #19 is implemented to keep the same p5 renderer between sketch rebuilds.

osresearch commented 5 years ago

Screenshot from 2019-07-26 15-33-48

Sample sketch that shows how objects can persist in the parent.stars array (although the clearing of the canvas between sketch compiles makes the traces disappear):

let p5;

function setup() {
    createCanvas(windowWidth, windowHeight);
    p5 = createGraphics(windowWidth, windowHeight)
    pixelDensity(1);
    if (!parent.stars)
        parent.stars = []
}

function Star() {
    this.x = random(width)
    this.y = random(height)
    this.sz = random(100)

    this.draw = function(p5){
        p5.fill(255-this.sz*5,0,5*this.sz ,this.sz * 256/10)
        p5.circle(this.x, this.y, this.sz)

        this.x++
        this.y++
        this.sz *= 0.99
        if (this.sz < 0.1)
            return 0
        else
            return 1
    }
}

function draw() {
    p5.background(0, 0, 0, 10)
    if (random(100) < 10)
        parent.stars.push(new Star())

    parent.stars = parent.stars.filter(i => i.draw(p5))
    image(p5, 0, 0)
}
ffd8 commented 5 years ago

I'm not sure if you've seen that it already has persistent frameCount, mouseX/Y, pmouseX/Y for this exact purpose of smooth animations between recompiles. So technically attaching things to frameCount would have a similar effect between changes to code. For a countdown, you could just watch how big the frameCount gets:

function setup() {
    createCanvas(windowWidth, windowHeight);
}

function draw() {
    print(frameCount);
    if(frameCount >= 1000){
        background(frameCount%255);
    }
}
osresearch commented 5 years ago

frameCount is helpful if the entire design is deterministic (although it can be tricky to turn into a runtime since the fps doesn't seem to be constant). If the sketch has randomness (like the example above), then it is helpful to store the random objects in a way that they can be retrieved after the rebuild.

If the soft-reload in #19 works, then the parent.foo trick might no longer be necessary.

ffd8 commented 4 years ago

@osresearch #26 now merged into master successfully performs a softCompile which is offers really smooth updates to any code taking place anywhere on the sketch besides the global space, preload, and setup (since those require rebuilding whole sketch for their purposes).