1 package com.badlogic.gdx.graphics.g3d.particles.influencers; 2 3 import java.util.Iterator; 4 5 import com.badlogic.gdx.assets.AssetDescriptor; 6 import com.badlogic.gdx.assets.AssetManager; 7 import com.badlogic.gdx.graphics.g3d.particles.ParallelArray.ObjectChannel; 8 import com.badlogic.gdx.graphics.g3d.particles.ParticleChannels; 9 import com.badlogic.gdx.graphics.g3d.particles.ParticleController; 10 import com.badlogic.gdx.graphics.g3d.particles.ParticleEffect; 11 import com.badlogic.gdx.graphics.g3d.particles.ResourceData; 12 import com.badlogic.gdx.graphics.g3d.particles.ResourceData.SaveData; 13 import com.badlogic.gdx.utils.Array; 14 import com.badlogic.gdx.utils.IntArray; 15 import com.badlogic.gdx.utils.Pool; 16 17 /** It's an {@link Influencer} which controls which {@link ParticleController} will be assigned to a particle. 18 * @author Inferno */ 19 public abstract class ParticleControllerInfluencer extends Influencer{ 20 21 /** Assigns the first controller of {@link ParticleControllerInfluencer#templates} to the particles.*/ 22 public static class Single extends ParticleControllerInfluencer{ 23 24 public Single (ParticleController... templates) { 25 super(templates); 26 } 27 28 public Single (){ 29 super(); 30 } 31 32 public Single (Single particleControllerSingle) { 33 super(particleControllerSingle); 34 } 35 36 @Override 37 public void init () { 38 ParticleController first = templates.first(); 39 for(int i=0, c = controller.particles.capacity; i < c; ++i){ 40 ParticleController copy = first.copy(); 41 copy.init(); 42 particleControllerChannel.data[i] = copy; 43 } 44 } 45 46 @Override 47 public void activateParticles (int startIndex, int count) { 48 for(int i=startIndex, c = startIndex +count; i < c; ++i){ 49 particleControllerChannel.data[i].start(); 50 } 51 } 52 53 @Override 54 public void killParticles (int startIndex, int count) { 55 for(int i=startIndex, c = startIndex +count; i < c; ++i){ 56 particleControllerChannel.data[i].end(); 57 } 58 } 59 60 @Override 61 public Single copy () { 62 return new Single(this); 63 } 64 } 65 66 67 /** Assigns a random controller of {@link ParticleControllerInfluencer#templates} to the particles.*/ 68 public static class Random extends ParticleControllerInfluencer{ 69 private class ParticleControllerPool extends Pool<ParticleController>{ 70 public ParticleControllerPool () {} 71 72 @Override 73 public ParticleController newObject () { 74 ParticleController controller = templates.random().copy(); 75 controller.init(); 76 return controller; 77 } 78 79 @Override 80 public void clear () { 81 //Dispose every allocated instance because the templates may be changed 82 for(int i=0, free = pool.getFree(); i < free; ++i){ 83 pool.obtain().dispose(); 84 } 85 super.clear(); 86 } 87 } 88 89 ParticleControllerPool pool; 90 91 public Random (){ 92 super(); 93 pool = new ParticleControllerPool(); 94 } 95 public Random (ParticleController... templates) { 96 super(templates); 97 pool = new ParticleControllerPool(); 98 } 99 100 public Random (Random particleControllerRandom) { 101 super(particleControllerRandom); 102 pool = new ParticleControllerPool(); 103 } 104 105 @Override 106 public void init () { 107 pool.clear(); 108 //Allocate the new instances 109 for(int i=0; i < controller.emitter.maxParticleCount; ++i){ 110 pool.free(pool.newObject()); 111 } 112 } 113 114 @Override 115 public void dispose(){ 116 pool.clear(); 117 super.dispose(); 118 } 119 120 @Override 121 public void activateParticles (int startIndex, int count) { 122 for(int i=startIndex, c = startIndex +count; i < c; ++i){ 123 ParticleController controller = pool.obtain(); 124 controller.start(); 125 particleControllerChannel.data[i] = controller; 126 } 127 } 128 129 @Override 130 public void killParticles (int startIndex, int count) { 131 for(int i=startIndex, c = startIndex +count; i < c; ++i){ 132 ParticleController controller = particleControllerChannel.data[i]; 133 controller.end(); 134 pool.free(controller); 135 particleControllerChannel.data[i] = null; 136 } 137 } 138 139 @Override 140 public Random copy () { 141 return new Random(this); 142 } 143 } 144 145 public Array<ParticleController> templates; 146 ObjectChannel<ParticleController> particleControllerChannel; 147 148 public ParticleControllerInfluencer(){ 149 this.templates = new Array<ParticleController>(true, 1, ParticleController.class); 150 } 151 152 public ParticleControllerInfluencer(ParticleController... templates){ 153 this.templates = new Array<ParticleController>(templates); 154 } 155 156 public ParticleControllerInfluencer(ParticleControllerInfluencer influencer){ 157 this(influencer.templates.items); 158 } 159 160 @Override 161 public void allocateChannels () { 162 particleControllerChannel = controller.particles.addChannel(ParticleChannels.ParticleController); 163 } 164 165 @Override 166 public void end(){ 167 for(int i=0; i < controller.particles.size; ++i){ 168 particleControllerChannel.data[i].end(); 169 } 170 } 171 172 @Override 173 public void dispose () { 174 if(controller != null){ 175 for(int i=0; i < controller.particles.size; ++i){ 176 ParticleController controller = particleControllerChannel.data[i]; 177 if(controller != null){ 178 controller.dispose(); 179 particleControllerChannel.data[i]= null; 180 } 181 } 182 } 183 } 184 185 @Override 186 public void save (AssetManager manager, ResourceData resources) { 187 SaveData data = resources.createSaveData(); 188 Array<ParticleEffect> effects = manager.getAll(ParticleEffect.class, new Array<ParticleEffect>()); 189 190 Array<ParticleController> controllers = new Array<ParticleController>(templates); 191 Array<IntArray>effectsIndices = new Array<IntArray>(); 192 193 for(int i=0; i < effects.size && controllers.size >0; ++i){ 194 ParticleEffect effect = effects.get(i); 195 Array<ParticleController> effectControllers = effect.getControllers(); 196 Iterator<ParticleController> iterator = controllers.iterator(); 197 IntArray indices = null; 198 while(iterator.hasNext()){ 199 ParticleController controller = iterator.next(); 200 int index = -1; 201 if( (index = effectControllers.indexOf(controller, true)) >-1){ 202 if(indices == null){ 203 indices = new IntArray(); 204 } 205 iterator.remove(); 206 indices.add(index); 207 } 208 } 209 210 if(indices != null){ 211 data.saveAsset(manager.getAssetFileName(effect), ParticleEffect.class); 212 effectsIndices.add(indices); 213 } 214 } 215 data.save("indices", effectsIndices); 216 } 217 218 @Override 219 public void load (AssetManager manager, ResourceData resources) { 220 SaveData data = resources.getSaveData(); 221 Array<IntArray>effectsIndices = data.load("indices"); 222 AssetDescriptor descriptor; 223 Iterator<IntArray> iterator = effectsIndices.iterator(); 224 while((descriptor = data.loadAsset()) != null){ 225 ParticleEffect effect = (ParticleEffect)manager.get(descriptor); 226 if(effect == null) 227 throw new RuntimeException("Template is null"); 228 Array<ParticleController> effectControllers = effect.getControllers(); 229 IntArray effectIndices = iterator.next(); 230 231 for (int i = 0, n = effectIndices.size; i < n; i++) { 232 templates.add(effectControllers.get(effectIndices.get(i))); 233 } 234 } 235 } 236 } 237