Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

How to remove a table via a reference?
Started by XeduR @Spyric Feb 10 2019 04:01 PM

- - - - -
13 replies to this topic
[TOPIC CONTROLS]
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

XeduR @Spyric

[GLOBAL: userInfoPane.html]
XeduR @Spyric
  • Contributor

  • 762 posts
  • Corona SDK

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!
 



[TOPIC: post.html]
#2

roaminggamer

[GLOBAL: userInfoPane.html]
roaminggamer
  • Corona Geek

  • 7,585 posts
  • Corona SDK

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 )


[TOPIC: post.html]
#3

roaminggamer

[GLOBAL: userInfoPane.html]
roaminggamer
  • Corona Geek

  • 7,585 posts
  • Corona SDK

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.



[TOPIC: post.html]
#4

XeduR @Spyric

[GLOBAL: userInfoPane.html]
XeduR @Spyric
  • Contributor

  • 762 posts
  • Corona SDK

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?



[TOPIC: post.html]
#5

anaqim

[GLOBAL: userInfoPane.html]
anaqim
  • Contributor

  • 770 posts
  • Corona SDK

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.



[TOPIC: post.html]
#6

XeduR @Spyric

[GLOBAL: userInfoPane.html]
XeduR @Spyric
  • Contributor

  • 762 posts
  • Corona SDK

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.



[TOPIC: post.html]
#7

anaqim

[GLOBAL: userInfoPane.html]
anaqim
  • Contributor

  • 770 posts
  • Corona SDK

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.  :)



[TOPIC: post.html]
#8

carloscosta

[GLOBAL: userInfoPane.html]
carloscosta
  • Contributor

  • 634 posts
  • Corona SDK

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.



[TOPIC: post.html]
#9

davebollinger

[GLOBAL: userInfoPane.html]
davebollinger
  • Corona Geek

  • 1,337 posts
  • Enterprise

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.


  • anaqim likes this

[TOPIC: post.html]
#10

XeduR @Spyric

[GLOBAL: userInfoPane.html]
XeduR @Spyric
  • Contributor

  • 762 posts
  • Corona SDK

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

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.



[TOPIC: post.html]
#11

roaminggamer

[GLOBAL: userInfoPane.html]
roaminggamer
  • Corona Geek

  • 7,585 posts
  • Corona SDK

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)

  • XeduR @Spyric likes this

[TOPIC: post.html]
#12

XeduR @Spyric

[GLOBAL: userInfoPane.html]
XeduR @Spyric
  • Contributor

  • 762 posts
  • Corona SDK

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.
 



[TOPIC: post.html]
#13

roaminggamer

[GLOBAL: userInfoPane.html]
roaminggamer
  • Corona Geek

  • 7,585 posts
  • Corona SDK

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:



[TOPIC: post.html]
#14

anaqim

[GLOBAL: userInfoPane.html]
anaqim
  • Contributor

  • 770 posts
  • Corona SDK

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




[topic_controls]
[/topic_controls]