Multi/Sub-Clipping

Hi everyone, I want to share this clipping method that I made to solve the problem of a clip() inside another clip(), so with this you can make sub-clipping. :slight_smile:

**UPDATE:

  • Clipping #1 in the example can now be moved by dragging (previously locked with touch position)
  • The clipping name tag is now inside the square boundary**

[Other than the update in the example, there is no change in the main multi-clipping function]

@marcelliino Not sure what you’re showing. When I run your code, I get a yellow square at the bottom left of the screen There are 3 squares, with one moving around that turns part of the yellow square red. Everything is dark grey, the background and the other squares, except the yellow square.

@dave1707 I’m sorry, I was too rushed to upload it and forgot to explain everything (duh). All of the squares are representations of clipping boundaries, then for one clipping which is cornered on the lower left, it can be moved with touch input.

I’m sorry for the lack of clarity, I’ll upload a better example later

@marcelliino Nice example. Moving the yellow square around shows a lot more of what’s going on. I should have looked thru the code and saw the currentTouch line of code. That would have told me to try moving the square. As for being rushed, don’t worry about it. I’ve put stuff out several times and totally forgot to post the code that goes with it.

@dave1707 Here’s an update

Bonus screenshot :wink:

Main

-- MultiClip by Louis Marcellino (IG: @invinixity)

function setup()
    
    displayMode(FULLSCREEN)
    
end

function draw()
    
    local time = {
        sin=math.sin(ElapsedTime)* 0.5 + 0.5,
        cos=math.cos(ElapsedTime)* 0.5 + 0.5
    }
    
    background(255, 200, 25) -- set background to yellow
    
    Clip:on(CurrentTouch.pos-vec2(400, 200), vec2(800, 400)) -- create new clipping layer #1
    
    background(125) -- set background to grey
    
        Clip:on(vec2(WIDTH/2 - 150 * time.cos, HEIGHT/2 - 150 * time.cos), vec2(300, 300) + vec2(1, 1) * 300 * time.cos) -- clip layer #2 inside layer #1
        
        -- layer #2 --
        
        background(125, 225, 55) -- set background to green
    
        pushMatrix()
        pushStyle()
        
        translate(WIDTH/2+150, HEIGHT/2+150)
        rotate(ElapsedTime * 45) -- rotate lines pattern
        
        stroke(255)
        strokeWidth(10)
        for i = -20, 20 do
            line(40 * i, -400, 40 * i, 400) -- draw lines pattern
        end
        popStyle()
        popMatrix()
    
        Clip:off() -- unclip layer #2
    
    -- create polka dots between leyer #2 and layer #3 --
    
    fill(0, 255, 255) -- set color to cyan
    for i = 0, WIDTH/120 do
        for j = 0, HEIGHT/120 do
            ellipse(120 * i, 120 * j, 60) -- draw polka dots
        end
    end
    
        Clip:on(vec2(WIDTH/6 + WIDTH/6 * time.sin, HEIGHT/6 + HEIGHT/6 * time.cos), vec2(1, 1) * 300) -- clip layer 3# inside layer #1 (on top of layer #2)
        
        -- later #3 --
        
        background(255, 25, 55) -- set background to red
    
        pushMatrix()
        pushStyle()
        
        translate(WIDTH/3, HEIGHT/3)
        rotate(ElapsedTime * 45) -- rotate squares pattern
        
        fill(55)
        for i = -20, 20 do
            for j = -20, 20 do
                rect(120 * i, 120 * j, 60) -- draw squares pattern
            end
        end
        popStyle()
        popMatrix()
    
            Clip:on(vec2(1, 1) * 200, vec2(250 + 250 * time.cos, 100 + 100 * time.sin)) -- clip layer #4 inside layer #3
    
            background(55, 125, 255) -- set bacground to blue
    
            Clip:off() -- unclip layer 4#
    
        Clip:off() -- unclip layer #3
    
    Clip:off() -- unclip layer #1
    
    -- draw clipping boundaries / frames --
    
    fill(25)
    rect(CurrentTouch.x-400, CurrentTouch.y+200, textSize("clipping #1"))
    rect(WIDTH/2 - 150 * time.cos, HEIGHT/2 + 300 + 150 * time.cos, textSize("clipping #2 inside #1"))
    rect(WIDTH/6 + WIDTH/6 * time.sin, HEIGHT/6 + HEIGHT/6 * time.cos + 300, textSize("clipping #3 inside #1"))
    rect(200, 200 + 100 + 100 * time.sin, textSize("clipping #4 inside #3"))
    
    stroke(fill())
    strokeWidth(2)
    noFill()
    rect(CurrentTouch.x-400, CurrentTouch.y-200, 800, 400)
    rect(WIDTH/2 - 150 * time.cos, HEIGHT/2 - 150 * time.cos, 300 + 300 * time.cos)
    rect(WIDTH/6 + WIDTH/6 * time.sin, HEIGHT/6 + HEIGHT/6 * time.cos, 300)
    rect(200, 200, 250 + 250 * time.cos, 100 + 100 * time.sin)
    
    noStroke()
    fill(225)
    font("Inconsolata")
    fontSize(20)
    textMode(CORNER)
    text("clipping #1", CurrentTouch.x-400, CurrentTouch.y+200)
    text("clipping #2 inside #1", WIDTH/2 - 150 * time.cos, HEIGHT/2 + 300 + 150 * time.cos)
    text("clipping #3 inside #1", WIDTH/6 + WIDTH/6 * time.sin, HEIGHT/6 + HEIGHT/6 * time.cos + 300)
    text("clipping #4 inside #3", 200, 200 + 100 + 100 * time.sin)
    
end

Clip

Clip = class()

local pos_n_size = {}
local N = 0

function Clip:on(pos, size)
    
    N = N+1
    
    if N > 1 then
        pos, size =
            vec2(
                math.min(math.max(pos.x, pos_n_size[N-1].x), pos_n_size[N-1].x+pos_n_size[N-1].z),
                math.min(math.max(pos.y, pos_n_size[N-1].y), pos_n_size[N-1].y+pos_n_size[N-1].w)
            ),
            vec2(
                math.max(math.min(math.min(size.x, size.x+pos.x-pos_n_size[N-1].x), math.min(pos_n_size[N-1].z, pos_n_size[N-1].z+pos_n_size[N-1].x-pos.x)), 0),
                math.max(math.min(math.min(size.y, size.y+pos.y-pos_n_size[N-1].y), math.min(pos_n_size[N-1].w, pos_n_size[N-1].w+pos_n_size[N-1].y-pos.y)), 0)
            )
    end
    pos_n_size[N] = vec4(pos.x, pos.y, size.x, size.y)
    
    clip(pos_n_size[N]:unpack())
    
end

function Clip:off()
    
    N = N-1
    
    if N < 1 then
        clip()
    else
        clip(pos_n_size[N]:unpack())
    end
    
end

@marcelliino Wow, that’s even better than the last on. It really shows how the clipping works.