diff --git a/jme3-core/src/main/java/com/jme3/effect/ParticleEmitter.java b/jme3-core/src/main/java/com/jme3/effect/ParticleEmitter.java index d53273c4e..3baf8feb6 100644 --- a/jme3-core/src/main/java/com/jme3/effect/ParticleEmitter.java +++ b/jme3-core/src/main/java/com/jme3/effect/ParticleEmitter.java @@ -65,12 +65,12 @@ import java.io.IOException; * Particle emitters can be used to simulate various kinds of phenomena, * such as fire, smoke, explosions and much more. *

- * Particle emitters have many properties which are used to control the - * simulation. The interpretation of these properties depends on the + * Particle emitters have many properties which are used to control the + * simulation. The interpretation of these properties depends on the * {@link ParticleInfluencer} that has been assigned to the emitter via * {@link ParticleEmitter#setParticleInfluencer(com.jme3.effect.influencers.ParticleInfluencer) }. * By default the implementation {@link DefaultParticleInfluencer} is used. - * + * * @author Kirill Vainer */ public class ParticleEmitter extends Geometry { @@ -100,7 +100,7 @@ public class ParticleEmitter extends Geometry { private Vector3f faceNormal = new Vector3f(Vector3f.NAN); private int imagesX = 1; private int imagesY = 1; - + private ColorRGBA startColor = new ColorRGBA(0.4f, 0.4f, 0.4f, 0.5f); private ColorRGBA endColor = new ColorRGBA(0.1f, 0.1f, 0.1f, 0.0f); private float startSize = 0.2f; @@ -127,20 +127,20 @@ public class ParticleEmitter extends Geometry { // fixed automatically by ParticleEmitter.clone() method. } - @Override + @Override public Object jmeClone() { try { return super.clone(); } catch( CloneNotSupportedException e ) { throw new RuntimeException("Error cloning", e); } - } + } - @Override - public void cloneFields( Cloner cloner, Object original ) { + @Override + public void cloneFields( Cloner cloner, Object original ) { this.parentEmitter = cloner.clone(parentEmitter); } - + public void setSpatial(Spatial spatial) { } @@ -211,6 +211,42 @@ public class ParticleEmitter extends Geometry { return clone; } + /** + * Called internally by com.jme3.util.clone.Cloner. Do not call directly. + */ + @Override + public void cloneFields( Cloner cloner, Object original ) { + this.shape = cloner.clone(shape); + this.control = cloner.clone(control); + this.faceNormal = cloner.clone(faceNormal); + this.startColor = cloner.clone(startColor); + this.endColor = cloner.clone(endColor); + this.particleInfluencer = cloner.clone(particleInfluencer); + + // change in behavior: gravity was not cloned before -pspeed + this.gravity = cloner.clone(gravity); + + // So, simply setting the mesh type will cause all kinds of things + // to happen: + // 1) the new mesh gets created. + // 2) it is set to the Geometry + // 3) the particles array is recreated because setNumParticles() + // + // ...so this should be equivalent but simpler than half of the old clone() + // method. Note: we do not ever want to share particleMesh so we do not + // clone it at all. + setMeshType(meshType); + + // change in behavior: temp and lastPos were not cloned before... + // perhaps because it was believed that 'transient' fields were exluded + // from cloning? (they aren't) + // If it was ok for these to be shared because of how they are used + // then they could just as well be made static... else I think it's clearer + // to clone them. + this.temp = cloner.clone(temp); + this.lastPos = cloner.clone(lastPos); + } + public ParticleEmitter(String name, Type type, int numParticles) { super(name); setBatchHint(BatchHint.Never); @@ -225,7 +261,7 @@ public class ParticleEmitter extends Geometry { meshType = type; - // Must create clone of shape/influencer so that a reference to a static is + // Must create clone of shape/influencer so that a reference to a static is // not maintained shape = shape.deepClone(); particleInfluencer = particleInfluencer.clone(); @@ -267,10 +303,10 @@ public class ParticleEmitter extends Geometry { /** * Set the {@link ParticleInfluencer} to influence this particle emitter. - * - * @param particleInfluencer the {@link ParticleInfluencer} to influence + * + * @param particleInfluencer the {@link ParticleInfluencer} to influence * this particle emitter. - * + * * @see ParticleInfluencer */ public void setParticleInfluencer(ParticleInfluencer particleInfluencer) { @@ -278,12 +314,12 @@ public class ParticleEmitter extends Geometry { } /** - * Returns the {@link ParticleInfluencer} that influences this + * Returns the {@link ParticleInfluencer} that influences this * particle emitter. - * - * @return the {@link ParticleInfluencer} that influences this + * + * @return the {@link ParticleInfluencer} that influences this * particle emitter. - * + * * @see ParticleInfluencer */ public ParticleInfluencer getParticleInfluencer() { @@ -292,12 +328,12 @@ public class ParticleEmitter extends Geometry { /** * Returns the mesh type used by the particle emitter. - * - * + * + * * @return the mesh type used by the particle emitter. - * + * * @see #setMeshType(com.jme3.effect.ParticleMesh.Type) - * @see ParticleEmitter#ParticleEmitter(java.lang.String, com.jme3.effect.ParticleMesh.Type, int) + * @see ParticleEmitter#ParticleEmitter(java.lang.String, com.jme3.effect.ParticleMesh.Type, int) */ public ParticleMesh.Type getMeshType() { return meshType; @@ -325,26 +361,26 @@ public class ParticleEmitter extends Geometry { } /** - * Returns true if particles should spawn in world space. - * - * @return true if particles should spawn in world space. - * - * @see ParticleEmitter#setInWorldSpace(boolean) + * Returns true if particles should spawn in world space. + * + * @return true if particles should spawn in world space. + * + * @see ParticleEmitter#setInWorldSpace(boolean) */ public boolean isInWorldSpace() { return worldSpace; } /** - * Set to true if particles should spawn in world space. - * + * Set to true if particles should spawn in world space. + * *

If set to true and the particle emitter is moved in the scene, * then particles that have already spawned won't be effected by this * motion. If set to false, the particles will emit in local space * and when the emitter is moved, so are all the particles that * were emitted previously. - * - * @param worldSpace true if particles should spawn in world space. + * + * @param worldSpace true if particles should spawn in world space. */ public void setInWorldSpace(boolean worldSpace) { this.setIgnoreTransform(worldSpace); @@ -353,7 +389,7 @@ public class ParticleEmitter extends Geometry { /** * Returns the number of visible particles (spawned but not dead). - * + * * @return the number of visible particles */ public int getNumVisibleParticles() { @@ -365,7 +401,7 @@ public class ParticleEmitter extends Geometry { * Set the maximum amount of particles that * can exist at the same time with this emitter. * Calling this method many times is not recommended. - * + * * @param numParticles the maximum amount of particles that * can exist at the same time with this emitter. */ @@ -387,13 +423,13 @@ public class ParticleEmitter extends Geometry { /** * Returns a list of all particles (shouldn't be used in most cases). - * + * *

* This includes both existing and non-existing particles. * The size of the array is set to the numParticles value * specified in the constructor or {@link ParticleEmitter#setNumParticles(int) } - * method. - * + * method. + * * @return a list of all particles. */ public Particle[] getParticles() { @@ -401,11 +437,11 @@ public class ParticleEmitter extends Geometry { } /** - * Get the normal which particles are facing. - * - * @return the normal which particles are facing. - * - * @see ParticleEmitter#setFaceNormal(com.jme3.math.Vector3f) + * Get the normal which particles are facing. + * + * @return the normal which particles are facing. + * + * @see ParticleEmitter#setFaceNormal(com.jme3.math.Vector3f) */ public Vector3f getFaceNormal() { if (Vector3f.isValidVector(faceNormal)) { @@ -416,8 +452,8 @@ public class ParticleEmitter extends Geometry { } /** - * Sets the normal which particles are facing. - * + * Sets the normal which particles are facing. + * *

By default, particles * will face the camera, but for some effects (e.g shockwave) it may * be necessary to face a specific direction instead. To restore @@ -437,10 +473,10 @@ public class ParticleEmitter extends Geometry { /** * Returns the rotation speed in radians/sec for particles. - * + * * @return the rotation speed in radians/sec for particles. - * - * @see ParticleEmitter#setRotateSpeed(float) + * + * @see ParticleEmitter#setRotateSpeed(float) */ public float getRotateSpeed() { return rotateSpeed; @@ -449,7 +485,7 @@ public class ParticleEmitter extends Geometry { /** * Set the rotation speed in radians/sec for particles * spawned after the invocation of this method. - * + * * @param rotateSpeed the rotation speed in radians/sec for particles * spawned after the invocation of this method. */ @@ -459,12 +495,12 @@ public class ParticleEmitter extends Geometry { /** * Returns true if every particle spawned - * should have a random facing angle. - * + * should have a random facing angle. + * * @return true if every particle spawned - * should have a random facing angle. - * - * @see ParticleEmitter#setRandomAngle(boolean) + * should have a random facing angle. + * + * @see ParticleEmitter#setRandomAngle(boolean) */ public boolean isRandomAngle() { return randomAngle; @@ -472,8 +508,8 @@ public class ParticleEmitter extends Geometry { /** * Set to true if every particle spawned - * should have a random facing angle. - * + * should have a random facing angle. + * * @param randomAngle if every particle spawned * should have a random facing angle. */ @@ -484,11 +520,11 @@ public class ParticleEmitter extends Geometry { /** * Returns true if every particle spawned should get a random * image. - * + * * @return True if every particle spawned should get a random * image. - * - * @see ParticleEmitter#setSelectRandomImage(boolean) + * + * @see ParticleEmitter#setSelectRandomImage(boolean) */ public boolean isSelectRandomImage() { return selectRandomImage; @@ -498,7 +534,7 @@ public class ParticleEmitter extends Geometry { * Set to true if every particle spawned * should get a random image from a pool of images constructed from * the texture, with X by Y possible images. - * + * *

By default, X and Y are equal * to 1, thus allowing only 1 possible image to be selected, but if the * particle is configured with multiple images by using {@link ParticleEmitter#setImagesX(int) } @@ -506,7 +542,7 @@ public class ParticleEmitter extends Geometry { * can be selected. Setting to false will cause each particle to have an animation * of images displayed, starting at image 1, and going until image X*Y when * the particle reaches its end of life. - * + * * @param selectRandomImage True if every particle spawned should get a random * image. */ @@ -516,10 +552,10 @@ public class ParticleEmitter extends Geometry { /** * Check if particles spawned should face their velocity. - * + * * @return True if particles spawned should face their velocity. - * - * @see ParticleEmitter#setFacingVelocity(boolean) + * + * @see ParticleEmitter#setFacingVelocity(boolean) */ public boolean isFacingVelocity() { return facingVelocity; @@ -528,11 +564,11 @@ public class ParticleEmitter extends Geometry { /** * Set to true if particles spawned should face * their velocity (or direction to which they are moving towards). - * + * *

This is typically used for e.g spark effects. - * + * * @param followVelocity True if particles spawned should face their velocity. - * + * */ public void setFacingVelocity(boolean followVelocity) { this.facingVelocity = followVelocity; @@ -540,10 +576,10 @@ public class ParticleEmitter extends Geometry { /** * Get the end color of the particles spawned. - * + * * @return the end color of the particles spawned. - * - * @see ParticleEmitter#setEndColor(com.jme3.math.ColorRGBA) + * + * @see ParticleEmitter#setEndColor(com.jme3.math.ColorRGBA) */ public ColorRGBA getEndColor() { return endColor; @@ -551,12 +587,12 @@ public class ParticleEmitter extends Geometry { /** * Set the end color of the particles spawned. - * + * *

The * particle color at any time is determined by blending the start color * and end color based on the particle's current time of life relative * to its end of life. - * + * * @param endColor the end color of the particles spawned. */ public void setEndColor(ColorRGBA endColor) { @@ -565,10 +601,10 @@ public class ParticleEmitter extends Geometry { /** * Get the end size of the particles spawned. - * + * * @return the end size of the particles spawned. - * - * @see ParticleEmitter#setEndSize(float) + * + * @see ParticleEmitter#setEndSize(float) */ public float getEndSize() { return endSize; @@ -576,12 +612,12 @@ public class ParticleEmitter extends Geometry { /** * Set the end size of the particles spawned. - * + * *

The * particle size at any time is determined by blending the start size * and end size based on the particle's current time of life relative * to its end of life. - * + * * @param endSize the end size of the particles spawned. */ public void setEndSize(float endSize) { @@ -590,10 +626,10 @@ public class ParticleEmitter extends Geometry { /** * Get the gravity vector. - * + * * @return the gravity vector. - * - * @see ParticleEmitter#setGravity(com.jme3.math.Vector3f) + * + * @see ParticleEmitter#setGravity(com.jme3.math.Vector3f) */ public Vector3f getGravity() { return gravity; @@ -601,7 +637,7 @@ public class ParticleEmitter extends Geometry { /** * This method sets the gravity vector. - * + * * @param gravity the gravity vector */ public void setGravity(Vector3f gravity) { @@ -610,7 +646,7 @@ public class ParticleEmitter extends Geometry { /** * Sets the gravity vector. - * + * * @param x the x component of the gravity vector * @param y the y component of the gravity vector * @param z the z component of the gravity vector @@ -623,10 +659,10 @@ public class ParticleEmitter extends Geometry { /** * Get the high value of life. - * + * * @return the high value of life. - * - * @see ParticleEmitter#setHighLife(float) + * + * @see ParticleEmitter#setHighLife(float) */ public float getHighLife() { return highLife; @@ -634,10 +670,10 @@ public class ParticleEmitter extends Geometry { /** * Set the high value of life. - * + * *

The particle's lifetime/expiration * is determined by randomly selecting a time between low life and high life. - * + * * @param highLife the high value of life. */ public void setHighLife(float highLife) { @@ -646,10 +682,10 @@ public class ParticleEmitter extends Geometry { /** * Get the number of images along the X axis (width). - * + * * @return the number of images along the X axis (width). - * - * @see ParticleEmitter#setImagesX(int) + * + * @see ParticleEmitter#setImagesX(int) */ public int getImagesX() { return imagesX; @@ -657,11 +693,11 @@ public class ParticleEmitter extends Geometry { /** * Set the number of images along the X axis (width). - * + * *

To determine * how multiple particle images are selected and used, see the * {@link ParticleEmitter#setSelectRandomImage(boolean) } method. - * + * * @param imagesX the number of images along the X axis (width). */ public void setImagesX(int imagesX) { @@ -671,10 +707,10 @@ public class ParticleEmitter extends Geometry { /** * Get the number of images along the Y axis (height). - * + * * @return the number of images along the Y axis (height). - * - * @see ParticleEmitter#setImagesY(int) + * + * @see ParticleEmitter#setImagesY(int) */ public int getImagesY() { return imagesY; @@ -682,10 +718,10 @@ public class ParticleEmitter extends Geometry { /** * Set the number of images along the Y axis (height). - * + * *

To determine how multiple particle images are selected and used, see the * {@link ParticleEmitter#setSelectRandomImage(boolean) } method. - * + * * @param imagesY the number of images along the Y axis (height). */ public void setImagesY(int imagesY) { @@ -695,10 +731,10 @@ public class ParticleEmitter extends Geometry { /** * Get the low value of life. - * + * * @return the low value of life. - * - * @see ParticleEmitter#setLowLife(float) + * + * @see ParticleEmitter#setLowLife(float) */ public float getLowLife() { return lowLife; @@ -706,10 +742,10 @@ public class ParticleEmitter extends Geometry { /** * Set the low value of life. - * + * *

The particle's lifetime/expiration * is determined by randomly selecting a time between low life and high life. - * + * * @param lowLife the low value of life. */ public void setLowLife(float lowLife) { @@ -719,11 +755,11 @@ public class ParticleEmitter extends Geometry { /** * Get the number of particles to spawn per * second. - * + * * @return the number of particles to spawn per * second. - * - * @see ParticleEmitter#setParticlesPerSec(float) + * + * @see ParticleEmitter#setParticlesPerSec(float) */ public float getParticlesPerSec() { return particlesPerSec; @@ -732,7 +768,7 @@ public class ParticleEmitter extends Geometry { /** * Set the number of particles to spawn per * second. - * + * * @param particlesPerSec the number of particles to spawn per * second. */ @@ -740,13 +776,13 @@ public class ParticleEmitter extends Geometry { this.particlesPerSec = particlesPerSec; timeDifference = 0; } - + /** * Get the start color of the particles spawned. - * + * * @return the start color of the particles spawned. - * - * @see ParticleEmitter#setStartColor(com.jme3.math.ColorRGBA) + * + * @see ParticleEmitter#setStartColor(com.jme3.math.ColorRGBA) */ public ColorRGBA getStartColor() { return startColor; @@ -754,11 +790,11 @@ public class ParticleEmitter extends Geometry { /** * Set the start color of the particles spawned. - * + * *

The particle color at any time is determined by blending the start color * and end color based on the particle's current time of life relative * to its end of life. - * + * * @param startColor the start color of the particles spawned */ public void setStartColor(ColorRGBA startColor) { @@ -767,10 +803,10 @@ public class ParticleEmitter extends Geometry { /** * Get the start color of the particles spawned. - * + * * @return the start color of the particles spawned. - * - * @see ParticleEmitter#setStartSize(float) + * + * @see ParticleEmitter#setStartSize(float) */ public float getStartSize() { return startSize; @@ -778,11 +814,11 @@ public class ParticleEmitter extends Geometry { /** * Set the start size of the particles spawned. - * + * *

The particle size at any time is determined by blending the start size * and end size based on the particle's current time of life relative * to its end of life. - * + * * @param startSize the start size of the particles spawned. */ public void setStartSize(float startSize) { @@ -805,10 +841,10 @@ public class ParticleEmitter extends Geometry { * gravity. * * @deprecated - * This method is deprecated. + * This method is deprecated. * Use ParticleEmitter.getParticleInfluencer().setInitialVelocity(initialVelocity); instead. * - * @see ParticleEmitter#setVelocityVariation(float) + * @see ParticleEmitter#setVelocityVariation(float) * @see ParticleEmitter#setGravity(float) */ @Deprecated @@ -818,7 +854,7 @@ public class ParticleEmitter extends Geometry { /** * @deprecated - * This method is deprecated. + * This method is deprecated. * Use ParticleEmitter.getParticleInfluencer().getVelocityVariation(); instead. * @return the initial velocity variation factor */ @@ -833,9 +869,9 @@ public class ParticleEmitter extends Geometry { * from 0 to 1, where 0 means particles are to spawn with exactly * the velocity given in {@link ParticleEmitter#setStartVel(com.jme3.math.Vector3f) }, * and 1 means particles are to spawn with a completely random velocity. - * + * * @deprecated - * This method is deprecated. + * This method is deprecated. * Use ParticleEmitter.getParticleInfluencer().setVelocityVariation(variation); instead. */ @Deprecated @@ -923,7 +959,7 @@ public class ParticleEmitter extends Geometry { vars.release(); } - + /** * Instantly kills all active particles, after this method is called, all * particles will be dead and no longer visible. @@ -935,12 +971,12 @@ public class ParticleEmitter extends Geometry { } } } - + /** * Kills the particle at the given index. - * + * * @param index The index of the particle to kill - * @see #getParticles() + * @see #getParticles() */ public void killParticle(int index){ freeParticle(index); @@ -995,7 +1031,7 @@ public class ParticleEmitter extends Geometry { p.imageIndex = (int) (b * imagesX * imagesY); } } - + private void updateParticleState(float tpf) { // Force world transform to update this.getWorldTransform(); @@ -1028,7 +1064,7 @@ public class ParticleEmitter extends Geometry { firstUnUsed++; } } - + // Spawns particles within the tpf timeslot with proper age float interval = 1f / particlesPerSec; float originalTpf = tpf; @@ -1065,10 +1101,10 @@ public class ParticleEmitter extends Geometry { /** * Set to enable or disable the particle emitter - * + * *

When a particle is * disabled, it will be "frozen in time" and not update. - * + * * @param enabled True to enable the particle emitter */ public void setEnabled(boolean enabled) { @@ -1077,10 +1113,10 @@ public class ParticleEmitter extends Geometry { /** * Check if a particle emitter is enabled for update. - * + * * @return True if a particle emitter is enabled for update. - * - * @see ParticleEmitter#setEnabled(boolean) + * + * @see ParticleEmitter#setEnabled(boolean) */ public boolean isEnabled() { return enabled; @@ -1088,7 +1124,7 @@ public class ParticleEmitter extends Geometry { /** * Callback from Control.update(), do not use. - * @param tpf + * @param tpf */ public void updateFromControl(float tpf) { if (enabled) { @@ -1098,9 +1134,9 @@ public class ParticleEmitter extends Geometry { /** * Callback from Control.render(), do not use. - * + * * @param rm - * @param vp + * @param vp */ private void renderFromControl(RenderManager rm, ViewPort vp) { Camera cam = vp.getCamera(); @@ -1236,7 +1272,7 @@ public class ParticleEmitter extends Geometry { gravity.y = ic.readFloat("gravity", 0); } } else { - // since the parentEmitter is not loaded, it must be + // since the parentEmitter is not loaded, it must be // loaded separately control = getControl(ParticleEmitterControl.class); control.parentEmitter = this; diff --git a/jme3-core/src/main/java/com/jme3/effect/influencers/DefaultParticleInfluencer.java b/jme3-core/src/main/java/com/jme3/effect/influencers/DefaultParticleInfluencer.java index b52d8df80..9cd06f0e3 100644 --- a/jme3-core/src/main/java/com/jme3/effect/influencers/DefaultParticleInfluencer.java +++ b/jme3-core/src/main/java/com/jme3/effect/influencers/DefaultParticleInfluencer.java @@ -39,6 +39,8 @@ import com.jme3.export.JmeImporter; import com.jme3.export.OutputCapsule; import com.jme3.math.FastMath; import com.jme3.math.Vector3f; +import com.jme3.util.clone.Cloner; +import com.jme3.util.clone.JmeCloneable; import java.io.IOException; /** @@ -49,7 +51,7 @@ import java.io.IOException; */ public class DefaultParticleInfluencer implements ParticleInfluencer { - //Version #1 : changed startVelocity to initialvelocity for consistency with accessors + //Version #1 : changed startVelocity to initialvelocity for consistency with accessors //and also changed it in serialization public static final int SAVABLE_VERSION = 1; /** Temporary variable used to help with calculations. */ @@ -94,7 +96,7 @@ public class DefaultParticleInfluencer implements ParticleInfluencer { initialVelocity = (Vector3f) ic.readSavable("startVelocity", Vector3f.ZERO.clone()); }else{ initialVelocity = (Vector3f) ic.readSavable("initialVelocity", Vector3f.ZERO.clone()); - } + } velocityVariation = ic.readFloat("variation", 0.2f); } @@ -109,6 +111,35 @@ public class DefaultParticleInfluencer implements ParticleInfluencer { } } + /** + * Called internally by com.jme3.util.clone.Cloner. Do not call directly. + */ + @Override + public Object jmeClone() { + try { + return super.clone(); + } catch (CloneNotSupportedException ex) { + throw new AssertionError(); + } + } + + /** + * Called internally by com.jme3.util.clone.Cloner. Do not call directly. + */ + @Override + public void cloneFields( Cloner cloner, Object original ) { + this.initialVelocity = cloner.clone(initialVelocity); + + // Change in behavior: I'm cloning 'for real' the 'temp' field because + // otherwise it will be shared across all clones. Note: if this is + // ok because of how its used then it might as well be static and let + // everything share it. + // Note 2: transient fields _are_ cloned just like anything else so + // thinking it wouldn't get cloned is also not right. + // -pspeed + this.temp = cloner.clone(temp); + } + @Override public void setInitialVelocity(Vector3f initialVelocity) { this.initialVelocity.set(initialVelocity); diff --git a/jme3-core/src/main/java/com/jme3/effect/influencers/EmptyParticleInfluencer.java b/jme3-core/src/main/java/com/jme3/effect/influencers/EmptyParticleInfluencer.java index ccbc7e5e6..88e938430 100644 --- a/jme3-core/src/main/java/com/jme3/effect/influencers/EmptyParticleInfluencer.java +++ b/jme3-core/src/main/java/com/jme3/effect/influencers/EmptyParticleInfluencer.java @@ -36,6 +36,8 @@ import com.jme3.effect.shapes.EmitterShape; import com.jme3.export.JmeExporter; import com.jme3.export.JmeImporter; import com.jme3.math.Vector3f; +import com.jme3.util.clone.Cloner; +import com.jme3.util.clone.JmeCloneable; import java.io.IOException; /** @@ -83,4 +85,23 @@ public class EmptyParticleInfluencer implements ParticleInfluencer { throw new AssertionError(); } } + + /** + * Called internally by com.jme3.util.clone.Cloner. Do not call directly. + */ + @Override + public Object jmeClone() { + try { + return super.clone(); + } catch (CloneNotSupportedException ex) { + throw new AssertionError(); + } + } + + /** + * Called internally by com.jme3.util.clone.Cloner. Do not call directly. + */ + @Override + public void cloneFields( Cloner cloner, Object original ) { + } } diff --git a/jme3-core/src/main/java/com/jme3/effect/influencers/NewtonianParticleInfluencer.java b/jme3-core/src/main/java/com/jme3/effect/influencers/NewtonianParticleInfluencer.java index b2f81f9a8..b0bc1be25 100644 --- a/jme3-core/src/main/java/com/jme3/effect/influencers/NewtonianParticleInfluencer.java +++ b/jme3-core/src/main/java/com/jme3/effect/influencers/NewtonianParticleInfluencer.java @@ -39,6 +39,8 @@ import com.jme3.export.JmeImporter; import com.jme3.export.OutputCapsule; import com.jme3.math.FastMath; import com.jme3.math.Matrix3f; +import com.jme3.util.clone.Cloner; +import com.jme3.util.clone.JmeCloneable; import java.io.IOException; /** diff --git a/jme3-core/src/main/java/com/jme3/effect/influencers/ParticleInfluencer.java b/jme3-core/src/main/java/com/jme3/effect/influencers/ParticleInfluencer.java index 5e3532bb0..4f322df74 100644 --- a/jme3-core/src/main/java/com/jme3/effect/influencers/ParticleInfluencer.java +++ b/jme3-core/src/main/java/com/jme3/effect/influencers/ParticleInfluencer.java @@ -36,12 +36,13 @@ import com.jme3.effect.ParticleEmitter; import com.jme3.effect.shapes.EmitterShape; import com.jme3.export.Savable; import com.jme3.math.Vector3f; +import com.jme3.util.clone.JmeCloneable; /** * An interface that defines the methods to affect initial velocity of the particles. * @author Marcin Roguski (Kaelthas) */ -public interface ParticleInfluencer extends Savable, Cloneable { +public interface ParticleInfluencer extends Savable, Cloneable, JmeCloneable { /** * This method influences the particle. diff --git a/jme3-core/src/main/java/com/jme3/effect/influencers/RadialParticleInfluencer.java b/jme3-core/src/main/java/com/jme3/effect/influencers/RadialParticleInfluencer.java index 87c5ce507..0cacfe5b0 100644 --- a/jme3-core/src/main/java/com/jme3/effect/influencers/RadialParticleInfluencer.java +++ b/jme3-core/src/main/java/com/jme3/effect/influencers/RadialParticleInfluencer.java @@ -38,6 +38,7 @@ import com.jme3.export.JmeImporter; import com.jme3.export.OutputCapsule; import com.jme3.math.FastMath; import com.jme3.math.Vector3f; +import com.jme3.util.clone.Cloner; import java.io.IOException; /** @@ -81,7 +82,7 @@ public class RadialParticleInfluencer extends DefaultParticleInfluencer { /** * the origin used for computing the radial velocity direction - * @param origin + * @param origin */ public void setOrigin(Vector3f origin) { this.origin = origin; @@ -97,7 +98,7 @@ public class RadialParticleInfluencer extends DefaultParticleInfluencer { /** * the radial velocity - * @param radialVelocity + * @param radialVelocity */ public void setRadialVelocity(float radialVelocity) { this.radialVelocity = radialVelocity; @@ -105,7 +106,7 @@ public class RadialParticleInfluencer extends DefaultParticleInfluencer { /** * nullify y component of particle velocity to make the effect expand only on x and z axis - * @return + * @return */ public boolean isHorizontal() { return horizontal; @@ -113,12 +114,22 @@ public class RadialParticleInfluencer extends DefaultParticleInfluencer { /** * nullify y component of particle velocity to make the effect expand only on x and z axis - * @param horizontal + * @param horizontal */ public void setHorizontal(boolean horizontal) { this.horizontal = horizontal; } + /** + * Called internally by com.jme3.util.clone.Cloner. Do not call directly. + */ + @Override + public void cloneFields( Cloner cloner, Object original ) { + // Change in behavior: the old origin was not cloned -pspeed + this.origin = cloner.clone(origin); + } + + @Override public void write(JmeExporter ex) throws IOException { super.write(ex); diff --git a/jme3-core/src/main/java/com/jme3/effect/shapes/EmitterBoxShape.java b/jme3-core/src/main/java/com/jme3/effect/shapes/EmitterBoxShape.java index 63323db7b..6b29843c9 100644 --- a/jme3-core/src/main/java/com/jme3/effect/shapes/EmitterBoxShape.java +++ b/jme3-core/src/main/java/com/jme3/effect/shapes/EmitterBoxShape.java @@ -37,6 +37,8 @@ import com.jme3.export.JmeImporter; import com.jme3.export.OutputCapsule; import com.jme3.math.FastMath; import com.jme3.math.Vector3f; +import com.jme3.util.clone.Cloner; +import com.jme3.util.clone.JmeCloneable; import java.io.IOException; public class EmitterBoxShape implements EmitterShape { @@ -86,6 +88,27 @@ public class EmitterBoxShape implements EmitterShape { } } + /** + * Called internally by com.jme3.util.clone.Cloner. Do not call directly. + */ + @Override + public Object jmeClone() { + try { + return super.clone(); + } catch (CloneNotSupportedException ex) { + throw new AssertionError(); + } + } + + /** + * Called internally by com.jme3.util.clone.Cloner. Do not call directly. + */ + @Override + public void cloneFields( Cloner cloner, Object original ) { + this.min = cloner.clone(min); + this.len = cloner.clone(len); + } + public Vector3f getMin() { return min; } diff --git a/jme3-core/src/main/java/com/jme3/effect/shapes/EmitterMeshVertexShape.java b/jme3-core/src/main/java/com/jme3/effect/shapes/EmitterMeshVertexShape.java index 0a5ba128a..b996e63cb 100644 --- a/jme3-core/src/main/java/com/jme3/effect/shapes/EmitterMeshVertexShape.java +++ b/jme3-core/src/main/java/com/jme3/effect/shapes/EmitterMeshVertexShape.java @@ -40,6 +40,8 @@ import com.jme3.math.Vector3f; import com.jme3.scene.Mesh; import com.jme3.scene.VertexBuffer.Type; import com.jme3.util.BufferUtils; +import com.jme3.util.clone.Cloner; +import com.jme3.util.clone.JmeCloneable; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; @@ -168,6 +170,27 @@ public class EmitterMeshVertexShape implements EmitterShape { } } + /** + * Called internally by com.jme3.util.clone.Cloner. Do not call directly. + */ + @Override + public Object jmeClone() { + try { + return super.clone(); + } catch (CloneNotSupportedException ex) { + throw new AssertionError(); + } + } + + /** + * Called internally by com.jme3.util.clone.Cloner. Do not call directly. + */ + @Override + public void cloneFields( Cloner cloner, Object original ) { + this.vertices = cloner.clone(vertices); + this.normals = cloner.clone(normals); + } + @Override public void write(JmeExporter ex) throws IOException { OutputCapsule oc = ex.getCapsule(this); @@ -180,7 +203,7 @@ public class EmitterMeshVertexShape implements EmitterShape { public void read(JmeImporter im) throws IOException { InputCapsule ic = im.getCapsule(this); this.vertices = ic.readSavableArrayList("vertices", null); - + List> tmpNormals = ic.readSavableArrayList("normals", null); if (tmpNormals != null){ this.normals = tmpNormals; diff --git a/jme3-core/src/main/java/com/jme3/effect/shapes/EmitterPointShape.java b/jme3-core/src/main/java/com/jme3/effect/shapes/EmitterPointShape.java index 9f7e71107..e33691101 100644 --- a/jme3-core/src/main/java/com/jme3/effect/shapes/EmitterPointShape.java +++ b/jme3-core/src/main/java/com/jme3/effect/shapes/EmitterPointShape.java @@ -35,6 +35,8 @@ import com.jme3.export.JmeExporter; import com.jme3.export.JmeImporter; import com.jme3.export.OutputCapsule; import com.jme3.math.Vector3f; +import com.jme3.util.clone.Cloner; +import com.jme3.util.clone.JmeCloneable; import java.io.IOException; public class EmitterPointShape implements EmitterShape { @@ -59,6 +61,26 @@ public class EmitterPointShape implements EmitterShape { } } + /** + * Called internally by com.jme3.util.clone.Cloner. Do not call directly. + */ + @Override + public Object jmeClone() { + try { + return super.clone(); + } catch (CloneNotSupportedException ex) { + throw new AssertionError(); + } + } + + /** + * Called internally by com.jme3.util.clone.Cloner. Do not call directly. + */ + @Override + public void cloneFields( Cloner cloner, Object original ) { + this.point = cloner.clone(point); + } + @Override public void getRandomPoint(Vector3f store) { store.set(point); diff --git a/jme3-core/src/main/java/com/jme3/effect/shapes/EmitterShape.java b/jme3-core/src/main/java/com/jme3/effect/shapes/EmitterShape.java index bdecd5b5f..f247412d0 100644 --- a/jme3-core/src/main/java/com/jme3/effect/shapes/EmitterShape.java +++ b/jme3-core/src/main/java/com/jme3/effect/shapes/EmitterShape.java @@ -33,12 +33,13 @@ package com.jme3.effect.shapes; import com.jme3.export.Savable; import com.jme3.math.Vector3f; +import com.jme3.util.clone.JmeCloneable; /** * This interface declares methods used by all shapes that represent particle emitters. * @author Kirill */ -public interface EmitterShape extends Savable, Cloneable { +public interface EmitterShape extends Savable, Cloneable, JmeCloneable { /** * This method fills in the initial position of the particle. diff --git a/jme3-core/src/main/java/com/jme3/effect/shapes/EmitterSphereShape.java b/jme3-core/src/main/java/com/jme3/effect/shapes/EmitterSphereShape.java index 770ba6c9d..99d76205d 100644 --- a/jme3-core/src/main/java/com/jme3/effect/shapes/EmitterSphereShape.java +++ b/jme3-core/src/main/java/com/jme3/effect/shapes/EmitterSphereShape.java @@ -37,6 +37,8 @@ import com.jme3.export.JmeImporter; import com.jme3.export.OutputCapsule; import com.jme3.math.FastMath; import com.jme3.math.Vector3f; +import com.jme3.util.clone.Cloner; +import com.jme3.util.clone.JmeCloneable; import java.io.IOException; public class EmitterSphereShape implements EmitterShape { @@ -71,6 +73,26 @@ public class EmitterSphereShape implements EmitterShape { } } + /** + * Called internally by com.jme3.util.clone.Cloner. Do not call directly. + */ + @Override + public Object jmeClone() { + try { + return super.clone(); + } catch (CloneNotSupportedException ex) { + throw new AssertionError(); + } + } + + /** + * Called internally by com.jme3.util.clone.Cloner. Do not call directly. + */ + @Override + public void cloneFields( Cloner cloner, Object original ) { + this.center = cloner.clone(center); + } + @Override public void getRandomPoint(Vector3f store) { do {