Scroll and let a part of text/sprite be cut off

Hello all, I’m working on a project and I’m wondering what would be the best way to cut off a piece of text/sprite when scrolling? You know… like in the code sprite picker
or when someone would have a textbox, text dissapears as well, partially

Now, I’ve been thinking, it could be done by using image:copy, but idk how expansive that is.
Maybe it’s begter to do with shaders? Or is there another way? :slight_smile:
(I’dd rather get a good answer instead or a piece of code, tho that’s appreciated too)

If shaders are the way to go, then I’ll finally start learning them

thanks in advance, Steven

I think the clip() function might do the trick for you. Be aware though that you can only specify an axis-aligned rect in screen space with clip().

@toadkick many thanks, that will do the job, I feel so dumb now, I should have searched longer before asking this question xc

Eh don’t let my grumpy ranting get to you. Clearly you were not asking me to do your homework for you! :smiley:

Honestly, sometimes one just doesn’t know what to look for, or even what a thing/concept is called (like “clipping” for example), which can make it hard to do a proper search.

The nice thing about clip() is that it’s pretty easy to use, at least if you are working in screen space. There are cases where it’s not great though; since the rect is axis aligned, clipping rotated top-level objects can be problematic (their corners will get cut off). Also, clipped regions in a full-screen transition probably won’t behave the way you expect if your transition uses any rotation. In those cases setContext() (also known as “render to texture” more generally outside of Codea) is the only way that I know of to achieve clipping.

Yeah and I read somewhere about clipping already but never knew what it did, I guess I’ll read the full reference soon, and I’m gonna learn about all the other thing, shaders, matrices, etc etc soon :wink:

Also, is there already any topic about the performance of readimage? I’dd like to know how expensive it is if you have to read between 10 and 15 images every draw

I had forgotten why I needed this but I was having issues with clip() on one of my projects. I do not recall who wrote the code (might have been toadkick) but I now use it everytime I’m using a project where clip is needed.

-- ClipUpgrade
_clip = clip

function clip(x, y, w, h)
    if not _clip then
        _clip = clip
    if x then
        local m = modelMatrix()
        x = x * m[1] + m[13]
        y = y * m[6] + m[14]
        w = w * m[1]
        h = h * m[6]
        _clip(x, y, w, h)

@stevon8ter: Well, I can’t say with certainty without profiling how expensive it is, but I can probably safely say it’s not cheap!

This is something you can actually experiment some with, using the os.clock() function. this isn’t an accurate way to test performance, but it can give you a good idea of how expensive something is relative to something else. Here is one way I do basic performance profiling sometimes (I’ll bet others have their own ways too, and they’re probably better than mine…maybe they’ll share them!):

function setup()
    local iterations = 1000
    local t = os.clock()
    for i = 1, iterations do
        -- put some code here to use as a basis for comparison.
        -- we'll use the sprite function as a baseline.
        sprite("Planet Cute:Character Boy")
    print(os.clock() - t)
    t = os.clock()
    for i = 1, iterations do
        -- put the code here that you want to test the performance of.
        sprite(readImage("Planet Cute:Character Boy"))
    print(os.clock() - t)

Be aware, at 1000 iterations this takes about 4 seconds to complete on my iPad 4.

After running, 2 numbers will be printed: the approximate time it takes to draw a sprite(), vs the time it takes to draw a sprite created with readImage().

On my iPad 4, I get numbers that look similar to:


I say similar because there are tiny fluctuations each time (again, this isn’t exact), but you can kind of mitigate this by running the program several times and averaging the numbers. Anyway, what this tells us, is that using readImage() and rendering that image with sprite(), is massively more expensive than just calling sprite() by itself. This is a pretty naive test, but clearly readImage() is something you want to do only when you have to.

@Briarfox, so your custom function (or whoever wrote it) is better than the codea one? Since this one shouldn’t have issues…?

@toadkick, thanks, but I think I’ll make it as inexpensive as possible, I’ll be loading the images into a table, but only once they should get loaded, so they should only be loaded 3 images at a time tops, but thanks for your answer anyways

Just a quick remark: an alternative to clip() is to write whatever into a small image with setContext() and sprite it. Might be slower than clip, but better control.

@Briarfox: I believe @Jordan is the one who wrote that originally. It works well, but I don’t like replacing the default clip() function with it, since this actually changes the meaning from “clip in screen space” to “clip in world space”. Maybe “clipWorld” might be more appropriate? Anyway, I think I’d actually prefer a function that converts something from world space into screen space, and then I can pass the result of that to clip:

-- note: does not take rotation into account (axis-aligned rects only)
function worldToScreen(x, y, w, h)
    local m = modelMatrix()
    x = x * m[1] + m[13]
    y = y * m[6] + m[14]
    w = w * m[1]
    h = h * m[6]
    return x, y, w, h

-- and then later:
clip(worldToScreen(rect.x, rect.y, rect.w, rect.h))

@stevon8ter: Oh, sorry, I wasn’t suggesting that you should/shouldn’t implement anything a certain way, I was just showing you an example of how you might test to get an idea of how cheap/expensive something might be.

@toadkick yeah excuse me, I didn’t read it completely, I only slept 4hours in the last 3 days --’

But thanks, I’ll certainly think of this when in need of testing some peformances

@Jmv38: Yeah I mentioned that, though it might not have been very clear. FWIW, that method is significantly slower than just using clip(), so if you can get away with using clip(), you should.

@toadkick i assume the speed is 30Hz max with set context, but the coordinate mechanism is so special (different) with clip… I remember it was really tricky to manage (it didnt easily fit with the rest). I was just pointing out an alternative option, but i am sure you are right!

@toadkick @jmv38 yes setContext makes sence, I already used it several times since I started using the basic functions beyond sprite, rect, etc

But I’ll experiment a bit and I hope I’ll post my project soon :wink:

Tho idk if I’ll work on it alot this weekend, ludum dare 28 starts in a few hours, I might give it a try for one time, tho I’m in the middle of exams, but I’ll see :wink:

But a little idea about what I’m making… I’m making a codea-editor-like sprite selector, tho some of the things will be different, basically everything xD but yeah you’ll see it soon :wink:

@Jmv38: The main trick with clip() is realizing that it only works in screen space (well, window space to be more precise, but in Codea those are effectively the same thing). Unfortunately, the documentation does not mention that.

You are correct that setContext() can also be used to achieve clipping (and in some cases, it’s the only way), but I just wanted to point out that it does not come without a (significant) cost :slight_smile:

Well just a questions for you @toadkick @jmv38
in what cases couldn’t I use clip?

Thanks, yes, i know that. But it is difficult anyway… :wink:

@stevon8ter: Usually cases where rotation is involved. For example, imagine I have a sprite picker, and I want to clip everything inside (should be easy, since that’s what you’re doing! :D).

Now, imagine that using clip() is like taking a piece of paper that is exactly the size of the screen, cutting out a rectangle with exactly the size and position of the sprite picker, and taping it over the entire screen, so that only the sprite picker window shows through.

Now, imagine that underneath that piece of paper, I rotate the sprite picker window. The paper can’t rotate…it’s taped to the screen…so what happens is, as the picker is rotated, any areas of it that go outside of the cutout in the paper will not be seen (in this case, the corners).

Does that make sense?

@toadkick yes I get what you mean, well for now I’ll be using the clip function, since a sprite picker shouldn’t normally be rotated :wink:

But I’ll look into it after I finished most of my class
maybe @simeon or @john could inform us if they’re going to look into this in one of the next updates (no pressure guys, the editor update would be awesome, so don’t rush stuff :wink: )

I would probably have done this the lazy way and just sprited a blank image over the text I wanted hidden :smiley: