Skip to content

The influencer data system has been changed #6

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
180 changes: 145 additions & 35 deletions src/main/java/tonegod/emitter/ParticleEmitterNode.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
package tonegod.emitter;

import static java.lang.Class.forName;
import static java.util.Objects.requireNonNull;
import static tonegod.emitter.material.ParticlesMaterial.PROP_TEXTURE;
import com.jme3.animation.AnimChannel;
import com.jme3.animation.AnimControl;
import com.jme3.animation.LoopMode;
Expand Down Expand Up @@ -36,6 +33,7 @@
import tonegod.emitter.EmitterMesh.DirectionType;
import tonegod.emitter.geometry.EmitterShapeGeometry;
import tonegod.emitter.geometry.ParticleGeometry;
import tonegod.emitter.influencers.InfluencerData;
import tonegod.emitter.influencers.ParticleInfluencer;
import tonegod.emitter.interpolation.Interpolation;
import tonegod.emitter.material.ParticlesMaterial;
Expand All @@ -45,6 +43,14 @@
import tonegod.emitter.shapes.TriangleEmitterShape;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import static java.lang.Class.forName;
import static java.util.Objects.requireNonNull;
import static tonegod.emitter.material.ParticlesMaterial.PROP_TEXTURE;

/**
* The implementation of a {@link Node} to emit particles.
Expand All @@ -54,6 +60,77 @@
@SuppressWarnings("WeakerAccess")
public class ParticleEmitterNode extends Node implements JmeCloneable, Cloneable {


public class InfluencerInstance implements JmeCloneable {
private int id = -1;
private InfluencerData dataSample;
private ParticleInfluencer influencer;

private InfluencerInstance() { }

public InfluencerInstance(ParticleInfluencer influencer, Class<InfluencerData> dataClass) {
if(dataClass != null) {
this.id = reservations++;

try {
Constructor<InfluencerData> constructor = dataClass.getDeclaredConstructor();
constructor.setAccessible(true);
this.dataSample = constructor.newInstance();
} catch (IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}

this.influencer = influencer;
}

public int getId() {
return id;
}

public ParticleInfluencer getInfluencer() {
return influencer;
}

public boolean hasData() {
return id >= 0;
}

public InfluencerData createData() {
return dataSample.create();
}

@Override
public boolean equals(Object o) {
if(o instanceof ParticleInfluencer) {
return o.equals(influencer);
}

if (this == o) return true;

if (o == null || getClass() != o.getClass()) return false;

InfluencerInstance other = (InfluencerInstance) o;

return this.influencer.equals(other.influencer);
}

@Override
public int hashCode() {
return influencer.hashCode();
}

@Override
public Object jmeClone() {
try { return super.clone(); } catch (CloneNotSupportedException ex) { throw new RuntimeException(ex); }
}

@Override
public void cloneFields(Cloner cloner, Object original) {
influencer = cloner.clone(influencer);
}
}

@NotNull
private static final ParticleInfluencer[] EMPTY_INFLUENCERS = new ParticleInfluencer[0];

Expand All @@ -64,7 +141,8 @@ public class ParticleEmitterNode extends Node implements JmeCloneable, Cloneable
* The Influencers.
*/
@NotNull
protected SafeArrayList<ParticleInfluencer> influencers;
protected SafeArrayList<InfluencerInstance> influencerInstances;
private int reservations;

/**
* The flags of this emitter.
Expand Down Expand Up @@ -449,7 +527,7 @@ public ParticleEmitterNode() {
this.emissionPoint = EmissionPoint.CENTER;
this.directionType = DirectionType.RANDOM;
this.interpolation = Interpolation.LINEAR;
this.influencers = new SafeArrayList<>(ParticleInfluencer.class);
this.influencerInstances = new SafeArrayList<>(InfluencerInstance.class);
this.particleDataMeshType = ParticleDataTriMesh.class;
this.emitterShape = new EmitterMesh();
this.particleGeometry = new ParticleGeometry("Particle Geometry");
Expand Down Expand Up @@ -1337,13 +1415,10 @@ public int getMaxParticles() {
*/
public void addInfluencers(@NotNull final ParticleInfluencer... newInfluencers) {

final SafeArrayList<ParticleInfluencer> influencers = getInfluencers();

for (final ParticleInfluencer influencer : newInfluencers) {
influencers.add(influencer);
addInfluencer(influencer);
}

requiresUpdate = true;
}

/**
Expand All @@ -1352,7 +1427,26 @@ public void addInfluencers(@NotNull final ParticleInfluencer... newInfluencers)
* @param influencer The particle influencer to add to the chain
*/
public void addInfluencer(@NotNull final ParticleInfluencer influencer) {
influencers.add(influencer);
Type type = influencer.getClass().getGenericSuperclass();

Class generic = null;
if(type instanceof ParameterizedType) {
generic = (Class) ((ParameterizedType) type).getActualTypeArguments()[0];
}

// Class generic = (Class) ((ParameterizedType)influencer.getClass().getGenericSuperclass()).getActualTypeArguments()[0];

InfluencerInstance influencerInstance = new InfluencerInstance(influencer, generic);
influencerInstances.add(influencerInstance);

if(isEmitterInitialized()) {
for(ParticleData particleData : particles) {
if(particleData.isActive()) {
particleData.initializeInfluencer(influencerInstance);
}
}
}

requiresUpdate = true;
}

Expand All @@ -1364,23 +1458,27 @@ public void addInfluencer(@NotNull final ParticleInfluencer influencer) {
*/
public void addInfluencer(@NotNull final ParticleInfluencer influencer, final int index) {

final SafeArrayList<ParticleInfluencer> temp = new SafeArrayList<>(ParticleInfluencer.class);
final SafeArrayList<ParticleInfluencer> influencers = getInfluencers();
final SafeArrayList<InfluencerInstance> aux = new SafeArrayList<>(InfluencerInstance.class);
final SafeArrayList<InfluencerInstance> influencerInstances = getInfluencerInstances();

aux.addAll(influencerInstances);

influencerInstances.clear();

for (int i = 0; i < index; i++) {
temp.add(influencers.get(i));
influencerInstances.add(aux.get(i));
}

temp.add(influencer);
addInfluencer(influencer);

for (int i = index, length = this.influencers.size(); i < length; i++) {
temp.add(influencers.get(i));
for (int i = index, length = this.influencerInstances.size(); i < length; i++) {
influencerInstances.add(aux.get(i));
}

influencers.clear();
influencers.addAll(temp);
// influencers.clear();
// influencers.addAll(temp);

requiresUpdate = true;
// requiresUpdate = true;
}

/**
Expand All @@ -1389,7 +1487,7 @@ public void addInfluencer(@NotNull final ParticleInfluencer influencer, final in
* @param influencer the influencer to remove.
*/
public void removeInfluencer(@NotNull final ParticleInfluencer influencer) {
influencers.remove(influencer);
influencerInstances.remove(influencer);
requiresUpdate = true;
}

Expand All @@ -1398,10 +1496,22 @@ public void removeInfluencer(@NotNull final ParticleInfluencer influencer) {
*
* @return The Collection of particle influencers
*/
@Deprecated
public @NotNull SafeArrayList<ParticleInfluencer> getInfluencers() {

SafeArrayList<ParticleInfluencer> influencers = new SafeArrayList<>(ParticleInfluencer.class);

for(InfluencerInstance influencerInstance : influencerInstances.getArray()) {
influencers.add(influencerInstance.getInfluencer());
}

return influencers;
}

public @NotNull SafeArrayList<InfluencerInstance> getInfluencerInstances() {
return influencerInstances;
}

/**
* Returns the first instance of a specified ParticleData Influencer type
*
Expand All @@ -1411,11 +1521,11 @@ public void removeInfluencer(@NotNull final ParticleInfluencer influencer) {
*/
public @Nullable <T extends ParticleInfluencer> T getInfluencer(@NotNull final Class<T> type) {

final SafeArrayList<ParticleInfluencer> influencers = getInfluencers();
final SafeArrayList<InfluencerInstance> influencerInstances = getInfluencerInstances();

for (final ParticleInfluencer influencer : influencers.getArray()) {
if (type.isInstance(influencer)) {
return type.cast(influencer);
for (final InfluencerInstance influencerInstance : influencerInstances.getArray()) {
if (type.isInstance(influencerInstance.influencer)) {
return type.cast(influencerInstance.influencer);
}
}

Expand All @@ -1431,15 +1541,16 @@ public void removeInfluencer(@NotNull final ParticleInfluencer influencer) {
public <T extends ParticleInfluencer> void removeInfluencer(@NotNull final Class<T> type) {
final T influencer = getInfluencer(type);
if (influencer == null) return;
influencers.remove(influencer);

influencerInstances.remove(influencer);
requiresUpdate = true;
}

/**
* Removes all influencers
*/
public void removeAllInfluencers() {
influencers.clear();
influencerInstances.clear();
requiresUpdate = true;
}

Expand Down Expand Up @@ -1895,7 +2006,9 @@ public void updateLogicalState(final float tpf) {
emittedTime += tpf;

for (final ParticleData particleData : particles) {
if (particleData.isActive()) particleData.update(tpf);
if (particleData.isActive()) {
particleData.update(tpf);
}
}

currentInterval += (tpf <= targetInterval) ? tpf : targetInterval;
Expand Down Expand Up @@ -2108,7 +2221,8 @@ public void write(@NotNull final JmeExporter exporter) throws IOException {

final OutputCapsule capsule = exporter.getCapsule(this);

capsule.write(influencers.toArray(new ParticleInfluencer[influencers.size()]), "influencers", EMPTY_INFLUENCERS);
SafeArrayList<ParticleInfluencer> influencers = getInfluencers();
capsule.write(influencers.getArray(), "influencers", EMPTY_INFLUENCERS);
capsule.write(enabled, "enabled", true);

// EMITTER
Expand Down Expand Up @@ -2168,9 +2282,9 @@ public void read(@NotNull final JmeImporter importer) throws IOException {
attachChildAt(particleNode, particleIndex);

final InputCapsule capsule = importer.getCapsule(this);
final Savable[] influencerses = capsule.readSavableArray("influencers", EMPTY_INFLUENCERS);
final Savable[] influencers = capsule.readSavableArray("influencers", EMPTY_INFLUENCERS);

for (final Savable influencer : influencerses) {
for (final Savable influencer : influencers) {
addInfluencer((ParticleInfluencer) influencer);
}

Expand Down Expand Up @@ -2248,11 +2362,7 @@ public void read(@NotNull final JmeImporter importer) throws IOException {
public void cloneFields(@NotNull final Cloner cloner, @NotNull final Object original) {
super.cloneFields(cloner, original);

influencers = cloner.clone(influencers);

for (int i = 0; i < influencers.size(); i++) {
influencers.set(i, cloner.clone(influencers.get(i)));
}
influencerInstances = cloner.clone(influencerInstances);

emitterShape = cloner.clone(emitterShape);
emitterShapeTestGeometry = null;
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/tonegod/emitter/influencers/InfluencerData.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package tonegod.emitter.influencers;

public interface InfluencerData<T extends InfluencerData> {

T create();

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
*
* @author JavaSaBr
*/
public interface InterpolatedParticleInfluencer extends ParticleInfluencer {
public interface InterpolatedParticleInfluencer<T extends InfluencerData> extends ParticleInfluencer<T> {

/**
* Get the count of interpolation steps.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
*
* @author t0neg0d, JavaSaBr
*/
public interface ParticleInfluencer extends Savable, Cloneable {
public interface ParticleInfluencer<T extends InfluencerData> extends Savable, Cloneable {

/**
* Gets name.
Expand All @@ -33,14 +33,14 @@ public interface ParticleInfluencer extends Savable, Cloneable {
* @param particleData The particle to update
* @param tpf The time since last frame
*/
void update(@NotNull ParticleData particleData, float tpf);
void update(@NotNull ParticleData particleData, T influencerData, float tpf);

/**
* Called when a particle is emitted.
*
* @param particleData The particle being emitted
*/
void initialize(@NotNull ParticleData particleData);
void initialize(@NotNull ParticleData particleData, T influencerData);

/**
* Called once the life span of the particle has been reached.
Expand Down
Loading