How to remove a table via a reference?

Hey!

Instead of removing a table directly, I’m trying to remove it via a reference to.

Here’s a demonstration of what I am trying to do:
 

local object1 = display.newCircle( 120, 60, 40 ) local object2 = display.newCircle( 220, 60, 30 ) object2.reference = object1 print( object1 ) print( object2.reference ) display.remove( object2.reference ) object2.reference = nil print( object1 ) print( object2.reference )

Now, as expected, if I adjust the position of either object1 or object2.reference, both tables are updated and the display object moves on the screen. Also, if I print object1 or object2.reference, the console outputs the same table, as expected.

However, if I remove the display object and set the table to nil via either object1 or object2.reference, then the display object is removed, but the table that was not explicitly set to nil remains with all of its information.

Any suggestions on how I could get rid of both using a method similar to this?

Thanks!
 

What you have shown is mostly correct, but you still need to nil the object1 reference.

local object1 = display.newCircle( 120, 60, 40 ) local object2 = display.newCircle( 220, 60, 30 ) object2.reference = object1 print( object1 ) print( object2.reference ) display.remove( object2.reference ) object2.reference = nil object1 = nil -- TILL YOU DO THIS, object1 still refers to a stub of the object. print( object1 ) print( object2.reference )

Just remember, you can delete an object, but until ALL references to that object are cleared (assigned nil) OR fall out of scope, the stub stays around and the object cannot be garbage collected.

Thanks, Ed!

That final bit that you pointed out is actually exactly the thing that I am trying to avoid.

Let’s say that I have the function that removes objects in another file, like so:
 

-- delete.lua local f = {} function f.deleteAll( target ) if target then if type(target.reference) == "table" then for i = 1, #target.reference do display.remove( target.reference[i] ) target.reference[i] = nil end end display.remove( target ) target = nil end end

The function first checks that the given input exists, that it is a table and then removes any associated references and finally the object itself.

Then, I have my Lua file:

 

-- main.lua local func = require("delete") local object1 = display.newCircle( 100, 60, 20 ) local object2 = display.newCircle( 140, 60, 20 ) local object3 = display.newCircle( 180, 60, 20 ) local object4 = display.newCircle( 220, 60, 20 ) object4.reference = { object1, object2, object3 } print( object1, object2, object3, object4 ) print( object4.reference[1], object4.reference[2], object4.reference[3] ) func.deleteAll( object4 ) print( object1, object2, object3, object4 ) print( object4.reference[1], object4.reference[2], object4.reference[3] )

The thing is that I can’t know ahead of time what references an object may have, so I can’t pass them along to the function. Furthermore, with this specific example, while object4’s display object is removed, its table still sticks around. Its references are removed though (as are the associated display objects, but the tables remain as before).

Is this doable, or should I just find some other way to remove the tables directly?

Ed is spot on but besides that frankly I’m not quite sure i get what you are trying to do here.

Would it be possible to use display groups instead for “grouping”?

Would likely me object removal easier.

Yep, that he is.

I’m trying to add this feature to the shadow engine before I release it as a plugin.

I’m working on a function to remove either all shadows associated with an object or to remove all shadows associated with a light. The current approach is/was to let the user call a function, such as “shadow.remove( object1 )” or “shadow.remove( light1 )”.

Now, the thing is that the shadows are directly attached to the objects themselves, so removing all shadows from a single object is easy. However, doing the same with the lights isn’t as easy since the shadows aren’t attached to them directly, which is why I was exploring the option to remove the shadows via references.

As my current approach seems to be impossible, I’m probably just going to force the user to add all shadows into a single table that contains a subtable for each light, something along the lines of:
 

local shadow = {} for i = 1, #light do shadow[i] = {} for j = 1, #object do shadow[i][j] = shadow.cast( ... ) end end

This way, I’ll at least have the option to more easily (and realistically) remove any shadows from a single object or from a single light.

so the trick here is how to know which shadows are associated with given lights, right?

i dont know exactly how this plugin is suposed to work so i might be way out there, but wouldnt it be possible, instead of using object references, create a reference lookup table that you can use to keep track of objects and references? That way you should be able to let  a shadow be referenced for both object and light(s), without the perils of having variables preventing objects from being removed, if that makes any sense. the lookup table itself can easily be maintained.  :slight_smile:

if you can’t fight it, join it.

local tableObj={} tableObj[#tableObj+1]=display.newCircle(120, 60, 40 ) tableObj[#tableObj+1]=display.newCircle(120, 60, 30 ) print (#tableObj) print (tableObj[1]) print (tableObj[2]) for i=#tableObj, 1, -1 do display.remove(tableObj[i]) tableObj[i]=nil end print (#tableObj) print (tableObj[1]) print (tableObj[2])

NOTE: removing a table/group use always inverted for cicle. you can thank me later.

if YOU create a reference, then YOU must dispose of it, simple as that.

local a = display.newRect(... a.b = display.newRect(... a.b.c = display.newRect(... a.b.c.d = display.newRect(... display.remove(a) -- incomplete!!! -- b,c,d still exist as display objects -- AND a still exists as a table -- AND a still has a ref to b (which has a ref to c (which has a ref to d)) -- so, what would be necessary to properly clean up this mess? -- (assume that the incomplete "display.remove(a)" above has NOT been executed) display.remove(a.b.c.d) display.remove(a.b.c) display.remove(a.b) display.remove(a) a = nil -- releasing a will release b (which will release c (which will release d)) -- ok, now we're "clean" - because all refs that WE created WE deleted

there are various ways to “hide” or “obscure” or “automate” the cleanup (fe finalize listeners) but the fact remains that you must do your own cleanup somewhere.

@carloscosta, that wasn’t really the point of this thread, but thanks still :smiley:

Also, thank you everyone else for your input. Seems that the answer to my question of can I remove the originals via references alone and how is simply: “No.”

I’ll just go with my plan B and stuff all of the shadows into one table for an easy fix.

I’m not sure what your end goal is, but if you’re creating an object A with dependent objects B, C, … that you want removed and cleaned up when A is removed, just do this:

-- example of one 'dependent' object; a shadow local a = display.newCircle( 10, 10, 10 ) a.shadow = display.newCircle( 12, 12, 10 ) a.shadow:setFillColor(0,0,0.0.5) a:toFront() function a:finalize() display.remove( self.shadow ) end a:addEventListener( "finalize" )

Now, later if you do this, the shadow is auto-removed:

display.remove(a)

I had actually completely forgotten about that finalize listener. It’s pretty cool and I think I’ll implement it in my final solution.

My original idea was to have a parent with unknown number of children that, when the parent was removed, would also be removed. In addition to just removing the display objects, I also wanted to set them to nil.

This would have been a part of the shadow engine plugin that I’m finalising atm. Until a few days ago, the plugin was object-centric, i.e. each shadow was owned by the object that cast it. With this method, the parent (a light source) could have any number of children (shadows that were cast because of it) from variables of all names. For instance, there could be a light source “local candle” and objects “local chair, table, character”. I wanted to know if there was a way for me to destroy these objects and set them to nil by removing only the light source. Well, the simple answer is: No. Sure, there are ways of doing this but without knowing the objects’ names in advance there doesn’t seem to be a way as I can’t set the original references to the tables to nil from within a general function.

Now, I swapped things around and made the plugin light-centric, meaning that all of the shadows are now by the specific lights, destroying all shadows associated with a specific light is as easy as looping through a table. I’ll probably add that finalize listener to my final approach here. As for destroying all shadows cast by a specific object, I will simply give each object a name that the plugin can track by using:
 

local object = display.newCircle( 160, 240, 32 ) object.name = tostring(object):sub(8) print(object.name) -\> output: "0C341B30"

And then I just loop through every light, find the object with that name, and if found, remove that shadow from the light.
 

In the case of an arbitrary number of children, I typically just make the top object a group and put all the children in the group at <0,0> or an offset as needed.

Then move the group where you need it.

Thus, deleting the group deletes the children.

This is how I made most of the complex (multi-part) objects in SSK:

i’m a fan of using a parent display group for all children as well. makes things so much easier.

What you have shown is mostly correct, but you still need to nil the object1 reference.

local object1 = display.newCircle( 120, 60, 40 ) local object2 = display.newCircle( 220, 60, 30 ) object2.reference = object1 print( object1 ) print( object2.reference ) display.remove( object2.reference ) object2.reference = nil object1 = nil -- TILL YOU DO THIS, object1 still refers to a stub of the object. print( object1 ) print( object2.reference )

Just remember, you can delete an object, but until ALL references to that object are cleared (assigned nil) OR fall out of scope, the stub stays around and the object cannot be garbage collected.

Thanks, Ed!

That final bit that you pointed out is actually exactly the thing that I am trying to avoid.

Let’s say that I have the function that removes objects in another file, like so:
 

-- delete.lua local f = {} function f.deleteAll( target ) if target then if type(target.reference) == "table" then for i = 1, #target.reference do display.remove( target.reference[i] ) target.reference[i] = nil end end display.remove( target ) target = nil end end

The function first checks that the given input exists, that it is a table and then removes any associated references and finally the object itself.

Then, I have my Lua file:

 

-- main.lua local func = require("delete") local object1 = display.newCircle( 100, 60, 20 ) local object2 = display.newCircle( 140, 60, 20 ) local object3 = display.newCircle( 180, 60, 20 ) local object4 = display.newCircle( 220, 60, 20 ) object4.reference = { object1, object2, object3 } print( object1, object2, object3, object4 ) print( object4.reference[1], object4.reference[2], object4.reference[3] ) func.deleteAll( object4 ) print( object1, object2, object3, object4 ) print( object4.reference[1], object4.reference[2], object4.reference[3] )

The thing is that I can’t know ahead of time what references an object may have, so I can’t pass them along to the function. Furthermore, with this specific example, while object4’s display object is removed, its table still sticks around. Its references are removed though (as are the associated display objects, but the tables remain as before).

Is this doable, or should I just find some other way to remove the tables directly?

Ed is spot on but besides that frankly I’m not quite sure i get what you are trying to do here.

Would it be possible to use display groups instead for “grouping”?

Would likely me object removal easier.

Yep, that he is.

I’m trying to add this feature to the shadow engine before I release it as a plugin.

I’m working on a function to remove either all shadows associated with an object or to remove all shadows associated with a light. The current approach is/was to let the user call a function, such as “shadow.remove( object1 )” or “shadow.remove( light1 )”.

Now, the thing is that the shadows are directly attached to the objects themselves, so removing all shadows from a single object is easy. However, doing the same with the lights isn’t as easy since the shadows aren’t attached to them directly, which is why I was exploring the option to remove the shadows via references.

As my current approach seems to be impossible, I’m probably just going to force the user to add all shadows into a single table that contains a subtable for each light, something along the lines of:
 

local shadow = {} for i = 1, #light do shadow[i] = {} for j = 1, #object do shadow[i][j] = shadow.cast( ... ) end end

This way, I’ll at least have the option to more easily (and realistically) remove any shadows from a single object or from a single light.

so the trick here is how to know which shadows are associated with given lights, right?

i dont know exactly how this plugin is suposed to work so i might be way out there, but wouldnt it be possible, instead of using object references, create a reference lookup table that you can use to keep track of objects and references? That way you should be able to let  a shadow be referenced for both object and light(s), without the perils of having variables preventing objects from being removed, if that makes any sense. the lookup table itself can easily be maintained.  :slight_smile: