* Small javadoc fixes

* Formatting for com.jme3.effect package
 * Formatting for blender importer and networking tests
 * All networking tests ported to new SpiderMonkey
 * Removed all mentions of java.util.Serializable
 * RMI now works under new SpiderMonkey

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7593 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
sha..rd 14 years ago
parent 95cdde7f53
commit 8cbb0f210d
  1. 5
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/MaterialHelper.java
  2. 32
      engine/src/core/com/jme3/animation/AnimChannel.java
  3. 18
      engine/src/core/com/jme3/animation/AnimControl.java
  4. 55
      engine/src/core/com/jme3/animation/Bone.java
  5. 10
      engine/src/core/com/jme3/animation/BoneAnimation.java
  6. 5
      engine/src/core/com/jme3/animation/MeshAnimation.java
  7. 5
      engine/src/core/com/jme3/animation/Pose.java
  8. 5
      engine/src/core/com/jme3/animation/PoseTrack.java
  9. 5
      engine/src/core/com/jme3/animation/Track.java
  10. 119
      engine/src/core/com/jme3/effect/influencers/DefaultParticleInfluencer.java
  11. 71
      engine/src/core/com/jme3/effect/influencers/EmptyParticleInfluencer.java
  12. 247
      engine/src/core/com/jme3/effect/influencers/NewtonianParticleInfluencer.java
  13. 93
      engine/src/core/com/jme3/effect/influencers/ParticleInfluencer.java
  14. 23
      engine/src/core/com/jme3/effect/shapes/EmitterBoxShape.java
  15. 88
      engine/src/core/com/jme3/effect/shapes/EmitterMeshConvexHullShape.java
  16. 152
      engine/src/core/com/jme3/effect/shapes/EmitterMeshFaceShape.java
  17. 230
      engine/src/core/com/jme3/effect/shapes/EmitterMeshVertexShape.java
  18. 20
      engine/src/core/com/jme3/effect/shapes/EmitterPointShape.java
  19. 40
      engine/src/core/com/jme3/effect/shapes/EmitterShape.java
  20. 26
      engine/src/core/com/jme3/effect/shapes/EmitterSphereShape.java
  21. 3
      engine/src/core/com/jme3/math/ColorRGBA.java
  22. 3
      engine/src/core/com/jme3/math/Line.java
  23. 1062
      engine/src/core/com/jme3/math/LineSegment.java
  24. 1
      engine/src/core/com/jme3/math/Ray.java
  25. 4
      engine/src/core/com/jme3/math/Rectangle.java
  26. 4
      engine/src/core/com/jme3/math/Ring.java
  27. 2
      engine/src/core/com/jme3/math/Vector2f.java
  28. 2
      engine/src/core/com/jme3/scene/shape/Box.java
  29. 2
      engine/src/core/com/jme3/scene/shape/PQTorus.java
  30. 153
      engine/src/networking/com/jme3/network/rmi/ObjectStore.java
  31. 4
      engine/src/networking/com/jme3/network/rmi/RemoteMethodCallMessage.java
  32. 5
      engine/src/networking/com/jme3/network/rmi/RemoteMethodReturnMessage.java
  33. 7
      engine/src/networking/com/jme3/network/rmi/RemoteObject.java
  34. 6
      engine/src/networking/com/jme3/network/rmi/RemoteObjectDefMessage.java
  35. 146
      engine/src/terrain/com/jme3/terrain/geomipmap/LRUCache.java
  36. 311
      engine/src/test/jme3test/blender/ManualBlenderTester.java
  37. 661
      engine/src/test/jme3test/blender/config/AbstractConfigDialog.java
  38. 806
      engine/src/test/jme3test/blender/config/ConfigDialog.java
  39. 2
      engine/src/test/jme3test/blender/config/ConfigExecutable.java
  40. 1863
      engine/src/test/jme3test/blender/config/NoiseConstantsGenerator.java
  41. 65
      engine/src/test/jme3test/blender/scene/Pivot.java
  42. 49
      engine/src/test/jme3test/blender/scene/VisibleBone.java
  43. 154
      engine/src/test/jme3test/network/TestChatClient.java
  44. 95
      engine/src/test/jme3test/network/TestChatServer.java
  45. 58
      engine/src/test/jme3test/network/TestHostDiscovery.java
  46. 63
      engine/src/test/jme3test/network/TestLatency.java
  47. 17
      engine/src/test/jme3test/network/TestMessages.java
  48. 30
      engine/src/test/jme3test/network/TestNetworkStress.java
  49. 36
      engine/src/test/jme3test/network/TestRemoteCall.java
  50. 58
      engine/src/test/jme3test/network/TestThroughput.java

@ -260,7 +260,10 @@ public class MaterialHelper extends AbstractBlenderHelper {
Texture texture = textureHelper.getTexture(tex, dataRepository); Texture texture = textureHelper.getTexture(tex, dataRepository);
if (texture != null) { if (texture != null) {
if ((mapto & 0x01) != 0) {// Col if ((mapto & 0x01) != 0) {// Col
result.setBoolean("UseMaterialColors", Boolean.FALSE); if (!shadeless){
result.setBoolean("UseMaterialColors", false);
}
// blending the texture with material color and texture's defined color // blending the texture with material color and texture's defined color
int blendType = ((Number) textureLink.getFieldValue("blendtype")).intValue(); int blendType = ((Number) textureLink.getFieldValue("blendtype")).intValue();
float[] color = new float[]{((Number) textureLink.getFieldValue("r")).floatValue(), ((Number) textureLink.getFieldValue("g")).floatValue(), ((Number) textureLink.getFieldValue("b")).floatValue()}; float[] color = new float[]{((Number) textureLink.getFieldValue("r")).floatValue(), ((Number) textureLink.getFieldValue("g")).floatValue(), ((Number) textureLink.getFieldValue("b")).floatValue()};

@ -48,6 +48,8 @@ import java.util.BitSet;
*/ */
public final class AnimChannel { public final class AnimChannel {
private static final float DEFAULT_BLEND_TIME = 0.15f;
private AnimControl control; private AnimControl control;
// private ArrayList<Integer> affectedBones; // private ArrayList<Integer> affectedBones;
@ -61,7 +63,7 @@ public final class AnimChannel {
private float speedBlendFrom; private float speedBlendFrom;
private LoopMode loopMode, loopModeBlendFrom; private LoopMode loopMode, loopModeBlendFrom;
private float defaultBlendTime = 0.15f;
private float blendAmount = 1f; private float blendAmount = 1f;
private float blendRate = 0; private float blendRate = 0;
@ -95,6 +97,15 @@ public final class AnimChannel {
this.control = control; this.control = control;
} }
/**
* Returns the parent control of this AnimChannel.
* @return the parent control of this AnimChannel.
* @see AnimControl
*/
public AnimControl getControl() {
return control;
}
/** /**
* @return The name of the currently playing animation, or null if * @return The name of the currently playing animation, or null if
* none is assigned. * none is assigned.
@ -180,6 +191,7 @@ public final class AnimChannel {
/** /**
* Set the current animation that is played by this AnimChannel. * Set the current animation that is played by this AnimChannel.
* <p>
* This resets the time to zero, and optionally blends the animation * This resets the time to zero, and optionally blends the animation
* over <code>blendTime</code> seconds with the currently playing animation. * over <code>blendTime</code> seconds with the currently playing animation.
* Notice that this method will reset the control's speed to 1.0. * Notice that this method will reset the control's speed to 1.0.
@ -219,11 +231,15 @@ public final class AnimChannel {
} }
/** /**
* * Set the current animation that is played by this AnimChannel.
* @param name * <p>
* See {@link #setAnim(java.lang.String, float) }.
* The blendTime argument by default is 150 milliseconds.
*
* @param name The name of the animation to play
*/ */
public void setAnim(String name){ public void setAnim(String name){
setAnim(name, defaultBlendTime); setAnim(name, DEFAULT_BLEND_TIME);
} }
/** /**
@ -294,7 +310,6 @@ public final class AnimChannel {
} }
} }
void reset(){ void reset(){
animation = null; animation = null;
blendFrom = null; blendFrom = null;
@ -340,11 +355,4 @@ public final class AnimChannel {
} }
public AnimControl getControl() {
return control;
}
} }

@ -110,13 +110,14 @@ public final class AnimControl extends AbstractControl implements Savable, Clone
} }
/** /**
* Used only for Saving/Loading models (all parameters of the non-default * Serialization only. Do not use.
* constructor are restored from the saved model, but the object must be
* constructed beforehand)
*/ */
public AnimControl() { public AnimControl() {
} }
/**
* Internal use only.
*/
public Control cloneForSpatial(Spatial spatial) { public Control cloneForSpatial(Spatial spatial) {
try { try {
AnimControl clone = (AnimControl) super.clone(); AnimControl clone = (AnimControl) super.clone();
@ -268,6 +269,9 @@ public final class AnimControl extends AbstractControl implements Savable, Clone
} }
} }
/**
* Internal use only.
*/
@Override @Override
public void setSpatial(Spatial spatial) { public void setSpatial(Spatial spatial) {
if (spatial == null && skeletonControl != null){ if (spatial == null && skeletonControl != null){
@ -310,7 +314,10 @@ public final class AnimControl extends AbstractControl implements Savable, Clone
return a.getLength(); return a.getLength();
} }
/**
* Internal use only.
*/
@Override @Override
protected void controlUpdate(float tpf) { protected void controlUpdate(float tpf) {
skeleton.reset(); // reset skeleton to bind pose skeleton.reset(); // reset skeleton to bind pose
@ -322,6 +329,9 @@ public final class AnimControl extends AbstractControl implements Savable, Clone
skeleton.updateWorldVectors(); skeleton.updateWorldVectors();
} }
/**
* Internal use only.
*/
@Override @Override
protected void controlRender(RenderManager rm, ViewPort vp) { protected void controlRender(RenderManager rm, ViewPort vp) {
} }

@ -93,9 +93,8 @@ public final class Bone implements Savable {
private Vector3f worldPos = new Vector3f(); private Vector3f worldPos = new Vector3f();
private Quaternion worldRot = new Quaternion(); private Quaternion worldRot = new Quaternion();
private Vector3f worldScale = new Vector3f(); private Vector3f worldScale = new Vector3f();
//used for getCombinedTransform //used for getCombinedTransform
private Transform tmpTransform=new Transform(); private Transform tmpTransform = new Transform();
/** /**
* Creates a new bone with the given name. * Creates a new bone with the given name.
@ -143,6 +142,8 @@ public final class Bone implements Savable {
} }
/** /**
* Returns the name of the bone, set in the constructor.
*
* @return The name of the bone, set in the constructor. * @return The name of the bone, set in the constructor.
*/ */
public String getName() { public String getName() {
@ -150,6 +151,7 @@ public final class Bone implements Savable {
} }
/** /**
* Returns parent bone of this bone, or null if it is a root bone.
* @return The parent bone of this bone, or null if it is a root bone. * @return The parent bone of this bone, or null if it is a root bone.
*/ */
public Bone getParent() { public Bone getParent() {
@ -157,6 +159,8 @@ public final class Bone implements Savable {
} }
/** /**
* Returns all the children bones of this bone.
*
* @return All the children bones of this bone. * @return All the children bones of this bone.
*/ */
public ArrayList<Bone> getChildren() { public ArrayList<Bone> getChildren() {
@ -164,6 +168,8 @@ public final class Bone implements Savable {
} }
/** /**
* Returns the local position of the bone, relative to the parent bone.
*
* @return The local position of the bone, relative to the parent bone. * @return The local position of the bone, relative to the parent bone.
*/ */
public Vector3f getLocalPosition() { public Vector3f getLocalPosition() {
@ -171,6 +177,8 @@ public final class Bone implements Savable {
} }
/** /**
* Returns the local rotation of the bone, relative to the parent bone.
*
* @return The local rotation of the bone, relative to the parent bone. * @return The local rotation of the bone, relative to the parent bone.
*/ */
public Quaternion getLocalRotation() { public Quaternion getLocalRotation() {
@ -178,6 +186,8 @@ public final class Bone implements Savable {
} }
/** /**
* Returns the local scale of the bone, relative to the parent bone.
*
* @return The local scale of the bone, relative to the parent bone. * @return The local scale of the bone, relative to the parent bone.
*/ */
public Vector3f getLocalScale() { public Vector3f getLocalScale() {
@ -185,6 +195,8 @@ public final class Bone implements Savable {
} }
/** /**
* Returns the position of the bone in model space.
*
* @return The position of the bone in model space. * @return The position of the bone in model space.
*/ */
public Vector3f getModelSpacePosition() { public Vector3f getModelSpacePosition() {
@ -192,6 +204,8 @@ public final class Bone implements Savable {
} }
/** /**
* Returns the rotation of the bone in model space.
*
* @return The rotation of the bone in model space. * @return The rotation of the bone in model space.
*/ */
public Quaternion getModelSpaceRotation() { public Quaternion getModelSpaceRotation() {
@ -199,20 +213,37 @@ public final class Bone implements Savable {
} }
/** /**
* Returns the scale of the bone in model space.
*
* @return The scale of the bone in model space. * @return The scale of the bone in model space.
*/ */
public Vector3f getModelSpaceScale() { public Vector3f getModelSpaceScale() {
return worldScale; return worldScale;
} }
/**
* Returns the inverse world bind pose position.
*
* @return the inverse world bind pose position.
*/
public Vector3f getWorldBindInversePosition() { public Vector3f getWorldBindInversePosition() {
return worldBindInversePos; return worldBindInversePos;
} }
/**
* Returns the inverse world bind pose rotation.
*
* @return the inverse world bind pose rotation.
*/
public Quaternion getWorldBindInverseRotation() { public Quaternion getWorldBindInverseRotation() {
return worldBindInverseRot; return worldBindInverseRot;
} }
/**
* Returns the inverse world bind pose scale.
*
* @return the inverse world bind pose scale.
*/
public Vector3f getWorldBindInverseScale() { public Vector3f getWorldBindInverseScale() {
return worldBindInverseScale; return worldBindInverseScale;
} }
@ -375,18 +406,18 @@ public final class Bone implements Savable {
worldPos.set(translation); worldPos.set(translation);
worldRot.set(rotation); worldRot.set(rotation);
} }
/** /**
* Returns the local transform of this bone combined with the given position and rotation * Returns the local transform of this bone combined with the given position and rotation
* @param position a position * @param position a position
* @param rotation a rotation * @param rotation a rotation
*/ */
public Transform getCombinedTransform(Vector3f position, Quaternion rotation){ public Transform getCombinedTransform(Vector3f position, Quaternion rotation) {
rotation.mult(localPos, tmpTransform.getTranslation()).addLocal(position); rotation.mult(localPos, tmpTransform.getTranslation()).addLocal(position);
tmpTransform.setRotation(rotation).getRotation().multLocal(localRot); tmpTransform.setRotation(rotation).getRotation().multLocal(localRot);
return tmpTransform; return tmpTransform;
} }
/** /**
* Returns the attachment node. * Returns the attachment node.
* Attach models and effects to this node to make * Attach models and effects to this node to make
@ -477,14 +508,6 @@ public final class Bone implements Savable {
} }
} }
void setAnimTransforms(Vector3f translation, Quaternion rotation) {
this.setAnimTransforms(translation, rotation, Vector3f.UNIT_XYZ);
}
public void setBindTransforms(Vector3f translation, Quaternion rotation) {
this.setBindTransforms(translation, rotation, Vector3f.UNIT_XYZ);
}
private String toString(int depth) { private String toString(int depth) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
for (int i = 0; i < depth; i++) { for (int i = 0; i < depth; i++) {

@ -41,18 +41,22 @@ import java.io.IOException;
import java.util.BitSet; import java.util.BitSet;
/** /**
* Bone animation updates each of it's tracks with the skeleton and time * Bone animation updates each of its tracks with the skeleton and time
* to apply the animation. * to apply the animation.
*/ */
public final class BoneAnimation implements Savable { public final class BoneAnimation implements Savable {
private static final long serialVersionUID = 1L;
private String name; private String name;
private float length; private float length;
private BoneTrack[] tracks; private BoneTrack[] tracks;
/**
* Creates a new BoneAnimation with the given name and length.
*
* @param name The name of the bone animation.
* @param length Length in seconds of the bone animation.
*/
public BoneAnimation(String name, float length){ public BoneAnimation(String name, float length){
this.name = name; this.name = name;
this.length = length; this.length = length;

@ -39,11 +39,8 @@ import com.jme3.export.OutputCapsule;
import com.jme3.export.Savable; import com.jme3.export.Savable;
import com.jme3.scene.Mesh; import com.jme3.scene.Mesh;
import java.io.IOException; import java.io.IOException;
import java.io.Serializable;
public class MeshAnimation implements Serializable, Savable { public class MeshAnimation implements Savable {
private static final long serialVersionUID = 1L;
private String name; private String name;
private float length; private float length;

@ -40,15 +40,12 @@ import com.jme3.export.Savable;
import com.jme3.math.Vector3f; import com.jme3.math.Vector3f;
import com.jme3.util.BufferUtils; import com.jme3.util.BufferUtils;
import java.io.IOException; import java.io.IOException;
import java.io.Serializable;
import java.nio.FloatBuffer; import java.nio.FloatBuffer;
/** /**
* A pose is a list of offsets that say where a mesh verticles should be for this pose. * A pose is a list of offsets that say where a mesh verticles should be for this pose.
*/ */
public final class Pose implements Serializable, Savable { public final class Pose implements Savable {
private static final long serialVersionUID = 1L;
private String name; private String name;
private int targetMeshIndex; private int targetMeshIndex;

@ -41,7 +41,6 @@ import com.jme3.scene.Mesh;
import com.jme3.scene.VertexBuffer; import com.jme3.scene.VertexBuffer;
import com.jme3.scene.VertexBuffer.Type; import com.jme3.scene.VertexBuffer.Type;
import java.io.IOException; import java.io.IOException;
import java.io.Serializable;
import java.nio.FloatBuffer; import java.nio.FloatBuffer;
/** /**
@ -49,15 +48,11 @@ import java.nio.FloatBuffer;
*/ */
public final class PoseTrack extends Track { public final class PoseTrack extends Track {
private static final long serialVersionUID = 1L;
private PoseFrame[] frames; private PoseFrame[] frames;
private float[] times; private float[] times;
public static class PoseFrame implements Savable { public static class PoseFrame implements Savable {
private static final long serialVersionUID = 1L;
Pose[] poses; Pose[] poses;
float[] weights; float[] weights;

@ -37,15 +37,12 @@ import com.jme3.export.JmeImporter;
import com.jme3.export.Savable; import com.jme3.export.Savable;
import com.jme3.scene.Mesh; import com.jme3.scene.Mesh;
import java.io.IOException; import java.io.IOException;
import java.io.Serializable;
/** /**
* A single track of mesh animation (either morph or pose based). * A single track of mesh animation (either morph or pose based).
* Currently morph animations are not supported (only pose). * Currently morph animations are not supported (only pose).
*/ */
public abstract class Track implements Serializable, Savable { public abstract class Track implements Savable {
private static final long serialVersionUID = 1L;
protected int targetMeshIndex; protected int targetMeshIndex;

@ -18,72 +18,73 @@ import com.jme3.math.Vector3f;
* @author Marcin Roguski (Kaelthas) * @author Marcin Roguski (Kaelthas)
*/ */
public class DefaultParticleInfluencer implements ParticleInfluencer { public class DefaultParticleInfluencer implements ParticleInfluencer {
/** Temporary variable used to help with calculations. */
protected transient Vector3f temp = new Vector3f();
/** The initial velocity of the particles. */
protected Vector3f startVelocity = new Vector3f();
/** The velocity's variation of the particles. */
protected float velocityVariation = 0.2f;
@Override /** Temporary variable used to help with calculations. */
public void influenceParticle(Particle particle, EmitterShape emitterShape) { protected transient Vector3f temp = new Vector3f();
emitterShape.getRandomPoint(particle.position); /** The initial velocity of the particles. */
this.applyVelocityVariation(particle); protected Vector3f startVelocity = new Vector3f();
} /** The velocity's variation of the particles. */
protected float velocityVariation = 0.2f;
/** @Override
* This method applies the variation to the particle with already set velocity. public void influenceParticle(Particle particle, EmitterShape emitterShape) {
* @param particle emitterShape.getRandomPoint(particle.position);
* the particle to be affected this.applyVelocityVariation(particle);
*/ }
protected void applyVelocityVariation(Particle particle) {
temp.set(FastMath.nextRandomFloat(), FastMath.nextRandomFloat(), FastMath.nextRandomFloat());
temp.multLocal(2f);
temp.subtractLocal(1f, 1f, 1f);
temp.multLocal(startVelocity.length());
particle.velocity.interpolate(temp, velocityVariation);
}
@Override /**
public void write(JmeExporter ex) throws IOException { * This method applies the variation to the particle with already set velocity.
OutputCapsule oc = ex.getCapsule(this); * @param particle
oc.write(startVelocity, "startVelocity", Vector3f.ZERO); * the particle to be affected
oc.write(velocityVariation, "variation", 0.2f); */
} protected void applyVelocityVariation(Particle particle) {
temp.set(FastMath.nextRandomFloat(), FastMath.nextRandomFloat(), FastMath.nextRandomFloat());
temp.multLocal(2f);
temp.subtractLocal(1f, 1f, 1f);
temp.multLocal(startVelocity.length());
particle.velocity.interpolate(temp, velocityVariation);
}
@Override @Override
public void read(JmeImporter im) throws IOException { public void write(JmeExporter ex) throws IOException {
InputCapsule ic = im.getCapsule(this); OutputCapsule oc = ex.getCapsule(this);
startVelocity = (Vector3f) ic.readSavable("startVelocity", Vector3f.ZERO); oc.write(startVelocity, "startVelocity", Vector3f.ZERO);
velocityVariation = ic.readFloat("variation", 0.2f); oc.write(velocityVariation, "variation", 0.2f);
} }
@Override @Override
public ParticleInfluencer clone() { public void read(JmeImporter im) throws IOException {
try { InputCapsule ic = im.getCapsule(this);
return (ParticleInfluencer) super.clone(); startVelocity = (Vector3f) ic.readSavable("startVelocity", Vector3f.ZERO);
} catch (CloneNotSupportedException e) { velocityVariation = ic.readFloat("variation", 0.2f);
return null; }
}
}
@Override @Override
public void setInitialVelocity(Vector3f initialVelocity) { public ParticleInfluencer clone() {
this.startVelocity.set(initialVelocity); try {
} return (ParticleInfluencer) super.clone();
} catch (CloneNotSupportedException e) {
return null;
}
}
@Override @Override
public Vector3f getInitialVelocity() { public void setInitialVelocity(Vector3f initialVelocity) {
return startVelocity; this.startVelocity.set(initialVelocity);
} }
@Override @Override
public void setVelocityVariation(float variation) { public Vector3f getInitialVelocity() {
this.velocityVariation = variation; return startVelocity;
} }
@Override @Override
public float getVelocityVariation() { public void setVelocityVariation(float variation) {
return velocityVariation; this.velocityVariation = variation;
} }
@Override
public float getVelocityVariation() {
return velocityVariation;
}
} }

@ -15,37 +15,42 @@ import com.jme3.math.Vector3f;
*/ */
public class EmptyParticleInfluencer implements ParticleInfluencer { public class EmptyParticleInfluencer implements ParticleInfluencer {
@Override @Override
public void write(JmeExporter ex) throws IOException {} public void write(JmeExporter ex) throws IOException {
}
@Override
public void read(JmeImporter im) throws IOException {} @Override
public void read(JmeImporter im) throws IOException {
@Override }
public void influenceParticle(Particle particle, EmitterShape emitterShape) {}
@Override
@Override public void influenceParticle(Particle particle, EmitterShape emitterShape) {
public void setInitialVelocity(Vector3f initialVelocity) {} }
@Override @Override
public Vector3f getInitialVelocity() { public void setInitialVelocity(Vector3f initialVelocity) {
return null; }
}
@Override
@Override public Vector3f getInitialVelocity() {
public void setVelocityVariation(float variation) {} return null;
}
@Override
public float getVelocityVariation() { @Override
return 0; public void setVelocityVariation(float variation) {
} }
@Override @Override
public ParticleInfluencer clone() { public float getVelocityVariation() {
try { return 0;
return (ParticleInfluencer) super.clone(); }
} catch (CloneNotSupportedException e) {
return new EmptyParticleInfluencer(); @Override
} public ParticleInfluencer clone() {
} try {
return (ParticleInfluencer) super.clone();
} catch (CloneNotSupportedException e) {
return new EmptyParticleInfluencer();
}
}
} }

@ -16,127 +16,128 @@ import com.jme3.math.Matrix3f;
* @author Marcin Roguski (Kaelthas) * @author Marcin Roguski (Kaelthas)
*/ */
public class NewtonianParticleInfluencer extends DefaultParticleInfluencer { public class NewtonianParticleInfluencer extends DefaultParticleInfluencer {
/** Normal to emitter's shape factor. */
protected float normalVelocity; /** Normal to emitter's shape factor. */
/** Emitter's surface tangent factor. */ protected float normalVelocity;
protected float surfaceTangentFactor; /** Emitter's surface tangent factor. */
/** Emitters tangent rotation factor. */ protected float surfaceTangentFactor;
protected float surfaceTangentRotation; /** Emitters tangent rotation factor. */
protected float surfaceTangentRotation;
/**
* Constructor. Sets velocity variation to 0.0f. /**
*/ * Constructor. Sets velocity variation to 0.0f.
public NewtonianParticleInfluencer() { */
this.velocityVariation = 0.0f; public NewtonianParticleInfluencer() {
} this.velocityVariation = 0.0f;
}
@Override
public void influenceParticle(Particle particle, EmitterShape emitterShape) { @Override
emitterShape.getRandomPointAndNormal(particle.position, particle.velocity); public void influenceParticle(Particle particle, EmitterShape emitterShape) {
// influencing the particle's velocity emitterShape.getRandomPointAndNormal(particle.position, particle.velocity);
if (surfaceTangentFactor == 0.0f) { // influencing the particle's velocity
particle.velocity.multLocal(normalVelocity); if (surfaceTangentFactor == 0.0f) {
} else { particle.velocity.multLocal(normalVelocity);
// calculating surface tangent (velocity contains the 'normal' value) } else {
temp.set(particle.velocity.z * surfaceTangentFactor, particle.velocity.y * surfaceTangentFactor, -particle.velocity.x * surfaceTangentFactor); // calculating surface tangent (velocity contains the 'normal' value)
if (surfaceTangentRotation != 0.0f) {// rotating the tangent temp.set(particle.velocity.z * surfaceTangentFactor, particle.velocity.y * surfaceTangentFactor, -particle.velocity.x * surfaceTangentFactor);
Matrix3f m = new Matrix3f(); if (surfaceTangentRotation != 0.0f) {// rotating the tangent
m.fromAngleNormalAxis(FastMath.PI * surfaceTangentRotation, particle.velocity); Matrix3f m = new Matrix3f();
temp = m.multLocal(temp); m.fromAngleNormalAxis(FastMath.PI * surfaceTangentRotation, particle.velocity);
} temp = m.multLocal(temp);
// applying normal factor (this must be done first) }
particle.velocity.multLocal(normalVelocity); // applying normal factor (this must be done first)
// adding tangent vector particle.velocity.multLocal(normalVelocity);
particle.velocity.addLocal(temp); // adding tangent vector
} particle.velocity.addLocal(temp);
if (velocityVariation != 0.0f) { }
this.applyVelocityVariation(particle); if (velocityVariation != 0.0f) {
} this.applyVelocityVariation(particle);
} }
}
/**
* This method returns the normal velocity factor. /**
* @return the normal velocity factor * This method returns the normal velocity factor.
*/ * @return the normal velocity factor
public float getNormalVelocity() { */
return normalVelocity; public float getNormalVelocity() {
} return normalVelocity;
}
/**
* This method sets the normal velocity factor. /**
* @param normalVelocity * This method sets the normal velocity factor.
* the normal velocity factor * @param normalVelocity
*/ * the normal velocity factor
public void setNormalVelocity(float normalVelocity) { */
this.normalVelocity = normalVelocity; public void setNormalVelocity(float normalVelocity) {
} this.normalVelocity = normalVelocity;
}
/**
* This method sets the surface tangent factor. /**
* @param surfaceTangentFactor * This method sets the surface tangent factor.
* the surface tangent factor * @param surfaceTangentFactor
*/ * the surface tangent factor
public void setSurfaceTangentFactor(float surfaceTangentFactor) { */
this.surfaceTangentFactor = surfaceTangentFactor; public void setSurfaceTangentFactor(float surfaceTangentFactor) {
} this.surfaceTangentFactor = surfaceTangentFactor;
}
/**
* This method returns the surface tangent factor. /**
* @return the surface tangent factor * This method returns the surface tangent factor.
*/ * @return the surface tangent factor
public float getSurfaceTangentFactor() { */
return surfaceTangentFactor; public float getSurfaceTangentFactor() {
} return surfaceTangentFactor;
}
/**
* This method sets the surface tangent rotation factor. /**
* @param surfaceTangentRotation * This method sets the surface tangent rotation factor.
* the surface tangent rotation factor * @param surfaceTangentRotation
*/ * the surface tangent rotation factor
public void setSurfaceTangentRotation(float surfaceTangentRotation) { */
this.surfaceTangentRotation = surfaceTangentRotation; public void setSurfaceTangentRotation(float surfaceTangentRotation) {
} this.surfaceTangentRotation = surfaceTangentRotation;
}
/**
* This method returns the surface tangent rotation factor. /**
* @return the surface tangent rotation factor * This method returns the surface tangent rotation factor.
*/ * @return the surface tangent rotation factor
public float getSurfaceTangentRotation() { */
return surfaceTangentRotation; public float getSurfaceTangentRotation() {
} return surfaceTangentRotation;
}
@Override
protected void applyVelocityVariation(Particle particle) { @Override
temp.set(FastMath.nextRandomFloat() * velocityVariation, FastMath.nextRandomFloat() * velocityVariation, FastMath.nextRandomFloat() * velocityVariation); protected void applyVelocityVariation(Particle particle) {
particle.velocity.addLocal(temp); temp.set(FastMath.nextRandomFloat() * velocityVariation, FastMath.nextRandomFloat() * velocityVariation, FastMath.nextRandomFloat() * velocityVariation);
} particle.velocity.addLocal(temp);
}
@Override
public ParticleInfluencer clone() { @Override
NewtonianParticleInfluencer result = new NewtonianParticleInfluencer(); public ParticleInfluencer clone() {
result.normalVelocity = normalVelocity; NewtonianParticleInfluencer result = new NewtonianParticleInfluencer();
result.startVelocity = startVelocity; result.normalVelocity = normalVelocity;
result.velocityVariation = velocityVariation; result.startVelocity = startVelocity;
result.surfaceTangentFactor = surfaceTangentFactor; result.velocityVariation = velocityVariation;
result.surfaceTangentRotation = surfaceTangentRotation; result.surfaceTangentFactor = surfaceTangentFactor;
return result; result.surfaceTangentRotation = surfaceTangentRotation;
} return result;
}
@Override
public void write(JmeExporter ex) throws IOException { @Override
super.write(ex); public void write(JmeExporter ex) throws IOException {
OutputCapsule oc = ex.getCapsule(this); super.write(ex);
oc.write(normalVelocity, "normalVelocity", 0.0f); OutputCapsule oc = ex.getCapsule(this);
oc.write(surfaceTangentFactor, "surfaceTangentFactor", 0.0f); oc.write(normalVelocity, "normalVelocity", 0.0f);
oc.write(surfaceTangentRotation, "surfaceTangentRotation", 0.0f); oc.write(surfaceTangentFactor, "surfaceTangentFactor", 0.0f);
} oc.write(surfaceTangentRotation, "surfaceTangentRotation", 0.0f);
}
@Override
public void read(JmeImporter im) throws IOException { @Override
super.read(im); public void read(JmeImporter im) throws IOException {
InputCapsule ic = im.getCapsule(this); super.read(im);
normalVelocity = ic.readFloat("normalVelocity", 0.0f); InputCapsule ic = im.getCapsule(this);
surfaceTangentFactor = ic.readFloat("surfaceTangentFactor", 0.0f); normalVelocity = ic.readFloat("normalVelocity", 0.0f);
surfaceTangentRotation = ic.readFloat("surfaceTangentRotation", 0.0f); surfaceTangentFactor = ic.readFloat("surfaceTangentFactor", 0.0f);
} surfaceTangentRotation = ic.readFloat("surfaceTangentRotation", 0.0f);
}
} }

@ -11,50 +11,51 @@ import com.jme3.math.Vector3f;
* @author Marcin Roguski (Kaelthas) * @author Marcin Roguski (Kaelthas)
*/ */
public interface ParticleInfluencer extends Savable, Cloneable { public interface ParticleInfluencer extends Savable, Cloneable {
/**
* This method influences the particle. /**
* @param particle * This method influences the particle.
* particle to be influenced * @param particle
* @param emitterShape * particle to be influenced
* the shape of it emitter * @param emitterShape
*/ * the shape of it emitter
void influenceParticle(Particle particle, EmitterShape emitterShape); */
void influenceParticle(Particle particle, EmitterShape emitterShape);
/**
* This method clones the influencer instance. /**
* @return cloned instance * This method clones the influencer instance.
*/ * @return cloned instance
public ParticleInfluencer clone(); */
public ParticleInfluencer clone();
/**
* @param initialVelocity /**
* Set the initial velocity a particle is spawned with, * @param initialVelocity
* the initial velocity given in the parameter will be varied according * Set the initial velocity a particle is spawned with,
* to the velocity variation set in {@link ParticleEmitter#setVelocityVariation(float) }. * the initial velocity given in the parameter will be varied according
* A particle will move toward its velocity unless it is effected by the * to the velocity variation set in {@link ParticleEmitter#setVelocityVariation(float) }.
* gravity. * A particle will move toward its velocity unless it is effected by the
*/ * gravity.
void setInitialVelocity(Vector3f initialVelocity); */
void setInitialVelocity(Vector3f initialVelocity);
/**
* This method returns the initial velocity. /**
* @return the initial velocity * This method returns the initial velocity.
*/ * @return the initial velocity
Vector3f getInitialVelocity(); */
Vector3f getInitialVelocity();
/**
* @param variation /**
* Set the variation by which the initial velocity * @param variation
* of the particle is determined. <code>variation</code> should be a value * Set the variation by which the initial velocity
* from 0 to 1, where 0 means particles are to spawn with exactly * of the particle is determined. <code>variation</code> should be a value
* the velocity given in {@link ParticleEmitter#setStartVel(com.jme3.math.Vector3f) }, * from 0 to 1, where 0 means particles are to spawn with exactly
* and 1 means particles are to spawn with a completely random velocity. * the velocity given in {@link ParticleEmitter#setStartVel(com.jme3.math.Vector3f) },
*/ * and 1 means particles are to spawn with a completely random velocity.
void setVelocityVariation(float variation); */
void setVelocityVariation(float variation);
/**
* This method returns the velocity variation. /**
* @return the velocity variation * This method returns the velocity variation.
*/ * @return the velocity variation
float getVelocityVariation(); */
float getVelocityVariation();
} }

@ -29,7 +29,6 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package com.jme3.effect.shapes; package com.jme3.effect.shapes;
import com.jme3.export.JmeExporter; import com.jme3.export.JmeExporter;
@ -44,26 +43,26 @@ public class EmitterBoxShape implements EmitterShape {
private Vector3f min, len; private Vector3f min, len;
public EmitterBoxShape(){ public EmitterBoxShape() {
} }
public EmitterBoxShape(Vector3f min, Vector3f max) { public EmitterBoxShape(Vector3f min, Vector3f max) {
if (min == null || max == null) { if (min == null || max == null) {
throw new NullPointerException(); throw new NullPointerException();
} }
this.min = min; this.min = min;
this.len = new Vector3f(); this.len = new Vector3f();
this.len.set(max).subtractLocal(min); this.len.set(max).subtractLocal(min);
} }
@Override @Override
public void getRandomPoint(Vector3f store) { public void getRandomPoint(Vector3f store) {
store.x = min.x + len.x * FastMath.nextRandomFloat(); store.x = min.x + len.x * FastMath.nextRandomFloat();
store.y = min.y + len.y * FastMath.nextRandomFloat(); store.y = min.y + len.y * FastMath.nextRandomFloat();
store.z = min.z + len.z * FastMath.nextRandomFloat(); store.z = min.z + len.z * FastMath.nextRandomFloat();
} }
/** /**
* This method fills the point with data. * This method fills the point with data.
* It does not fill the normal. * It does not fill the normal.
@ -72,11 +71,11 @@ public class EmitterBoxShape implements EmitterShape {
*/ */
@Override @Override
public void getRandomPointAndNormal(Vector3f store, Vector3f normal) { public void getRandomPointAndNormal(Vector3f store, Vector3f normal) {
this.getRandomPoint(store); this.getRandomPoint(store);
} }
@Override @Override
public EmitterShape deepClone(){ public EmitterShape deepClone() {
try { try {
EmitterBoxShape clone = (EmitterBoxShape) super.clone(); EmitterBoxShape clone = (EmitterBoxShape) super.clone();
clone.min = min.clone(); clone.min = min.clone();
@ -104,16 +103,16 @@ public class EmitterBoxShape implements EmitterShape {
} }
@Override @Override
public void write(JmeExporter ex) throws IOException { public void write(JmeExporter ex) throws IOException {
OutputCapsule oc = ex.getCapsule(this); OutputCapsule oc = ex.getCapsule(this);
oc.write(min, "min", null); oc.write(min, "min", null);
oc.write(len, "length", null); oc.write(len, "length", null);
} }
@Override @Override
public void read(JmeImporter im) throws IOException { public void read(JmeImporter im) throws IOException {
InputCapsule ic = im.getCapsule(this); InputCapsule ic = im.getCapsule(this);
min = (Vector3f) ic.readSavable("min", null); min = (Vector3f) ic.readSavable("min", null);
len = (Vector3f) ic.readSavable("length", null); len = (Vector3f) ic.readSavable("length", null);
} }
} }

@ -13,50 +13,52 @@ import com.jme3.scene.Mesh;
* @author Marcin Roguski (Kaelthas) * @author Marcin Roguski (Kaelthas)
*/ */
public class EmitterMeshConvexHullShape extends EmitterMeshFaceShape { public class EmitterMeshConvexHullShape extends EmitterMeshFaceShape {
/**
* Empty constructor. Sets nothing.
*/
public EmitterMeshConvexHullShape() {}
/** /**
* Constructor. It stores a copy of vertex list of all meshes. * Empty constructor. Sets nothing.
* @param meshes */
* a list of meshes that will form the emitter's shape public EmitterMeshConvexHullShape() {
*/ }
public EmitterMeshConvexHullShape(List<Mesh> meshes) {
super(meshes);
}
/** /**
* This method fills the point with coordinates of randomly selected point inside a convex hull * Constructor. It stores a copy of vertex list of all meshes.
* of randomly selected mesh. * @param meshes
* @param store * a list of meshes that will form the emitter's shape
* the variable to store with coordinates of randomly selected selected point inside a convex hull */
* of randomly selected mesh public EmitterMeshConvexHullShape(List<Mesh> meshes) {
*/ super(meshes);
@Override }
public void getRandomPoint(Vector3f store) {
super.getRandomPoint(store);
// now move the point from the meshe's face towards the center of the mesh
// the center is in (0, 0, 0) in the local coordinates
store.multLocal(FastMath.nextRandomFloat());
}
/** /**
* This method fills the point with coordinates of randomly selected point inside a convex hull * This method fills the point with coordinates of randomly selected point inside a convex hull
* of randomly selected mesh. * of randomly selected mesh.
* The normal param is not used. * @param store
* @param store * the variable to store with coordinates of randomly selected selected point inside a convex hull
* the variable to store with coordinates of randomly selected selected point inside a convex hull * of randomly selected mesh
* of randomly selected mesh */
* @param normal @Override
* not used in this class public void getRandomPoint(Vector3f store) {
*/ super.getRandomPoint(store);
@Override // now move the point from the meshe's face towards the center of the mesh
public void getRandomPointAndNormal(Vector3f store, Vector3f normal) { // the center is in (0, 0, 0) in the local coordinates
super.getRandomPointAndNormal(store, normal); store.multLocal(FastMath.nextRandomFloat());
// now move the point from the meshe's face towards the center of the mesh }
// the center is in (0, 0, 0) in the local coordinates
store.multLocal(FastMath.nextRandomFloat()); /**
} * This method fills the point with coordinates of randomly selected point inside a convex hull
* of randomly selected mesh.
* The normal param is not used.
* @param store
* the variable to store with coordinates of randomly selected selected point inside a convex hull
* of randomly selected mesh
* @param normal
* not used in this class
*/
@Override
public void getRandomPointAndNormal(Vector3f store, Vector3f normal) {
super.getRandomPointAndNormal(store, normal);
// now move the point from the meshe's face towards the center of the mesh
// the center is in (0, 0, 0) in the local coordinates
store.multLocal(FastMath.nextRandomFloat());
}
} }

@ -14,83 +14,85 @@ import com.jme3.util.BufferUtils;
* @author Marcin Roguski (Kaelthas) * @author Marcin Roguski (Kaelthas)
*/ */
public class EmitterMeshFaceShape extends EmitterMeshVertexShape { public class EmitterMeshFaceShape extends EmitterMeshVertexShape {
/**
* Empty constructor. Sets nothing.
*/
public EmitterMeshFaceShape() {}
/** /**
* Constructor. It stores a copy of vertex list of all meshes. * Empty constructor. Sets nothing.
* @param meshes */
* a list of meshes that will form the emitter's shape public EmitterMeshFaceShape() {
*/ }
public EmitterMeshFaceShape(List<Mesh> meshes) {
super(meshes);
}
@Override /**
public void setMeshes(List<Mesh> meshes) { * Constructor. It stores a copy of vertex list of all meshes.
this.vertices = new ArrayList<List<Vector3f>>(meshes.size()); * @param meshes
this.normals = new ArrayList<List<Vector3f>>(meshes.size()); * a list of meshes that will form the emitter's shape
for (Mesh mesh : meshes) { */
Vector3f[] vertexTable = BufferUtils.getVector3Array(mesh.getFloatBuffer(Type.Position)); public EmitterMeshFaceShape(List<Mesh> meshes) {
int[] indices = new int[3]; super(meshes);
List<Vector3f> vertices = new ArrayList<Vector3f>(mesh.getTriangleCount() * 3); }
List<Vector3f> normals = new ArrayList<Vector3f>(mesh.getTriangleCount());
for (int i = 0; i < mesh.getTriangleCount(); ++i) {
mesh.getTriangle(i, indices);
vertices.add(vertexTable[indices[0]]);
vertices.add(vertexTable[indices[1]]);
vertices.add(vertexTable[indices[2]]);
normals.add(FastMath.computeNormal(vertexTable[indices[0]], vertexTable[indices[1]], vertexTable[indices[2]]));
}
this.vertices.add(vertices);
this.normals.add(normals);
}
}
/** @Override
* This method fills the point with coordinates of randomly selected point on a random face. public void setMeshes(List<Mesh> meshes) {
* @param store this.vertices = new ArrayList<List<Vector3f>>(meshes.size());
* the variable to store with coordinates of randomly selected selected point on a random face this.normals = new ArrayList<List<Vector3f>>(meshes.size());
*/ for (Mesh mesh : meshes) {
@Override Vector3f[] vertexTable = BufferUtils.getVector3Array(mesh.getFloatBuffer(Type.Position));
public void getRandomPoint(Vector3f store) { int[] indices = new int[3];
int meshIndex = FastMath.nextRandomInt(0, vertices.size() - 1); List<Vector3f> vertices = new ArrayList<Vector3f>(mesh.getTriangleCount() * 3);
// the index of the first vertex of a face (must be dividable by 3) List<Vector3f> normals = new ArrayList<Vector3f>(mesh.getTriangleCount());
int vertIndex = FastMath.nextRandomInt(0, vertices.get(meshIndex).size() / 3 - 1) * 3; for (int i = 0; i < mesh.getTriangleCount(); ++i) {
// put the point somewhere between the first and the second vertex of a face mesh.getTriangle(i, indices);
float moveFactor = FastMath.nextRandomFloat(); vertices.add(vertexTable[indices[0]]);
store.set(Vector3f.ZERO); vertices.add(vertexTable[indices[1]]);
store.addLocal(vertices.get(meshIndex).get(vertIndex)); vertices.add(vertexTable[indices[2]]);
store.addLocal((vertices.get(meshIndex).get(vertIndex + 1).x - vertices.get(meshIndex).get(vertIndex).x) * moveFactor, (vertices.get(meshIndex).get(vertIndex + 1).y - vertices.get(meshIndex).get(vertIndex).y) * moveFactor, (vertices.get(meshIndex).get(vertIndex + 1).z - vertices.get(meshIndex).get(vertIndex).z) * moveFactor); normals.add(FastMath.computeNormal(vertexTable[indices[0]], vertexTable[indices[1]], vertexTable[indices[2]]));
// move the result towards the last face vertex }
moveFactor = FastMath.nextRandomFloat(); this.vertices.add(vertices);
store.addLocal((vertices.get(meshIndex).get(vertIndex + 2).x - store.x) * moveFactor, (vertices.get(meshIndex).get(vertIndex + 2).y - store.y) * moveFactor, (vertices.get(meshIndex).get(vertIndex + 2).z - store.z) * moveFactor); this.normals.add(normals);
} }
}
/** /**
* This method fills the point with coordinates of randomly selected point on a random face. * This method fills the point with coordinates of randomly selected point on a random face.
* The normal param is filled with selected face's normal. * @param store
* @param store * the variable to store with coordinates of randomly selected selected point on a random face
* the variable to store with coordinates of randomly selected selected point on a random face */
* @param normal @Override
* filled with selected face's normal public void getRandomPoint(Vector3f store) {
*/ int meshIndex = FastMath.nextRandomInt(0, vertices.size() - 1);
@Override // the index of the first vertex of a face (must be dividable by 3)
public void getRandomPointAndNormal(Vector3f store, Vector3f normal) { int vertIndex = FastMath.nextRandomInt(0, vertices.get(meshIndex).size() / 3 - 1) * 3;
int meshIndex = FastMath.nextRandomInt(0, vertices.size() - 1); // put the point somewhere between the first and the second vertex of a face
// the index of the first vertex of a face (must be dividable by 3) float moveFactor = FastMath.nextRandomFloat();
int faceIndex = FastMath.nextRandomInt(0, vertices.get(meshIndex).size() / 3 - 1); store.set(Vector3f.ZERO);
int vertIndex = faceIndex * 3; store.addLocal(vertices.get(meshIndex).get(vertIndex));
// put the point somewhere between the first and the second vertex of a face store.addLocal((vertices.get(meshIndex).get(vertIndex + 1).x - vertices.get(meshIndex).get(vertIndex).x) * moveFactor, (vertices.get(meshIndex).get(vertIndex + 1).y - vertices.get(meshIndex).get(vertIndex).y) * moveFactor, (vertices.get(meshIndex).get(vertIndex + 1).z - vertices.get(meshIndex).get(vertIndex).z) * moveFactor);
float moveFactor = FastMath.nextRandomFloat(); // move the result towards the last face vertex
store.set(Vector3f.ZERO); moveFactor = FastMath.nextRandomFloat();
store.addLocal(vertices.get(meshIndex).get(vertIndex)); store.addLocal((vertices.get(meshIndex).get(vertIndex + 2).x - store.x) * moveFactor, (vertices.get(meshIndex).get(vertIndex + 2).y - store.y) * moveFactor, (vertices.get(meshIndex).get(vertIndex + 2).z - store.z) * moveFactor);
store.addLocal((vertices.get(meshIndex).get(vertIndex + 1).x - vertices.get(meshIndex).get(vertIndex).x) * moveFactor, (vertices.get(meshIndex).get(vertIndex + 1).y - vertices.get(meshIndex).get(vertIndex).y) * moveFactor, (vertices.get(meshIndex).get(vertIndex + 1).z - vertices.get(meshIndex).get(vertIndex).z) * moveFactor); }
// move the result towards the last face vertex
moveFactor = FastMath.nextRandomFloat(); /**
store.addLocal((vertices.get(meshIndex).get(vertIndex + 2).x - store.x) * moveFactor, (vertices.get(meshIndex).get(vertIndex + 2).y - store.y) * moveFactor, (vertices.get(meshIndex).get(vertIndex + 2).z - store.z) * moveFactor); * This method fills the point with coordinates of randomly selected point on a random face.
normal.set(normals.get(meshIndex).get(faceIndex)); * The normal param is filled with selected face's normal.
} * @param store
* the variable to store with coordinates of randomly selected selected point on a random face
* @param normal
* filled with selected face's normal
*/
@Override
public void getRandomPointAndNormal(Vector3f store, Vector3f normal) {
int meshIndex = FastMath.nextRandomInt(0, vertices.size() - 1);
// the index of the first vertex of a face (must be dividable by 3)
int faceIndex = FastMath.nextRandomInt(0, vertices.get(meshIndex).size() / 3 - 1);
int vertIndex = faceIndex * 3;
// put the point somewhere between the first and the second vertex of a face
float moveFactor = FastMath.nextRandomFloat();
store.set(Vector3f.ZERO);
store.addLocal(vertices.get(meshIndex).get(vertIndex));
store.addLocal((vertices.get(meshIndex).get(vertIndex + 1).x - vertices.get(meshIndex).get(vertIndex).x) * moveFactor, (vertices.get(meshIndex).get(vertIndex + 1).y - vertices.get(meshIndex).get(vertIndex).y) * moveFactor, (vertices.get(meshIndex).get(vertIndex + 1).z - vertices.get(meshIndex).get(vertIndex).z) * moveFactor);
// move the result towards the last face vertex
moveFactor = FastMath.nextRandomFloat();
store.addLocal((vertices.get(meshIndex).get(vertIndex + 2).x - store.x) * moveFactor, (vertices.get(meshIndex).get(vertIndex + 2).y - store.y) * moveFactor, (vertices.get(meshIndex).get(vertIndex + 2).z - store.z) * moveFactor);
normal.set(normals.get(meshIndex).get(faceIndex));
}
} }

@ -21,129 +21,131 @@ import com.jme3.util.BufferUtils;
* @author Marcin Roguski (Kaelthas) * @author Marcin Roguski (Kaelthas)
*/ */
public class EmitterMeshVertexShape implements EmitterShape { public class EmitterMeshVertexShape implements EmitterShape {
protected List<List<Vector3f>> vertices;
protected List<List<Vector3f>> normals;
/** protected List<List<Vector3f>> vertices;
* Empty constructor. Sets nothing. protected List<List<Vector3f>> normals;
*/
public EmitterMeshVertexShape() {}
/** /**
* Constructor. It stores a copy of vertex list of all meshes. * Empty constructor. Sets nothing.
* @param meshes */
* a list of meshes that will form the emitter's shape public EmitterMeshVertexShape() {
*/ }
public EmitterMeshVertexShape(List<Mesh> meshes) {
this.setMeshes(meshes);
}
/** /**
* This method sets the meshes that will form the emiter's shape. * Constructor. It stores a copy of vertex list of all meshes.
* @param meshes * @param meshes
* a list of meshes that will form the emitter's shape * a list of meshes that will form the emitter's shape
*/ */
public void setMeshes(List<Mesh> meshes) { public EmitterMeshVertexShape(List<Mesh> meshes) {
Map<Vector3f, Vector3f> vertToNormalMap = new HashMap<Vector3f, Vector3f>(); this.setMeshes(meshes);
}
this.vertices = new ArrayList<List<Vector3f>>(meshes.size()); /**
this.normals = new ArrayList<List<Vector3f>>(meshes.size()); * This method sets the meshes that will form the emiter's shape.
for (Mesh mesh : meshes) { * @param meshes
// fetching the data * a list of meshes that will form the emitter's shape
float[] vertexTable = BufferUtils.getFloatArray(mesh.getFloatBuffer(Type.Position)); */
float[] normalTable = BufferUtils.getFloatArray(mesh.getFloatBuffer(Type.Normal)); public void setMeshes(List<Mesh> meshes) {
Map<Vector3f, Vector3f> vertToNormalMap = new HashMap<Vector3f, Vector3f>();
// unifying normals this.vertices = new ArrayList<List<Vector3f>>(meshes.size());
for (int i = 0; i < vertexTable.length; i += 3) {// the tables should have the same size and be dividable by 3 this.normals = new ArrayList<List<Vector3f>>(meshes.size());
Vector3f vert = new Vector3f(vertexTable[i], vertexTable[i + 1], vertexTable[i + 2]); for (Mesh mesh : meshes) {
Vector3f norm = vertToNormalMap.get(vert); // fetching the data
if (norm == null) { float[] vertexTable = BufferUtils.getFloatArray(mesh.getFloatBuffer(Type.Position));
norm = new Vector3f(normalTable[i], normalTable[i + 1], normalTable[i + 2]); float[] normalTable = BufferUtils.getFloatArray(mesh.getFloatBuffer(Type.Normal));
vertToNormalMap.put(vert, norm);
} else {
norm.addLocal(normalTable[i], normalTable[i + 1], normalTable[i + 2]);
}
}
// adding data to vertices and normals // unifying normals
List<Vector3f> vertices = new ArrayList<Vector3f>(vertToNormalMap.size()); for (int i = 0; i < vertexTable.length; i += 3) {// the tables should have the same size and be dividable by 3
List<Vector3f> normals = new ArrayList<Vector3f>(vertToNormalMap.size()); Vector3f vert = new Vector3f(vertexTable[i], vertexTable[i + 1], vertexTable[i + 2]);
for (Entry<Vector3f, Vector3f> entry : vertToNormalMap.entrySet()) { Vector3f norm = vertToNormalMap.get(vert);
vertices.add(entry.getKey()); if (norm == null) {
normals.add(entry.getValue().normalizeLocal()); norm = new Vector3f(normalTable[i], normalTable[i + 1], normalTable[i + 2]);
} vertToNormalMap.put(vert, norm);
this.vertices.add(vertices); } else {
this.normals.add(normals); norm.addLocal(normalTable[i], normalTable[i + 1], normalTable[i + 2]);
} }
} }
/** // adding data to vertices and normals
* This method fills the point with coordinates of randomly selected mesh vertex. List<Vector3f> vertices = new ArrayList<Vector3f>(vertToNormalMap.size());
* @param store List<Vector3f> normals = new ArrayList<Vector3f>(vertToNormalMap.size());
* the variable to store with coordinates of randomly selected mesh vertex for (Entry<Vector3f, Vector3f> entry : vertToNormalMap.entrySet()) {
*/ vertices.add(entry.getKey());
@Override normals.add(entry.getValue().normalizeLocal());
public void getRandomPoint(Vector3f store) { }
int meshIndex = FastMath.nextRandomInt(0, vertices.size() - 1); this.vertices.add(vertices);
int vertIndex = FastMath.nextRandomInt(0, vertices.get(meshIndex).size() - 1); this.normals.add(normals);
store.set(vertices.get(meshIndex).get(vertIndex)); }
} }
/** /**
* This method fills the point with coordinates of randomly selected mesh vertex. * This method fills the point with coordinates of randomly selected mesh vertex.
* The normal param is filled with selected vertex's normal. * @param store
* @param store * the variable to store with coordinates of randomly selected mesh vertex
* the variable to store with coordinates of randomly selected mesh vertex */
* @param normal @Override
* filled with selected vertex's normal public void getRandomPoint(Vector3f store) {
*/ int meshIndex = FastMath.nextRandomInt(0, vertices.size() - 1);
@Override int vertIndex = FastMath.nextRandomInt(0, vertices.get(meshIndex).size() - 1);
public void getRandomPointAndNormal(Vector3f store, Vector3f normal) { store.set(vertices.get(meshIndex).get(vertIndex));
int meshIndex = FastMath.nextRandomInt(0, vertices.size() - 1); }
int vertIndex = FastMath.nextRandomInt(0, vertices.get(meshIndex).size() - 1);
store.set(vertices.get(meshIndex).get(vertIndex));
normal.set(normals.get(meshIndex).get(vertIndex));
}
@Override /**
public EmitterShape deepClone() { * This method fills the point with coordinates of randomly selected mesh vertex.
try { * The normal param is filled with selected vertex's normal.
EmitterMeshVertexShape clone = (EmitterMeshVertexShape) super.clone(); * @param store
if (this.vertices != null) { * the variable to store with coordinates of randomly selected mesh vertex
clone.vertices = new ArrayList<List<Vector3f>>(vertices.size()); * @param normal
for (List<Vector3f> list : vertices) { * filled with selected vertex's normal
List<Vector3f> vectorList = new ArrayList<Vector3f>(list.size()); */
for (Vector3f vector : list) { @Override
vectorList.add(vector.clone()); public void getRandomPointAndNormal(Vector3f store, Vector3f normal) {
} int meshIndex = FastMath.nextRandomInt(0, vertices.size() - 1);
clone.vertices.add(vectorList); int vertIndex = FastMath.nextRandomInt(0, vertices.get(meshIndex).size() - 1);
} store.set(vertices.get(meshIndex).get(vertIndex));
} normal.set(normals.get(meshIndex).get(vertIndex));
if (this.normals != null) { }
clone.normals = new ArrayList<List<Vector3f>>(normals.size());
for (List<Vector3f> list : normals) {
List<Vector3f> vectorList = new ArrayList<Vector3f>(list.size());
for (Vector3f vector : list) {
vectorList.add(vector.clone());
}
clone.normals.add(vectorList);
}
}
return clone;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
@Override @Override
public void write(JmeExporter ex) throws IOException { public EmitterShape deepClone() {
OutputCapsule oc = ex.getCapsule(this); try {
oc.writeSavableArrayList((ArrayList<List<Vector3f>>) vertices, "vertices", null); EmitterMeshVertexShape clone = (EmitterMeshVertexShape) super.clone();
} if (this.vertices != null) {
clone.vertices = new ArrayList<List<Vector3f>>(vertices.size());
for (List<Vector3f> list : vertices) {
List<Vector3f> vectorList = new ArrayList<Vector3f>(list.size());
for (Vector3f vector : list) {
vectorList.add(vector.clone());
}
clone.vertices.add(vectorList);
}
}
if (this.normals != null) {
clone.normals = new ArrayList<List<Vector3f>>(normals.size());
for (List<Vector3f> list : normals) {
List<Vector3f> vectorList = new ArrayList<Vector3f>(list.size());
for (Vector3f vector : list) {
vectorList.add(vector.clone());
}
clone.normals.add(vectorList);
}
}
return clone;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
@Override @Override
@SuppressWarnings("unchecked") public void write(JmeExporter ex) throws IOException {
public void read(JmeImporter im) throws IOException { OutputCapsule oc = ex.getCapsule(this);
this.vertices = im.getCapsule(this).readSavableArrayList("vertices", null); oc.writeSavableArrayList((ArrayList<List<Vector3f>>) vertices, "vertices", null);
} }
@Override
@SuppressWarnings("unchecked")
public void read(JmeImporter im) throws IOException {
this.vertices = im.getCapsule(this).readSavableArrayList("vertices", null);
}
} }

@ -29,7 +29,6 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package com.jme3.effect.shapes; package com.jme3.effect.shapes;
import com.jme3.export.JmeExporter; import com.jme3.export.JmeExporter;
@ -42,15 +41,15 @@ public class EmitterPointShape implements EmitterShape {
private Vector3f point; private Vector3f point;
public EmitterPointShape(){ public EmitterPointShape() {
} }
public EmitterPointShape(Vector3f point){ public EmitterPointShape(Vector3f point) {
this.point = point; this.point = point;
} }
@Override @Override
public EmitterShape deepClone(){ public EmitterShape deepClone() {
try { try {
EmitterPointShape clone = (EmitterPointShape) super.clone(); EmitterPointShape clone = (EmitterPointShape) super.clone();
clone.point = point.clone(); clone.point = point.clone();
@ -61,10 +60,10 @@ public class EmitterPointShape implements EmitterShape {
} }
@Override @Override
public void getRandomPoint(Vector3f store) { public void getRandomPoint(Vector3f store) {
store.set(point); store.set(point);
} }
/** /**
* This method fills the point with data. * This method fills the point with data.
* It does not fill the normal. * It does not fill the normal.
@ -73,7 +72,7 @@ public class EmitterPointShape implements EmitterShape {
*/ */
@Override @Override
public void getRandomPointAndNormal(Vector3f store, Vector3f normal) { public void getRandomPointAndNormal(Vector3f store, Vector3f normal) {
store.set(point); store.set(point);
} }
public Vector3f getPoint() { public Vector3f getPoint() {
@ -85,14 +84,13 @@ public class EmitterPointShape implements EmitterShape {
} }
@Override @Override
public void write(JmeExporter ex) throws IOException { public void write(JmeExporter ex) throws IOException {
OutputCapsule oc = ex.getCapsule(this); OutputCapsule oc = ex.getCapsule(this);
oc.write(point, "point", null); oc.write(point, "point", null);
} }
@Override @Override
public void read(JmeImporter im) throws IOException { public void read(JmeImporter im) throws IOException {
this.point = (Vector3f) im.getCapsule(this).readSavable("point", null); this.point = (Vector3f) im.getCapsule(this).readSavable("point", null);
} }
} }

@ -29,7 +29,6 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package com.jme3.effect.shapes; package com.jme3.effect.shapes;
import com.jme3.export.Savable; import com.jme3.export.Savable;
@ -40,25 +39,26 @@ import com.jme3.math.Vector3f;
* @author Kirill * @author Kirill
*/ */
public interface EmitterShape extends Savable, Cloneable { public interface EmitterShape extends Savable, Cloneable {
/**
* This method fills in the initial position of the particle.
* @param store
* store variable for initial position
*/
public void getRandomPoint(Vector3f store);
/** /**
* This method fills in the initial position of the particle and its normal vector. * This method fills in the initial position of the particle.
* @param store * @param store
* store variable for initial position * store variable for initial position
* @param normal */
* store variable for initial normal public void getRandomPoint(Vector3f store);
*/
public void getRandomPointAndNormal(Vector3f store, Vector3f normal); /**
* This method fills in the initial position of the particle and its normal vector.
* @param store
* store variable for initial position
* @param normal
* store variable for initial normal
*/
public void getRandomPointAndNormal(Vector3f store, Vector3f normal);
/** /**
* This method creates a deep clone of the current instance of the emitter shape. * This method creates a deep clone of the current instance of the emitter shape.
* @return deep clone of the current instance of the emitter shape * @return deep clone of the current instance of the emitter shape
*/ */
public EmitterShape deepClone(); public EmitterShape deepClone();
} }

@ -29,7 +29,6 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package com.jme3.effect.shapes; package com.jme3.effect.shapes;
import com.jme3.export.JmeExporter; import com.jme3.export.JmeExporter;
@ -45,24 +44,24 @@ public class EmitterSphereShape implements EmitterShape {
private Vector3f center; private Vector3f center;
private float radius; private float radius;
public EmitterSphereShape(){ public EmitterSphereShape() {
} }
public EmitterSphereShape(Vector3f center, float radius) { public EmitterSphereShape(Vector3f center, float radius) {
if (center == null) { if (center == null) {
throw new NullPointerException(); throw new NullPointerException();
} }
if (radius <= 0) { if (radius <= 0) {
throw new IllegalArgumentException("Radius must be greater than 0"); throw new IllegalArgumentException("Radius must be greater than 0");
} }
this.center = center; this.center = center;
this.radius = radius; this.radius = radius;
} }
@Override @Override
public EmitterShape deepClone(){ public EmitterShape deepClone() {
try { try {
EmitterSphereShape clone = (EmitterSphereShape) super.clone(); EmitterSphereShape clone = (EmitterSphereShape) super.clone();
clone.center = center.clone(); clone.center = center.clone();
@ -73,17 +72,17 @@ public class EmitterSphereShape implements EmitterShape {
} }
@Override @Override
public void getRandomPoint(Vector3f store) { public void getRandomPoint(Vector3f store) {
do { do {
store.x = (FastMath.nextRandomFloat() * 2f - 1f) * radius; store.x = (FastMath.nextRandomFloat() * 2f - 1f) * radius;
store.y = (FastMath.nextRandomFloat() * 2f - 1f) * radius; store.y = (FastMath.nextRandomFloat() * 2f - 1f) * radius;
store.z = (FastMath.nextRandomFloat() * 2f - 1f) * radius; store.z = (FastMath.nextRandomFloat() * 2f - 1f) * radius;
} while (store.distance(center) > radius); } while (store.distance(center) > radius);
} }
@Override @Override
public void getRandomPointAndNormal(Vector3f store, Vector3f normal) { public void getRandomPointAndNormal(Vector3f store, Vector3f normal) {
this.getRandomPoint(store); this.getRandomPoint(store);
} }
public Vector3f getCenter() { public Vector3f getCenter() {
@ -101,19 +100,18 @@ public class EmitterSphereShape implements EmitterShape {
public void setRadius(float radius) { public void setRadius(float radius) {
this.radius = radius; this.radius = radius;
} }
@Override @Override
public void write(JmeExporter ex) throws IOException { public void write(JmeExporter ex) throws IOException {
OutputCapsule oc = ex.getCapsule(this); OutputCapsule oc = ex.getCapsule(this);
oc.write(center, "center", null); oc.write(center, "center", null);
oc.write(radius, "radius", 0); oc.write(radius, "radius", 0);
} }
@Override @Override
public void read(JmeImporter im) throws IOException { public void read(JmeImporter im) throws IOException {
InputCapsule ic = im.getCapsule(this); InputCapsule ic = im.getCapsule(this);
center = (Vector3f) ic.readSavable("center", null); center = (Vector3f) ic.readSavable("center", null);
radius = ic.readFloat("radius", 0); radius = ic.readFloat("radius", 0);
} }
} }

@ -55,8 +55,7 @@ import java.io.IOException;
* @version $Id: ColorRGBA.java,v 1.29 2007/09/09 18:25:14 irrisor Exp $ * @version $Id: ColorRGBA.java,v 1.29 2007/09/09 18:25:14 irrisor Exp $
*/ */
public final class ColorRGBA implements Savable, Cloneable { public final class ColorRGBA implements Savable, Cloneable {
private static final long serialVersionUID = 1L;
/** /**
* the color black (0,0,0). * the color black (0,0,0).
*/ */

@ -40,7 +40,6 @@ import com.jme3.export.Savable;
import com.jme3.util.BufferUtils; import com.jme3.util.BufferUtils;
import com.jme3.util.TempVars; import com.jme3.util.TempVars;
import java.io.IOException; import java.io.IOException;
import java.io.Serializable;
import java.nio.FloatBuffer; import java.nio.FloatBuffer;
/** /**
@ -51,8 +50,6 @@ import java.nio.FloatBuffer;
* @author Joshua Slack * @author Joshua Slack
*/ */
public class Line implements Savable, Cloneable { public class Line implements Savable, Cloneable {
//todo: merge with Ray?
private static final long serialVersionUID = 1L;
private Vector3f origin; private Vector3f origin;
private Vector3f direction; private Vector3f direction;

File diff suppressed because it is too large Load Diff

@ -57,7 +57,6 @@ import java.io.IOException;
public final class Ray implements Savable, Cloneable, Collidable { public final class Ray implements Savable, Cloneable, Collidable {
//todo: merge with Line? //todo: merge with Line?
private static final long serialVersionUID = 1L;
/** The ray's begining point. */ /** The ray's begining point. */
public Vector3f origin; public Vector3f origin;

@ -38,7 +38,6 @@ import com.jme3.export.JmeImporter;
import com.jme3.export.OutputCapsule; import com.jme3.export.OutputCapsule;
import com.jme3.export.Savable; import com.jme3.export.Savable;
import java.io.IOException; import java.io.IOException;
import java.io.Serializable;
/** /**
@ -51,8 +50,7 @@ import java.io.Serializable;
* @author Joshua Slack * @author Joshua Slack
*/ */
public final class Rectangle implements Serializable, Savable, Cloneable { public final class Rectangle implements Savable, Cloneable {
private static final long serialVersionUID = 1L;
private Vector3f a, b, c; private Vector3f a, b, c;

@ -38,7 +38,6 @@ import com.jme3.export.JmeImporter;
import com.jme3.export.OutputCapsule; import com.jme3.export.OutputCapsule;
import com.jme3.export.Savable; import com.jme3.export.Savable;
import java.io.IOException; import java.io.IOException;
import java.io.Serializable;
/** /**
@ -50,8 +49,7 @@ import java.io.Serializable;
* @author Joshua Slack * @author Joshua Slack
*/ */
public final class Ring implements Serializable, Savable, Cloneable { public final class Ring implements Savable, Cloneable {
private static final long serialVersionUID = 1L;
private Vector3f center, up; private Vector3f center, up;
private float innerRadius, outerRadius; private float innerRadius, outerRadius;

@ -52,8 +52,6 @@ import java.util.logging.Logger;
public final class Vector2f implements Savable, Cloneable { public final class Vector2f implements Savable, Cloneable {
private static final Logger logger = Logger.getLogger(Vector2f.class.getName()); private static final Logger logger = Logger.getLogger(Vector2f.class.getName());
private static final long serialVersionUID = 1L;
public static final Vector2f ZERO = new Vector2f(0f, 0f); public static final Vector2f ZERO = new Vector2f(0f, 0f);
public static final Vector2f UNIT_XY = new Vector2f(1f, 1f); public static final Vector2f UNIT_XY = new Vector2f(1f, 1f);

@ -73,8 +73,6 @@ public class Box extends AbstractBox {
1, 0, 0, 0, 0, 1, 1, 1 // bottom 1, 0, 0, 0, 0, 1, 1, 1 // bottom
}; };
private static final long serialVersionUID = 1L;
/** /**
* Creates a new box. * Creates a new box.
* <p> * <p>

@ -56,8 +56,6 @@ import java.nio.ShortBuffer;
*/ */
public class PQTorus extends Mesh { public class PQTorus extends Mesh {
private static final long serialVersionUID = 1L;
private float p, q; private float p, q;
private float radius, width; private float radius, width;

@ -32,12 +32,14 @@
package com.jme3.network.rmi; package com.jme3.network.rmi;
import com.jme3.network.Client;
import com.jme3.network.connection.Client; import com.jme3.network.ClientStateListener;
import com.jme3.network.connection.Server; import com.jme3.network.ClientStateListener.DisconnectInfo;
import com.jme3.network.events.ConnectionListener; import com.jme3.network.ConnectionListener;
import com.jme3.network.events.MessageListener; import com.jme3.network.HostedConnection;
import com.jme3.network.message.Message; import com.jme3.network.Message;
import com.jme3.network.MessageListener;
import com.jme3.network.Server;
import com.jme3.network.serializing.Serializer; import com.jme3.network.serializing.Serializer;
import com.jme3.util.IntMap; import com.jme3.util.IntMap;
import com.jme3.util.IntMap.Entry; import com.jme3.util.IntMap.Entry;
@ -45,11 +47,12 @@ import java.io.IOException;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Proxy; import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
public class ObjectStore implements MessageListener, ConnectionListener { public class ObjectStore {
private static final Logger logger = Logger.getLogger(ObjectStore.class.getName()); private static final Logger logger = Logger.getLogger(ObjectStore.class.getName());
@ -66,6 +69,9 @@ public class ObjectStore implements MessageListener, ConnectionListener {
private Client client; private Client client;
private Server server; private Server server;
private ClientEventHandler clientEventHandler = new ClientEventHandler();
private ServerEventHandler serverEventHandler = new ServerEventHandler();
// Local object ID counter // Local object ID counter
private volatile short objectIdCounter = 0; private volatile short objectIdCounter = 0;
@ -85,6 +91,38 @@ public class ObjectStore implements MessageListener, ConnectionListener {
private final Object receiveObjectLock = new Object(); private final Object receiveObjectLock = new Object();
public class ServerEventHandler implements MessageListener<HostedConnection>,
ConnectionListener {
public void messageReceived(HostedConnection source, Message m) {
onMessage(source, m);
}
public void connectionAdded(Server server, HostedConnection conn) {
onConnection(conn);
}
public void connectionRemoved(Server server, HostedConnection conn) {
}
}
public class ClientEventHandler implements MessageListener,
ClientStateListener {
public void messageReceived(Object source, Message m) {
onMessage(null, m);
}
public void clientConnected(Client c) {
onConnection(null);
}
public void clientDisconnected(Client c, DisconnectInfo info) {
}
}
static { static {
Serializer s = new RmiSerializer(); Serializer s = new RmiSerializer();
Serializer.registerClass(RemoteObjectDefMessage.class, s); Serializer.registerClass(RemoteObjectDefMessage.class, s);
@ -92,20 +130,22 @@ public class ObjectStore implements MessageListener, ConnectionListener {
Serializer.registerClass(RemoteMethodReturnMessage.class, s); Serializer.registerClass(RemoteMethodReturnMessage.class, s);
} }
public ObjectStore(Client client){ public ObjectStore(Client client) {
this.client = client; this.client = client;
client.addMessageListener(this, RemoteObjectDefMessage.class, client.addMessageListener(clientEventHandler,
RemoteMethodCallMessage.class, RemoteObjectDefMessage.class,
RemoteMethodReturnMessage.class); RemoteMethodCallMessage.class,
client.addConnectionListener(this); RemoteMethodReturnMessage.class);
client.addClientStateListener(clientEventHandler);
} }
public ObjectStore(Server server){ public ObjectStore(Server server) {
this.server = server; this.server = server;
server.addMessageListener(this, RemoteObjectDefMessage.class, server.addMessageListener(serverEventHandler,
RemoteMethodCallMessage.class, RemoteObjectDefMessage.class,
RemoteMethodReturnMessage.class); RemoteMethodCallMessage.class,
server.addConnectionListener(this); RemoteMethodReturnMessage.class);
server.addConnectionListener(serverEventHandler);
} }
private ObjectDef makeObjectDef(LocalObject localObj){ private ObjectDef makeObjectDef(LocalObject localObj){
@ -122,7 +162,15 @@ public class ObjectStore implements MessageListener, ConnectionListener {
localObj.objectName = name; localObj.objectName = name;
localObj.objectId = objectIdCounter++; localObj.objectId = objectIdCounter++;
localObj.theObject = obj; localObj.theObject = obj;
localObj.methods = obj.getClass().getMethods(); //localObj.methods = obj.getClass().getMethods();
ArrayList<Method> methodList = new ArrayList<Method>();
for (Method method : obj.getClass().getMethods()){
if (method.getDeclaringClass() == obj.getClass()){
methodList.add(method);
}
}
localObj.methods = methodList.toArray(new Method[methodList.size()]);
// Put it in the store // Put it in the store
localObjects.put(localObj.objectId, localObj); localObjects.put(localObj.objectId, localObj);
@ -180,18 +228,14 @@ public class ObjectStore implements MessageListener, ConnectionListener {
pendingInvocations.put(call.invocationId, invoke); pendingInvocations.put(call.invocationId, invoke);
} }
try{ if (server != null){
if (server != null){ remoteObj.client.send(call);
remoteObj.client.send(call); logger.log(Level.INFO, "Server: Sending {0}", call);
logger.log(Level.INFO, "Server: Sending {0}", call); }else{
}else{ client.send(call);
client.send(call); logger.log(Level.INFO, "Client: Sending {0}", call);
logger.log(Level.INFO, "Client: Sending {0}", call);
}
} catch (IOException ex){
ex.printStackTrace();
} }
if (invoke != null){ if (invoke != null){
synchronized(invoke){ synchronized(invoke){
while (!invoke.available){ while (!invoke.available){
@ -210,7 +254,7 @@ public class ObjectStore implements MessageListener, ConnectionListener {
} }
} }
public void messageReceived(Message message) { private void onMessage(HostedConnection source, Message message) {
// Might want to do more strict validation of the data // Might want to do more strict validation of the data
// in the message to prevent crashes // in the message to prevent crashes
@ -219,7 +263,7 @@ public class ObjectStore implements MessageListener, ConnectionListener {
ObjectDef[] defs = defMsg.objects; ObjectDef[] defs = defMsg.objects;
for (ObjectDef def : defs){ for (ObjectDef def : defs){
RemoteObject remoteObject = new RemoteObject(this, message.getClient()); RemoteObject remoteObject = new RemoteObject(this, source);
remoteObject.objectId = (short)def.objectId; remoteObject.objectId = (short)def.objectId;
remoteObject.methodDefs = def.methodDefs; remoteObject.methodDefs = def.methodDefs;
remoteObjects.put(def.objectName, remoteObject); remoteObjects.put(def.objectName, remoteObject);
@ -257,16 +301,12 @@ public class ObjectStore implements MessageListener, ConnectionListener {
RemoteMethodReturnMessage retMsg = new RemoteMethodReturnMessage(); RemoteMethodReturnMessage retMsg = new RemoteMethodReturnMessage();
retMsg.invocationID = call.invocationId; retMsg.invocationID = call.invocationId;
retMsg.retVal = ret; retMsg.retVal = ret;
try { if (server != null){
if (server != null){ source.send(retMsg);
call.getClient().send(retMsg); logger.log(Level.INFO, "Server: Sending {0}", retMsg);
logger.log(Level.INFO, "Server: Sending {0}", retMsg); } else{
} else{ client.send(retMsg);
client.send(retMsg); logger.log(Level.INFO, "Client: Sending {0}", retMsg);
logger.log(Level.INFO, "Client: Sending {0}", retMsg);
}
} catch (IOException ex){
ex.printStackTrace();
} }
} }
}else if (message instanceof RemoteMethodReturnMessage){ }else if (message instanceof RemoteMethodReturnMessage){
@ -285,7 +325,7 @@ public class ObjectStore implements MessageListener, ConnectionListener {
} }
} }
public void clientConnected(Client client) { private void onConnection(HostedConnection conn) {
if (localObjects.size() > 0){ if (localObjects.size() > 0){
// send a object definition message // send a object definition message
ObjectDef[] defs = new ObjectDef[localObjects.size()]; ObjectDef[] defs = new ObjectDef[localObjects.size()];
@ -297,31 +337,14 @@ public class ObjectStore implements MessageListener, ConnectionListener {
RemoteObjectDefMessage defMsg = new RemoteObjectDefMessage(); RemoteObjectDefMessage defMsg = new RemoteObjectDefMessage();
defMsg.objects = defs; defMsg.objects = defs;
try { if (this.client != null){
if (this.client != null){ this.client.send(defMsg);
this.client.send(defMsg); logger.log(Level.INFO, "Client: Sending {0}", defMsg);
logger.log(Level.INFO, "Client: Sending {0}", defMsg); } else{
} else{ conn.send(defMsg);
client.send(defMsg); logger.log(Level.INFO, "Server: Sending {0}", defMsg);
logger.log(Level.INFO, "Server: Sending {0}", defMsg);
}
} catch (IOException ex){
ex.printStackTrace();
} }
} }
} }
public void clientDisconnected(Client client) {
}
public void messageSent(Message message) {
}
public void objectReceived(Object object) {
}
public void objectSent(Object object) {
}
} }

@ -32,7 +32,7 @@
package com.jme3.network.rmi; package com.jme3.network.rmi;
import com.jme3.network.message.Message; import com.jme3.network.AbstractMessage;
import com.jme3.network.serializing.Serializable; import com.jme3.network.serializing.Serializable;
/** /**
@ -41,7 +41,7 @@ import com.jme3.network.serializing.Serializable;
* @author Kirill Vainer * @author Kirill Vainer
*/ */
@Serializable @Serializable
public class RemoteMethodCallMessage extends Message { public class RemoteMethodCallMessage extends AbstractMessage {
public RemoteMethodCallMessage(){ public RemoteMethodCallMessage(){
super(true); super(true);

@ -32,8 +32,7 @@
package com.jme3.network.rmi; package com.jme3.network.rmi;
import com.jme3.network.AbstractMessage;
import com.jme3.network.message.Message;
import com.jme3.network.serializing.Serializable; import com.jme3.network.serializing.Serializable;
/** /**
@ -43,7 +42,7 @@ import com.jme3.network.serializing.Serializable;
* @author Kirill Vainer. * @author Kirill Vainer.
*/ */
@Serializable @Serializable
public class RemoteMethodReturnMessage extends Message { public class RemoteMethodReturnMessage extends AbstractMessage {
public RemoteMethodReturnMessage(){ public RemoteMethodReturnMessage(){
super(true); super(true);

@ -32,8 +32,7 @@
package com.jme3.network.rmi; package com.jme3.network.rmi;
import com.jme3.network.HostedConnection;
import com.jme3.network.connection.Client;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
@ -72,9 +71,9 @@ public class RemoteObject implements InvocationHandler {
* The client who exposed the RMI interface, or null if the server * The client who exposed the RMI interface, or null if the server
* exposed it. * exposed it.
*/ */
Client client; HostedConnection client;
public RemoteObject(ObjectStore store, Client client){ public RemoteObject(ObjectStore store, HostedConnection client){
this.store = store; this.store = store;
this.client = client; this.client = client;
} }

@ -32,9 +32,7 @@
package com.jme3.network.rmi; package com.jme3.network.rmi;
import com.jme3.network.AbstractMessage;
import com.jme3.network.message.Message;
import com.jme3.network.serializing.Serializable; import com.jme3.network.serializing.Serializable;
/** /**
@ -42,7 +40,7 @@ import com.jme3.network.serializing.Serializable;
* @author Kirill Vainer * @author Kirill Vainer
*/ */
@Serializable @Serializable
public class RemoteObjectDefMessage extends Message { public class RemoteObjectDefMessage extends AbstractMessage {
public ObjectDef[] objects; public ObjectDef[] objects;

@ -17,7 +17,6 @@ package com.jme3.terrain.geomipmap;
// //
// Please contact the author if you need another license. // Please contact the author if you need another license.
// This module is provided "as is", without warranties of any kind. // This module is provided "as is", without warranties of any kind.
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
@ -40,85 +39,84 @@ import java.util.Map;
*/ */
public class LRUCache<K, V> { public class LRUCache<K, V> {
private static final float hashTableLoadFactor = 0.75f; private static final float hashTableLoadFactor = 0.75f;
private LinkedHashMap<K, V> map;
private LinkedHashMap<K, V> map; private int cacheSize;
private int cacheSize;
/** /**
* Creates a new LRU cache. * Creates a new LRU cache.
* *
* @param cacheSize * @param cacheSize
* the maximum number of entries that will be kept in this cache. * the maximum number of entries that will be kept in this cache.
*/ */
public LRUCache(int cacheSize) { public LRUCache(int cacheSize) {
this.cacheSize = cacheSize; this.cacheSize = cacheSize;
int hashTableCapacity = (int) Math.ceil(cacheSize / LRUCache.hashTableLoadFactor) + 1; int hashTableCapacity = (int) Math.ceil(cacheSize / LRUCache.hashTableLoadFactor) + 1;
this.map = new LinkedHashMap<K, V>(hashTableCapacity, LRUCache.hashTableLoadFactor, true) { this.map = new LinkedHashMap<K, V>(hashTableCapacity, LRUCache.hashTableLoadFactor, true) {
// (an anonymous inner class) // (an anonymous inner class)
private static final long serialVersionUID = 1;
@Override private static final long serialVersionUID = 1;
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
return this.size() > LRUCache.this.cacheSize;
}
};
}
/** @Override
* Retrieves an entry from the cache.<br> protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
* The retrieved entry becomes the MRU (most recently used) entry. return this.size() > LRUCache.this.cacheSize;
* }
* @param key };
* the key whose associated value is to be returned. }
* @return the value associated to this key, or null if no value with this
* key exists in the cache.
*/
public synchronized V get(K key) {
return this.map.get(key);
}
/** /**
* Adds an entry to this cache. * Retrieves an entry from the cache.<br>
* The new entry becomes the MRU (most recently used) entry. * The retrieved entry becomes the MRU (most recently used) entry.
* If an entry with the specified key already exists in the cache, it is *
* replaced by the new entry. * @param key
* If the cache is full, the LRU (least recently used) entry is removed from * the key whose associated value is to be returned.
* the cache. * @return the value associated to this key, or null if no value with this
* * key exists in the cache.
* @param key */
* the key with which the specified value is to be associated. public synchronized V get(K key) {
* @param value return this.map.get(key);
* a value to be associated with the specified key. }
*/
public synchronized void put(K key, V value) {
this.map.put(key, value);
}
/** /**
* Clears the cache. * Adds an entry to this cache.
*/ * The new entry becomes the MRU (most recently used) entry.
public synchronized void clear() { * If an entry with the specified key already exists in the cache, it is
this.map.clear(); * replaced by the new entry.
} * If the cache is full, the LRU (least recently used) entry is removed from
* the cache.
*
* @param key
* the key with which the specified value is to be associated.
* @param value
* a value to be associated with the specified key.
*/
public synchronized void put(K key, V value) {
this.map.put(key, value);
}
/** /**
* Returns the number of used entries in the cache. * Clears the cache.
* */
* @return the number of entries currently in the cache. public synchronized void clear() {
*/ this.map.clear();
public synchronized int usedEntries() { }
return this.map.size();
}
/** /**
* Returns a <code>Collection</code> that contains a copy of all cache * Returns the number of used entries in the cache.
* entries. *
* * @return the number of entries currently in the cache.
* @return a <code>Collection</code> with a copy of the cache content. */
*/ public synchronized int usedEntries() {
public synchronized Collection<Map.Entry<K, V>> getAll() { return this.map.size();
return new ArrayList<Map.Entry<K, V>>(this.map.entrySet()); }
}
/**
* Returns a <code>Collection</code> that contains a copy of all cache
* entries.
*
* @return a <code>Collection</code> with a copy of the cache content.
*/
public synchronized Collection<Map.Entry<K, V>> getAll() {
return new ArrayList<Map.Entry<K, V>>(this.map.entrySet());
}
} // end class LRUCache } // end class LRUCache

@ -41,7 +41,7 @@ import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import jme3test.blender.config.ConfigDialog; import jme3test.blender.config.ConfigDialog;
import jme3test.blender.config.IConfigExecutable; import jme3test.blender.config.ConfigExecutable;
import jme3test.blender.scene.Pivot; import jme3test.blender.scene.Pivot;
import com.jme3.animation.AnimControl; import com.jme3.animation.AnimControl;
@ -67,157 +67,160 @@ import com.jme3.texture.plugins.AWTLoader;
* @author Marcin Roguski (Kaelthas) * @author Marcin Roguski (Kaelthas)
*/ */
public class ManualBlenderTester extends SimpleApplication { public class ManualBlenderTester extends SimpleApplication {
private static final Logger LOGGER = Logger.getLogger(ManualBlenderTester.class.getName());
private ModelKey modelKey;//the key that holds the test file configuration private static final Logger LOGGER = Logger.getLogger(ManualBlenderTester.class.getName());
private final boolean debug; private ModelKey modelKey;//the key that holds the test file configuration
private final boolean debug;
/**
* Starting method /**
* @param args input parameters; the following options can be passed to the application: * Starting method
* <li> -debug : this one indicates if the application runs in debug or not (it is used under linux * @param args input parameters; the following options can be passed to the application:
* in order to enable the mouse in debug mode since linuxes tend not to give the cursor back * <li> -debug : this one indicates if the application runs in debug or not (it is used under linux
* to eclipse) * in order to enable the mouse in debug mode since linuxes tend not to give the cursor back
*/ * to eclipse)
public static void main(String[] args) { */
//veryfying if the application is in debug mode public static void main(String[] args) {
boolean debug = false; //veryfying if the application is in debug mode
for(String arg : args) { boolean debug = false;
if("-debug".equalsIgnoreCase(arg)) { for (String arg : args) {
debug = true; if ("-debug".equalsIgnoreCase(arg)) {
break; debug = true;
} break;
} }
final boolean debugMode = debug; }
//running the application final boolean debugMode = debug;
new ConfigDialog("./src/test-data/Blender", new IConfigExecutable() { //running the application
@Override new ConfigDialog("./src/test-data/Blender", new ConfigExecutable() {
public void execute(ModelKey modelKey, Level logLevel) {
new ManualBlenderTester(modelKey, logLevel, debugMode).start(); @Override
} public void execute(ModelKey modelKey, Level logLevel) {
}); new ManualBlenderTester(modelKey, logLevel, debugMode).start();
} }
});
/** }
* Constructor stores the given key and disables the settings screen.
* @param modelKey the key to be stored /**
* @param logLevel the jme logger log level * Constructor stores the given key and disables the settings screen.
* @param debug variable that indicates if the application runs in debug mode * @param modelKey the key to be stored
* (this is required on linux to show release the mouse to be used in debug mode) * @param logLevel the jme logger log level
*/ * @param debug variable that indicates if the application runs in debug mode
public ManualBlenderTester(ModelKey modelKey, Level logLevel, boolean debug) { * (this is required on linux to show release the mouse to be used in debug mode)
this.debug = debug; */
Logger.getLogger("com.jme3").setLevel(logLevel); public ManualBlenderTester(ModelKey modelKey, Level logLevel, boolean debug) {
this.modelKey = modelKey; this.debug = debug;
this.showSettings = false; Logger.getLogger("com.jme3").setLevel(logLevel);
} this.modelKey = modelKey;
this.showSettings = false;
@Override }
public void simpleInitApp() {
if(debug) { @Override
mouseInput.setCursorVisible(true); public void simpleInitApp() {
} if (debug) {
assetManager.registerLocator(".", FileLocator.class); mouseInput.setCursorVisible(true);
assetManager.registerLoader(BlenderLoader.class, "blend"); }
assetManager.registerLoader(AWTLoader.class, "png"); assetManager.registerLocator(".", FileLocator.class);
assetManager.registerLoader(BlenderLoader.class, "blend");
viewPort.setBackgroundColor(ColorRGBA.Gray); assetManager.registerLoader(AWTLoader.class, "png");
flyCam.setMoveSpeed(20); viewPort.setBackgroundColor(ColorRGBA.Gray);
cam.setFrustumFar(1000.0f);
cam.setFrustumNear(1.0f); flyCam.setMoveSpeed(20);
AssetInfo ai = new AssetInfo(assetManager, modelKey) { cam.setFrustumFar(1000.0f);
@Override cam.setFrustumNear(1.0f);
public InputStream openStream() { AssetInfo ai = new AssetInfo(assetManager, modelKey) {
try {
return new FileInputStream(this.key.getName()); @Override
} catch(FileNotFoundException e) { public InputStream openStream() {
LOGGER.log(Level.SEVERE, e.getMessage(), e); try {
return null; return new FileInputStream(this.key.getName());
} } catch (FileNotFoundException e) {
} LOGGER.log(Level.SEVERE, e.getMessage(), e);
}; return null;
rootNode.attachChild(new Pivot(assetManager)); }
if(modelKey instanceof BlenderKey) { }
Node blenderModel = this.testBlenderLoader(ai); };
Map<String, Map<String, int[]>> animations = ((BlenderKey) modelKey).getAnimations(); rootNode.attachChild(new Pivot(assetManager));
//setting the first animation as active if (modelKey instanceof BlenderKey) {
if(((BlenderKey) modelKey).getAnimations()!=null) { Node blenderModel = this.testBlenderLoader(ai);
for(Entry<String, Map<String, int[]>> animEntry : animations.entrySet()) { Map<String, Map<String, int[]>> animations = ((BlenderKey) modelKey).getAnimations();
for(Entry<String, int[]> anim : animEntry.getValue().entrySet()) { //setting the first animation as active
Spatial animatedSpatial = this.findNode(blenderModel, animEntry.getKey()); if (((BlenderKey) modelKey).getAnimations() != null) {
animatedSpatial.getControl(AnimControl.class).createChannel().setAnim(anim.getKey()); for (Entry<String, Map<String, int[]>> animEntry : animations.entrySet()) {
break; for (Entry<String, int[]> anim : animEntry.getValue().entrySet()) {
} Spatial animatedSpatial = this.findNode(blenderModel, animEntry.getKey());
break; animatedSpatial.getControl(AnimControl.class).createChannel().setAnim(anim.getKey());
} break;
} }
} else { break;
this.testBlenderModelLoader(ai); }
} }
} else {
DirectionalLight sun = new DirectionalLight(); this.testBlenderModelLoader(ai);
sun.setDirection(new Vector3f(0, -10, 0).normalizeLocal()); }
sun.setColor(ColorRGBA.White);
rootNode.addLight(sun); DirectionalLight sun = new DirectionalLight();
} sun.setDirection(new Vector3f(0, -10, 0).normalizeLocal());
sun.setColor(ColorRGBA.White);
/** rootNode.addLight(sun);
* This method finds a node of a given name. }
* @param rootNode the root node to search
* @param name the name of the searched node /**
* @return the found node or null * This method finds a node of a given name.
*/ * @param rootNode the root node to search
private Spatial findNode(Node rootNode, String name) { * @param name the name of the searched node
if(name.equals(rootNode.getName())) { * @return the found node or null
return rootNode; */
} private Spatial findNode(Node rootNode, String name) {
return rootNode.getChild(name); if (name.equals(rootNode.getName())) {
} return rootNode;
}
/** return rootNode.getChild(name);
* This method loads the model using blenderLoader. }
* @param assetInfo
* the asset info /**
* @return the loaded model * This method loads the model using blenderLoader.
*/ * @param assetInfo
private Node testBlenderLoader(AssetInfo assetInfo) { * the asset info
Node blenderModel = null; * @return the loaded model
BlenderLoader blenderLoader = new BlenderLoader(); */
try { private Node testBlenderLoader(AssetInfo assetInfo) {
LoadingResults loadingResults = blenderLoader.load(assetInfo); Node blenderModel = null;
for(Node object : loadingResults.getObjects()) { BlenderLoader blenderLoader = new BlenderLoader();
this.rootNode.attachChild(object); try {
blenderModel = object; LoadingResults loadingResults = blenderLoader.load(assetInfo);
} for (Node object : loadingResults.getObjects()) {
for(Light light : loadingResults.getLights()) { this.rootNode.attachChild(object);
this.rootNode.addLight(light); blenderModel = object;
} }
for(Camera camera : loadingResults.getCameras()) { for (Light light : loadingResults.getLights()) {
LOGGER.info(camera.toString()); this.rootNode.addLight(light);
} }
} catch(IOException e) { for (Camera camera : loadingResults.getCameras()) {
LOGGER.log(Level.SEVERE, e.getMessage(), e); LOGGER.info(camera.toString());
} }
return blenderModel; } catch (IOException e) {
} LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
/** return blenderModel;
* This method loads the model using blenderModelLoader. }
* @param assetInfo
* the asset info /**
* @return the loaded model * This method loads the model using blenderModelLoader.
*/ * @param assetInfo
private Node testBlenderModelLoader(AssetInfo assetInfo) { * the asset info
BlenderModelLoader blenderLoader = new BlenderModelLoader(); * @return the loaded model
try { */
Spatial loadingResults = blenderLoader.load(assetInfo); private Node testBlenderModelLoader(AssetInfo assetInfo) {
this.rootNode.attachChild(loadingResults); BlenderModelLoader blenderLoader = new BlenderModelLoader();
if(loadingResults instanceof Node) { try {
return (Node)loadingResults; Spatial loadingResults = blenderLoader.load(assetInfo);
} this.rootNode.attachChild(loadingResults);
} catch(IOException e) { if (loadingResults instanceof Node) {
LOGGER.log(Level.SEVERE, e.getMessage(), e); return (Node) loadingResults;
} }
return null; } catch (IOException e) {
} LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
return null;
}
} }

@ -45,332 +45,337 @@ import javax.swing.table.TableCellEditor;
* @author Marcin Roguski (Kaelthas) * @author Marcin Roguski (Kaelthas)
*/ */
public abstract class AbstractConfigDialog extends JFrame { public abstract class AbstractConfigDialog extends JFrame {
private static final long serialVersionUID = -3677493125861310310L;
private static final Logger LOGGER = Logger.getLogger(AbstractConfigDialog.class.getName()); private static final long serialVersionUID = -3677493125861310310L;
private static final Logger LOGGER = Logger.getLogger(AbstractConfigDialog.class.getName());
protected JComboBox jComboBoxVersionSelection; protected JComboBox jComboBoxVersionSelection;
protected JList jListBlenderFiles; protected JList jListBlenderFiles;
protected JTable jTableProperties; protected JTable jTableProperties;
protected JTable jTableAnimations; protected JTable jTableAnimations;
protected JButton jButtonAddAnimation; protected JButton jButtonAddAnimation;
protected JButton jButtonRemoveAnimation; protected JButton jButtonRemoveAnimation;
protected JCheckBox jCheckBoxUseModelKey; protected JCheckBox jCheckBoxUseModelKey;
protected JButton jButtonOK; protected JButton jButtonOK;
protected JButton jButtonCancel; protected JButton jButtonCancel;
/** /**
* Cionstructor initializes the gui. * Cionstructor initializes the gui.
*/ */
public AbstractConfigDialog() { public AbstractConfigDialog() {
this.init(); this.init();
} }
/** /**
* This method initializes the window. * This method initializes the window.
*/ */
private void init() { private void init() {
try {//setting the system Look And Feel try {//setting the system Look And Feel
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e); LOGGER.log(Level.SEVERE, e.getMessage(), e);
} catch (InstantiationException e) { } catch (InstantiationException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e); LOGGER.log(Level.SEVERE, e.getMessage(), e);
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e); LOGGER.log(Level.SEVERE, e.getMessage(), e);
} catch (UnsupportedLookAndFeelException e) { } catch (UnsupportedLookAndFeelException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e); LOGGER.log(Level.SEVERE, e.getMessage(), e);
} }
this.setLayout(new BorderLayout()); this.setLayout(new BorderLayout());
this.add(this.prepareBlenderFilesAndLogLevelPanel(), BorderLayout.WEST); this.add(this.prepareBlenderFilesAndLogLevelPanel(), BorderLayout.WEST);
this.add(this.prepareFilePropertiesPanel(), BorderLayout.CENTER); this.add(this.prepareFilePropertiesPanel(), BorderLayout.CENTER);
this.add(this.prepareButtonsPanel(), BorderLayout.SOUTH); this.add(this.prepareButtonsPanel(), BorderLayout.SOUTH);
this.pack(); this.pack();
this.setLocationRelativeTo(null); this.setLocationRelativeTo(null);
this.setVisible(true); this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
} }
/** /**
* This method prepares a swing panel containing the list of blender files * This method prepares a swing panel containing the list of blender files
* and log level chooser. * and log level chooser.
* @return prepared swing panel * @return prepared swing panel
*/ */
private JPanel prepareBlenderFilesAndLogLevelPanel() { private JPanel prepareBlenderFilesAndLogLevelPanel() {
JPanel jPanelBlenderFilesListAndLogLevel = new JPanel(); JPanel jPanelBlenderFilesListAndLogLevel = new JPanel();
jPanelBlenderFilesListAndLogLevel.setBorder(new TitledBorder("Blender test files")); jPanelBlenderFilesListAndLogLevel.setBorder(new TitledBorder("Blender test files"));
jPanelBlenderFilesListAndLogLevel.setLayout(new BorderLayout()); jPanelBlenderFilesListAndLogLevel.setLayout(new BorderLayout());
//blender version selection combo box //blender version selection combo box
jComboBoxVersionSelection = new JComboBox(new DefaultComboBoxModel()); jComboBoxVersionSelection = new JComboBox(new DefaultComboBoxModel());
jComboBoxVersionSelection.setEditable(false); jComboBoxVersionSelection.setEditable(false);
jPanelBlenderFilesListAndLogLevel.add(jComboBoxVersionSelection, BorderLayout.NORTH); jPanelBlenderFilesListAndLogLevel.add(jComboBoxVersionSelection, BorderLayout.NORTH);
//blender list files //blender list files
jListBlenderFiles = new JList(new DefaultListModel()); jListBlenderFiles = new JList(new DefaultListModel());
jListBlenderFiles.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); jListBlenderFiles.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
JScrollPane listScroller = new JScrollPane(jListBlenderFiles); JScrollPane listScroller = new JScrollPane(jListBlenderFiles);
jPanelBlenderFilesListAndLogLevel.add(listScroller, BorderLayout.CENTER); jPanelBlenderFilesListAndLogLevel.add(listScroller, BorderLayout.CENTER);
//Log Level list //Log Level list
Box box = Box.createVerticalBox(); Box box = Box.createVerticalBox();
box.add(new Label("Log level:")); box.add(new Label("Log level:"));
ButtonGroup buttonGroup = new ButtonGroup(); ButtonGroup buttonGroup = new ButtonGroup();
Level[] levels = new Level[] {Level.OFF, Level.SEVERE, Level.WARNING, Level.INFO, Level[] levels = new Level[]{Level.OFF, Level.SEVERE, Level.WARNING, Level.INFO,
Level.CONFIG, Level.FINE, Level.FINER, Level.FINEST, Level.ALL}; Level.CONFIG, Level.FINE, Level.FINER, Level.FINEST, Level.ALL};
for(Level level : levels) { for (Level level : levels) {
JRadioButtonLevel jRadioButtonLevel = new JRadioButtonLevel(level); JRadioButtonLevel jRadioButtonLevel = new JRadioButtonLevel(level);
buttonGroup.add(jRadioButtonLevel); buttonGroup.add(jRadioButtonLevel);
box.add(jRadioButtonLevel); box.add(jRadioButtonLevel);
} }
jPanelBlenderFilesListAndLogLevel.add(box, BorderLayout.SOUTH); jPanelBlenderFilesListAndLogLevel.add(box, BorderLayout.SOUTH);
return jPanelBlenderFilesListAndLogLevel; return jPanelBlenderFilesListAndLogLevel;
} }
/** /**
* This method prepares a swing panel containing the file's animations. * This method prepares a swing panel containing the file's animations.
* @return prepared swing panel * @return prepared swing panel
*/ */
protected JPanel prepareFilePropertiesPanel() { protected JPanel prepareFilePropertiesPanel() {
//properties table //properties table
JPanel jPanelProperties = new JPanel(); JPanel jPanelProperties = new JPanel();
jPanelProperties.setBorder(new EmptyBorder(new Insets(0, 5, 0, 5))); jPanelProperties.setBorder(new EmptyBorder(new Insets(0, 5, 0, 5)));
jPanelProperties.setLayout(new BorderLayout()); jPanelProperties.setLayout(new BorderLayout());
jPanelProperties.add(new JLabel("Properties"), BorderLayout.NORTH); jPanelProperties.add(new JLabel("Properties"), BorderLayout.NORTH);
jTableProperties = new JTable(); jTableProperties = new JTable();
jTableProperties.setSelectionMode(DefaultListSelectionModel.SINGLE_SELECTION); jTableProperties.setSelectionMode(DefaultListSelectionModel.SINGLE_SELECTION);
jTableProperties.setModel(new BlenderTableModel(new Object[] {"Name", "Value"})); jTableProperties.setModel(new BlenderTableModel(new Object[]{"Name", "Value"}));
jTableProperties.getColumnModel().getColumn(1).setCellEditor(new BlenderTableCellEditor()); jTableProperties.getColumnModel().getColumn(1).setCellEditor(new BlenderTableCellEditor());
JScrollPane jScrollPaneProperties = new JScrollPane(jTableProperties); JScrollPane jScrollPaneProperties = new JScrollPane(jTableProperties);
jTableProperties.setFillsViewportHeight(true); jTableProperties.setFillsViewportHeight(true);
jPanelProperties.add(jScrollPaneProperties, BorderLayout.CENTER); jPanelProperties.add(jScrollPaneProperties, BorderLayout.CENTER);
//animations table //animations table
JPanel jPanelAnimations = new JPanel(); JPanel jPanelAnimations = new JPanel();
jPanelAnimations.setBorder(new EmptyBorder(new Insets(0, 5, 0, 5))); jPanelAnimations.setBorder(new EmptyBorder(new Insets(0, 5, 0, 5)));
jPanelAnimations.setLayout(new BorderLayout()); jPanelAnimations.setLayout(new BorderLayout());
jPanelAnimations.add(new JLabel("Animations"), BorderLayout.NORTH); jPanelAnimations.add(new JLabel("Animations"), BorderLayout.NORTH);
jTableAnimations = new JTable(); jTableAnimations = new JTable();
jTableAnimations.setSelectionMode(DefaultListSelectionModel.SINGLE_SELECTION); jTableAnimations.setSelectionMode(DefaultListSelectionModel.SINGLE_SELECTION);
jTableAnimations.setModel(new DefaultTableModel(new Object[] {"Object", "Name", "Start frame", "Stop frame"}, 0)); jTableAnimations.setModel(new DefaultTableModel(new Object[]{"Object", "Name", "Start frame", "Stop frame"}, 0));
for(int i=0;i<jTableAnimations.getColumnModel().getColumnCount();++i) { for (int i = 0; i < jTableAnimations.getColumnModel().getColumnCount(); ++i) {
jTableAnimations.getColumnModel().getColumn(i).setCellEditor(new BlenderTableCellEditor()); jTableAnimations.getColumnModel().getColumn(i).setCellEditor(new BlenderTableCellEditor());
} }
JScrollPane jScrollPaneAnimations = new JScrollPane(jTableAnimations); JScrollPane jScrollPaneAnimations = new JScrollPane(jTableAnimations);
jTableAnimations.setFillsViewportHeight(true); jTableAnimations.setFillsViewportHeight(true);
JPanel jPanelTableButtons = new JPanel(); JPanel jPanelTableButtons = new JPanel();
jPanelTableButtons.setLayout(new FlowLayout(FlowLayout.LEFT)); jPanelTableButtons.setLayout(new FlowLayout(FlowLayout.LEFT));
jButtonAddAnimation = new JButton("Add animation"); jButtonAddAnimation = new JButton("Add animation");
jButtonAddAnimation.setEnabled(false); jButtonAddAnimation.setEnabled(false);
jButtonRemoveAnimation = new JButton("Remove animation"); jButtonRemoveAnimation = new JButton("Remove animation");
jButtonRemoveAnimation.setEnabled(false); jButtonRemoveAnimation.setEnabled(false);
jPanelTableButtons.add(jButtonAddAnimation); jPanelTableButtons.add(jButtonAddAnimation);
jPanelTableButtons.add(jButtonRemoveAnimation); jPanelTableButtons.add(jButtonRemoveAnimation);
jPanelAnimations.add(jScrollPaneAnimations, BorderLayout.CENTER); jPanelAnimations.add(jScrollPaneAnimations, BorderLayout.CENTER);
jPanelAnimations.add(jPanelTableButtons, BorderLayout.SOUTH); jPanelAnimations.add(jPanelTableButtons, BorderLayout.SOUTH);
//model key check-box //model key check-box
jCheckBoxUseModelKey = new JCheckBox(); jCheckBoxUseModelKey = new JCheckBox();
jCheckBoxUseModelKey.setText("Use ModelKey to start the test"); jCheckBoxUseModelKey.setText("Use ModelKey to start the test");
jCheckBoxUseModelKey.setToolTipText("All BlenderKey settings will remain here, but the application will be " + jCheckBoxUseModelKey.setToolTipText("All BlenderKey settings will remain here, but the application will be "
"started using a model key. So only the path to the file will be given!"); + "started using a model key. So only the path to the file will be given!");
//building the result panel //building the result panel
JPanel jPanelResult = new JPanel(); JPanel jPanelResult = new JPanel();
jPanelResult.setBorder(new TitledBorder("Loading properties")); jPanelResult.setBorder(new TitledBorder("Loading properties"));
jPanelResult.setLayout(new BorderLayout()); jPanelResult.setLayout(new BorderLayout());
jPanelResult.add(jPanelProperties, BorderLayout.WEST); jPanelResult.add(jPanelProperties, BorderLayout.WEST);
jPanelResult.add(jPanelAnimations, BorderLayout.CENTER); jPanelResult.add(jPanelAnimations, BorderLayout.CENTER);
jPanelResult.add(jCheckBoxUseModelKey, BorderLayout.SOUTH); jPanelResult.add(jCheckBoxUseModelKey, BorderLayout.SOUTH);
return jPanelResult; return jPanelResult;
} }
/** /**
* This method prepares a swing panel containing the buttons. * This method prepares a swing panel containing the buttons.
* @return prepared swing panel * @return prepared swing panel
*/ */
protected JPanel prepareButtonsPanel() { protected JPanel prepareButtonsPanel() {
JPanel jPanelButtons = new JPanel(); JPanel jPanelButtons = new JPanel();
jButtonOK = new JButton("OK"); jButtonOK = new JButton("OK");
jButtonOK.setEnabled(false); jButtonOK.setEnabled(false);
jPanelButtons.add(jButtonOK); jPanelButtons.add(jButtonOK);
jButtonCancel = new JButton("Cancel"); jButtonCancel = new JButton("Cancel");
jPanelButtons.add(jButtonCancel); jPanelButtons.add(jButtonCancel);
return jPanelButtons; return jPanelButtons;
} }
/** /**
* This class was made only to make the selection of a level radio button easier. * This class was made only to make the selection of a level radio button easier.
* @author Marcin Roguski * @author Marcin Roguski
*/ */
protected static class JRadioButtonLevel extends JRadioButton { protected static class JRadioButtonLevel extends JRadioButton {
private static final long serialVersionUID = 8874525909060993518L;
private static Level selectedLevel; private static final long serialVersionUID = 8874525909060993518L;
private static Map<Level, JRadioButtonLevel> radioButtons = new HashMap<Level, AbstractConfigDialog.JRadioButtonLevel>(); private static Level selectedLevel;
private Level level; private static Map<Level, JRadioButtonLevel> radioButtons = new HashMap<Level, AbstractConfigDialog.JRadioButtonLevel>();
private Level level;
/**
* Constructor. Creates the radio button. /**
* Stores it inside the buttons map. * Constructor. Creates the radio button.
* @param level the level of log info * Stores it inside the buttons map.
*/ * @param level the level of log info
public JRadioButtonLevel(Level level) { */
super(level.getName()); public JRadioButtonLevel(Level level) {
this.level = level; super(level.getName());
radioButtons.put(level, this); this.level = level;
this.addActionListener(new ActionListener() { radioButtons.put(level, this);
@Override this.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JRadioButtonLevel.selectedLevel = JRadioButtonLevel.this.level; @Override
} public void actionPerformed(ActionEvent e) {
}); JRadioButtonLevel.selectedLevel = JRadioButtonLevel.this.level;
} }
});
/** }
* This method returns the currently selected info level.
* @return currently selected info level /**
*/ * This method returns the currently selected info level.
public static Level getSelectedLevel() { * @return currently selected info level
return selectedLevel; */
} public static Level getSelectedLevel() {
return selectedLevel;
/** }
* This method sets the current info level.
* @param level the current info level /**
*/ * This method sets the current info level.
public static synchronized void setSelectedLevel(Level level) { * @param level the current info level
radioButtons.get(level).setSelected(true); */
} public static synchronized void setSelectedLevel(Level level) {
} radioButtons.get(level).setSelected(true);
}
/** }
* This class is an item that should be stored in the files' list.
* @author Marcin Roguski (Kaelthas) /**
*/ * This class is an item that should be stored in the files' list.
protected static class FileListItem { * @author Marcin Roguski (Kaelthas)
private File file; //the file to be stored */
/** protected static class FileListItem {
* Constructore. Stores the given file.
* @param file the file to be stored private File file; //the file to be stored
*/
public FileListItem(File file) { /**
this.file = file; * Constructore. Stores the given file.
} * @param file the file to be stored
*/
/** public FileListItem(File file) {
* This method returns the stored file. this.file = file;
* @return the stored file }
*/
public File getFile() { /**
return file; * This method returns the stored file.
} * @return the stored file
*/
@Override public File getFile() {
public String toString() { return file;
return file.getName(); }
}
} @Override
public String toString() {
/** return file.getName();
* The model for properties table. }
* It makes left column ineditable. }
* @author Marcin Roguski (Kaelthas)
*/ /**
protected static class BlenderTableModel extends DefaultTableModel { * The model for properties table.
private static final long serialVersionUID = -4211206550875326553L; * It makes left column ineditable.
* @author Marcin Roguski (Kaelthas)
/** */
* Constructor only calls super-constuctor. protected static class BlenderTableModel extends DefaultTableModel {
* @param columnNames the names of table columns
*/ private static final long serialVersionUID = -4211206550875326553L;
public BlenderTableModel(Object[] columnNames) {
super(columnNames, 0); /**
} * Constructor only calls super-constuctor.
* @param columnNames the names of table columns
@Override */
public void addRow(Object[] rowData) { public BlenderTableModel(Object[] columnNames) {
for(int i=0;i<rowData.length;++i) { super(columnNames, 0);
if(rowData[i]==null) { }
rowData[i] = "";
} @Override
} public void addRow(Object[] rowData) {
super.addRow(rowData); for (int i = 0; i < rowData.length; ++i) {
} if (rowData[i] == null) {
rowData[i] = "";
@Override }
public boolean isCellEditable(int row, int column) { }
return column>0; super.addRow(rowData);
} }
}
@Override
/** public boolean isCellEditable(int row, int column) {
* A cell editor tah improves data input to the table. return column > 0;
* @author Marcin Roguski (Kaelthas) }
*/ }
protected static class BlenderTableCellEditor extends AbstractCellEditor implements TableCellEditor {
private static final long serialVersionUID = -8601975203921608519L; /**
private JCheckBox jCheckBox = new JCheckBox(); * A cell editor tah improves data input to the table.
private JTextField jTextField = new JTextField(); * @author Marcin Roguski (Kaelthas)
private JComboBox jComboBox = new JComboBox(); */
private Object lastValue; protected static class BlenderTableCellEditor extends AbstractCellEditor implements TableCellEditor {
@Override private static final long serialVersionUID = -8601975203921608519L;
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { private JCheckBox jCheckBox = new JCheckBox();
this.lastValue = value; private JTextField jTextField = new JTextField();
if(value instanceof Boolean) { private JComboBox jComboBox = new JComboBox();
jCheckBox.setSelected(((Boolean) value).booleanValue()); private Object lastValue;
return jCheckBox;
} else if(value instanceof String || value instanceof Number || value instanceof Character) { @Override
jTextField.setText(value.toString()); public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
return jTextField; this.lastValue = value;
} else if(value instanceof Enum<?>) { if (value instanceof Boolean) {
DefaultComboBoxModel defaultComboBoxModel = (DefaultComboBoxModel)jComboBox.getModel(); jCheckBox.setSelected(((Boolean) value).booleanValue());
defaultComboBoxModel.removeAllElements(); return jCheckBox;
for(Object object : value.getClass().getEnumConstants()) { } else if (value instanceof String || value instanceof Number || value instanceof Character) {
defaultComboBoxModel.addElement(object); jTextField.setText(value.toString());
} return jTextField;
return jComboBox; } else if (value instanceof Enum<?>) {
} DefaultComboBoxModel defaultComboBoxModel = (DefaultComboBoxModel) jComboBox.getModel();
else { defaultComboBoxModel.removeAllElements();
jTextField.setText(value==null ? "" : value.toString()); for (Object object : value.getClass().getEnumConstants()) {
return jTextField; defaultComboBoxModel.addElement(object);
} }
} return jComboBox;
} else {
@Override jTextField.setText(value == null ? "" : value.toString());
public Object getCellEditorValue() { return jTextField;
if(lastValue instanceof Boolean) { }
return Boolean.valueOf(jCheckBox.isSelected()); }
} else if(lastValue instanceof String) {
return jTextField.getText(); @Override
} else if(lastValue instanceof Character) { public Object getCellEditorValue() {
return Character.valueOf(jTextField.getText().charAt(0)); if (lastValue instanceof Boolean) {
} else if(lastValue instanceof Byte) { return Boolean.valueOf(jCheckBox.isSelected());
return Byte.valueOf(jTextField.getText()); } else if (lastValue instanceof String) {
} else if(lastValue instanceof Short) { return jTextField.getText();
return Short.valueOf(jTextField.getText()); } else if (lastValue instanceof Character) {
} else if(lastValue instanceof Integer) { return Character.valueOf(jTextField.getText().charAt(0));
return Integer.valueOf(jTextField.getText()); } else if (lastValue instanceof Byte) {
} else if(lastValue instanceof Long) { return Byte.valueOf(jTextField.getText());
return Long.valueOf(jTextField.getText()); } else if (lastValue instanceof Short) {
} else if(lastValue instanceof Float) { return Short.valueOf(jTextField.getText());
return Float.valueOf(jTextField.getText()); } else if (lastValue instanceof Integer) {
} else if(lastValue instanceof Double) { return Integer.valueOf(jTextField.getText());
return Double.valueOf(jTextField.getText()); } else if (lastValue instanceof Long) {
} else if(lastValue instanceof Enum<?>) { return Long.valueOf(jTextField.getText());
return jComboBox.getSelectedItem(); } else if (lastValue instanceof Float) {
} return Float.valueOf(jTextField.getText());
//TODO: savable objects } else if (lastValue instanceof Double) {
return null; return Double.valueOf(jTextField.getText());
} } else if (lastValue instanceof Enum<?>) {
} return jComboBox.getSelectedItem();
}
//TODO: savable objects
return null;
}
}
} }

@ -41,400 +41,414 @@ import com.jme3.export.binary.BinaryImporter;
* @author Marcin Roguski (Kaelthas) * @author Marcin Roguski (Kaelthas)
*/ */
public class ConfigDialog extends AbstractConfigDialog { public class ConfigDialog extends AbstractConfigDialog {
private static final long serialVersionUID = 2863364888664674247L;
private static final Logger LOGGER = Logger.getLogger(ConfigDialog.class.getName()); private static final long serialVersionUID = 2863364888664674247L;
private static final Logger LOGGER = Logger.getLogger(ConfigDialog.class.getName());
private String baseFolderName; private String baseFolderName;
private File configFile; //the config file private File configFile; //the config file
private Map<String, BlenderKeyConfiguration> configMap; //the blender key configuration map private Map<String, BlenderKeyConfiguration> configMap; //the blender key configuration map
private BlenderKeyConfiguration blenderKeyConfiguration;//the configuration for the files private BlenderKeyConfiguration blenderKeyConfiguration;//the configuration for the files
private IConfigExecutable configExecutable; //this is called after clicking the 'OK' button private ConfigExecutable configExecutable; //this is called after clicking the 'OK' button
/** /**
* Constructor. Builds the whole window and stores its data. * Constructor. Builds the whole window and stores its data.
* @param testAssetsFolderName the path to test files folder * @param testAssetsFolderName the path to test files folder
*/ */
public ConfigDialog(String baseFolderName, IConfigExecutable configExecutable) { public ConfigDialog(String baseFolderName, ConfigExecutable configExecutable) {
if(baseFolderName==null) { if (baseFolderName == null) {
throw new IllegalArgumentException("No test asset folder given!"); throw new IllegalArgumentException("No test asset folder given!");
} }
if(configExecutable==null) { if (configExecutable == null) {
throw new IllegalArgumentException("No config executable given!"); throw new IllegalArgumentException("No config executable given!");
} }
this.baseFolderName = baseFolderName; this.baseFolderName = baseFolderName;
this.configExecutable = configExecutable; this.configExecutable = configExecutable;
this.configMap = new HashMap<String, ConfigDialog.BlenderKeyConfiguration>(); this.configMap = new HashMap<String, ConfigDialog.BlenderKeyConfiguration>();
//setting up version selection (as a folder list in a compo box) //setting up version selection (as a folder list in a compo box)
File baseFolder = new File(baseFolderName); File baseFolder = new File(baseFolderName);
if(!baseFolder.exists() || !baseFolder.isDirectory()) { if (!baseFolder.exists() || !baseFolder.isDirectory()) {
throw new IllegalArgumentException("The given base folder path either does not exists or does not point to a directory!"); throw new IllegalArgumentException("The given base folder path either does not exists or does not point to a directory!");
} }
File[] folders = baseFolder.listFiles(new FileFilter() { File[] folders = baseFolder.listFiles(new FileFilter() {
@Override
public boolean accept(File file) { @Override
return file.isDirectory() && file.getName().charAt(0)!='.'; public boolean accept(File file) {
} return file.isDirectory() && file.getName().charAt(0) != '.';
}); }
for(File folder : folders) { });
((DefaultComboBoxModel)jComboBoxVersionSelection.getModel()).addElement(folder.getName()); for (File folder : folders) {
configMap.put(folder.getName(), null); ((DefaultComboBoxModel) jComboBoxVersionSelection.getModel()).addElement(folder.getName());
} configMap.put(folder.getName(), null);
this.initListeners(); }
this.initListeners();
jComboBoxVersionSelection.setSelectedIndex(0);
} jComboBoxVersionSelection.setSelectedIndex(0);
}
/**
* This method returns the selected blender key. /**
* @return the selected blender key * This method returns the selected blender key.
*/ * @return the selected blender key
public BlenderKey getSelectedBlenderKey() { */
return blenderKeyConfiguration.lastUsedKey; public BlenderKey getSelectedBlenderKey() {
} return blenderKeyConfiguration.lastUsedKey;
}
/**
* This method prepares the blender files' list. /**
* @param testAssetsFolderName the path to test files folder * This method prepares the blender files' list.
* @return array of blender files * @param testAssetsFolderName the path to test files folder
*/ * @return array of blender files
private File[] prepareFilesList(String testAssetsFolderName) { */
File testAssetsFolder = new File(testAssetsFolderName); private File[] prepareFilesList(String testAssetsFolderName) {
File testAssetsFolder = new File(testAssetsFolderName);
//loading blender files
File[] blenderFiles = testAssetsFolder.listFiles(new FileFilter() { //loading blender files
@Override File[] blenderFiles = testAssetsFolder.listFiles(new FileFilter() {
public boolean accept(File file) {
return file.isFile() && file.canRead() && file.getName().endsWith(".blend"); @Override
} public boolean accept(File file) {
}); return file.isFile() && file.canRead() && file.getName().endsWith(".blend");
}
//loading the blender files configuration });
File[] files = testAssetsFolder.listFiles(new FileFilter() {
@Override //loading the blender files configuration
public boolean accept(File file) { File[] files = testAssetsFolder.listFiles(new FileFilter() {
return file.isFile() && file.canRead() && file.getName().endsWith(".conf");
} @Override
}); public boolean accept(File file) {
if (files == null || files.length == 0) { return file.isFile() && file.canRead() && file.getName().endsWith(".conf");
blenderKeyConfiguration = new BlenderKeyConfiguration(blenderFiles.length); }
});
} else { if (files == null || files.length == 0) {
BinaryImporter jmeImporter = new BinaryImporter(); blenderKeyConfiguration = new BlenderKeyConfiguration(blenderFiles.length);
String instructionToUser = files.length==1 ?
"No other config file to load! No configuration set!" : } else {
"Please choose different config file!"; BinaryImporter jmeImporter = new BinaryImporter();
do { String instructionToUser = files.length == 1
if (files.length > 1) { ? "No other config file to load! No configuration set!"
configFile = (File) JOptionPane.showInputDialog(null, "Choose the config file!", "Config file selection", : "Please choose different config file!";
JOptionPane.INFORMATION_MESSAGE, null, files, files[0]); do {
} else { if (files.length > 1) {
configFile = files[0]; configFile = (File) JOptionPane.showInputDialog(null, "Choose the config file!", "Config file selection",
} JOptionPane.INFORMATION_MESSAGE, null, files, files[0]);
if(configFile==null) { } else {
JOptionPane.showMessageDialog(this, "No config file selected!\nEmpty configuration will be created!", configFile = files[0];
"No configuration selected", JOptionPane.INFORMATION_MESSAGE); }
blenderKeyConfiguration = new BlenderKeyConfiguration(blenderFiles.length); if (configFile == null) {
} else { JOptionPane.showMessageDialog(this, "No config file selected!\nEmpty configuration will be created!",
try { "No configuration selected", JOptionPane.INFORMATION_MESSAGE);
Savable loadedData = jmeImporter.load(configFile); blenderKeyConfiguration = new BlenderKeyConfiguration(blenderFiles.length);
if (loadedData instanceof BlenderKeyConfiguration) { } else {
blenderKeyConfiguration = (BlenderKeyConfiguration) loadedData; try {
} else { Savable loadedData = jmeImporter.load(configFile);
LOGGER.warning("Cannot load data drom the given file!"); if (loadedData instanceof BlenderKeyConfiguration) {
JOptionPane.showMessageDialog(this, "The data stored in the config file is of invalid type!\n" blenderKeyConfiguration = (BlenderKeyConfiguration) loadedData;
+ instructionToUser, "Config data error", JOptionPane.ERROR_MESSAGE); } else {
} LOGGER.warning("Cannot load data drom the given file!");
} catch (IOException e) { JOptionPane.showMessageDialog(this, "The data stored in the config file is of invalid type!\n"
JOptionPane.showMessageDialog(this, "Unable to load configuration! Reason: " + e.getLocalizedMessage(), + instructionToUser, "Config data error", JOptionPane.ERROR_MESSAGE);
"Loading data error", JOptionPane.ERROR_MESSAGE); }
LOGGER.severe("Unable to load configuration"); } catch (IOException e) {
} catch (Exception e) { JOptionPane.showMessageDialog(this, "Unable to load configuration! Reason: " + e.getLocalizedMessage(),
JOptionPane.showMessageDialog(this, "Unable to load configuration!", "Loading data error", JOptionPane.ERROR_MESSAGE);
"Loading data error", JOptionPane.ERROR_MESSAGE); LOGGER.severe("Unable to load configuration");
LOGGER.log(Level.SEVERE, "Unable to load configuration due to unpredicted error!", e); } catch (Exception e) {
} JOptionPane.showMessageDialog(this, "Unable to load configuration!",
} "Loading data error", JOptionPane.ERROR_MESSAGE);
} while (blenderKeyConfiguration == null && files.length>1); LOGGER.log(Level.SEVERE, "Unable to load configuration due to unpredicted error!", e);
} }
configFile = new File(testAssetsFolder, "test.conf"); }
} while (blenderKeyConfiguration == null && files.length > 1);
jCheckBoxUseModelKey.setSelected(blenderKeyConfiguration.useModelKey); }
configFile = new File(testAssetsFolder, "test.conf");
//enlisting the files in the list
DefaultListModel defaultListModel = (DefaultListModel) jListBlenderFiles.getModel(); jCheckBoxUseModelKey.setSelected(blenderKeyConfiguration.useModelKey);
defaultListModel.removeAllElements();
for(int i=0; i<blenderFiles.length; ++i) { //enlisting the files in the list
defaultListModel.addElement(new FileListItem(blenderFiles[i])); DefaultListModel defaultListModel = (DefaultListModel) jListBlenderFiles.getModel();
} defaultListModel.removeAllElements();
return blenderFiles; for (int i = 0; i < blenderFiles.length; ++i) {
} defaultListModel.addElement(new FileListItem(blenderFiles[i]));
}
/** return blenderFiles;
* This method fills the properties panel with blender key data. }
* @param blenderKey the belnder key data
*/ /**
private void setBlenderKey(BlenderKey blenderKey) { * This method fills the properties panel with blender key data.
//setting properties * @param blenderKey the belnder key data
BlenderTableModel propertiesModel = (BlenderTableModel) jTableProperties.getModel(); */
int rowCount = propertiesModel.getRowCount(); private void setBlenderKey(BlenderKey blenderKey) {
for(int i=0;i<rowCount;++i) { //setting properties
propertiesModel.removeRow(0); BlenderTableModel propertiesModel = (BlenderTableModel) jTableProperties.getModel();
} int rowCount = propertiesModel.getRowCount();
Field[] fields = blenderKey.getClass().getDeclaredFields(); for (int i = 0; i < rowCount; ++i) {
for(Field field : fields) { propertiesModel.removeRow(0);
}
field.setAccessible(true); Field[] fields = blenderKey.getClass().getDeclaredFields();
if(!"animations".equalsIgnoreCase(field.getName()) && for (Field field : fields) {
(field.getModifiers() & Modifier.STATIC)==0) {
try { field.setAccessible(true);
propertiesModel.addRow(new Object[] {field.getName(), field.get(blenderKey)}); if (!"animations".equalsIgnoreCase(field.getName())
} catch (IllegalArgumentException e) { && (field.getModifiers() & Modifier.STATIC) == 0) {
LOGGER.log(Level.SEVERE, e.getMessage(), e); try {
} catch (IllegalAccessException e) { propertiesModel.addRow(new Object[]{field.getName(), field.get(blenderKey)});
LOGGER.log(Level.SEVERE, e.getMessage(), e); } catch (IllegalArgumentException e) {
} LOGGER.log(Level.SEVERE, e.getMessage(), e);
} } catch (IllegalAccessException e) {
} LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
//setting animations }
DefaultTableModel animationsModel = (DefaultTableModel) jTableAnimations.getModel(); }
rowCount = animationsModel.getRowCount();
for(int i=0;i<rowCount;++i) { //setting animations
animationsModel.removeRow(0); DefaultTableModel animationsModel = (DefaultTableModel) jTableAnimations.getModel();
} rowCount = animationsModel.getRowCount();
Map<String, Map<String, int[]>> animations = blenderKey.getAnimations(); for (int i = 0; i < rowCount; ++i) {
if(animations!=null) { animationsModel.removeRow(0);
for(Entry<String, Map<String, int[]>> animationEntry : animations.entrySet()) { }
for(Entry<String, int[]> animDataEntry : animationEntry.getValue().entrySet()) { Map<String, Map<String, int[]>> animations = blenderKey.getAnimations();
int[] frames = animDataEntry.getValue(); if (animations != null) {
animationsModel.addRow(new Object[] {animationEntry.getKey(), animDataEntry.getKey(), for (Entry<String, Map<String, int[]>> animationEntry : animations.entrySet()) {
Integer.valueOf(frames[0]), Integer.valueOf(frames[1])}); for (Entry<String, int[]> animDataEntry : animationEntry.getValue().entrySet()) {
} int[] frames = animDataEntry.getValue();
} animationsModel.addRow(new Object[]{animationEntry.getKey(), animDataEntry.getKey(),
} Integer.valueOf(frames[0]), Integer.valueOf(frames[1])});
}
this.jButtonOK.setEnabled(true); }
this.jButtonOK.requestFocusInWindow(); }
this.jButtonAddAnimation.setEnabled(true);
} this.jButtonOK.setEnabled(true);
this.jButtonOK.requestFocusInWindow();
/** this.jButtonAddAnimation.setEnabled(true);
* This method stores the current blender config. }
* @param configuration the blender config to store
*/ /**
private void storeConfig(BlenderKeyConfiguration configuration) { * This method stores the current blender config.
if(configuration.lastUsedKey!=null) {//reading animations * @param configuration the blender config to store
DefaultTableModel animationsTableModel = (DefaultTableModel)jTableAnimations.getModel(); */
if(configuration.lastUsedKey.getAnimations()!=null) { private void storeConfig(BlenderKeyConfiguration configuration) {
configuration.lastUsedKey.getAnimations().clear(); if (configuration.lastUsedKey != null) {//reading animations
} DefaultTableModel animationsTableModel = (DefaultTableModel) jTableAnimations.getModel();
int animCounter = 0; if (configuration.lastUsedKey.getAnimations() != null) {
for(int i=0;i<animationsTableModel.getRowCount();++i) { configuration.lastUsedKey.getAnimations().clear();
String objectName = (String)animationsTableModel.getValueAt(i, 0); }
String animName = (String)animationsTableModel.getValueAt(i, 1); int animCounter = 0;
Number startFrame = (Number)animationsTableModel.getValueAt(i, 2); for (int i = 0; i < animationsTableModel.getRowCount(); ++i) {
Number stopFrame = (Number)animationsTableModel.getValueAt(i, 3); String objectName = (String) animationsTableModel.getValueAt(i, 0);
if(objectName!=null && animName!=null && startFrame.intValue()<=stopFrame.intValue()) { String animName = (String) animationsTableModel.getValueAt(i, 1);
configuration.lastUsedKey.addAnimation(objectName, animName, startFrame.intValue(), stopFrame.intValue()); Number startFrame = (Number) animationsTableModel.getValueAt(i, 2);
++animCounter; Number stopFrame = (Number) animationsTableModel.getValueAt(i, 3);
} if (objectName != null && animName != null && startFrame.intValue() <= stopFrame.intValue()) {
} configuration.lastUsedKey.addAnimation(objectName, animName, startFrame.intValue(), stopFrame.intValue());
if(animCounter<animationsTableModel.getRowCount()) { ++animCounter;
JOptionPane.showMessageDialog(ConfigDialog.this, "Some animations had errors!\nThey had not been added!", }
"Invalid animations definitions", JOptionPane.WARNING_MESSAGE); }
} if (animCounter < animationsTableModel.getRowCount()) {
} JOptionPane.showMessageDialog(ConfigDialog.this, "Some animations had errors!\nThey had not been added!",
//getting the key type "Invalid animations definitions", JOptionPane.WARNING_MESSAGE);
configuration.useModelKey = jCheckBoxUseModelKey.isSelected(); }
configuration.logLevel = JRadioButtonLevel.getSelectedLevel(); }
//getting the key type
//storing the config configuration.useModelKey = jCheckBoxUseModelKey.isSelected();
JmeExporter jmeExporter = new BinaryExporter(); configuration.logLevel = JRadioButtonLevel.getSelectedLevel();
try {
if(!jmeExporter.save(configuration, configFile)) { //storing the config
JOptionPane.showMessageDialog(ConfigDialog.this, "Unable to save the config data!", "Config save problem", JOptionPane.ERROR_MESSAGE); JmeExporter jmeExporter = new BinaryExporter();
} try {
} catch (IOException e) { if (!jmeExporter.save(configuration, configFile)) {
JOptionPane.showMessageDialog(ConfigDialog.this, "Error occured during config saving!\nReason: " + e.getLocalizedMessage(), JOptionPane.showMessageDialog(ConfigDialog.this, "Unable to save the config data!", "Config save problem", JOptionPane.ERROR_MESSAGE);
"Config save problem", JOptionPane.ERROR_MESSAGE); }
} } catch (IOException e) {
} JOptionPane.showMessageDialog(ConfigDialog.this, "Error occured during config saving!\nReason: " + e.getLocalizedMessage(),
"Config save problem", JOptionPane.ERROR_MESSAGE);
/** }
* This method initiates components listeners. }
*/
private void initListeners() { /**
//selection of blender version * This method initiates components listeners.
jComboBoxVersionSelection.addActionListener(new ActionListener() { */
@Override private void initListeners() {
public void actionPerformed(ActionEvent evt) { //selection of blender version
//save the previous congifuration jComboBoxVersionSelection.addActionListener(new ActionListener() {
if(blenderKeyConfiguration!=null) {
ConfigDialog.this.storeConfig(blenderKeyConfiguration); @Override
blenderKeyConfiguration = null; public void actionPerformed(ActionEvent evt) {
} //save the previous congifuration
if (blenderKeyConfiguration != null) {
//load new configuration ConfigDialog.this.storeConfig(blenderKeyConfiguration);
File[] blenderFiles = ConfigDialog.this.prepareFilesList(baseFolderName+'/'+jComboBoxVersionSelection.getSelectedItem().toString()); blenderKeyConfiguration = null;
if(blenderKeyConfiguration.lastUsedKey!=null) { }
for(int i=0;i<blenderFiles.length; ++i) {
if(blenderFiles[i].getPath().equalsIgnoreCase(blenderKeyConfiguration.lastUsedKey.getName())) { //load new configuration
jListBlenderFiles.setSelectedIndex(i); File[] blenderFiles = ConfigDialog.this.prepareFilesList(baseFolderName + '/' + jComboBoxVersionSelection.getSelectedItem().toString());
break; if (blenderKeyConfiguration.lastUsedKey != null) {
} for (int i = 0; i < blenderFiles.length; ++i) {
} if (blenderFiles[i].getPath().equalsIgnoreCase(blenderKeyConfiguration.lastUsedKey.getName())) {
} jListBlenderFiles.setSelectedIndex(i);
if(blenderKeyConfiguration.logLevel==null) { break;
blenderKeyConfiguration.logLevel = Level.INFO; }
} }
JRadioButtonLevel.setSelectedLevel(blenderKeyConfiguration.logLevel); }
} if (blenderKeyConfiguration.logLevel == null) {
}); blenderKeyConfiguration.logLevel = Level.INFO;
//selection of the file changes the config on the right }
jListBlenderFiles.addListSelectionListener(new ListSelectionListener() { JRadioButtonLevel.setSelectedLevel(blenderKeyConfiguration.logLevel);
@Override }
public void valueChanged(ListSelectionEvent evt) { });
BlenderKeyConfiguration config = ConfigDialog.this.blenderKeyConfiguration; //selection of the file changes the config on the right
FileListItem selectedItem = (FileListItem) ConfigDialog.this.jListBlenderFiles.getSelectedValue(); jListBlenderFiles.addListSelectionListener(new ListSelectionListener() {
if(selectedItem != null) {
String fileName = selectedItem.getFile().getName(); @Override
config.lastUsedKey = config.blenderKeys.get(fileName); public void valueChanged(ListSelectionEvent evt) {
if(config.lastUsedKey==null) { BlenderKeyConfiguration config = ConfigDialog.this.blenderKeyConfiguration;
config.lastUsedKey = new BlenderKey(selectedItem.getFile().getPath()); FileListItem selectedItem = (FileListItem) ConfigDialog.this.jListBlenderFiles.getSelectedValue();
config.blenderKeys.put(fileName, config.lastUsedKey); if (selectedItem != null) {
} String fileName = selectedItem.getFile().getName();
ConfigDialog.this.setBlenderKey(config.lastUsedKey); config.lastUsedKey = config.blenderKeys.get(fileName);
} else { if (config.lastUsedKey == null) {
config.lastUsedKey = null; config.lastUsedKey = new BlenderKey(selectedItem.getFile().getPath());
} config.blenderKeys.put(fileName, config.lastUsedKey);
} }
}); ConfigDialog.this.setBlenderKey(config.lastUsedKey);
jTableProperties.getModel().addTableModelListener(new TableModelListener() { } else {
@Override config.lastUsedKey = null;
public void tableChanged(TableModelEvent evt) { }
if(evt.getType()==TableModelEvent.UPDATE) { }
BlenderKeyConfiguration config = ConfigDialog.this.blenderKeyConfiguration; });
int row = evt.getFirstRow(); jTableProperties.getModel().addTableModelListener(new TableModelListener() {
String name = (String)jTableProperties.getModel().getValueAt(row, 0);
Object value = jTableProperties.getModel().getValueAt(row, 1); @Override
try { public void tableChanged(TableModelEvent evt) {
Field field = config.lastUsedKey.getClass().getDeclaredField(name); if (evt.getType() == TableModelEvent.UPDATE) {
field.setAccessible(true); BlenderKeyConfiguration config = ConfigDialog.this.blenderKeyConfiguration;
field.set(config.lastUsedKey, value); int row = evt.getFirstRow();
} catch (IllegalArgumentException e) { String name = (String) jTableProperties.getModel().getValueAt(row, 0);
LOGGER.log(Level.SEVERE, e.getMessage(), e); Object value = jTableProperties.getModel().getValueAt(row, 1);
} catch (SecurityException e) { try {
LOGGER.log(Level.SEVERE, e.getMessage(), e); Field field = config.lastUsedKey.getClass().getDeclaredField(name);
} catch (IllegalAccessException e) { field.setAccessible(true);
LOGGER.log(Level.SEVERE, e.getMessage(), e); field.set(config.lastUsedKey, value);
} catch (NoSuchFieldException e) { } catch (IllegalArgumentException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e); LOGGER.log(Level.SEVERE, e.getMessage(), e);
} } catch (SecurityException e) {
} LOGGER.log(Level.SEVERE, e.getMessage(), e);
} } catch (IllegalAccessException e) {
}); LOGGER.log(Level.SEVERE, e.getMessage(), e);
jTableAnimations.getModel().addTableModelListener(new TableModelListener() { } catch (NoSuchFieldException e) {
@Override LOGGER.log(Level.SEVERE, e.getMessage(), e);
public void tableChanged(TableModelEvent evt) { }
if(evt.getType()==TableModelEvent.INSERT) { }
jButtonRemoveAnimation.setEnabled(true); }
} else if(evt.getType()==TableModelEvent.DELETE && jTableAnimations.getModel().getRowCount()==0) { });
jButtonRemoveAnimation.setEnabled(false); jTableAnimations.getModel().addTableModelListener(new TableModelListener() {
}
} @Override
}); public void tableChanged(TableModelEvent evt) {
jButtonAddAnimation.addActionListener(new ActionListener() { if (evt.getType() == TableModelEvent.INSERT) {
@Override jButtonRemoveAnimation.setEnabled(true);
public void actionPerformed(ActionEvent evt) { } else if (evt.getType() == TableModelEvent.DELETE && jTableAnimations.getModel().getRowCount() == 0) {
((DefaultTableModel)jTableAnimations.getModel()).addRow(new Object[] {"", "", Integer.valueOf(-1), Integer.valueOf(-1)}); jButtonRemoveAnimation.setEnabled(false);
} }
}); }
jButtonRemoveAnimation.addActionListener(new ActionListener() { });
@Override jButtonAddAnimation.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
int row = jTableAnimations.getSelectedRow(); @Override
if(row>=0) { public void actionPerformed(ActionEvent evt) {
((DefaultTableModel)jTableAnimations.getModel()).removeRow(row); ((DefaultTableModel) jTableAnimations.getModel()).addRow(new Object[]{"", "", Integer.valueOf(-1), Integer.valueOf(-1)});
} }
} });
}); jButtonRemoveAnimation.addActionListener(new ActionListener() {
//button listeners @Override
jButtonOK.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) {
@Override int row = jTableAnimations.getSelectedRow();
public void actionPerformed(ActionEvent evt) { if (row >= 0) {
ConfigDialog.this.storeConfig(blenderKeyConfiguration); ((DefaultTableModel) jTableAnimations.getModel()).removeRow(row);
//running the test }
SwingUtilities.invokeLater(new Runnable() { }
@Override });
public void run() {
configExecutable.execute(ConfigDialog.this.blenderKeyConfiguration.getKeyToUse(), //button listeners
ConfigDialog.this.blenderKeyConfiguration.logLevel); jButtonOK.addActionListener(new ActionListener() {
}
}); @Override
//disposing the config window public void actionPerformed(ActionEvent evt) {
ConfigDialog.this.dispose(); ConfigDialog.this.storeConfig(blenderKeyConfiguration);
} //running the test
}); SwingUtilities.invokeLater(new Runnable() {
jButtonCancel.addActionListener(new ActionListener() {
@Override @Override
public void actionPerformed(ActionEvent evt) { public void run() {
ConfigDialog.this.dispose(); configExecutable.execute(ConfigDialog.this.blenderKeyConfiguration.getKeyToUse(),
} ConfigDialog.this.blenderKeyConfiguration.logLevel);
}); }
} });
//disposing the config window
/** ConfigDialog.this.dispose();
* This class holds the configuration for all the files. }
* It can be saved and loaded using jme mechanisms. });
* @author Marcin Roguski (Kaelthas) jButtonCancel.addActionListener(new ActionListener() {
*/
public static class BlenderKeyConfiguration implements Savable { @Override
private Map<String, BlenderKey> blenderKeys; public void actionPerformed(ActionEvent evt) {
private BlenderKey lastUsedKey; ConfigDialog.this.dispose();
private Level logLevel; }
private boolean useModelKey; });
}
/**
* Constructor for jme serialization. /**
*/ * This class holds the configuration for all the files.
public BlenderKeyConfiguration() {} * It can be saved and loaded using jme mechanisms.
* @author Marcin Roguski (Kaelthas)
/** */
* Constructor that creates new empty configuration for every blender file. public static class BlenderKeyConfiguration implements Savable {
* @param blenderFilesAmount the amount of blender files
*/ private Map<String, BlenderKey> blenderKeys;
public BlenderKeyConfiguration(int blenderFilesAmount) { private BlenderKey lastUsedKey;
blenderKeys = new HashMap<String, BlenderKey>(blenderFilesAmount); private Level logLevel;
} private boolean useModelKey;
/** /**
* This method returns the key that will be used during the test. * Constructor for jme serialization.
* @return the key that will be used during the test */
*/ public BlenderKeyConfiguration() {
public ModelKey getKeyToUse() { }
return useModelKey ? new ModelKey(lastUsedKey.getName()) : lastUsedKey;
} /**
* Constructor that creates new empty configuration for every blender file.
@Override * @param blenderFilesAmount the amount of blender files
public void write(JmeExporter ex) throws IOException { */
OutputCapsule oc = ex.getCapsule(this); public BlenderKeyConfiguration(int blenderFilesAmount) {
oc.writeStringSavableMap(blenderKeys, "keys", null); blenderKeys = new HashMap<String, BlenderKey>(blenderFilesAmount);
oc.write(lastUsedKey, "last-key", null); }
oc.write(useModelKey, "use-model-key", false);
oc.write(logLevel==null ? null : logLevel.getName(), "log-level", Level.INFO.getName()); /**
} * This method returns the key that will be used during the test.
* @return the key that will be used during the test
@Override */
@SuppressWarnings("unchecked") public ModelKey getKeyToUse() {
public void read(JmeImporter im) throws IOException { return useModelKey ? new ModelKey(lastUsedKey.getName()) : lastUsedKey;
InputCapsule ic = im.getCapsule(this); }
blenderKeys = (Map<String, BlenderKey>) ic.readStringSavableMap("keys", null);
lastUsedKey = (BlenderKey) ic.readSavable("last-key", null); @Override
useModelKey = ic.readBoolean("use-model-key", false); public void write(JmeExporter ex) throws IOException {
String logLevelName = ic.readString("log-level", Level.INFO.getName()); OutputCapsule oc = ex.getCapsule(this);
logLevel = logLevelName==null ? Level.INFO : Level.parse(logLevelName); oc.writeStringSavableMap(blenderKeys, "keys", null);
} oc.write(lastUsedKey, "last-key", null);
} oc.write(useModelKey, "use-model-key", false);
oc.write(logLevel == null ? null : logLevel.getName(), "log-level", Level.INFO.getName());
}
@Override
@SuppressWarnings("unchecked")
public void read(JmeImporter im) throws IOException {
InputCapsule ic = im.getCapsule(this);
blenderKeys = (Map<String, BlenderKey>) ic.readStringSavableMap("keys", null);
lastUsedKey = (BlenderKey) ic.readSavable("last-key", null);
useModelKey = ic.readBoolean("use-model-key", false);
String logLevelName = ic.readString("log-level", Level.INFO.getName());
logLevel = logLevelName == null ? Level.INFO : Level.parse(logLevelName);
}
}
} }

@ -9,7 +9,7 @@ import com.jme3.asset.ModelKey;
* itself. * itself.
* @author Marcin Roguski (Kaelthas) * @author Marcin Roguski (Kaelthas)
*/ */
public interface IConfigExecutable { public interface ConfigExecutable {
/** /**
* This method runs the test with the given blender key. * This method runs the test with the given blender key.
* @param modelKey * @param modelKey

@ -14,40 +14,41 @@ import com.jme3.scene.shape.Sphere;
* @author Marcin Roguski * @author Marcin Roguski
*/ */
public class Pivot extends Node { public class Pivot extends Node {
public Pivot(AssetManager assetManager) {
this.attachChild(this.getAxis("x", new Vector3f(10, 0, 0), ColorRGBA.Red, assetManager));
this.attachChild(this.getAxis("y", new Vector3f(0, 10, 0), ColorRGBA.Green, assetManager));
this.attachChild(this.getAxis("z", new Vector3f(0, 0, 10), ColorRGBA.Blue, assetManager));
this.assignPoints(assetManager);
}
private void assignPoints(AssetManager assetManager) { public Pivot(AssetManager assetManager) {
Material defaultMaterial = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); this.attachChild(this.getAxis("x", new Vector3f(10, 0, 0), ColorRGBA.Red, assetManager));
defaultMaterial.setColor("Color", ColorRGBA.DarkGray); this.attachChild(this.getAxis("y", new Vector3f(0, 10, 0), ColorRGBA.Green, assetManager));
for(int i = -10; i <= 10; ++i) { this.attachChild(this.getAxis("z", new Vector3f(0, 0, 10), ColorRGBA.Blue, assetManager));
Geometry g = new Geometry("", new Sphere(3, 3, 0.05f)); this.assignPoints(assetManager);
g.setLocalTranslation(i, 0, 0); }
g.setMaterial(defaultMaterial);
this.attachChild(g);
g = new Geometry("", new Sphere(3, 3, 0.05f)); private void assignPoints(AssetManager assetManager) {
g.setLocalTranslation(0, i, 0); Material defaultMaterial = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
g.setMaterial(defaultMaterial); defaultMaterial.setColor("Color", ColorRGBA.DarkGray);
this.attachChild(g); for (int i = -10; i <= 10; ++i) {
Geometry g = new Geometry("", new Sphere(3, 3, 0.05f));
g.setLocalTranslation(i, 0, 0);
g.setMaterial(defaultMaterial);
this.attachChild(g);
g = new Geometry("", new Sphere(3, 3, 0.05f)); g = new Geometry("", new Sphere(3, 3, 0.05f));
g.setLocalTranslation(0, 0, i); g.setLocalTranslation(0, i, 0);
g.setMaterial(defaultMaterial); g.setMaterial(defaultMaterial);
this.attachChild(g); this.attachChild(g);
}
}
private Geometry getAxis(String name, Vector3f endPoint, ColorRGBA color, AssetManager assetManager) { g = new Geometry("", new Sphere(3, 3, 0.05f));
Line axis = new Line(new Vector3f(0, 0, 0), endPoint); g.setLocalTranslation(0, 0, i);
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); g.setMaterial(defaultMaterial);
mat.setColor("Color", color); this.attachChild(g);
Geometry geom = new Geometry(name, axis); }
geom.setMaterial(mat); }
return geom;
} private Geometry getAxis(String name, Vector3f endPoint, ColorRGBA color, AssetManager assetManager) {
Line axis = new Line(new Vector3f(0, 0, 0), endPoint);
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat.setColor("Color", color);
Geometry geom = new Geometry(name, axis);
geom.setMaterial(mat);
return geom;
}
} }

@ -16,32 +16,33 @@ import com.jme3.scene.shape.Sphere;
* @author Marcin Roguski * @author Marcin Roguski
*/ */
public class VisibleBone extends Node { public class VisibleBone extends Node {
private Vector3f globalPosition;
public VisibleBone(Bone bone, Vector3f parentLocation, Quaternion parentRotation, AssetManager assetManager) { private Vector3f globalPosition;
Material redMat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
redMat.setColor("Color", ColorRGBA.Red);
Material whiteMat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); public VisibleBone(Bone bone, Vector3f parentLocation, Quaternion parentRotation, AssetManager assetManager) {
whiteMat.setColor("Color", ColorRGBA.White); Material redMat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
redMat.setColor("Color", ColorRGBA.Red);
Geometry g = new Geometry(bone.getName(), new Sphere(9, 9, 0.01f)); Material whiteMat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
globalPosition = bone.getLocalPosition().add(parentLocation); whiteMat.setColor("Color", ColorRGBA.White);
g.setLocalTranslation(globalPosition);
g.setLocalRotation(bone.getLocalRotation().mult(parentRotation));
g.setMaterial(redMat);
this.attachChild(g);
if(bone.getChildren() != null) { Geometry g = new Geometry(bone.getName(), new Sphere(9, 9, 0.01f));
for(Bone child : bone.getChildren()) { globalPosition = bone.getLocalPosition().add(parentLocation);
VisibleBone vb = new VisibleBone(child, bone.getLocalPosition(), bone.getLocalRotation(), assetManager); g.setLocalTranslation(globalPosition);
this.attachChild(vb); g.setLocalRotation(bone.getLocalRotation().mult(parentRotation));
Line line = new Line(globalPosition, vb.globalPosition); g.setMaterial(redMat);
line.setLineWidth(2); this.attachChild(g);
Geometry geom = new Geometry("", line);
geom.setMaterial(whiteMat); if (bone.getChildren() != null) {
this.attachChild(geom); for (Bone child : bone.getChildren()) {
} VisibleBone vb = new VisibleBone(child, bone.getLocalPosition(), bone.getLocalRotation(), assetManager);
} this.attachChild(vb);
} Line line = new Line(globalPosition, vb.globalPosition);
line.setLineWidth(2);
Geometry geom = new Geometry("", line);
geom.setMaterial(whiteMat);
this.attachChild(geom);
}
}
}
} }

@ -29,7 +29,6 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package jme3test.network; package jme3test.network;
import java.awt.Dimension; import java.awt.Dimension;
@ -38,19 +37,13 @@ import java.awt.Component;
import java.io.IOException; import java.io.IOException;
import javax.swing.*; import javax.swing.*;
import com.jme3.network.AbstractMessage;
import com.jme3.network.Client; import com.jme3.network.Client;
import com.jme3.network.HostedConnection;
import com.jme3.network.Message; import com.jme3.network.Message;
import com.jme3.network.MessageListener; import com.jme3.network.MessageListener;
import com.jme3.network.Network; import com.jme3.network.Network;
import com.jme3.network.Server;
import com.jme3.network.serializing.Serializable;
import com.jme3.network.serializing.Serializer;
import jme3test.network.TestChatServer.ChatMessage; import jme3test.network.TestChatServer.ChatMessage;
/** /**
* A simple test chat server. When SM implements a set * A simple test chat server. When SM implements a set
* of standard chat classes this can become a lot simpler. * of standard chat classes this can become a lot simpler.
@ -58,115 +51,108 @@ import jme3test.network.TestChatServer.ChatMessage;
* @version $Revision$ * @version $Revision$
* @author Paul Speed * @author Paul Speed
*/ */
public class TestChatClient extends JFrame public class TestChatClient extends JFrame {
{
private Client client; private Client client;
private JEditorPane chatLog; private JEditorPane chatLog;
private StringBuilder chatMessages = new StringBuilder(); private StringBuilder chatMessages = new StringBuilder();
private JTextField nameField; private JTextField nameField;
private JTextField messageField; private JTextField messageField;
public TestChatClient( String host ) throws IOException public TestChatClient(String host) throws IOException {
{ super("jME3 Test Chat Client - to:" + host);
super( "jME3 Test Chat Client - to:" + host );
// Build out the UI // Build out the UI
setDefaultCloseOperation( DISPOSE_ON_CLOSE ); setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setSize( 800, 600 ); setSize(800, 600);
chatLog = new JEditorPane(); chatLog = new JEditorPane();
chatLog.setEditable(false); chatLog.setEditable(false);
chatLog.setContentType("text/html"); chatLog.setContentType("text/html");
chatLog.setText( "<html><body>" ); chatLog.setText("<html><body>");
getContentPane().add( new JScrollPane(chatLog), "Center" ); getContentPane().add(new JScrollPane(chatLog), "Center");
// A crude form // A crude form
JPanel p = new JPanel(); JPanel p = new JPanel();
p.setLayout( new BoxLayout(p, BoxLayout.X_AXIS) ); p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));
p.add( new JLabel( "Name:" ) ); p.add(new JLabel("Name:"));
nameField = new JTextField( System.getProperty( "user.name", "yourname" ) ); nameField = new JTextField(System.getProperty("user.name", "yourname"));
Dimension d = nameField.getPreferredSize(); Dimension d = nameField.getPreferredSize();
nameField.setMaximumSize( new Dimension(120, d.height + 6) ); nameField.setMaximumSize(new Dimension(120, d.height + 6));
p.add( nameField ); p.add(nameField);
p.add( new JLabel( " Message:" ) ); p.add(new JLabel(" Message:"));
messageField = new JTextField(); messageField = new JTextField();
p.add( messageField ); p.add(messageField);
p.add( new JButton(new SendAction(true)) ); p.add(new JButton(new SendAction(true)));
p.add( new JButton(new SendAction(false)) ); p.add(new JButton(new SendAction(false)));
getContentPane().add( p, "South" ); getContentPane().add(p, "South");
client = Network.connectToServer( TestChatServer.NAME, TestChatServer.VERSION, client = Network.connectToServer(TestChatServer.NAME, TestChatServer.VERSION,
host, TestChatServer.PORT, TestChatServer.UDP_PORT ); host, TestChatServer.PORT, TestChatServer.UDP_PORT);
client.addMessageListener( new ChatHandler(), ChatMessage.class ); client.addMessageListener(new ChatHandler(), ChatMessage.class);
client.start(); client.start();
} }
public static String getString( Component owner, String title, String message, String initialValue ) public static String getString(Component owner, String title, String message, String initialValue) {
{ return (String) JOptionPane.showInputDialog(owner, message, title, JOptionPane.PLAIN_MESSAGE,
return (String)JOptionPane.showInputDialog( owner, message, title, JOptionPane.PLAIN_MESSAGE, null, null, initialValue);
null, null, initialValue );
} }
public static void main( String... args ) throws Exception public static void main(String... args) throws Exception {
{
TestChatServer.initializeClasses(); TestChatServer.initializeClasses();
// Grab a host string from the user // Grab a host string from the user
String s = getString( null, "Host Info", "Enter chat host:", "localhost" ); String s = getString(null, "Host Info", "Enter chat host:", "localhost");
if( s == null ) { if (s == null) {
System.out.println( "User cancelled." ); System.out.println("User cancelled.");
return; return;
} }
TestChatClient test = new TestChatClient( s ); TestChatClient test = new TestChatClient(s);
test.setVisible( true ); test.setVisible(true);
} }
private class ChatHandler implements MessageListener<Client> private class ChatHandler implements MessageListener<Client> {
{
public void messageReceived( Client source, Message m ) public void messageReceived(Client source, Message m) {
{ ChatMessage chat = (ChatMessage) m;
ChatMessage chat = (ChatMessage)m;
System.out.println("Received:" + chat);
System.out.println( "Received:" + chat );
// One of the least efficient ways to add text to a // One of the least efficient ways to add text to a
// JEditorPane // JEditorPane
chatMessages.append( "<font color='#00a000'>" + (m.isReliable() ? "TCP" : "UDP") + "</font>" ); chatMessages.append("<font color='#00a000'>" + (m.isReliable() ? "TCP" : "UDP") + "</font>");
chatMessages.append( " -- <font color='#000080'><b>" + chat.getName() + "</b></font> : " ); chatMessages.append(" -- <font color='#000080'><b>" + chat.getName() + "</b></font> : ");
chatMessages.append( chat.getMessage() ); chatMessages.append(chat.getMessage());
chatMessages.append( "<br />" ); chatMessages.append("<br />");
String s = "<html><body>" + chatMessages + "</body></html>"; String s = "<html><body>" + chatMessages + "</body></html>";
chatLog.setText( s ); chatLog.setText(s);
// Set selection to the end so that the scroll panel will scroll // Set selection to the end so that the scroll panel will scroll
// down. // down.
chatLog.select( s.length(), s.length() ); chatLog.select(s.length(), s.length());
} }
} }
private class SendAction extends AbstractAction private class SendAction extends AbstractAction {
{
private boolean reliable; private boolean reliable;
public SendAction( boolean reliable ) public SendAction(boolean reliable) {
{ super(reliable ? "TCP" : "UDP");
super( reliable ? "TCP" : "UDP" );
this.reliable = reliable; this.reliable = reliable;
} }
public void actionPerformed( ActionEvent evt ) public void actionPerformed(ActionEvent evt) {
{
String name = nameField.getText(); String name = nameField.getText();
String message = messageField.getText(); String message = messageField.getText();
ChatMessage chat = new ChatMessage( name, message ); ChatMessage chat = new ChatMessage(name, message);
chat.setReliable(reliable); chat.setReliable(reliable);
System.out.println( "Sending:" + chat ); System.out.println("Sending:" + chat);
client.send( chat ); client.send(chat);
} }
} }
} }

@ -29,7 +29,6 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package jme3test.network; package jme3test.network;
import com.jme3.network.Message; import com.jme3.network.Message;
@ -41,7 +40,6 @@ import com.jme3.network.Server;
import com.jme3.network.serializing.Serializable; import com.jme3.network.serializing.Serializable;
import com.jme3.network.serializing.Serializer; import com.jme3.network.serializing.Serializer;
/** /**
* A simple test chat server. When SM implements a set * A simple test chat server. When SM implements a set
* of standard chat classes this can become a lot simpler. * of standard chat classes this can become a lot simpler.
@ -49,105 +47,92 @@ import com.jme3.network.serializing.Serializer;
* @version $Revision$ * @version $Revision$
* @author Paul Speed * @author Paul Speed
*/ */
public class TestChatServer public class TestChatServer {
{
// Normally these and the initialized method would // Normally these and the initialized method would
// be in shared constants or something. // be in shared constants or something.
public static final String NAME = "Test Chat Server"; public static final String NAME = "Test Chat Server";
public static final int VERSION = 1; public static final int VERSION = 1;
public static final int PORT = 5110; public static final int PORT = 5110;
public static final int UDP_PORT = 5110; public static final int UDP_PORT = 5110;
public static void initializeClasses() public static void initializeClasses() {
{
// Doing it here means that the client code only needs to // Doing it here means that the client code only needs to
// call our initialize. // call our initialize.
Serializer.registerClass(ChatMessage.class); Serializer.registerClass(ChatMessage.class);
} }
public static void main( String... args ) throws Exception public static void main(String... args) throws Exception {
{
initializeClasses(); initializeClasses();
// Use this to test the client/server name version check // Use this to test the client/server name version check
Server server = Network.createServer( NAME, VERSION, PORT, UDP_PORT ); Server server = Network.createServer(NAME, VERSION, PORT, UDP_PORT);
server.start(); server.start();
ChatHandler handler = new ChatHandler(); ChatHandler handler = new ChatHandler();
server.addMessageListener( handler, ChatMessage.class ); server.addMessageListener(handler, ChatMessage.class);
// Keep running basically forever // Keep running basically forever
synchronized( NAME ) { synchronized (NAME) {
NAME.wait(); NAME.wait();
} }
} }
private static class ChatHandler implements MessageListener<HostedConnection> private static class ChatHandler implements MessageListener<HostedConnection> {
{
public ChatHandler() public ChatHandler() {
{
} }
public void messageReceived( HostedConnection source, Message m ) public void messageReceived(HostedConnection source, Message m) {
{ if (m instanceof ChatMessage) {
if( m instanceof ChatMessage ) {
// Keep track of the name just in case we // Keep track of the name just in case we
// want to know it for some other reason later and it's // want to know it for some other reason later and it's
// a good example of session data // a good example of session data
source.setAttribute( "name", ((ChatMessage)m).getName() ); source.setAttribute("name", ((ChatMessage) m).getName());
System.out.println( "Broadcasting:" + m + " reliable:" + m.isReliable() ); System.out.println("Broadcasting:" + m + " reliable:" + m.isReliable());
// Just rebroadcast... the reliable flag will stay the // Just rebroadcast... the reliable flag will stay the
// same so if it came in on UDP it will go out on that too // same so if it came in on UDP it will go out on that too
source.getServer().broadcast( m ); source.getServer().broadcast(m);
} else { } else {
System.err.println( "Received odd message:" + m ); System.err.println("Received odd message:" + m);
} }
} }
} }
@Serializable @Serializable
public static class ChatMessage extends AbstractMessage public static class ChatMessage extends AbstractMessage {
{
private String name; private String name;
private String message; private String message;
public ChatMessage() public ChatMessage() {
{
} }
public ChatMessage( String name, String message ) public ChatMessage(String name, String message) {
{
setName(name); setName(name);
setMessage(message); setMessage(message);
} }
public void setName( String name ) public void setName(String name) {
{
this.name = name; this.name = name;
} }
public String getName() public String getName() {
{
return name; return name;
} }
public void setMessage( String s ) public void setMessage(String s) {
{
this.message = s; this.message = s;
} }
public String getMessage() public String getMessage() {
{
return message; return message;
} }
public String toString() public String toString() {
{
return name + ":" + message; return name + ":" + message;
} }
} }
} }

@ -1,58 +0,0 @@
/*
* Copyright (c) 2009-2010 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jme3test.network;
import com.jme3.network.connection.Client;
import com.jme3.network.connection.Server;
import java.io.IOException;
import java.net.InetAddress;
import java.util.List;
public class TestHostDiscovery {
public static void main(String[] args) throws IOException, InterruptedException{
Server server = new Server(5110, 5110);
server.start();
Client client = new Client();
client.start();
List<InetAddress> hosts = client.discoverHosts(5110, 5000);
for (InetAddress host : hosts){
System.out.println("Found host: " + host);
System.out.println("Reachable? " + host.isReachable(5000));
}
System.out.println("Connecting to: "+ hosts.get(0));
client.connect(hosts.get(0).getCanonicalHostName(), 5110, 5110);
}
}

@ -32,16 +32,18 @@
package jme3test.network; package jme3test.network;
import com.jme3.network.connection.Client; import com.jme3.network.Client;
import com.jme3.network.connection.Server; import com.jme3.network.HostedConnection;
import com.jme3.network.events.MessageAdapter; import com.jme3.network.MessageListener;
import com.jme3.network.message.Message; import com.jme3.network.Network;
import com.jme3.network.Server;
import com.jme3.network.Message;
import com.jme3.network.serializing.Serializable; import com.jme3.network.serializing.Serializable;
import com.jme3.network.serializing.Serializer; import com.jme3.network.serializing.Serializer;
import com.jme3.network.sync.MovingAverage; import com.jme3.network.sync.MovingAverage;
import java.io.IOException; import java.io.IOException;
public class TestLatency extends MessageAdapter { public class TestLatency {
private static long startTime; private static long startTime;
private static Client client; private static Client client;
@ -56,7 +58,7 @@ public class TestLatency extends MessageAdapter {
} }
@Serializable @Serializable
public static class TimestampMessage extends Message { public static class TimestampMessage extends com.jme3.network.message.Message {
long timeSent = 0; long timeSent = 0;
long timeReceived = 0; long timeReceived = 0;
@ -73,14 +75,19 @@ public class TestLatency extends MessageAdapter {
} }
@Override public static void main(String[] args) throws IOException, InterruptedException{
public void messageReceived(Message msg){ Serializer.registerClass(TimestampMessage.class);
TimestampMessage timeMsg = (TimestampMessage) msg;
try { Server server = Network.createServer(5110);
if (timeMsg.timeReceived == 0){ server.start();
TimestampMessage outMsg = new TimestampMessage(timeMsg.timeSent, getTime());
msg.getClient().send(outMsg); client = Network.connectToServer("localhost", 5110);
}else{ client.start();
client.addMessageListener(new MessageListener<Client>(){
public void messageReceived(Client source, Message m) {
TimestampMessage timeMsg = (TimestampMessage) m;
long curTime = getTime(); long curTime = getTime();
//System.out.println("Time sent: " + timeMsg.timeSent); //System.out.println("Time sent: " + timeMsg.timeSent);
//System.out.println("Time received by server: " + timeMsg.timeReceived); //System.out.println("Time received by server: " + timeMsg.timeReceived);
@ -99,26 +106,24 @@ public class TestLatency extends MessageAdapter {
client.send(new TimestampMessage(getTime(), 0)); client.send(new TimestampMessage(getTime(), 0));
} }
} catch (IOException ex) { }, TimestampMessage.class);
ex.printStackTrace();
}
}
public static void main(String[] args) throws IOException, InterruptedException{ server.addMessageListener(new MessageListener<HostedConnection>(){
Serializer.registerClass(TimestampMessage.class); public void messageReceived(HostedConnection source, Message m) {
TimestampMessage timeMsg = (TimestampMessage) m;
Server server = new Server(5110, 5110); TimestampMessage outMsg = new TimestampMessage(timeMsg.timeSent, getTime());
server.start(); source.send(outMsg);
}
client = new Client("localhost", 5110, 5110); }, TimestampMessage.class);
client.start();
client.addMessageListener(new TestLatency(), TimestampMessage.class);
server.addMessageListener(new TestLatency(), TimestampMessage.class);
Thread.sleep(1); Thread.sleep(1);
client.send(new TimestampMessage(getTime(), 0)); client.send(new TimestampMessage(getTime(), 0));
Object obj = new Object();
synchronized(obj){
obj.wait();
}
} }
} }

@ -32,12 +32,12 @@
package jme3test.network; package jme3test.network;
import com.jme3.network.AbstractMessage;
import com.jme3.network.Client; import com.jme3.network.Client;
import com.jme3.network.HostedConnection; import com.jme3.network.HostedConnection;
import com.jme3.network.MessageListener; import com.jme3.network.MessageListener;
import com.jme3.network.Network; import com.jme3.network.Network;
import com.jme3.network.Server; import com.jme3.network.Server;
import com.jme3.network.message.Message;
import com.jme3.network.serializing.Serializable; import com.jme3.network.serializing.Serializable;
import com.jme3.network.serializing.Serializer; import com.jme3.network.serializing.Serializer;
import java.io.IOException; import java.io.IOException;
@ -45,11 +45,11 @@ import java.io.IOException;
public class TestMessages { public class TestMessages {
@Serializable @Serializable
public static class PingMessage extends Message { public static class PingMessage extends AbstractMessage {
} }
@Serializable @Serializable
public static class PongMessage extends Message { public static class PongMessage extends AbstractMessage {
} }
private static class ServerPingResponder implements MessageListener<HostedConnection> { private static class ServerPingResponder implements MessageListener<HostedConnection> {
@ -76,15 +76,18 @@ public class TestMessages {
Server server = Network.createServer(5110); Server server = Network.createServer(5110);
server.start(); server.start();
Client client = Network.connectToServer("192.168.1.101", 5110, 5111); Client client = Network.connectToServer("localhost", 5110);
client.start(); client.start();
server.addMessageListener(new ServerPingResponder(), PingMessage.class); server.addMessageListener(new ServerPingResponder(), PingMessage.class);
client.addMessageListener(new ClientPingResponder(), PongMessage.class); client.addMessageListener(new ClientPingResponder(), PongMessage.class);
Thread.sleep(100); System.out.println("Client: Sending ping message..");
System.out.println("Sending ping message..");
client.send(new PingMessage()); client.send(new PingMessage());
Object obj = new Object();
synchronized (obj){
obj.wait();
}
} }
} }

@ -32,37 +32,39 @@
package jme3test.network; package jme3test.network;
import com.jme3.network.connection.Client; import com.jme3.network.Client;
import com.jme3.network.connection.Server; import com.jme3.network.ConnectionListener;
import com.jme3.network.events.ConnectionAdapter; import com.jme3.network.HostedConnection;
import com.jme3.network.Network;
import com.jme3.network.Server;
import java.io.IOException; import java.io.IOException;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
public class TestNetworkStress extends ConnectionAdapter { public class TestNetworkStress implements ConnectionListener {
@Override public void connectionAdded(Server server, HostedConnection conn) {
public void clientConnected(Client client) { System.out.println("Client Connected: "+conn.getId());
System.out.println("CLIENT CONNECTED: "+client.getClientID()); //conn.close("goodbye");
try { }
client.kick("goodbye");
} catch (IOException ex) { public void connectionRemoved(Server server, HostedConnection conn) {
ex.printStackTrace();
}
} }
public static void main(String[] args) throws IOException, InterruptedException{ public static void main(String[] args) throws IOException, InterruptedException{
Logger.getLogger("").getHandlers()[0].setLevel(Level.OFF); Logger.getLogger("").getHandlers()[0].setLevel(Level.OFF);
Server server = new Server(5110, 5110); Server server = Network.createServer(5110);
server.start(); server.start();
server.addConnectionListener(new TestNetworkStress()); server.addConnectionListener(new TestNetworkStress());
for (int i = 0; i < 1000; i++){ for (int i = 0; i < 1000; i++){
Client client = new Client("localhost", 5110, 5110); Client client = Network.connectToServer("localhost", 5110);
client.start(); client.start();
Thread.sleep(10); Thread.sleep(10);
client.close();
} }
} }
} }

@ -34,25 +34,45 @@ package jme3test.network;
import com.jme3.app.SimpleApplication; import com.jme3.app.SimpleApplication;
import com.jme3.export.Savable; import com.jme3.export.Savable;
import com.jme3.network.connection.Client; import com.jme3.network.Client;
import com.jme3.network.connection.Server; import com.jme3.network.Network;
import com.jme3.network.Server;
import com.jme3.network.rmi.ObjectDef;
import com.jme3.network.rmi.ObjectStore; import com.jme3.network.rmi.ObjectStore;
import com.jme3.network.rmi.RemoteObjectDefMessage;
import com.jme3.network.serializing.Serializer; import com.jme3.network.serializing.Serializer;
import com.jme3.network.serializing.serializers.SavableSerializer; import com.jme3.network.serializing.serializers.SavableSerializer;
import com.jme3.scene.Spatial; import com.jme3.scene.Spatial;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Method;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
public class TestRemoteCall { public class TestRemoteCall {
private static SimpleApplication serverApp; private static SimpleApplication serverApp;
/**
* Interface implemented by the server, exposing
* RMI calls that clients can use.
*/
public static interface ServerAccess { public static interface ServerAccess {
public void attachChild(String model); /**
* Attaches the model with the given name to the server's scene.
*
* @param model The model name
*
* @return True if the model was attached.
*
* @throws RuntimeException If some error occurs.
*/
public boolean attachChild(String model);
} }
public static class ServerAccessImpl implements ServerAccess { public static class ServerAccessImpl implements ServerAccess {
public void attachChild(String model) { public boolean attachChild(String model) {
if (model == null)
throw new RuntimeException("Cannot be null. .. etc");
final String finalModel = model; final String finalModel = model;
serverApp.enqueue(new Callable<Void>() { serverApp.enqueue(new Callable<Void>() {
public Void call() throws Exception { public Void call() throws Exception {
@ -61,6 +81,7 @@ public class TestRemoteCall {
return null; return null;
} }
}); });
return true;
} }
} }
@ -73,7 +94,7 @@ public class TestRemoteCall {
serverApp.start(); serverApp.start();
try { try {
Server server = new Server(5110, 5110); Server server = Network.createServer(5110);
server.start(); server.start();
ObjectStore store = new ObjectStore(server); ObjectStore store = new ObjectStore(server);
@ -88,11 +109,12 @@ public class TestRemoteCall {
createServer(); createServer();
Client client = new Client("localhost", 5110, 5110); Client client = Network.connectToServer("localhost", 5110);
client.start(); client.start();
ObjectStore store = new ObjectStore(client); ObjectStore store = new ObjectStore(client);
ServerAccess access = store.getExposedObject("access", ServerAccess.class, true); ServerAccess access = store.getExposedObject("access", ServerAccess.class, true);
access.attachChild("Models/Ferrari/WheelBackLeft.mesh.xml"); boolean result = access.attachChild("Models/Oto/Oto.mesh.xml");
System.out.println(result);
} }
} }

@ -29,9 +29,9 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package jme3test.network; package jme3test.network;
import com.jme3.network.AbstractMessage;
import com.jme3.network.Client; import com.jme3.network.Client;
import com.jme3.network.Message; import com.jme3.network.Message;
import com.jme3.network.MessageConnection; import com.jme3.network.MessageConnection;
@ -47,59 +47,64 @@ public class TestThroughput implements MessageListener<MessageConnection> { //ex
private static long lastTime = -1; private static long lastTime = -1;
private static long counter = 0; private static long counter = 0;
private static long total = 0; private static long total = 0;
private static Client client;
// Change this flag to test UDP instead of TCP // Change this flag to test UDP instead of TCP
private static boolean testReliable = false; private static boolean testReliable = false;
private boolean isOnServer; private boolean isOnServer;
public TestThroughput( boolean isOnServer ) { public TestThroughput(boolean isOnServer) {
this.isOnServer = isOnServer; this.isOnServer = isOnServer;
} }
@Serializable
public static class TestMessage extends AbstractMessage {
public TestMessage() {
setReliable(testReliable);
}
}
@Override @Override
public void messageReceived( MessageConnection source, Message msg){ public void messageReceived(MessageConnection source, Message msg) {
if( !isOnServer ) { if (!isOnServer) {
// It's local to the client so we got it back // It's local to the client so we got it back
counter++; counter++;
total++; total++;
long time = System.currentTimeMillis(); long time = System.currentTimeMillis();
//System.out.println( "total:" + total + " counter:" + counter + " lastTime:" + lastTime + " time:" + time ); //System.out.println( "total:" + total + " counter:" + counter + " lastTime:" + lastTime + " time:" + time );
if( lastTime < 0 ) { if (lastTime < 0) {
lastTime = time; lastTime = time;
} else if( time - lastTime > 1000 ) { } else if (time - lastTime > 1000) {
long delta = time - lastTime; long delta = time - lastTime;
double scale = delta / 1000.0; double scale = delta / 1000.0;
double pps = counter / scale; double pps = counter / scale;
System.out.println( "messages per second:" + pps + " total messages:" + total ); System.out.println("messages per second:" + pps + " total messages:" + total);
counter = 0; counter = 0;
lastTime = time; lastTime = time;
} }
} else { } else {
if( source == null ) { if (source == null) {
System.out.println( "Received a message from a not fully connected source, msg:"+ msg ); System.out.println("Received a message from a not fully connected source, msg:" + msg);
} else { } else {
//System.out.println( "sending:" + msg + " back to client:" + source ); //System.out.println( "sending:" + msg + " back to client:" + source );
// The 'reliable' flag is transient and the server doesn't // The 'reliable' flag is transient and the server doesn't
// (yet) reset this value for us. // (yet) reset this value for us.
((com.jme3.network.message.Message)msg).setReliable(testReliable); ((com.jme3.network.Message) msg).setReliable(testReliable);
source.send(msg); source.send(msg);
} }
} }
} }
public static void main(String[] args) throws IOException, InterruptedException{ public static void main(String[] args) throws IOException, InterruptedException {
Serializer.registerClass(TestMessage.class); Serializer.registerClass(TestMessage.class);
// Use this to test the client/server name version check // Use this to test the client/server name version check
//Server server = Network.createServer( "bad name", 42, 5110, 5110 ); //Server server = Network.createServer( "bad name", 42, 5110, 5110 );
Server server = Network.createServer( 5110, 5110 ); Server server = Network.createServer(5110, 5110);
server.start(); server.start();
Client client = Network.connectToServer( "localhost", 5110 ); Client client = Network.connectToServer("localhost", 5110);
client.start(); client.start();
client.addMessageListener(new TestThroughput(false), TestMessage.class); client.addMessageListener(new TestThroughput(false), TestMessage.class);
@ -109,20 +114,11 @@ public class TestThroughput implements MessageListener<MessageConnection> { //ex
TestMessage test = new TestMessage(); TestMessage test = new TestMessage();
// for( int i = 0; i < 10; i++ ) { // for( int i = 0; i < 10; i++ ) {
while( true ) { while (true) {
//System.out.println( "sending." ); //System.out.println( "sending." );
client.send(test); client.send(test);
}
//Thread.sleep(5000);
}
@Serializable
public static class TestMessage extends com.jme3.network.message.Message {
public TestMessage(){
setReliable(testReliable);
} }
}
//Thread.sleep(5000);
}
} }

Loading…
Cancel
Save