Are subfolder Particle Systems possible?

I remember seeing a small discussion of this on the announcement page, and ran into the same core problem myself:

The Corona particleDesigner library doesn’t support subfolders.

Assuming a basic ParticleDesigner 2 setup; both the textures and json file need to be in the root directory or bust.

Is there a bug filed for this? Or a relatively common workaround?

Hi Richard.  I did a query on the bug data base for particle and folder and didn’t find anything.  Perhaps you should file one.

Rob

I have ParticleDesigner json and png files in a subfolder without issues.

Use this function for a fix:

-- ------------------------------- -- emitter functions -- ------------------------------- local newEmitter = function(emitterFile, baseDir) baseDir = baseDir or system.ResourceDirectory local filePath = system.pathForFile(emitterFile, baseDir) local f = io.open(filePath, "r") local fileData = f:read("\*a") f:close() local emitterParams = json.decode(fileData) -- fix start -------------------------------- -- Corona builds do not support particle textures in subfolders -- the code below fixes this issue local slashPos = nil local tmpPos = 0 -- find last slash in input string repeat tmpPos = emitterFile:find("/", tmpPos + 1) if (tmpPos) then slashPos = tmpPos end until not tmpPos if (slashPos) then local subfolder = emitterFile:sub(1, slashPos) -- future-proofing in case CoronaLabs fixes this issue if (not emitterParams.textureFileName:find("/")) then emitterParams.textureFileName = subfolder .. emitterParams.textureFileName end end -- fix end ---------------------------------- local emitter = display.newEmitter(emitterParams) return emitter end

Usage:

local emitter = newEmitter("img/emitters/MyAwesomeEmitter.json")

This will search for the json and png in the img/emitters folder in the ResourceDirectory.

Thanks ingemar but on trying your code it definitely doesn’t work in cases where there are multiple subfolders. (i.e.: “assets/particles”) I can get your code to find the JSON in a deep subfolder but that’s it, the image must be in root for it to work.

I’ll have to fix that in my code…

One quick and dirty fix you can do is to edit the json file and point the png to the directory you want.
This is the root of the problem. The json file doesn’t include the file path for the png.
Once you’ve manually added the path to the png, you should be fine.

Quick chime in.  Hopefully I understood the question, but “Corona” can handle having the particle images in subfolders no problem.  I use the exact technique Ingemar just mentions (overriding image location before creating particle).

@richard

I tested my function, and it works perfectly with nested subfolders.

One thing though. The function above replaces the call to display.newEmitter() so you shouldn’t call the latter yourself.

There are two options to fix this issue:

  1. Use my function above instead of display.newEmitter()

  2. Edit the json file in a text editor and add the path to the png entry

Tore my code apart 3 times, and finally got it to work. About all I found out is that appending strings inside of a system.pathForFile() call doesn’t seem to work. But thanks ingemar, finally got it functional.

From a purely “Corona user” perspective I would suggest building your function differently (99% of users won’t need to specify a baseDir, but I bet 50% want to specify custom folders) - I was initially expecting it to work as newEmitter(file, subDir, baseDir) but even just showing the usage method there helps a lot.

I will try and file a bug with Corona later today, though; they seem to operate under this just working so may as well make it official that it does not. :slight_smile:

@richard

Ah! I think I see the source of confusion…

Yes, the ‘baseDir’ in my function is only for the base directory, not the subdirectories of the files. The baseDir there, as you found out the hard way, is just the base directory, which only needs to be the ResourceDirectory here and never needs to be changed. If you want to specify multiple subdirectories within the base dir, you specify those as in my Usage example above.

I hoped that the “Usage” example would’ve clarified where to put the subfolders for the asset itself.

(Note: The json and png must be in the same subfolder)

Sorry about that…

I can confirm that changing the image file path does fix the issue, however, their is a case when there is not a fix.  I haven’t have the time to provide an accurate test app to reproduce, but when the particle effect and image is another directory folder other than Resources it errors.  For example, if you extract a zip file to CacheDirectory that contains your particles, it will fail.

I’ve modified my function above to take the baseDir as an argument.

If you use my function above and pass system.CachesDirectory as the second argument, it should work. 

(This assumes that the PNG and JSON is in the same place though)

Hi Richard.  I did a query on the bug data base for particle and folder and didn’t find anything.  Perhaps you should file one.

Rob

I have ParticleDesigner json and png files in a subfolder without issues.

Use this function for a fix:

-- ------------------------------- -- emitter functions -- ------------------------------- local newEmitter = function(emitterFile, baseDir) baseDir = baseDir or system.ResourceDirectory local filePath = system.pathForFile(emitterFile, baseDir) local f = io.open(filePath, "r") local fileData = f:read("\*a") f:close() local emitterParams = json.decode(fileData) -- fix start -------------------------------- -- Corona builds do not support particle textures in subfolders -- the code below fixes this issue local slashPos = nil local tmpPos = 0 -- find last slash in input string repeat tmpPos = emitterFile:find("/", tmpPos + 1) if (tmpPos) then slashPos = tmpPos end until not tmpPos if (slashPos) then local subfolder = emitterFile:sub(1, slashPos) -- future-proofing in case CoronaLabs fixes this issue if (not emitterParams.textureFileName:find("/")) then emitterParams.textureFileName = subfolder .. emitterParams.textureFileName end end -- fix end ---------------------------------- local emitter = display.newEmitter(emitterParams) return emitter end

Usage:

local emitter = newEmitter("img/emitters/MyAwesomeEmitter.json")

This will search for the json and png in the img/emitters folder in the ResourceDirectory.

Thanks ingemar but on trying your code it definitely doesn’t work in cases where there are multiple subfolders. (i.e.: “assets/particles”) I can get your code to find the JSON in a deep subfolder but that’s it, the image must be in root for it to work.

I’ll have to fix that in my code…

One quick and dirty fix you can do is to edit the json file and point the png to the directory you want.
This is the root of the problem. The json file doesn’t include the file path for the png.
Once you’ve manually added the path to the png, you should be fine.

Quick chime in.  Hopefully I understood the question, but “Corona” can handle having the particle images in subfolders no problem.  I use the exact technique Ingemar just mentions (overriding image location before creating particle).

@richard

I tested my function, and it works perfectly with nested subfolders.

One thing though. The function above replaces the call to display.newEmitter() so you shouldn’t call the latter yourself.

There are two options to fix this issue:

  1. Use my function above instead of display.newEmitter()

  2. Edit the json file in a text editor and add the path to the png entry

Tore my code apart 3 times, and finally got it to work. About all I found out is that appending strings inside of a system.pathForFile() call doesn’t seem to work. But thanks ingemar, finally got it functional.

From a purely “Corona user” perspective I would suggest building your function differently (99% of users won’t need to specify a baseDir, but I bet 50% want to specify custom folders) - I was initially expecting it to work as newEmitter(file, subDir, baseDir) but even just showing the usage method there helps a lot.

I will try and file a bug with Corona later today, though; they seem to operate under this just working so may as well make it official that it does not. :slight_smile:

@richard

Ah! I think I see the source of confusion…

Yes, the ‘baseDir’ in my function is only for the base directory, not the subdirectories of the files. The baseDir there, as you found out the hard way, is just the base directory, which only needs to be the ResourceDirectory here and never needs to be changed. If you want to specify multiple subdirectories within the base dir, you specify those as in my Usage example above.

I hoped that the “Usage” example would’ve clarified where to put the subfolders for the asset itself.

(Note: The json and png must be in the same subfolder)

Sorry about that…

I can confirm that changing the image file path does fix the issue, however, their is a case when there is not a fix.  I haven’t have the time to provide an accurate test app to reproduce, but when the particle effect and image is another directory folder other than Resources it errors.  For example, if you extract a zip file to CacheDirectory that contains your particles, it will fail.