Why would drawing into one image in a (nested) table ALSO draw into images in OTHER tables?

Been stumped for weeks... I've tried both numeric and string indices.

All I want to do is take a table of images, back it up into various slots of the table cachedLevels and then retrieve one of the backed-up tables at will. I'm very open to any approach to that result.

A simple test case has no problem, but my game does... and I have failed to find the difference... Any ideas what mistake could cause this behavior?

I'm definitely drawing a circle into only ONE image of ONE table (I hardcoded both indices) but ALL the tables get the circle in that particular image!

Here's an example of code that fails:

cachedLevels is my table of 9 tables (I'm testing table 7), each with 7 images (I'm testing image 3)

gfx.pushContext(cachedLevels[7][3])
     gfx.fillCircleAtPoint(50, 50, 100)
gfx.popContext()

Then I draw cachedLevels[7][3] and cachedLevels[8][3]... and BOTH have a circle!

I am not doing any operation on cachedLevels[8]. I want it left alone.

(Meanwhile, cachedLevels [7][4], [8][4] etc. do NOT have a circle. But all the image [3]s in EVERY table 1 through 9 have the circle.)

FWIW, the tables within cachedLevels are initially populated by copying data into them as follows:

function table.clone(from)
     return {table.unpack(from)}
end

And then (whether the current level [n] already exists or not)...

cachedLevels[n] = table.clone(levels)

I would have thought the table.clone function (found online) was the problem, except it works fine in my simple test case (which is also nested tables of images).

FWIW, any time I need to dump all the tables and start fresh I do this (which seems awkward but is found all over Lua forums):

cachedLevels = {}
table.insert(cachedLevels, 1)
cachedLevels = {}

Your clone function clones the table, but doesn’t do anything with the images themselves which are a reference type. So you end up with a new table containing references to the same old image.

You’re going to have to either initialize new images for each one, or have your clone function check for images and perform :copy() on them.

3 Likes

Sounds promising and doable! Not sure why it was working OK in my test case, but I'll report back soon! Thanks!

Oh also if you’re using that clone function on anything but the innermost level of nested tables, it’s only cloning the table at the level you pass into it, not any inner ones within that. The SDK includes table.deepcopy which should solve that (it not only clones the table you pass in, but any nested ones within that), but I think the image references would still be a separate issue.

1 Like

I could never get table.shallowcopy or table.deepcopy to work--I always seemed to get references to tables and not a true independent copy. Thanks for the warning. Luckily, I never need to clone a nested table, I only need to clone single-level tables (into and out of a table--that's the only nesting). And nothing but images.

For posterity: here's my alternative to table.clone. It's all I need for copying a table that simply contains numbered images. (This assumes starting from an empty toTable.)

function copyTableOfImages(fromTable, toTable, numImages)
	for n = 1, numImages do
		toTable[n] = fromTable[n]:copy()
	end
end
1 Like