Home | History | Annotate | Download | only in influencers
      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