1 2 package com.badlogic.gdx.graphics.g3d.particles; 3 4 import java.io.File; 5 import java.io.FileWriter; 6 import java.io.IOException; 7 import java.io.Writer; 8 9 import com.badlogic.gdx.Application.ApplicationType; 10 import com.badlogic.gdx.Gdx; 11 import com.badlogic.gdx.assets.AssetDescriptor; 12 import com.badlogic.gdx.assets.AssetLoaderParameters; 13 import com.badlogic.gdx.assets.AssetManager; 14 import com.badlogic.gdx.assets.loaders.AsynchronousAssetLoader; 15 import com.badlogic.gdx.assets.loaders.FileHandleResolver; 16 import com.badlogic.gdx.files.FileHandle; 17 import com.badlogic.gdx.graphics.g3d.particles.ResourceData.AssetData; 18 import com.badlogic.gdx.graphics.g3d.particles.batches.ParticleBatch; 19 import com.badlogic.gdx.utils.Array; 20 import com.badlogic.gdx.utils.Json; 21 import com.badlogic.gdx.utils.ObjectMap; 22 import com.badlogic.gdx.utils.reflect.ClassReflection; 23 24 /** This class can save and load a {@link ParticleEffect}. It should be added as {@link AsynchronousAssetLoader} to the 25 * {@link AssetManager} so it will be able to load the effects. It's important to note that the two classes 26 * {@link ParticleEffectLoadParameter} and {@link ParticleEffectSaveParameter} should be passed in whenever possible, because when 27 * present the batches settings will be loaded automatically. When the load and save parameters are absent, once the effect will 28 * be created, one will have to set the required batches manually otherwise the {@link ParticleController} instances contained 29 * inside the effect will not be able to render themselves. 30 * @author inferno */ 31 public class ParticleEffectLoader extends 32 AsynchronousAssetLoader<ParticleEffect, ParticleEffectLoader.ParticleEffectLoadParameter> { 33 protected Array<ObjectMap.Entry<String, ResourceData<ParticleEffect>>> items = new Array<ObjectMap.Entry<String, ResourceData<ParticleEffect>>>(); 34 35 public ParticleEffectLoader (FileHandleResolver resolver) { 36 super(resolver); 37 } 38 39 @Override 40 public void loadAsync (AssetManager manager, String fileName, FileHandle file, ParticleEffectLoadParameter parameter) { 41 } 42 43 @Override 44 public Array<AssetDescriptor> getDependencies (String fileName, FileHandle file, ParticleEffectLoadParameter parameter) { 45 Json json = new Json(); 46 ResourceData<ParticleEffect> data = json.fromJson(ResourceData.class, file); 47 Array<AssetData> assets = null; 48 synchronized (items) { 49 ObjectMap.Entry<String, ResourceData<ParticleEffect>> entry = new ObjectMap.Entry<String, ResourceData<ParticleEffect>>(); 50 entry.key = fileName; 51 entry.value = data; 52 items.add(entry); 53 assets = data.getAssets(); 54 } 55 56 Array<AssetDescriptor> descriptors = new Array<AssetDescriptor>(); 57 for (AssetData<?> assetData : assets) { 58 59 // If the asset doesn't exist try to load it from loading effect directory 60 if (!resolve(assetData.filename).exists()) { 61 assetData.filename = file.parent().child(Gdx.files.internal(assetData.filename).name()).path(); 62 } 63 64 if (assetData.type == ParticleEffect.class) { 65 descriptors.add(new AssetDescriptor(assetData.filename, assetData.type, parameter)); 66 } else 67 descriptors.add(new AssetDescriptor(assetData.filename, assetData.type)); 68 } 69 70 return descriptors; 71 72 } 73 74 /** Saves the effect to the given file contained in the passed in parameter. */ 75 public void save (ParticleEffect effect, ParticleEffectSaveParameter parameter) throws IOException { 76 ResourceData<ParticleEffect> data = new ResourceData<ParticleEffect>(effect); 77 78 // effect assets 79 effect.save(parameter.manager, data); 80 81 // Batches configurations 82 if (parameter.batches != null) { 83 for (ParticleBatch<?> batch : parameter.batches) { 84 boolean save = false; 85 for (ParticleController controller : effect.getControllers()) { 86 if (controller.renderer.isCompatible(batch)) { 87 save = true; 88 break; 89 } 90 } 91 92 if (save) batch.save(parameter.manager, data); 93 } 94 } 95 96 // save 97 Json json = new Json(); 98 json.toJson(data, parameter.file); 99 } 100 101 @Override 102 public ParticleEffect loadSync (AssetManager manager, String fileName, FileHandle file, ParticleEffectLoadParameter parameter) { 103 ResourceData<ParticleEffect> effectData = null; 104 synchronized (items) { 105 for (int i = 0; i < items.size; ++i) { 106 ObjectMap.Entry<String, ResourceData<ParticleEffect>> entry = items.get(i); 107 if (entry.key.equals(fileName)) { 108 effectData = entry.value; 109 items.removeIndex(i); 110 break; 111 } 112 } 113 } 114 115 effectData.resource.load(manager, effectData); 116 if (parameter != null) { 117 if (parameter.batches != null) { 118 for (ParticleBatch<?> batch : parameter.batches) { 119 batch.load(manager, effectData); 120 } 121 } 122 effectData.resource.setBatch(parameter.batches); 123 } 124 return effectData.resource; 125 } 126 127 private <T> T find (Array<?> array, Class<T> type) { 128 for (Object object : array) { 129 if (ClassReflection.isAssignableFrom(type, object.getClass())) return (T)object; 130 } 131 return null; 132 } 133 134 public static class ParticleEffectLoadParameter extends AssetLoaderParameters<ParticleEffect> { 135 Array<ParticleBatch<?>> batches; 136 137 public ParticleEffectLoadParameter (Array<ParticleBatch<?>> batches) { 138 this.batches = batches; 139 } 140 } 141 142 public static class ParticleEffectSaveParameter extends AssetLoaderParameters<ParticleEffect> { 143 /** Optional parameters, but should be present to correctly load the settings */ 144 Array<ParticleBatch<?>> batches; 145 146 /** Required parameters */ 147 FileHandle file; 148 AssetManager manager; 149 150 public ParticleEffectSaveParameter (FileHandle file, AssetManager manager, Array<ParticleBatch<?>> batches) { 151 this.batches = batches; 152 this.file = file; 153 this.manager = manager; 154 } 155 } 156 157 } 158