Home | History | Annotate | Download | only in influencers
      1 package com.badlogic.gdx.graphics.g3d.particles.influencers;
      2 
      3 import com.badlogic.gdx.graphics.Texture;
      4 import com.badlogic.gdx.graphics.g2d.TextureRegion;
      5 import com.badlogic.gdx.graphics.g3d.particles.ParallelArray.FloatChannel;
      6 import com.badlogic.gdx.graphics.g3d.particles.ParticleChannels;
      7 import com.badlogic.gdx.utils.Array;
      8 import com.badlogic.gdx.utils.Json;
      9 import com.badlogic.gdx.utils.JsonValue;
     10 
     11 /** It's an {@link Influencer} which assigns a region of a {@link Texture} to the particles.
     12  * @author Inferno */
     13 public abstract class RegionInfluencer extends Influencer {
     14 
     15 	/** Assigns the first region of {@link RegionInfluencer#regions} to the particles.*/
     16 	public static class Single extends RegionInfluencer{
     17 		public Single(){}
     18 
     19 		public Single (Single regionInfluencer) {
     20 			super(regionInfluencer);
     21 		}
     22 
     23 		public Single (TextureRegion textureRegion) {
     24 			super(textureRegion);
     25 		}
     26 
     27 		public Single (Texture texture) {
     28 			super(texture);
     29 		}
     30 
     31 		@Override
     32 		public void init () {
     33 			AspectTextureRegion region = regions.items[0];
     34 			for(int 	i=0, c = controller.emitter.maxParticleCount*regionChannel.strideSize;
     35 				i < c;
     36 				i +=regionChannel.strideSize){
     37 				regionChannel.data[i +ParticleChannels.UOffset] = region.u;
     38 				regionChannel.data[i +ParticleChannels.VOffset] = region.v;
     39 				regionChannel.data[i +ParticleChannels.U2Offset] = region.u2;
     40 				regionChannel.data[i +ParticleChannels.V2Offset] = region.v2;
     41 				regionChannel.data[i +ParticleChannels.HalfWidthOffset] = 0.5f;
     42 				regionChannel.data[i +ParticleChannels.HalfHeightOffset] = region.halfInvAspectRatio;
     43 			}
     44 		}
     45 
     46 		@Override
     47 		public Single copy () {
     48 			return new Single(this);
     49 		}
     50 	}
     51 
     52 	/** Assigns a random region of {@link RegionInfluencer#regions} to the particles.*/
     53 	public static class Random extends RegionInfluencer{
     54 		public Random(){}
     55 		public Random (Random regionInfluencer) {
     56 			super(regionInfluencer);
     57 		}
     58 		public Random (TextureRegion textureRegion) {
     59 			super(textureRegion);
     60 		}
     61 
     62 		public Random (Texture texture) {
     63 			super(texture);
     64 		}
     65 
     66 		@Override
     67 		public void activateParticles (int startIndex, int count) {
     68 			for(int 	i=startIndex*regionChannel.strideSize, c = i +count*regionChannel.strideSize;
     69 				i < c;
     70 				i +=regionChannel.strideSize){
     71 				AspectTextureRegion region = regions.random();
     72 				regionChannel.data[i +ParticleChannels.UOffset] = region.u;
     73 				regionChannel.data[i +ParticleChannels.VOffset] = region.v;
     74 				regionChannel.data[i +ParticleChannels.U2Offset] = region.u2;
     75 				regionChannel.data[i +ParticleChannels.V2Offset] = region.v2;
     76 				regionChannel.data[i +ParticleChannels.HalfWidthOffset] = 0.5f;
     77 				regionChannel.data[i +ParticleChannels.HalfHeightOffset] = region.halfInvAspectRatio;
     78 			}
     79 		}
     80 
     81 		@Override
     82 		public Random copy () {
     83 			return new Random(this);
     84 		}
     85 	}
     86 
     87 	/** Assigns a region to the particles using the particle life percent
     88 	 * to calculate the current index in the {@link RegionInfluencer#regions} array.*/
     89 	public static class Animated extends RegionInfluencer{
     90 		FloatChannel lifeChannel;
     91 		public Animated(){}
     92 		public Animated (Animated regionInfluencer) {
     93 			super(regionInfluencer);
     94 		}
     95 
     96 		public Animated (TextureRegion textureRegion) {
     97 			super(textureRegion);
     98 		}
     99 
    100 		public Animated (Texture texture) {
    101 			super(texture);
    102 		}
    103 
    104 		@Override
    105 		public void allocateChannels () {
    106 			super.allocateChannels();
    107 			lifeChannel = controller.particles.addChannel(ParticleChannels.Life);
    108 		}
    109 
    110 		@Override
    111 		public void update () {
    112 			for(int 	i=0, l = ParticleChannels.LifePercentOffset,
    113 				c = controller.particles.size*regionChannel.strideSize;
    114 				i < c;
    115 				i +=regionChannel.strideSize, l +=lifeChannel.strideSize){
    116 				AspectTextureRegion region = regions.get( (int)(lifeChannel.data[l]*(regions.size-1)));
    117 				regionChannel.data[i +ParticleChannels.UOffset] = region.u;
    118 				regionChannel.data[i +ParticleChannels.VOffset] = region.v;
    119 				regionChannel.data[i +ParticleChannels.U2Offset] = region.u2;
    120 				regionChannel.data[i +ParticleChannels.V2Offset] = region.v2;
    121 				regionChannel.data[i +ParticleChannels.HalfWidthOffset] = 0.5f;
    122 				regionChannel.data[i +ParticleChannels.HalfHeightOffset] = region.halfInvAspectRatio;
    123 			}
    124 		}
    125 
    126 		@Override
    127 		public Animated copy () {
    128 			return new Animated(this);
    129 		}
    130 	}
    131 
    132 	/** It's a class used internally by the {@link RegionInfluencer} to represent a texture region.
    133 	 * It contains the uv coordinates of the region and the region inverse aspect ratio.*/
    134 	public static class AspectTextureRegion{
    135 		public float u, v, u2, v2;
    136 		public float halfInvAspectRatio;
    137 
    138 		public AspectTextureRegion(){}
    139 
    140 		public AspectTextureRegion( AspectTextureRegion aspectTextureRegion){
    141 			set(aspectTextureRegion);
    142 		}
    143 
    144 		public AspectTextureRegion(TextureRegion region){
    145 			set(region);
    146 		}
    147 
    148 		public void set(TextureRegion region){
    149 			this.u = region.getU();
    150 			this.v = region.getV();
    151 			this.u2 = region.getU2();
    152 			this.v2 = region.getV2();
    153 			this.halfInvAspectRatio = 0.5f*((float)region.getRegionHeight()/region.getRegionWidth());
    154 		}
    155 
    156 		public void set(AspectTextureRegion aspectTextureRegion){
    157 			u = aspectTextureRegion.u;
    158 			v = aspectTextureRegion.v;
    159 			u2 = aspectTextureRegion.u2;
    160 			v2 = aspectTextureRegion.v2;
    161 			halfInvAspectRatio = aspectTextureRegion.halfInvAspectRatio;
    162 		}
    163 	}
    164 
    165 	public Array<AspectTextureRegion> regions;
    166 	FloatChannel regionChannel;
    167 
    168 	public RegionInfluencer(int regionsCount){
    169 		this.regions = new Array<AspectTextureRegion>(false, regionsCount, AspectTextureRegion.class);
    170 	}
    171 
    172 	public RegionInfluencer(){
    173 		this(1);
    174 		AspectTextureRegion aspectRegion = new AspectTextureRegion();
    175 		aspectRegion.u = aspectRegion.v = 0;
    176 		aspectRegion.u2 = aspectRegion.v2 = 1;
    177 		aspectRegion.halfInvAspectRatio = 0.5f;
    178 		regions.add(aspectRegion);
    179 	}
    180 
    181 	/** All the regions must be defined on the same Texture */
    182 	public RegionInfluencer(TextureRegion...regions){
    183 		this.regions = new Array<AspectTextureRegion>( false, regions.length, AspectTextureRegion.class);
    184 		add(regions);
    185 	}
    186 
    187 	public RegionInfluencer(Texture texture){
    188 		this(new TextureRegion(texture));
    189 	}
    190 
    191 	public RegionInfluencer(RegionInfluencer regionInfluencer){
    192 		this(regionInfluencer.regions.size);
    193 		regions.ensureCapacity(regionInfluencer.regions.size);
    194 		for(int i=0; i < regionInfluencer.regions.size; ++i){
    195 			regions.add(new AspectTextureRegion((AspectTextureRegion)regionInfluencer.regions.get(i)));
    196 		}
    197 	}
    198 
    199 	public void add (TextureRegion...regions) {
    200 		this.regions.ensureCapacity(regions.length);
    201 		for(TextureRegion region : regions){
    202 			this.regions.add(new AspectTextureRegion(region));
    203 		}
    204 	}
    205 
    206 	public void clear(){
    207 		regions.clear();
    208 	}
    209 
    210 	@Override
    211 	public void allocateChannels () {
    212 		regionChannel = controller.particles.addChannel(ParticleChannels.TextureRegion);
    213 	}
    214 
    215 	@Override
    216 	public void write (Json json) {
    217 		json.writeValue("regions", regions, Array.class, AspectTextureRegion.class);
    218 	}
    219 
    220 	@Override
    221 	public void read (Json json, JsonValue jsonData) {
    222 		regions.clear();
    223 		regions.addAll(json.readValue("regions", Array.class, AspectTextureRegion.class, jsonData));
    224 	}
    225 }
    226