[RESOLVED] DP2.0: how about Invalidation of children without clearing cashed image

Invalidation of children

Groups automatically detect when a child’s properties have changed such as position. Thus, on the next render pass, the child will re-render.

Snapshots to not automatically detect when a child’s properties have changed. You must clear the snapshot’s cached image anytime you modify the child by calling snapshot:invalidate(). This invalidates the snapshot’s image so it will be updated on the next render pass.


Above description means cached image will be cleared whenever invalidate() is called. But, what i’m wanting is that cached image is not cleared and draw just last added object when some function(like invalidate(false)) is called.

I’m just want to clear cached image when i want.

 

Thanks.

 

 

Could you give an example of why this would be useful? Once you mark the snapshot as invalidated it will be redrawn completely, including the new image (ie so it will look the same anyway, just with the new image in it).

Let me give more detail explanation.

If you are making line drawing application like painter.

With corona sdk, you need to add display object(i,e, line, circle,…) whenever screen is touched and moved.

This will generate a lot of display objects and those are redrawn all at every invalidate() call.

And you can see performance degradation whenever line object is added.

Benefits what i think.

  1. No performance degradation when adding lines even 10000 times display objects is already drawn.

  2. can draw many lines by just reusing one display object.

That is indeed a good example :slight_smile:

Here’s a possible solution (but you’ll have to test as I don’t know if it is possible):

Nested snapshots.

You’d have two snapshots in total. A working one and the previously drawn one.
Every time you want to add a new element (could be a single line etc, or a batch of them), you stick them in the working snapshot and behind you add the previous state snapshot. Invalidate the working snapshot (which should update to include everything), and then clear the previous state snapshot entirely of all children. Then just swap the two - IE the working one is now considered the precius state, and the old previous state one is now the working one (and is empty ready for it).

It all depends on whether you can nest snapshots and how exactly the render to texture works, but it *might* work, so I figure it is worth your time to quickly check :slight_smile:

Sounds like you want some way to “accumulate” drawing on a texture? So like a finger painting-style effect?

This is fairly different from what snapshot does (render to texture). The major expense of line objects is tessellation, and right now it looks like an append operation forces the old tessellation to get thrown out. I’ll mark this as a performance request to see if we can do something more intelligent.

Yes, what i want is to accumulate drawing on a texture.

I think that just one option (which is prohibit to clear cached image) is needed like below.

  • invalidate(true) --> clear cached image and redraw all and add(or draw) object 

  • invalidate(false) --> don’t clear cached image and add(or draw) object.

I think below link is good example about render to texture functions.

http://www.learn-cocos2d.com/2011/12/how-to-use-ccrendertexture-motion-blur-screenshots-drawing-sketches/#sketching

Does that mean you aren’t even going to try to see if my suggestion works? :s

I didn’t try it what you suggest since snapshot has fundamental limitation when objects is added if snapshot have a lot of children.

Thanks

I think you are misunderstanding my suggestion - as it stands it should work, but since I am not aware of the exact snapshot implementation, I can’t say for sure it *will* work. I’ll try to look into this myself tonight or tomorrow to see if it does in fact work as I hope (which would enable what you want to do).

OK I tried out my idea and it works.

The only issue is how long you have to wait for the validation to take effect - in theory it is the next draw pass, but I had to insert a delay of 300 milliseconds between each update to actually have it kick in (or else it returned a blank texture).

Here’s my code.

Every 300 milliseconds it creates 100 random lines, swaps the two snapshot objects, then clears all the lines.

The end result is it keeps filling up and filling up with lines overlaid.

Just copy and paste the following code into a fresh main.lua (no other files needed) and run it (on the iphone simulator for ‘fullscreen’, heh - can always just set the width and height to whatever device you prefer simulating on).

[lua]-- Set up status bar

display.setStatusBar( display.HiddenStatusBar )


– Set up ----------------------------------------------------

local width  = 320

local height = 480

local snapshots = {

    active =  display.newSnapshot( width, height ),

    storage = display.newSnapshot( width, height ),

}

local drawGroup = display.newGroup()

local group     = drawGroup.parent

for k, v in pairs( snapshots ) do

    v.anchorX = 0

    v.anchorY = 0

end

group:insert( snapshots.active )

snapshots.active.x, snapshots.active.y = 0, 0

– Place the storage group into the active group

snapshots.active:insert( snapshots.storage )

snapshots.storage.x, snapshots.storage.y = -width / 2, -height / 2

– Place the draw group into the active group

snapshots.active:insert( drawGroup )

drawGroup.x, drawGroup.y = -width / 2, -height / 2


– Run event -------------------------------------------------

local function drawLines()

    for i = 1, 100 do

        local line = display.newLine( drawGroup, math.random( 0, width ), math.random( 0, height ), math.random( 0, width ), math.random( 0, height ) )

        line.strokeWidth = math.random( 1,  10 )

        line:setStrokeColor( math.random( 0, 255 ) / 255, math.random( 0, 255 ) / 255, math.random( 0, 255 ) / 255 )

    end

    

end

local function toggleGroups()

    – Swap snapshots

    snapshots.active, snapshots.storage = snapshots.storage, snapshots.active

    – Kill the draw group (and hence everything in it) and recreate it

    drawGroup:removeSelf()

    drawGroup = display.newGroup()

    – Place the active group into the group

    group:insert( snapshots.active )

    snapshots.active.x, snapshots.active.y = 0, 0

    

    – Place the storage group into the active group

    snapshots.active:insert( snapshots.storage )

    snapshots.storage.x, snapshots.storage.y = -width / 2, -height / 2

    – Place the draw group into the active group

    snapshots.active:insert( drawGroup )

    drawGroup.x, drawGroup.y = -width / 2, -height / 2

    

    – Draw more lines

    drawLines()

    

    – Update

    snapshots.active:invalidate()

end

– Repeat 10000 times

timer.performWithDelay( 300, toggleGroups, 10000 )

[/lua]

You can probably simplify the code above a bit - in particular the offsetting of everything cos I’m not really sure on the positioning etc - I just played with values until I saw what I expected.

Same goes for the draw group and parent group, these aren’t likely needed, but after trying to access the numChildren of the snapshot and getting back a nil value, I figured I’d just chuck everything into actual display groups as at least I knew how to manipulate 'em.

eltromac - given the delay in the updating, I would probably not recommend the above swapping system constantly, just in natural breaks (eg the user draws into a normal group, lifts his finger, and in that instant you chuck the new lines into the active snapshot’s drawgroup and update, ready for the next batch of drawing).

Thanks rakoonic,

Really appreciated.

But, i still want to get the solution as corona sdk platform level.

Could you give an example of why this would be useful? Once you mark the snapshot as invalidated it will be redrawn completely, including the new image (ie so it will look the same anyway, just with the new image in it).

Let me give more detail explanation.

If you are making line drawing application like painter.

With corona sdk, you need to add display object(i,e, line, circle,…) whenever screen is touched and moved.

This will generate a lot of display objects and those are redrawn all at every invalidate() call.

And you can see performance degradation whenever line object is added.

Benefits what i think.

  1. No performance degradation when adding lines even 10000 times display objects is already drawn.

  2. can draw many lines by just reusing one display object.

That is indeed a good example :slight_smile:

Here’s a possible solution (but you’ll have to test as I don’t know if it is possible):

Nested snapshots.

You’d have two snapshots in total. A working one and the previously drawn one.
Every time you want to add a new element (could be a single line etc, or a batch of them), you stick them in the working snapshot and behind you add the previous state snapshot. Invalidate the working snapshot (which should update to include everything), and then clear the previous state snapshot entirely of all children. Then just swap the two - IE the working one is now considered the precius state, and the old previous state one is now the working one (and is empty ready for it).

It all depends on whether you can nest snapshots and how exactly the render to texture works, but it *might* work, so I figure it is worth your time to quickly check :slight_smile:

Sounds like you want some way to “accumulate” drawing on a texture? So like a finger painting-style effect?

This is fairly different from what snapshot does (render to texture). The major expense of line objects is tessellation, and right now it looks like an append operation forces the old tessellation to get thrown out. I’ll mark this as a performance request to see if we can do something more intelligent.

Yes, what i want is to accumulate drawing on a texture.

I think that just one option (which is prohibit to clear cached image) is needed like below.

  • invalidate(true) --> clear cached image and redraw all and add(or draw) object 

  • invalidate(false) --> don’t clear cached image and add(or draw) object.

I think below link is good example about render to texture functions.

http://www.learn-cocos2d.com/2011/12/how-to-use-ccrendertexture-motion-blur-screenshots-drawing-sketches/#sketching

Does that mean you aren’t even going to try to see if my suggestion works? :s

I didn’t try it what you suggest since snapshot has fundamental limitation when objects is added if snapshot have a lot of children.

Thanks

I think you are misunderstanding my suggestion - as it stands it should work, but since I am not aware of the exact snapshot implementation, I can’t say for sure it *will* work. I’ll try to look into this myself tonight or tomorrow to see if it does in fact work as I hope (which would enable what you want to do).