/******************************************************************************* * Copyright 2011 See AUTHORS file. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package com.badlogic.gdx.graphics.g3d.particles.influencers; import java.util.Iterator; import com.badlogic.gdx.assets.AssetDescriptor; import com.badlogic.gdx.assets.AssetManager; import com.badlogic.gdx.graphics.g3d.particles.ParallelArray.ObjectChannel; import com.badlogic.gdx.graphics.g3d.particles.ParticleChannels; import com.badlogic.gdx.graphics.g3d.particles.ParticleController; import com.badlogic.gdx.graphics.g3d.particles.ParticleEffect; import com.badlogic.gdx.graphics.g3d.particles.ResourceData; import com.badlogic.gdx.graphics.g3d.particles.ResourceData.SaveData; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.IntArray; import com.badlogic.gdx.utils.Pool; /** It's an {@link Influencer} which controls which {@link ParticleController} will be assigned to a particle. * @author Inferno */ public abstract class ParticleControllerInfluencer extends Influencer { /** Assigns the first controller of {@link ParticleControllerInfluencer#templates} to the particles. */ public static class Single extends ParticleControllerInfluencer { public Single (ParticleController... templates) { super(templates); } public Single () { super(); } public Single (Single particleControllerSingle) { super(particleControllerSingle); } @Override public void init () { ParticleController first = templates.first(); for (int i = 0, c = controller.particles.capacity; i < c; ++i) { ParticleController copy = first.copy(); copy.init(); particleControllerChannel.data[i] = copy; } } @Override public void activateParticles (int startIndex, int count) { for (int i = startIndex, c = startIndex + count; i < c; ++i) { particleControllerChannel.data[i].start(); } } @Override public void killParticles (int startIndex, int count) { for (int i = startIndex, c = startIndex + count; i < c; ++i) { particleControllerChannel.data[i].end(); } } @Override public Single copy () { return new Single(this); } } /** Assigns a random controller of {@link ParticleControllerInfluencer#templates} to the particles. */ public static class Random extends ParticleControllerInfluencer { private class ParticleControllerPool extends Pool<ParticleController> { public ParticleControllerPool () { } @Override public ParticleController newObject () { ParticleController controller = templates.random().copy(); controller.init(); return controller; } @Override public void clear () { // Dispose every allocated instance because the templates may be changed for (int i = 0, free = pool.getFree(); i < free; ++i) { pool.obtain().dispose(); } super.clear(); } } ParticleControllerPool pool; public Random () { super(); pool = new ParticleControllerPool(); } public Random (ParticleController... templates) { super(templates); pool = new ParticleControllerPool(); } public Random (Random particleControllerRandom) { super(particleControllerRandom); pool = new ParticleControllerPool(); } @Override public void init () { pool.clear(); // Allocate the new instances for (int i = 0; i < controller.emitter.maxParticleCount; ++i) { pool.free(pool.newObject()); } } @Override public void dispose () { pool.clear(); super.dispose(); } @Override public void activateParticles (int startIndex, int count) { for (int i = startIndex, c = startIndex + count; i < c; ++i) { ParticleController controller = pool.obtain(); controller.start(); particleControllerChannel.data[i] = controller; } } @Override public void killParticles (int startIndex, int count) { for (int i = startIndex, c = startIndex + count; i < c; ++i) { ParticleController controller = particleControllerChannel.data[i]; controller.end(); pool.free(controller); particleControllerChannel.data[i] = null; } } @Override public Random copy () { return new Random(this); } } public Array<ParticleController> templates; ObjectChannel<ParticleController> particleControllerChannel; public ParticleControllerInfluencer () { this.templates = new Array<ParticleController>(true, 1, ParticleController.class); } public ParticleControllerInfluencer (ParticleController... templates) { this.templates = new Array<ParticleController>(templates); } public ParticleControllerInfluencer (ParticleControllerInfluencer influencer) { this(influencer.templates.items); } @Override public void allocateChannels () { particleControllerChannel = controller.particles.addChannel(ParticleChannels.ParticleController); } @Override public void end () { for (int i = 0; i < controller.particles.size; ++i) { particleControllerChannel.data[i].end(); } } @Override public void dispose () { if (controller != null) { for (int i = 0; i < controller.particles.size; ++i) { ParticleController controller = particleControllerChannel.data[i]; if (controller != null) { controller.dispose(); particleControllerChannel.data[i] = null; } } } } @Override public void save (AssetManager manager, ResourceData resources) { SaveData data = resources.createSaveData(); Array<ParticleEffect> effects = manager.getAll(ParticleEffect.class, new Array<ParticleEffect>()); Array<ParticleController> controllers = new Array<ParticleController>(templates); Array<IntArray> effectsIndices = new Array<IntArray>(); for (int i = 0; i < effects.size && controllers.size > 0; ++i) { ParticleEffect effect = effects.get(i); Array<ParticleController> effectControllers = effect.getControllers(); Iterator<ParticleController> iterator = controllers.iterator(); IntArray indices = null; while (iterator.hasNext()) { ParticleController controller = iterator.next(); int index = -1; if ((index = effectControllers.indexOf(controller, true)) > -1) { if (indices == null) { indices = new IntArray(); } iterator.remove(); indices.add(index); } } if (indices != null) { data.saveAsset(manager.getAssetFileName(effect), ParticleEffect.class); effectsIndices.add(indices); } } data.save("indices", effectsIndices); } @Override public void load (AssetManager manager, ResourceData resources) { SaveData data = resources.getSaveData(); Array<IntArray> effectsIndices = data.load("indices"); AssetDescriptor descriptor; Iterator<IntArray> iterator = effectsIndices.iterator(); while ((descriptor = data.loadAsset()) != null) { ParticleEffect effect = (ParticleEffect)manager.get(descriptor); if (effect == null) throw new RuntimeException("Template is null"); Array<ParticleController> effectControllers = effect.getControllers(); IntArray effectIndices = iterator.next(); for (int i = 0, n = effectIndices.size; i < n; i++) { templates.add(effectControllers.get(effectIndices.get(i))); } } } }