* 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
This commit is contained in:
		
							parent
							
								
									95cdde7f53
								
							
						
					
					
						commit
						8cbb0f210d
					
				| @ -260,7 +260,10 @@ public class MaterialHelper extends AbstractBlenderHelper { | ||||
|                             Texture texture = textureHelper.getTexture(tex, dataRepository); | ||||
|                             if (texture != null) { | ||||
|                                 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 | ||||
|                                     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()}; | ||||
|  | ||||
| @ -48,6 +48,8 @@ import java.util.BitSet; | ||||
|  */ | ||||
| public final class AnimChannel { | ||||
| 
 | ||||
|     private static final float DEFAULT_BLEND_TIME = 0.15f; | ||||
|      | ||||
|     private AnimControl control; | ||||
| 
 | ||||
| //    private ArrayList<Integer> affectedBones; | ||||
| @ -61,7 +63,7 @@ public final class AnimChannel { | ||||
|     private float speedBlendFrom; | ||||
| 
 | ||||
|     private LoopMode loopMode, loopModeBlendFrom; | ||||
|     private float defaultBlendTime = 0.15f; | ||||
|      | ||||
| 
 | ||||
|     private float blendAmount = 1f; | ||||
|     private float blendRate   = 0; | ||||
| @ -95,6 +97,15 @@ public final class AnimChannel { | ||||
|         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 | ||||
|      * none is assigned. | ||||
| @ -180,6 +191,7 @@ public final class AnimChannel { | ||||
| 
 | ||||
|     /** | ||||
|      * Set the current animation that is played by this AnimChannel. | ||||
|      * <p> | ||||
|      * This resets the time to zero, and optionally blends the animation | ||||
|      * over <code>blendTime</code> seconds with the currently playing animation. | ||||
|      * Notice that this method will reset the control's speed to 1.0. | ||||
| @ -219,11 +231,15 @@ public final class AnimChannel { | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * | ||||
|      * @param name | ||||
|      * Set the current animation that is played by this AnimChannel. | ||||
|      * <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){ | ||||
|         setAnim(name, defaultBlendTime); | ||||
|         setAnim(name, DEFAULT_BLEND_TIME); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -294,7 +310,6 @@ public final class AnimChannel { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     void reset(){ | ||||
|         animation = 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 | ||||
|      * constructor are restored from the saved model, but the object must be | ||||
|      * constructed beforehand) | ||||
|      * Serialization only. Do not use. | ||||
|      */ | ||||
|     public AnimControl() { | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Internal use only. | ||||
|      */ | ||||
|     public Control cloneForSpatial(Spatial spatial) { | ||||
|         try { | ||||
|             AnimControl clone = (AnimControl) super.clone(); | ||||
| @ -268,6 +269,9 @@ public final class AnimControl extends AbstractControl implements Savable, Clone | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Internal use only. | ||||
|      */ | ||||
|     @Override | ||||
|     public void setSpatial(Spatial spatial) { | ||||
|         if (spatial == null && skeletonControl != null){ | ||||
| @ -310,7 +314,10 @@ public final class AnimControl extends AbstractControl implements Savable, Clone | ||||
| 
 | ||||
|         return a.getLength(); | ||||
|     } | ||||
| 
 | ||||
|      | ||||
|     /** | ||||
|      * Internal use only. | ||||
|      */ | ||||
|     @Override | ||||
|     protected void controlUpdate(float tpf) { | ||||
|         skeleton.reset(); // reset skeleton to bind pose | ||||
| @ -322,6 +329,9 @@ public final class AnimControl extends AbstractControl implements Savable, Clone | ||||
|         skeleton.updateWorldVectors(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Internal use only. | ||||
|      */ | ||||
|     @Override | ||||
|     protected void controlRender(RenderManager rm, ViewPort vp) { | ||||
|     } | ||||
|  | ||||
| @ -93,9 +93,8 @@ public final class Bone implements Savable { | ||||
|     private Vector3f worldPos = new Vector3f(); | ||||
|     private Quaternion worldRot = new Quaternion(); | ||||
|     private Vector3f worldScale = new Vector3f(); | ||||
|      | ||||
|     //used for getCombinedTransform  | ||||
|     private Transform tmpTransform=new Transform(); | ||||
|     private Transform tmpTransform = new Transform(); | ||||
| 
 | ||||
|     /** | ||||
|      * 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. | ||||
|      */ | ||||
|     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. | ||||
|      */ | ||||
|     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. | ||||
|      */ | ||||
|     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. | ||||
|      */ | ||||
|     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. | ||||
|      */ | ||||
|     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. | ||||
|      */ | ||||
|     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. | ||||
|      */ | ||||
|     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. | ||||
|      */ | ||||
|     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. | ||||
|      */ | ||||
|     public Vector3f getModelSpaceScale() { | ||||
|         return worldScale; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Returns the inverse world bind pose position. | ||||
|      *  | ||||
|      * @return the inverse world bind pose position. | ||||
|      */ | ||||
|     public Vector3f getWorldBindInversePosition() { | ||||
|         return worldBindInversePos; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Returns the inverse world bind pose rotation. | ||||
|      *  | ||||
|      * @return the inverse world bind pose rotation. | ||||
|      */ | ||||
|     public Quaternion getWorldBindInverseRotation() { | ||||
|         return worldBindInverseRot; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Returns the inverse world bind pose scale. | ||||
|      *  | ||||
|      * @return the inverse world bind pose scale. | ||||
|      */ | ||||
|     public Vector3f getWorldBindInverseScale() { | ||||
|         return worldBindInverseScale; | ||||
|     } | ||||
| @ -375,18 +406,18 @@ public final class Bone implements Savable { | ||||
|         worldPos.set(translation); | ||||
|         worldRot.set(rotation); | ||||
|     } | ||||
|      | ||||
| 
 | ||||
|     /** | ||||
|      * Returns the local transform of this bone combined with the given position and rotation | ||||
|      * @param position a position | ||||
|      * @param rotation a rotation | ||||
|      */ | ||||
|     public Transform getCombinedTransform(Vector3f position, Quaternion rotation){ | ||||
|             rotation.mult(localPos, tmpTransform.getTranslation()).addLocal(position); | ||||
|             tmpTransform.setRotation(rotation).getRotation().multLocal(localRot); | ||||
|             return tmpTransform; | ||||
|     public Transform getCombinedTransform(Vector3f position, Quaternion rotation) { | ||||
|         rotation.mult(localPos, tmpTransform.getTranslation()).addLocal(position); | ||||
|         tmpTransform.setRotation(rotation).getRotation().multLocal(localRot); | ||||
|         return tmpTransform; | ||||
|     } | ||||
|      | ||||
| 
 | ||||
|     /** | ||||
|      * Returns the attachment node. | ||||
|      * 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) { | ||||
|         StringBuilder sb = new StringBuilder(); | ||||
|         for (int i = 0; i < depth; i++) { | ||||
|  | ||||
| @ -41,18 +41,22 @@ import java.io.IOException; | ||||
| 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. | ||||
|  */ | ||||
| public final class BoneAnimation implements Savable { | ||||
| 
 | ||||
|     private static final long serialVersionUID = 1L; | ||||
| 
 | ||||
|     private String name; | ||||
|     private float length; | ||||
| 
 | ||||
|     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){ | ||||
|         this.name = name; | ||||
|         this.length = length; | ||||
|  | ||||
| @ -39,11 +39,8 @@ import com.jme3.export.OutputCapsule; | ||||
| import com.jme3.export.Savable; | ||||
| import com.jme3.scene.Mesh; | ||||
| import java.io.IOException; | ||||
| import java.io.Serializable; | ||||
| 
 | ||||
| public class MeshAnimation implements Serializable, Savable { | ||||
| 
 | ||||
|     private static final long serialVersionUID = 1L; | ||||
| public class MeshAnimation implements Savable { | ||||
| 
 | ||||
|     private String name; | ||||
|     private float length; | ||||
|  | ||||
| @ -40,15 +40,12 @@ import com.jme3.export.Savable; | ||||
| import com.jme3.math.Vector3f; | ||||
| import com.jme3.util.BufferUtils; | ||||
| import java.io.IOException; | ||||
| import java.io.Serializable; | ||||
| import java.nio.FloatBuffer; | ||||
| 
 | ||||
| /** | ||||
|  * 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 { | ||||
| 
 | ||||
|     private static final long serialVersionUID = 1L; | ||||
| public final class Pose implements Savable { | ||||
| 
 | ||||
|     private String name; | ||||
|     private int targetMeshIndex; | ||||
|  | ||||
| @ -41,7 +41,6 @@ import com.jme3.scene.Mesh; | ||||
| import com.jme3.scene.VertexBuffer; | ||||
| import com.jme3.scene.VertexBuffer.Type; | ||||
| import java.io.IOException; | ||||
| import java.io.Serializable; | ||||
| import java.nio.FloatBuffer; | ||||
| 
 | ||||
| /** | ||||
| @ -49,15 +48,11 @@ import java.nio.FloatBuffer; | ||||
|  */ | ||||
| public final class PoseTrack extends Track { | ||||
|      | ||||
|     private static final long serialVersionUID = 1L; | ||||
| 
 | ||||
|     private PoseFrame[] frames; | ||||
|     private float[]     times; | ||||
| 
 | ||||
|     public static class PoseFrame implements Savable { | ||||
| 
 | ||||
|         private static final long serialVersionUID = 1L; | ||||
| 
 | ||||
|         Pose[] poses; | ||||
|         float[] weights; | ||||
| 
 | ||||
|  | ||||
| @ -37,15 +37,12 @@ import com.jme3.export.JmeImporter; | ||||
| import com.jme3.export.Savable; | ||||
| import com.jme3.scene.Mesh; | ||||
| import java.io.IOException; | ||||
| import java.io.Serializable; | ||||
| 
 | ||||
| /** | ||||
|  * A single track of mesh animation (either morph or pose based). | ||||
|  * Currently morph animations are not supported (only pose). | ||||
|  */ | ||||
| public abstract class Track implements Serializable, Savable { | ||||
|      | ||||
|     private static final long serialVersionUID = 1L; | ||||
| public abstract class Track implements Savable { | ||||
| 
 | ||||
|     protected int targetMeshIndex; | ||||
| 
 | ||||
|  | ||||
| @ -18,72 +18,73 @@ import com.jme3.math.Vector3f; | ||||
|  * @author Marcin Roguski (Kaelthas) | ||||
|  */ | ||||
| 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 | ||||
| 	public void influenceParticle(Particle particle, EmitterShape emitterShape) { | ||||
| 		emitterShape.getRandomPoint(particle.position); | ||||
| 		this.applyVelocityVariation(particle); | ||||
| 	} | ||||
|     /** 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; | ||||
| 
 | ||||
| 	/** | ||||
| 	 * This method applies the variation to the particle with already set velocity. | ||||
| 	 * @param particle | ||||
| 	 *        the particle to be affected | ||||
| 	 */ | ||||
| 	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 influenceParticle(Particle particle, EmitterShape emitterShape) { | ||||
|         emitterShape.getRandomPoint(particle.position); | ||||
|         this.applyVelocityVariation(particle); | ||||
|     } | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void write(JmeExporter ex) throws IOException { | ||||
| 		OutputCapsule oc = ex.getCapsule(this); | ||||
| 		oc.write(startVelocity, "startVelocity", Vector3f.ZERO); | ||||
| 		oc.write(velocityVariation, "variation", 0.2f); | ||||
| 	} | ||||
|     /** | ||||
|      * This method applies the variation to the particle with already set velocity. | ||||
|      * @param particle | ||||
|      *        the particle to be affected | ||||
|      */ | ||||
|     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 read(JmeImporter im) throws IOException { | ||||
| 		InputCapsule ic = im.getCapsule(this); | ||||
| 		startVelocity = (Vector3f) ic.readSavable("startVelocity", Vector3f.ZERO); | ||||
| 		velocityVariation = ic.readFloat("variation", 0.2f); | ||||
| 	} | ||||
|     @Override | ||||
|     public void write(JmeExporter ex) throws IOException { | ||||
|         OutputCapsule oc = ex.getCapsule(this); | ||||
|         oc.write(startVelocity, "startVelocity", Vector3f.ZERO); | ||||
|         oc.write(velocityVariation, "variation", 0.2f); | ||||
|     } | ||||
| 
 | ||||
| 	@Override | ||||
| 	public ParticleInfluencer clone() { | ||||
| 		try { | ||||
| 			return (ParticleInfluencer) super.clone(); | ||||
| 		} catch (CloneNotSupportedException e) { | ||||
| 			return null; | ||||
| 		} | ||||
| 	} | ||||
|     @Override | ||||
|     public void read(JmeImporter im) throws IOException { | ||||
|         InputCapsule ic = im.getCapsule(this); | ||||
|         startVelocity = (Vector3f) ic.readSavable("startVelocity", Vector3f.ZERO); | ||||
|         velocityVariation = ic.readFloat("variation", 0.2f); | ||||
|     } | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void setInitialVelocity(Vector3f initialVelocity) { | ||||
| 		this.startVelocity.set(initialVelocity); | ||||
| 	} | ||||
|     @Override | ||||
|     public ParticleInfluencer clone() { | ||||
|         try { | ||||
|             return (ParticleInfluencer) super.clone(); | ||||
|         } catch (CloneNotSupportedException e) { | ||||
|             return null; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| 	@Override | ||||
| 	public Vector3f getInitialVelocity() { | ||||
| 		return startVelocity; | ||||
| 	} | ||||
|     @Override | ||||
|     public void setInitialVelocity(Vector3f initialVelocity) { | ||||
|         this.startVelocity.set(initialVelocity); | ||||
|     } | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void setVelocityVariation(float variation) { | ||||
| 		this.velocityVariation = variation; | ||||
| 	} | ||||
|     @Override | ||||
|     public Vector3f getInitialVelocity() { | ||||
|         return startVelocity; | ||||
|     } | ||||
| 
 | ||||
| 	@Override | ||||
| 	public float getVelocityVariation() { | ||||
| 		return velocityVariation; | ||||
| 	} | ||||
|     @Override | ||||
|     public void setVelocityVariation(float variation) { | ||||
|         this.velocityVariation = variation; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public float getVelocityVariation() { | ||||
|         return velocityVariation; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -15,37 +15,42 @@ import com.jme3.math.Vector3f; | ||||
|  */ | ||||
| public class EmptyParticleInfluencer implements ParticleInfluencer { | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void write(JmeExporter ex) throws IOException {} | ||||
|     @Override | ||||
|     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 | ||||
|     public void influenceParticle(Particle particle, EmitterShape emitterShape) { | ||||
|     } | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void setInitialVelocity(Vector3f initialVelocity) {} | ||||
|     @Override | ||||
|     public void setInitialVelocity(Vector3f initialVelocity) { | ||||
|     } | ||||
| 
 | ||||
| 	@Override | ||||
| 	public Vector3f getInitialVelocity() { | ||||
| 		return null; | ||||
| 	} | ||||
|     @Override | ||||
|     public Vector3f getInitialVelocity() { | ||||
|         return null; | ||||
|     } | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void setVelocityVariation(float variation) {} | ||||
|     @Override | ||||
|     public void setVelocityVariation(float variation) { | ||||
|     } | ||||
| 
 | ||||
| 	@Override | ||||
| 	public float getVelocityVariation() { | ||||
| 		return 0; | ||||
| 	} | ||||
|     @Override | ||||
|     public float getVelocityVariation() { | ||||
|         return 0; | ||||
|     } | ||||
| 
 | ||||
| 	@Override | ||||
| 	public ParticleInfluencer clone() { | ||||
| 		try { | ||||
| 			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) | ||||
|  */ | ||||
| public class NewtonianParticleInfluencer extends DefaultParticleInfluencer { | ||||
| 	/** Normal to emitter's shape factor. */ | ||||
| 	protected float	normalVelocity; | ||||
| 	/** Emitter's surface tangent factor. */ | ||||
| 	protected float	surfaceTangentFactor; | ||||
| 	/** Emitters tangent rotation factor. */ | ||||
| 	protected float	surfaceTangentRotation; | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Constructor. Sets velocity variation to 0.0f. | ||||
| 	 */ | ||||
| 	public NewtonianParticleInfluencer() { | ||||
| 		this.velocityVariation = 0.0f; | ||||
| 	} | ||||
|     /** Normal to emitter's shape factor. */ | ||||
|     protected float normalVelocity; | ||||
|     /** Emitter's surface tangent factor. */ | ||||
|     protected float surfaceTangentFactor; | ||||
|     /** Emitters tangent rotation factor. */ | ||||
|     protected float surfaceTangentRotation; | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void influenceParticle(Particle particle, EmitterShape emitterShape) { | ||||
| 		emitterShape.getRandomPointAndNormal(particle.position, particle.velocity); | ||||
| 		// influencing the particle's velocity | ||||
| 		if (surfaceTangentFactor == 0.0f) { | ||||
| 			particle.velocity.multLocal(normalVelocity); | ||||
| 		} else { | ||||
| 			// calculating surface tangent (velocity contains the 'normal' value) | ||||
| 			temp.set(particle.velocity.z * surfaceTangentFactor, particle.velocity.y * surfaceTangentFactor, -particle.velocity.x * surfaceTangentFactor); | ||||
| 			if (surfaceTangentRotation != 0.0f) {// rotating the tangent | ||||
| 				Matrix3f m = new Matrix3f(); | ||||
| 				m.fromAngleNormalAxis(FastMath.PI * surfaceTangentRotation, particle.velocity); | ||||
| 				temp = m.multLocal(temp); | ||||
| 			} | ||||
| 			// applying normal factor (this must be done first) | ||||
| 			particle.velocity.multLocal(normalVelocity); | ||||
| 			// adding tangent vector | ||||
| 			particle.velocity.addLocal(temp); | ||||
| 		} | ||||
| 		if (velocityVariation != 0.0f) { | ||||
| 			this.applyVelocityVariation(particle); | ||||
| 		} | ||||
| 	} | ||||
|     /** | ||||
|      * Constructor. Sets velocity variation to 0.0f. | ||||
|      */ | ||||
|     public NewtonianParticleInfluencer() { | ||||
|         this.velocityVariation = 0.0f; | ||||
|     } | ||||
| 
 | ||||
| 	/** | ||||
| 	 * This method returns the normal velocity factor. | ||||
| 	 * @return the normal velocity factor | ||||
| 	 */ | ||||
| 	public float getNormalVelocity() { | ||||
| 		return normalVelocity; | ||||
| 	} | ||||
|     @Override | ||||
|     public void influenceParticle(Particle particle, EmitterShape emitterShape) { | ||||
|         emitterShape.getRandomPointAndNormal(particle.position, particle.velocity); | ||||
|         // influencing the particle's velocity | ||||
|         if (surfaceTangentFactor == 0.0f) { | ||||
|             particle.velocity.multLocal(normalVelocity); | ||||
|         } else { | ||||
|             // calculating surface tangent (velocity contains the 'normal' value) | ||||
|             temp.set(particle.velocity.z * surfaceTangentFactor, particle.velocity.y * surfaceTangentFactor, -particle.velocity.x * surfaceTangentFactor); | ||||
|             if (surfaceTangentRotation != 0.0f) {// rotating the tangent | ||||
|                 Matrix3f m = new Matrix3f(); | ||||
|                 m.fromAngleNormalAxis(FastMath.PI * surfaceTangentRotation, particle.velocity); | ||||
|                 temp = m.multLocal(temp); | ||||
|             } | ||||
|             // applying normal factor (this must be done first) | ||||
|             particle.velocity.multLocal(normalVelocity); | ||||
|             // adding tangent vector | ||||
|             particle.velocity.addLocal(temp); | ||||
|         } | ||||
|         if (velocityVariation != 0.0f) { | ||||
|             this.applyVelocityVariation(particle); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| 	/** | ||||
| 	 * This method sets the normal velocity factor. | ||||
| 	 * @param normalVelocity | ||||
| 	 *        the normal velocity factor | ||||
| 	 */ | ||||
| 	public void setNormalVelocity(float normalVelocity) { | ||||
| 		this.normalVelocity = normalVelocity; | ||||
| 	} | ||||
|     /** | ||||
|      * This method returns the normal velocity factor. | ||||
|      * @return the normal velocity factor | ||||
|      */ | ||||
|     public float getNormalVelocity() { | ||||
|         return normalVelocity; | ||||
|     } | ||||
| 
 | ||||
| 	/** | ||||
| 	 * This method sets the surface tangent factor. | ||||
| 	 * @param surfaceTangentFactor | ||||
| 	 *        the surface tangent factor | ||||
| 	 */ | ||||
| 	public void setSurfaceTangentFactor(float surfaceTangentFactor) { | ||||
| 		this.surfaceTangentFactor = surfaceTangentFactor; | ||||
| 	} | ||||
|     /** | ||||
|      * This method sets the normal velocity factor. | ||||
|      * @param normalVelocity | ||||
|      *        the normal velocity factor | ||||
|      */ | ||||
|     public void setNormalVelocity(float normalVelocity) { | ||||
|         this.normalVelocity = normalVelocity; | ||||
|     } | ||||
| 
 | ||||
| 	/** | ||||
| 	 * This method returns the surface tangent factor. | ||||
| 	 * @return the surface tangent factor | ||||
| 	 */ | ||||
| 	public float getSurfaceTangentFactor() { | ||||
| 		return surfaceTangentFactor; | ||||
| 	} | ||||
|     /** | ||||
|      * This method sets the surface tangent factor. | ||||
|      * @param surfaceTangentFactor | ||||
|      *        the surface tangent factor | ||||
|      */ | ||||
|     public void setSurfaceTangentFactor(float surfaceTangentFactor) { | ||||
|         this.surfaceTangentFactor = surfaceTangentFactor; | ||||
|     } | ||||
| 
 | ||||
| 	/** | ||||
| 	 * This method sets the surface tangent rotation factor. | ||||
| 	 * @param surfaceTangentRotation | ||||
| 	 *        the surface tangent rotation factor | ||||
| 	 */ | ||||
| 	public void setSurfaceTangentRotation(float surfaceTangentRotation) { | ||||
| 		this.surfaceTangentRotation = surfaceTangentRotation; | ||||
| 	} | ||||
|     /** | ||||
|      * This method returns the surface tangent factor. | ||||
|      * @return the surface tangent factor | ||||
|      */ | ||||
|     public float getSurfaceTangentFactor() { | ||||
|         return surfaceTangentFactor; | ||||
|     } | ||||
| 
 | ||||
| 	/** | ||||
| 	 * This method returns the surface tangent rotation factor. | ||||
| 	 * @return the surface tangent rotation factor | ||||
| 	 */ | ||||
| 	public float getSurfaceTangentRotation() { | ||||
| 		return surfaceTangentRotation; | ||||
| 	} | ||||
|     /** | ||||
|      * This method sets the surface tangent rotation factor. | ||||
|      * @param surfaceTangentRotation | ||||
|      *        the surface tangent rotation factor | ||||
|      */ | ||||
|     public void setSurfaceTangentRotation(float surfaceTangentRotation) { | ||||
|         this.surfaceTangentRotation = surfaceTangentRotation; | ||||
|     } | ||||
| 
 | ||||
| 	@Override | ||||
| 	protected void applyVelocityVariation(Particle particle) { | ||||
| 		temp.set(FastMath.nextRandomFloat() * velocityVariation, FastMath.nextRandomFloat() * velocityVariation, FastMath.nextRandomFloat() * velocityVariation); | ||||
| 		particle.velocity.addLocal(temp); | ||||
| 	} | ||||
|     /** | ||||
|      * This method returns the surface tangent rotation factor. | ||||
|      * @return the surface tangent rotation factor | ||||
|      */ | ||||
|     public float getSurfaceTangentRotation() { | ||||
|         return surfaceTangentRotation; | ||||
|     } | ||||
| 
 | ||||
| 	@Override | ||||
| 	public ParticleInfluencer clone() { | ||||
| 		NewtonianParticleInfluencer result = new NewtonianParticleInfluencer(); | ||||
| 		result.normalVelocity = normalVelocity; | ||||
| 		result.startVelocity = startVelocity; | ||||
| 		result.velocityVariation = velocityVariation; | ||||
| 		result.surfaceTangentFactor = surfaceTangentFactor; | ||||
| 		result.surfaceTangentRotation = surfaceTangentRotation; | ||||
| 		return result; | ||||
| 	} | ||||
|     @Override | ||||
|     protected void applyVelocityVariation(Particle particle) { | ||||
|         temp.set(FastMath.nextRandomFloat() * velocityVariation, FastMath.nextRandomFloat() * velocityVariation, FastMath.nextRandomFloat() * velocityVariation); | ||||
|         particle.velocity.addLocal(temp); | ||||
|     } | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void write(JmeExporter ex) throws IOException { | ||||
| 		super.write(ex); | ||||
| 		OutputCapsule oc = ex.getCapsule(this); | ||||
| 		oc.write(normalVelocity, "normalVelocity", 0.0f); | ||||
| 		oc.write(surfaceTangentFactor, "surfaceTangentFactor", 0.0f); | ||||
| 		oc.write(surfaceTangentRotation, "surfaceTangentRotation", 0.0f); | ||||
| 	} | ||||
|     @Override | ||||
|     public ParticleInfluencer clone() { | ||||
|         NewtonianParticleInfluencer result = new NewtonianParticleInfluencer(); | ||||
|         result.normalVelocity = normalVelocity; | ||||
|         result.startVelocity = startVelocity; | ||||
|         result.velocityVariation = velocityVariation; | ||||
|         result.surfaceTangentFactor = surfaceTangentFactor; | ||||
|         result.surfaceTangentRotation = surfaceTangentRotation; | ||||
|         return result; | ||||
|     } | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void read(JmeImporter im) throws IOException { | ||||
| 		super.read(im); | ||||
| 		InputCapsule ic = im.getCapsule(this); | ||||
| 		normalVelocity = ic.readFloat("normalVelocity", 0.0f); | ||||
| 		surfaceTangentFactor = ic.readFloat("surfaceTangentFactor", 0.0f); | ||||
| 		surfaceTangentRotation = ic.readFloat("surfaceTangentRotation", 0.0f); | ||||
| 	} | ||||
|     @Override | ||||
|     public void write(JmeExporter ex) throws IOException { | ||||
|         super.write(ex); | ||||
|         OutputCapsule oc = ex.getCapsule(this); | ||||
|         oc.write(normalVelocity, "normalVelocity", 0.0f); | ||||
|         oc.write(surfaceTangentFactor, "surfaceTangentFactor", 0.0f); | ||||
|         oc.write(surfaceTangentRotation, "surfaceTangentRotation", 0.0f); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void read(JmeImporter im) throws IOException { | ||||
|         super.read(im); | ||||
|         InputCapsule ic = im.getCapsule(this); | ||||
|         normalVelocity = ic.readFloat("normalVelocity", 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) | ||||
|  */ | ||||
| public interface ParticleInfluencer extends Savable, Cloneable { | ||||
| 	/** | ||||
| 	 * This method influences the particle. | ||||
| 	 * @param particle | ||||
| 	 *        particle to be influenced | ||||
| 	 * @param emitterShape | ||||
| 	 *        the shape of it emitter | ||||
| 	 */ | ||||
| 	void influenceParticle(Particle particle, EmitterShape emitterShape); | ||||
| 
 | ||||
| 	/** | ||||
| 	 * This method clones the influencer instance. | ||||
| 	 * @return cloned instance | ||||
| 	 */ | ||||
| 	public ParticleInfluencer clone(); | ||||
|     /** | ||||
|      * This method influences the particle. | ||||
|      * @param particle | ||||
|      *        particle to be influenced | ||||
|      * @param emitterShape | ||||
|      *        the shape of it emitter | ||||
|      */ | ||||
|     void influenceParticle(Particle particle, EmitterShape emitterShape); | ||||
| 
 | ||||
| 	/** | ||||
| 	 * @param initialVelocity | ||||
| 	 *        Set the initial velocity a particle is spawned with, | ||||
| 	 *        the initial velocity given in the parameter will be varied according | ||||
| 	 *        to the velocity variation set in {@link ParticleEmitter#setVelocityVariation(float) }. | ||||
| 	 *        A particle will move toward its velocity unless it is effected by the | ||||
| 	 *        gravity. | ||||
| 	 */ | ||||
| 	void setInitialVelocity(Vector3f initialVelocity); | ||||
|     /** | ||||
|      * This method clones the influencer instance. | ||||
|      * @return cloned instance | ||||
|      */ | ||||
|     public ParticleInfluencer clone(); | ||||
| 
 | ||||
| 	/** | ||||
| 	 * This method returns the initial velocity. | ||||
| 	 * @return the initial velocity | ||||
| 	 */ | ||||
| 	Vector3f getInitialVelocity(); | ||||
|     /** | ||||
|      * @param initialVelocity | ||||
|      *        Set the initial velocity a particle is spawned with, | ||||
|      *        the initial velocity given in the parameter will be varied according | ||||
|      *        to the velocity variation set in {@link ParticleEmitter#setVelocityVariation(float) }. | ||||
|      *        A particle will move toward its velocity unless it is effected by the | ||||
|      *        gravity. | ||||
|      */ | ||||
|     void setInitialVelocity(Vector3f initialVelocity); | ||||
| 
 | ||||
| 	/** | ||||
| 	 * @param variation | ||||
| 	 *        Set the variation by which the initial velocity | ||||
| 	 *        of the particle is determined. <code>variation</code> should be a value | ||||
| 	 *        from 0 to 1, where 0 means particles are to spawn with exactly | ||||
| 	 *        the velocity given in {@link ParticleEmitter#setStartVel(com.jme3.math.Vector3f) }, | ||||
| 	 *        and 1 means particles are to spawn with a completely random velocity. | ||||
| 	 */ | ||||
| 	void setVelocityVariation(float variation); | ||||
|     /** | ||||
|      * This method returns the initial velocity. | ||||
|      * @return the initial velocity | ||||
|      */ | ||||
|     Vector3f getInitialVelocity(); | ||||
| 
 | ||||
| 	/** | ||||
| 	 * This method returns the velocity variation. | ||||
| 	 * @return the velocity variation | ||||
| 	 */ | ||||
| 	float getVelocityVariation(); | ||||
|     /** | ||||
|      * @param variation | ||||
|      *        Set the variation by which the initial velocity | ||||
|      *        of the particle is determined. <code>variation</code> should be a value | ||||
|      *        from 0 to 1, where 0 means particles are to spawn with exactly | ||||
|      *        the velocity given in {@link ParticleEmitter#setStartVel(com.jme3.math.Vector3f) }, | ||||
|      *        and 1 means particles are to spawn with a completely random velocity. | ||||
|      */ | ||||
|     void setVelocityVariation(float variation); | ||||
| 
 | ||||
|     /** | ||||
|      * This method returns the velocity variation. | ||||
|      * @return the velocity variation | ||||
|      */ | ||||
|     float getVelocityVariation(); | ||||
| } | ||||
|  | ||||
| @ -29,7 +29,6 @@ | ||||
|  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| 
 | ||||
| package com.jme3.effect.shapes; | ||||
| 
 | ||||
| import com.jme3.export.JmeExporter; | ||||
| @ -44,26 +43,26 @@ public class EmitterBoxShape implements EmitterShape { | ||||
| 
 | ||||
|     private Vector3f min, len; | ||||
| 
 | ||||
|     public EmitterBoxShape(){ | ||||
|     public EmitterBoxShape() { | ||||
|     } | ||||
| 
 | ||||
|     public EmitterBoxShape(Vector3f min, Vector3f max) { | ||||
|         if (min == null || max == null) { | ||||
| 			throw new NullPointerException(); | ||||
| 		} | ||||
|             throw new NullPointerException(); | ||||
|         } | ||||
| 
 | ||||
|         this.min = min; | ||||
|         this.len = new Vector3f(); | ||||
|         this.len.set(max).subtractLocal(min); | ||||
|     } | ||||
|      | ||||
| 
 | ||||
|     @Override | ||||
| 	public void getRandomPoint(Vector3f store) { | ||||
|     public void getRandomPoint(Vector3f store) { | ||||
|         store.x = min.x + len.x * FastMath.nextRandomFloat(); | ||||
|         store.y = min.y + len.y * FastMath.nextRandomFloat(); | ||||
|         store.z = min.z + len.z * FastMath.nextRandomFloat(); | ||||
|     } | ||||
|      | ||||
| 
 | ||||
|     /** | ||||
|      * This method fills the point with data. | ||||
|      * It does not fill the normal. | ||||
| @ -72,11 +71,11 @@ public class EmitterBoxShape implements EmitterShape { | ||||
|      */ | ||||
|     @Override | ||||
|     public void getRandomPointAndNormal(Vector3f store, Vector3f normal) { | ||||
|     	this.getRandomPoint(store); | ||||
|         this.getRandomPoint(store); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
| 	public EmitterShape deepClone(){ | ||||
|     public EmitterShape deepClone() { | ||||
|         try { | ||||
|             EmitterBoxShape clone = (EmitterBoxShape) super.clone(); | ||||
|             clone.min = min.clone(); | ||||
| @ -104,16 +103,16 @@ public class EmitterBoxShape implements EmitterShape { | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
| 	public void write(JmeExporter ex) throws IOException { | ||||
|     public void write(JmeExporter ex) throws IOException { | ||||
|         OutputCapsule oc = ex.getCapsule(this); | ||||
|         oc.write(min, "min", null); | ||||
|         oc.write(len, "length", null); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
| 	public void read(JmeImporter im) throws IOException { | ||||
|     public void read(JmeImporter im) throws IOException { | ||||
|         InputCapsule ic = im.getCapsule(this); | ||||
|         min = (Vector3f) ic.readSavable("min", null); | ||||
|         len = (Vector3f) ic.readSavable("length", null); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | ||||
| @ -13,50 +13,52 @@ import com.jme3.scene.Mesh; | ||||
|  * @author Marcin Roguski (Kaelthas) | ||||
|  */ | ||||
| public class EmitterMeshConvexHullShape extends EmitterMeshFaceShape { | ||||
| 	/** | ||||
| 	 * Empty constructor. Sets nothing. | ||||
| 	 */ | ||||
| 	public EmitterMeshConvexHullShape() {} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Constructor. It stores a copy of vertex list of all meshes. | ||||
| 	 * @param meshes | ||||
| 	 *        a list of meshes that will form the emitter's shape | ||||
| 	 */ | ||||
| 	public EmitterMeshConvexHullShape(List<Mesh> meshes) { | ||||
| 		super(meshes); | ||||
| 	} | ||||
|     /** | ||||
|      * Empty constructor. Sets nothing. | ||||
|      */ | ||||
|     public EmitterMeshConvexHullShape() { | ||||
|     } | ||||
| 
 | ||||
| 	/** | ||||
| 	 * This method fills the point with coordinates of randomly selected point inside a convex hull | ||||
| 	 * of randomly selected mesh. | ||||
| 	 * @param store | ||||
| 	 *        the variable to store with coordinates of randomly selected selected point inside a convex hull | ||||
| 	 *        of randomly selected mesh | ||||
| 	 */ | ||||
| 	@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()); | ||||
| 	} | ||||
|     /** | ||||
|      * Constructor. It stores a copy of vertex list of all meshes. | ||||
|      * @param meshes | ||||
|      *        a list of meshes that will form the emitter's shape | ||||
|      */ | ||||
|     public EmitterMeshConvexHullShape(List<Mesh> meshes) { | ||||
|         super(meshes); | ||||
|     } | ||||
| 
 | ||||
| 	/** | ||||
| 	 * 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()); | ||||
| 	} | ||||
|     /** | ||||
|      * This method fills the point with coordinates of randomly selected point inside a convex hull | ||||
|      * of randomly selected mesh. | ||||
|      * @param store | ||||
|      *        the variable to store with coordinates of randomly selected selected point inside a convex hull | ||||
|      *        of randomly selected mesh | ||||
|      */ | ||||
|     @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 | ||||
|      * 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) | ||||
|  */ | ||||
| public class EmitterMeshFaceShape extends EmitterMeshVertexShape { | ||||
| 	/** | ||||
| 	 * Empty constructor. Sets nothing. | ||||
| 	 */ | ||||
| 	public EmitterMeshFaceShape() {} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Constructor. It stores a copy of vertex list of all meshes. | ||||
| 	 * @param meshes | ||||
| 	 *        a list of meshes that will form the emitter's shape | ||||
| 	 */ | ||||
| 	public EmitterMeshFaceShape(List<Mesh> meshes) { | ||||
| 		super(meshes); | ||||
| 	} | ||||
|     /** | ||||
|      * Empty constructor. Sets nothing. | ||||
|      */ | ||||
|     public EmitterMeshFaceShape() { | ||||
|     } | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void setMeshes(List<Mesh> meshes) { | ||||
| 		this.vertices = new ArrayList<List<Vector3f>>(meshes.size()); | ||||
| 		this.normals = new ArrayList<List<Vector3f>>(meshes.size()); | ||||
| 		for (Mesh mesh : meshes) { | ||||
| 			Vector3f[] vertexTable = BufferUtils.getVector3Array(mesh.getFloatBuffer(Type.Position)); | ||||
| 			int[] indices = new int[3]; | ||||
| 			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); | ||||
| 		} | ||||
| 	} | ||||
|     /** | ||||
|      * Constructor. It stores a copy of vertex list of all meshes. | ||||
|      * @param meshes | ||||
|      *        a list of meshes that will form the emitter's shape | ||||
|      */ | ||||
|     public EmitterMeshFaceShape(List<Mesh> meshes) { | ||||
|         super(meshes); | ||||
|     } | ||||
| 
 | ||||
| 	/** | ||||
| 	 * This method fills the point with coordinates of randomly selected point on a random face. | ||||
| 	 * @param store | ||||
| 	 *        the variable to store with coordinates of randomly selected selected point on a random face | ||||
| 	 */ | ||||
| 	@Override | ||||
| 	public void getRandomPoint(Vector3f store) { | ||||
| 		int meshIndex = FastMath.nextRandomInt(0, vertices.size() - 1); | ||||
| 		// the index of the first vertex of a face (must be dividable by 3) | ||||
| 		int vertIndex = FastMath.nextRandomInt(0, vertices.get(meshIndex).size() / 3 - 1) * 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); | ||||
| 	} | ||||
|     @Override | ||||
|     public void setMeshes(List<Mesh> meshes) { | ||||
|         this.vertices = new ArrayList<List<Vector3f>>(meshes.size()); | ||||
|         this.normals = new ArrayList<List<Vector3f>>(meshes.size()); | ||||
|         for (Mesh mesh : meshes) { | ||||
|             Vector3f[] vertexTable = BufferUtils.getVector3Array(mesh.getFloatBuffer(Type.Position)); | ||||
|             int[] indices = new int[3]; | ||||
|             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); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| 	/** | ||||
| 	 * 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 | ||||
| 	 *        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)); | ||||
| 	} | ||||
|     /** | ||||
|      * This method fills the point with coordinates of randomly selected point on a random face. | ||||
|      * @param store | ||||
|      *        the variable to store with coordinates of randomly selected selected point on a random face | ||||
|      */ | ||||
|     @Override | ||||
|     public void getRandomPoint(Vector3f store) { | ||||
|         int meshIndex = FastMath.nextRandomInt(0, vertices.size() - 1); | ||||
|         // the index of the first vertex of a face (must be dividable by 3) | ||||
|         int vertIndex = FastMath.nextRandomInt(0, vertices.get(meshIndex).size() / 3 - 1) * 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); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 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 | ||||
|      *        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) | ||||
|  */ | ||||
| public class EmitterMeshVertexShape implements EmitterShape { | ||||
| 	protected List<List<Vector3f>>	vertices; | ||||
| 	protected List<List<Vector3f>>	normals; | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Empty constructor. Sets nothing. | ||||
| 	 */ | ||||
| 	public EmitterMeshVertexShape() {} | ||||
|     protected List<List<Vector3f>> vertices; | ||||
|     protected List<List<Vector3f>> normals; | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Constructor. It stores a copy of vertex list of all meshes. | ||||
| 	 * @param meshes | ||||
| 	 *        a list of meshes that will form the emitter's shape | ||||
| 	 */ | ||||
| 	public EmitterMeshVertexShape(List<Mesh> meshes) { | ||||
| 		this.setMeshes(meshes); | ||||
| 	} | ||||
|     /** | ||||
|      * Empty constructor. Sets nothing. | ||||
|      */ | ||||
|     public EmitterMeshVertexShape() { | ||||
|     } | ||||
| 
 | ||||
| 	/** | ||||
| 	 * This method sets the meshes that will form the emiter's shape. | ||||
| 	 * @param meshes | ||||
| 	 *        a list of meshes that will form the emitter's shape | ||||
| 	 */ | ||||
| 	public void setMeshes(List<Mesh> meshes) { | ||||
| 		Map<Vector3f, Vector3f> vertToNormalMap = new HashMap<Vector3f, Vector3f>(); | ||||
|     /** | ||||
|      * Constructor. It stores a copy of vertex list of all meshes. | ||||
|      * @param meshes | ||||
|      *        a list of meshes that will form the emitter's shape | ||||
|      */ | ||||
|     public EmitterMeshVertexShape(List<Mesh> meshes) { | ||||
|         this.setMeshes(meshes); | ||||
|     } | ||||
| 
 | ||||
| 		this.vertices = new ArrayList<List<Vector3f>>(meshes.size()); | ||||
| 		this.normals = new ArrayList<List<Vector3f>>(meshes.size()); | ||||
| 		for (Mesh mesh : meshes) { | ||||
| 			// fetching the data | ||||
| 			float[] vertexTable = BufferUtils.getFloatArray(mesh.getFloatBuffer(Type.Position)); | ||||
| 			float[] normalTable = BufferUtils.getFloatArray(mesh.getFloatBuffer(Type.Normal)); | ||||
|     /** | ||||
|      * This method sets the meshes that will form the emiter's shape. | ||||
|      * @param meshes | ||||
|      *        a list of meshes that will form the emitter's shape | ||||
|      */ | ||||
|     public void setMeshes(List<Mesh> meshes) { | ||||
|         Map<Vector3f, Vector3f> vertToNormalMap = new HashMap<Vector3f, Vector3f>(); | ||||
| 
 | ||||
| 			// unifying normals | ||||
| 			for (int i = 0; i < vertexTable.length; i += 3) {// the tables should have the same size and be dividable by 3 | ||||
| 				Vector3f vert = new Vector3f(vertexTable[i], vertexTable[i + 1], vertexTable[i + 2]); | ||||
| 				Vector3f norm = vertToNormalMap.get(vert); | ||||
| 				if (norm == null) { | ||||
| 					norm = new Vector3f(normalTable[i], normalTable[i + 1], normalTable[i + 2]); | ||||
| 					vertToNormalMap.put(vert, norm); | ||||
| 				} else { | ||||
| 					norm.addLocal(normalTable[i], normalTable[i + 1], normalTable[i + 2]); | ||||
| 				} | ||||
| 			} | ||||
|         this.vertices = new ArrayList<List<Vector3f>>(meshes.size()); | ||||
|         this.normals = new ArrayList<List<Vector3f>>(meshes.size()); | ||||
|         for (Mesh mesh : meshes) { | ||||
|             // fetching the data | ||||
|             float[] vertexTable = BufferUtils.getFloatArray(mesh.getFloatBuffer(Type.Position)); | ||||
|             float[] normalTable = BufferUtils.getFloatArray(mesh.getFloatBuffer(Type.Normal)); | ||||
| 
 | ||||
| 			// adding data to vertices and normals | ||||
| 			List<Vector3f> vertices = new ArrayList<Vector3f>(vertToNormalMap.size()); | ||||
| 			List<Vector3f> normals = new ArrayList<Vector3f>(vertToNormalMap.size()); | ||||
| 			for (Entry<Vector3f, Vector3f> entry : vertToNormalMap.entrySet()) { | ||||
| 				vertices.add(entry.getKey()); | ||||
| 				normals.add(entry.getValue().normalizeLocal()); | ||||
| 			} | ||||
| 			this.vertices.add(vertices); | ||||
| 			this.normals.add(normals); | ||||
| 		} | ||||
| 	} | ||||
|             // unifying normals | ||||
|             for (int i = 0; i < vertexTable.length; i += 3) {// the tables should have the same size and be dividable by 3 | ||||
|                 Vector3f vert = new Vector3f(vertexTable[i], vertexTable[i + 1], vertexTable[i + 2]); | ||||
|                 Vector3f norm = vertToNormalMap.get(vert); | ||||
|                 if (norm == null) { | ||||
|                     norm = new Vector3f(normalTable[i], normalTable[i + 1], normalTable[i + 2]); | ||||
|                     vertToNormalMap.put(vert, norm); | ||||
|                 } else { | ||||
|                     norm.addLocal(normalTable[i], normalTable[i + 1], normalTable[i + 2]); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
| 	/** | ||||
| 	 * This method fills the point with coordinates of randomly selected mesh vertex. | ||||
| 	 * @param store | ||||
| 	 *        the variable to store with coordinates of randomly selected mesh vertex | ||||
| 	 */ | ||||
| 	@Override | ||||
| 	public void getRandomPoint(Vector3f store) { | ||||
| 		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)); | ||||
| 	} | ||||
|             // adding data to vertices and normals | ||||
|             List<Vector3f> vertices = new ArrayList<Vector3f>(vertToNormalMap.size()); | ||||
|             List<Vector3f> normals = new ArrayList<Vector3f>(vertToNormalMap.size()); | ||||
|             for (Entry<Vector3f, Vector3f> entry : vertToNormalMap.entrySet()) { | ||||
|                 vertices.add(entry.getKey()); | ||||
|                 normals.add(entry.getValue().normalizeLocal()); | ||||
|             } | ||||
|             this.vertices.add(vertices); | ||||
|             this.normals.add(normals); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| 	/** | ||||
| 	 * This method fills the point with coordinates of randomly selected mesh vertex. | ||||
| 	 * The normal param is filled with selected vertex's normal. | ||||
| 	 * @param store | ||||
| 	 *        the variable to store with coordinates of randomly selected mesh vertex | ||||
| 	 * @param normal | ||||
| 	 *        filled with selected vertex's normal | ||||
| 	 */ | ||||
| 	@Override | ||||
| 	public void getRandomPointAndNormal(Vector3f store, Vector3f normal) { | ||||
| 		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)); | ||||
| 	} | ||||
|     /** | ||||
|      * This method fills the point with coordinates of randomly selected mesh vertex. | ||||
|      * @param store | ||||
|      *        the variable to store with coordinates of randomly selected mesh vertex | ||||
|      */ | ||||
|     @Override | ||||
|     public void getRandomPoint(Vector3f store) { | ||||
|         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)); | ||||
|     } | ||||
| 
 | ||||
| 	@Override | ||||
| 	public EmitterShape deepClone() { | ||||
| 		try { | ||||
| 			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(); | ||||
| 		} | ||||
| 	} | ||||
|     /** | ||||
|      * This method fills the point with coordinates of randomly selected mesh vertex. | ||||
|      * The normal param is filled with selected vertex's normal. | ||||
|      * @param store | ||||
|      *        the variable to store with coordinates of randomly selected mesh vertex | ||||
|      * @param normal | ||||
|      *        filled with selected vertex's normal | ||||
|      */ | ||||
|     @Override | ||||
|     public void getRandomPointAndNormal(Vector3f store, Vector3f normal) { | ||||
|         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 void write(JmeExporter ex) throws IOException { | ||||
| 		OutputCapsule oc = ex.getCapsule(this); | ||||
| 		oc.writeSavableArrayList((ArrayList<List<Vector3f>>) vertices, "vertices", null); | ||||
| 	} | ||||
|     @Override | ||||
|     public EmitterShape deepClone() { | ||||
|         try { | ||||
|             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 | ||||
| 	@SuppressWarnings("unchecked") | ||||
| 	public void read(JmeImporter im) throws IOException { | ||||
| 		this.vertices = im.getCapsule(this).readSavableArrayList("vertices", null); | ||||
| 	} | ||||
|     @Override | ||||
|     public void write(JmeExporter ex) throws IOException { | ||||
|         OutputCapsule oc = ex.getCapsule(this); | ||||
|         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 | ||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| 
 | ||||
| package com.jme3.effect.shapes; | ||||
| 
 | ||||
| import com.jme3.export.JmeExporter; | ||||
| @ -42,15 +41,15 @@ public class EmitterPointShape implements EmitterShape { | ||||
| 
 | ||||
|     private Vector3f point; | ||||
| 
 | ||||
|     public EmitterPointShape(){ | ||||
|     public EmitterPointShape() { | ||||
|     } | ||||
| 
 | ||||
|     public EmitterPointShape(Vector3f point){ | ||||
|     public EmitterPointShape(Vector3f point) { | ||||
|         this.point = point; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
| 	public EmitterShape deepClone(){ | ||||
|     public EmitterShape deepClone() { | ||||
|         try { | ||||
|             EmitterPointShape clone = (EmitterPointShape) super.clone(); | ||||
|             clone.point = point.clone(); | ||||
| @ -61,10 +60,10 @@ public class EmitterPointShape implements EmitterShape { | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
| 	public void getRandomPoint(Vector3f store) { | ||||
|        store.set(point); | ||||
|     public void getRandomPoint(Vector3f store) { | ||||
|         store.set(point); | ||||
|     } | ||||
|      | ||||
| 
 | ||||
|     /** | ||||
|      * This method fills the point with data. | ||||
|      * It does not fill the normal. | ||||
| @ -73,7 +72,7 @@ public class EmitterPointShape implements EmitterShape { | ||||
|      */ | ||||
|     @Override | ||||
|     public void getRandomPointAndNormal(Vector3f store, Vector3f normal) { | ||||
|     	store.set(point); | ||||
|         store.set(point); | ||||
|     } | ||||
| 
 | ||||
|     public Vector3f getPoint() { | ||||
| @ -85,14 +84,13 @@ public class EmitterPointShape implements EmitterShape { | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
| 	public void write(JmeExporter ex) throws IOException { | ||||
|     public void write(JmeExporter ex) throws IOException { | ||||
|         OutputCapsule oc = ex.getCapsule(this); | ||||
|         oc.write(point, "point", null); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
| 	public void read(JmeImporter im) throws IOException { | ||||
|     public void read(JmeImporter im) throws IOException { | ||||
|         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 | ||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| 
 | ||||
| package com.jme3.effect.shapes; | ||||
| 
 | ||||
| import com.jme3.export.Savable; | ||||
| @ -40,25 +39,26 @@ import com.jme3.math.Vector3f; | ||||
|  * @author Kirill | ||||
|  */ | ||||
| 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. | ||||
| 	 * @param store | ||||
| 	 *        store variable for initial position | ||||
| 	 * @param normal | ||||
| 	 *        store variable for initial normal | ||||
| 	 */ | ||||
| 	public void getRandomPointAndNormal(Vector3f store, Vector3f normal); | ||||
|     /** | ||||
|      * This method fills in the initial position of the particle. | ||||
|      * @param store | ||||
|      *        store variable for initial position | ||||
|      */ | ||||
|     public void getRandomPoint(Vector3f store); | ||||
| 
 | ||||
| 	/** | ||||
| 	 * 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 | ||||
| 	 */ | ||||
| 	public EmitterShape deepClone(); | ||||
|     /** | ||||
|      * 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. | ||||
|      * @return deep clone of the current instance of the emitter shape | ||||
|      */ | ||||
|     public EmitterShape deepClone(); | ||||
| } | ||||
|  | ||||
| @ -29,7 +29,6 @@ | ||||
|  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| 
 | ||||
| package com.jme3.effect.shapes; | ||||
| 
 | ||||
| import com.jme3.export.JmeExporter; | ||||
| @ -45,24 +44,24 @@ public class EmitterSphereShape implements EmitterShape { | ||||
|     private Vector3f center; | ||||
|     private float radius; | ||||
| 
 | ||||
|     public EmitterSphereShape(){ | ||||
|     public EmitterSphereShape() { | ||||
|     } | ||||
| 
 | ||||
|     public EmitterSphereShape(Vector3f center, float radius) { | ||||
|         if (center == null) { | ||||
| 			throw new NullPointerException(); | ||||
| 		} | ||||
|             throw new NullPointerException(); | ||||
|         } | ||||
| 
 | ||||
|         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.radius = radius; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public EmitterShape deepClone(){ | ||||
|     public EmitterShape deepClone() { | ||||
|         try { | ||||
|             EmitterSphereShape clone = (EmitterSphereShape) super.clone(); | ||||
|             clone.center = center.clone(); | ||||
| @ -73,17 +72,17 @@ public class EmitterSphereShape implements EmitterShape { | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
| 	public void getRandomPoint(Vector3f store) { | ||||
|     public void getRandomPoint(Vector3f store) { | ||||
|         do { | ||||
|             store.x = (FastMath.nextRandomFloat() * 2f - 1f) * radius; | ||||
|             store.y = (FastMath.nextRandomFloat() * 2f - 1f) * radius; | ||||
|             store.z = (FastMath.nextRandomFloat() * 2f - 1f) * radius; | ||||
|         } while (store.distance(center) > radius); | ||||
|     } | ||||
|      | ||||
| 
 | ||||
|     @Override | ||||
|     public void getRandomPointAndNormal(Vector3f store, Vector3f normal) { | ||||
|     	this.getRandomPoint(store); | ||||
|         this.getRandomPoint(store); | ||||
|     } | ||||
| 
 | ||||
|     public Vector3f getCenter() { | ||||
| @ -101,19 +100,18 @@ public class EmitterSphereShape implements EmitterShape { | ||||
|     public void setRadius(float radius) { | ||||
|         this.radius = radius; | ||||
|     } | ||||
|      | ||||
| 
 | ||||
|     @Override | ||||
| 	public void write(JmeExporter ex) throws IOException { | ||||
|     public void write(JmeExporter ex) throws IOException { | ||||
|         OutputCapsule oc = ex.getCapsule(this); | ||||
|         oc.write(center, "center", null); | ||||
|         oc.write(radius, "radius", 0); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
| 	public void read(JmeImporter im) throws IOException { | ||||
|     public void read(JmeImporter im) throws IOException { | ||||
|         InputCapsule ic = im.getCapsule(this); | ||||
|         center = (Vector3f) ic.readSavable("center", null); | ||||
|         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 $ | ||||
|  */ | ||||
| public final class ColorRGBA implements Savable, Cloneable { | ||||
| 
 | ||||
|     private static final long serialVersionUID = 1L; | ||||
|      | ||||
|     /** | ||||
|      * the color black (0,0,0). | ||||
|      */ | ||||
|  | ||||
| @ -40,7 +40,6 @@ import com.jme3.export.Savable; | ||||
| import com.jme3.util.BufferUtils; | ||||
| import com.jme3.util.TempVars; | ||||
| import java.io.IOException; | ||||
| import java.io.Serializable; | ||||
| import java.nio.FloatBuffer; | ||||
| 
 | ||||
| /** | ||||
| @ -51,8 +50,6 @@ import java.nio.FloatBuffer; | ||||
|  * @author Joshua Slack | ||||
|  */ | ||||
| public class Line implements Savable, Cloneable { | ||||
|     //todo: merge with Ray? | ||||
|     private static final long serialVersionUID = 1L; | ||||
| 
 | ||||
|     private Vector3f origin; | ||||
|     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 { | ||||
| 
 | ||||
|     //todo: merge with Line? | ||||
|     private static final long serialVersionUID = 1L; | ||||
| 
 | ||||
|     /** The ray's begining point. */ | ||||
|     public Vector3f origin; | ||||
|  | ||||
| @ -38,7 +38,6 @@ import com.jme3.export.JmeImporter; | ||||
| import com.jme3.export.OutputCapsule; | ||||
| import com.jme3.export.Savable; | ||||
| import java.io.IOException; | ||||
| import java.io.Serializable; | ||||
| 
 | ||||
| 
 | ||||
| /** | ||||
| @ -51,8 +50,7 @@ import java.io.Serializable; | ||||
|  * @author Joshua Slack | ||||
|  */ | ||||
| 
 | ||||
| public final class Rectangle implements Serializable, Savable, Cloneable { | ||||
|     private static final long serialVersionUID = 1L; | ||||
| public final class Rectangle implements Savable, Cloneable { | ||||
| 
 | ||||
|     private Vector3f a, b, c; | ||||
| 
 | ||||
|  | ||||
| @ -38,7 +38,6 @@ import com.jme3.export.JmeImporter; | ||||
| import com.jme3.export.OutputCapsule; | ||||
| import com.jme3.export.Savable; | ||||
| import java.io.IOException; | ||||
| import java.io.Serializable; | ||||
| 
 | ||||
| 
 | ||||
| /** | ||||
| @ -50,8 +49,7 @@ import java.io.Serializable; | ||||
|  * @author Joshua Slack | ||||
|  */ | ||||
| 
 | ||||
| public final class Ring implements Serializable, Savable, Cloneable { | ||||
|     private static final long serialVersionUID = 1L; | ||||
| public final class Ring implements Savable, Cloneable { | ||||
|      | ||||
|     private Vector3f center, up; | ||||
|     private float innerRadius, outerRadius; | ||||
|  | ||||
| @ -52,8 +52,6 @@ import java.util.logging.Logger; | ||||
| public final class Vector2f implements Savable, Cloneable { | ||||
|     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 UNIT_XY = new Vector2f(1f, 1f); | ||||
|      | ||||
|  | ||||
| @ -73,8 +73,6 @@ public class Box extends AbstractBox { | ||||
|         1, 0, 0, 0, 0, 1, 1, 1  // bottom | ||||
|     }; | ||||
| 
 | ||||
|     private static final long serialVersionUID = 1L; | ||||
| 
 | ||||
|     /** | ||||
|      * Creates a new box. | ||||
|      * <p> | ||||
|  | ||||
| @ -56,8 +56,6 @@ import java.nio.ShortBuffer; | ||||
|  */ | ||||
| public class PQTorus extends Mesh { | ||||
| 
 | ||||
|     private static final long serialVersionUID = 1L; | ||||
| 
 | ||||
|     private float p, q; | ||||
| 
 | ||||
|     private float radius, width; | ||||
|  | ||||
| @ -32,12 +32,14 @@ | ||||
| 
 | ||||
| package com.jme3.network.rmi; | ||||
| 
 | ||||
| 
 | ||||
| import com.jme3.network.connection.Client; | ||||
| import com.jme3.network.connection.Server; | ||||
| import com.jme3.network.events.ConnectionListener; | ||||
| import com.jme3.network.events.MessageListener; | ||||
| import com.jme3.network.message.Message; | ||||
| import com.jme3.network.Client; | ||||
| import com.jme3.network.ClientStateListener; | ||||
| import com.jme3.network.ClientStateListener.DisconnectInfo; | ||||
| import com.jme3.network.ConnectionListener; | ||||
| import com.jme3.network.HostedConnection; | ||||
| import com.jme3.network.Message; | ||||
| import com.jme3.network.MessageListener; | ||||
| import com.jme3.network.Server; | ||||
| import com.jme3.network.serializing.Serializer; | ||||
| import com.jme3.util.IntMap; | ||||
| import com.jme3.util.IntMap.Entry; | ||||
| @ -45,11 +47,12 @@ import java.io.IOException; | ||||
| import java.lang.reflect.InvocationTargetException; | ||||
| import java.lang.reflect.Method; | ||||
| import java.lang.reflect.Proxy; | ||||
| import java.util.ArrayList; | ||||
| import java.util.HashMap; | ||||
| import java.util.logging.Level; | ||||
| import java.util.logging.Logger; | ||||
| 
 | ||||
| public class ObjectStore implements MessageListener, ConnectionListener { | ||||
| public class ObjectStore { | ||||
| 
 | ||||
|     private static final Logger logger = Logger.getLogger(ObjectStore.class.getName()); | ||||
| 
 | ||||
| @ -66,6 +69,9 @@ public class ObjectStore implements MessageListener, ConnectionListener { | ||||
| 
 | ||||
|     private Client client; | ||||
|     private Server server; | ||||
|      | ||||
|     private ClientEventHandler clientEventHandler = new ClientEventHandler(); | ||||
|     private ServerEventHandler serverEventHandler = new ServerEventHandler(); | ||||
| 
 | ||||
|     // Local object ID counter | ||||
|     private volatile short objectIdCounter = 0; | ||||
| @ -85,6 +91,38 @@ public class ObjectStore implements MessageListener, ConnectionListener { | ||||
| 
 | ||||
|     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 { | ||||
|         Serializer s = new RmiSerializer(); | ||||
|         Serializer.registerClass(RemoteObjectDefMessage.class, s); | ||||
| @ -92,20 +130,22 @@ public class ObjectStore implements MessageListener, ConnectionListener { | ||||
|         Serializer.registerClass(RemoteMethodReturnMessage.class, s); | ||||
|     } | ||||
| 
 | ||||
|     public ObjectStore(Client client){ | ||||
|     public ObjectStore(Client client) { | ||||
|         this.client = client; | ||||
|         client.addMessageListener(this, RemoteObjectDefMessage.class,  | ||||
|                                         RemoteMethodCallMessage.class, | ||||
|                                         RemoteMethodReturnMessage.class); | ||||
|         client.addConnectionListener(this); | ||||
|         client.addMessageListener(clientEventHandler,  | ||||
|                 RemoteObjectDefMessage.class, | ||||
|                 RemoteMethodCallMessage.class, | ||||
|                 RemoteMethodReturnMessage.class); | ||||
|         client.addClientStateListener(clientEventHandler); | ||||
|     } | ||||
| 
 | ||||
|     public ObjectStore(Server server){ | ||||
|     public ObjectStore(Server server) { | ||||
|         this.server = server; | ||||
|         server.addMessageListener(this, RemoteObjectDefMessage.class,  | ||||
|                                         RemoteMethodCallMessage.class, | ||||
|                                         RemoteMethodReturnMessage.class); | ||||
|         server.addConnectionListener(this); | ||||
|         server.addMessageListener(serverEventHandler,  | ||||
|                 RemoteObjectDefMessage.class, | ||||
|                 RemoteMethodCallMessage.class, | ||||
|                 RemoteMethodReturnMessage.class); | ||||
|         server.addConnectionListener(serverEventHandler); | ||||
|     } | ||||
| 
 | ||||
|     private ObjectDef makeObjectDef(LocalObject localObj){ | ||||
| @ -122,7 +162,15 @@ public class ObjectStore implements MessageListener, ConnectionListener { | ||||
|         localObj.objectName = name; | ||||
|         localObj.objectId  = objectIdCounter++; | ||||
|         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 | ||||
|         localObjects.put(localObj.objectId, localObj); | ||||
| @ -180,18 +228,14 @@ public class ObjectStore implements MessageListener, ConnectionListener { | ||||
|             pendingInvocations.put(call.invocationId, invoke); | ||||
|         } | ||||
| 
 | ||||
|         try{ | ||||
|             if (server != null){ | ||||
|                 remoteObj.client.send(call); | ||||
|                 logger.log(Level.INFO, "Server: Sending {0}", call); | ||||
|             }else{ | ||||
|                 client.send(call); | ||||
|                 logger.log(Level.INFO, "Client: Sending {0}", call); | ||||
|             } | ||||
|         } catch (IOException ex){ | ||||
|             ex.printStackTrace(); | ||||
|         if (server != null){ | ||||
|             remoteObj.client.send(call); | ||||
|             logger.log(Level.INFO, "Server: Sending {0}", call); | ||||
|         }else{ | ||||
|             client.send(call); | ||||
|             logger.log(Level.INFO, "Client: Sending {0}", call); | ||||
|         } | ||||
| 
 | ||||
|         | ||||
|         if (invoke != null){ | ||||
|             synchronized(invoke){ | ||||
|                 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 | ||||
|         // in the message to prevent crashes | ||||
| 
 | ||||
| @ -219,7 +263,7 @@ public class ObjectStore implements MessageListener, ConnectionListener { | ||||
| 
 | ||||
|             ObjectDef[] defs = defMsg.objects; | ||||
|             for (ObjectDef def : defs){ | ||||
|                 RemoteObject remoteObject = new RemoteObject(this, message.getClient()); | ||||
|                 RemoteObject remoteObject = new RemoteObject(this, source); | ||||
|                 remoteObject.objectId = (short)def.objectId; | ||||
|                 remoteObject.methodDefs = def.methodDefs; | ||||
|                 remoteObjects.put(def.objectName, remoteObject); | ||||
| @ -257,16 +301,12 @@ public class ObjectStore implements MessageListener, ConnectionListener { | ||||
|                 RemoteMethodReturnMessage retMsg = new RemoteMethodReturnMessage(); | ||||
|                 retMsg.invocationID = call.invocationId; | ||||
|                 retMsg.retVal = ret; | ||||
|                 try { | ||||
|                     if (server != null){ | ||||
|                         call.getClient().send(retMsg); | ||||
|                         logger.log(Level.INFO, "Server: Sending {0}", retMsg); | ||||
|                     } else{ | ||||
|                         client.send(retMsg); | ||||
|                         logger.log(Level.INFO, "Client: Sending {0}", retMsg); | ||||
|                     } | ||||
|                 } catch (IOException ex){ | ||||
|                     ex.printStackTrace(); | ||||
|                 if (server != null){ | ||||
|                     source.send(retMsg); | ||||
|                     logger.log(Level.INFO, "Server: Sending {0}", retMsg); | ||||
|                 } else{ | ||||
|                     client.send(retMsg); | ||||
|                     logger.log(Level.INFO, "Client: Sending {0}", retMsg); | ||||
|                 } | ||||
|             } | ||||
|         }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){ | ||||
|             // send a object definition message | ||||
|             ObjectDef[] defs = new ObjectDef[localObjects.size()]; | ||||
| @ -297,31 +337,14 @@ public class ObjectStore implements MessageListener, ConnectionListener { | ||||
| 
 | ||||
|             RemoteObjectDefMessage defMsg = new RemoteObjectDefMessage(); | ||||
|             defMsg.objects = defs; | ||||
|             try { | ||||
|                 if (this.client != null){ | ||||
|                     this.client.send(defMsg); | ||||
|                     logger.log(Level.INFO, "Client: Sending {0}", defMsg); | ||||
|                 } else{ | ||||
|                     client.send(defMsg); | ||||
|                     logger.log(Level.INFO, "Server: Sending {0}", defMsg); | ||||
|                 } | ||||
|             } catch (IOException ex){ | ||||
|                 ex.printStackTrace(); | ||||
|             if (this.client != null){ | ||||
|                 this.client.send(defMsg); | ||||
|                 logger.log(Level.INFO, "Client: Sending {0}", defMsg); | ||||
|             } else{ | ||||
|                 conn.send(defMsg); | ||||
|                 logger.log(Level.INFO, "Server: Sending {0}", defMsg); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     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; | ||||
| 
 | ||||
| import com.jme3.network.message.Message; | ||||
| import com.jme3.network.AbstractMessage; | ||||
| import com.jme3.network.serializing.Serializable; | ||||
| 
 | ||||
| /** | ||||
| @ -41,7 +41,7 @@ import com.jme3.network.serializing.Serializable; | ||||
|  * @author Kirill Vainer | ||||
|  */ | ||||
| @Serializable | ||||
| public class RemoteMethodCallMessage extends Message { | ||||
| public class RemoteMethodCallMessage extends AbstractMessage { | ||||
| 
 | ||||
|     public RemoteMethodCallMessage(){ | ||||
|         super(true); | ||||
|  | ||||
| @ -32,8 +32,7 @@ | ||||
| 
 | ||||
| package com.jme3.network.rmi; | ||||
| 
 | ||||
| 
 | ||||
| import com.jme3.network.message.Message; | ||||
| import com.jme3.network.AbstractMessage; | ||||
| import com.jme3.network.serializing.Serializable; | ||||
| 
 | ||||
| /** | ||||
| @ -43,7 +42,7 @@ import com.jme3.network.serializing.Serializable; | ||||
|  * @author Kirill Vainer. | ||||
|  */ | ||||
| @Serializable | ||||
| public class RemoteMethodReturnMessage extends Message { | ||||
| public class RemoteMethodReturnMessage extends AbstractMessage { | ||||
| 
 | ||||
|     public RemoteMethodReturnMessage(){ | ||||
|         super(true); | ||||
|  | ||||
| @ -32,8 +32,7 @@ | ||||
| 
 | ||||
| package com.jme3.network.rmi; | ||||
| 
 | ||||
| 
 | ||||
| import com.jme3.network.connection.Client; | ||||
| import com.jme3.network.HostedConnection; | ||||
| import java.lang.reflect.InvocationHandler; | ||||
| import java.lang.reflect.Method; | ||||
| 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 | ||||
|      * exposed it. | ||||
|      */ | ||||
|     Client client; | ||||
|     HostedConnection client; | ||||
| 
 | ||||
|     public RemoteObject(ObjectStore store, Client client){ | ||||
|     public RemoteObject(ObjectStore store, HostedConnection client){ | ||||
|         this.store = store; | ||||
|         this.client = client; | ||||
|     } | ||||
|  | ||||
| @ -32,9 +32,7 @@ | ||||
| 
 | ||||
| package com.jme3.network.rmi; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| import com.jme3.network.message.Message; | ||||
| import com.jme3.network.AbstractMessage; | ||||
| import com.jme3.network.serializing.Serializable; | ||||
| 
 | ||||
| /** | ||||
| @ -42,7 +40,7 @@ import com.jme3.network.serializing.Serializable; | ||||
|  * @author Kirill Vainer | ||||
|  */ | ||||
| @Serializable | ||||
| public class RemoteObjectDefMessage extends Message { | ||||
| public class RemoteObjectDefMessage extends AbstractMessage { | ||||
| 
 | ||||
|     public ObjectDef[] objects; | ||||
|      | ||||
|  | ||||
| @ -17,7 +17,6 @@ package com.jme3.terrain.geomipmap; | ||||
| // | ||||
| // Please contact the author if you need another license. | ||||
| // This module is provided "as is", without warranties of any kind. | ||||
| 
 | ||||
| import java.util.ArrayList; | ||||
| import java.util.Collection; | ||||
| import java.util.LinkedHashMap; | ||||
| @ -40,85 +39,84 @@ import java.util.Map; | ||||
|  */ | ||||
| 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 int cacheSize; | ||||
| 
 | ||||
| 	private LinkedHashMap<K, V> map; | ||||
| 	private int cacheSize; | ||||
|     /** | ||||
|      * Creates a new LRU cache. | ||||
|      *  | ||||
|      * @param cacheSize | ||||
|      *            the maximum number of entries that will be kept in this cache. | ||||
|      */ | ||||
|     public LRUCache(int cacheSize) { | ||||
|         this.cacheSize = cacheSize; | ||||
|         int hashTableCapacity = (int) Math.ceil(cacheSize / LRUCache.hashTableLoadFactor) + 1; | ||||
|         this.map = new LinkedHashMap<K, V>(hashTableCapacity, LRUCache.hashTableLoadFactor, true) { | ||||
|             // (an anonymous inner class) | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Creates a new LRU cache. | ||||
| 	 *  | ||||
| 	 * @param cacheSize | ||||
| 	 *            the maximum number of entries that will be kept in this cache. | ||||
| 	 */ | ||||
| 	public LRUCache(int cacheSize) { | ||||
| 		this.cacheSize = cacheSize; | ||||
| 		int hashTableCapacity = (int) Math.ceil(cacheSize / LRUCache.hashTableLoadFactor) + 1; | ||||
| 		this.map = new LinkedHashMap<K, V>(hashTableCapacity, LRUCache.hashTableLoadFactor, true) { | ||||
| 			// (an anonymous inner class) | ||||
| 			private static final long serialVersionUID = 1; | ||||
|             private static final long serialVersionUID = 1; | ||||
| 
 | ||||
| 			@Override | ||||
| 			protected boolean removeEldestEntry(Map.Entry<K, V> eldest) { | ||||
| 				return this.size() > LRUCache.this.cacheSize; | ||||
| 			} | ||||
| 		}; | ||||
| 	} | ||||
|             @Override | ||||
|             protected boolean removeEldestEntry(Map.Entry<K, V> eldest) { | ||||
|                 return this.size() > LRUCache.this.cacheSize; | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Retrieves an entry from the cache.<br> | ||||
| 	 * The retrieved entry becomes the MRU (most recently used) entry. | ||||
| 	 *  | ||||
| 	 * @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); | ||||
| 	} | ||||
|     /** | ||||
|      * Retrieves an entry from the cache.<br> | ||||
|      * The retrieved entry becomes the MRU (most recently used) entry. | ||||
|      *  | ||||
|      * @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. | ||||
| 	 * The new 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. | ||||
| 	 * 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); | ||||
| 	} | ||||
|     /** | ||||
|      * Adds an entry to this cache. | ||||
|      * The new 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. | ||||
|      * 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); | ||||
|     } | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Clears the cache. | ||||
| 	 */ | ||||
| 	public synchronized void clear() { | ||||
| 		this.map.clear(); | ||||
| 	} | ||||
|     /** | ||||
|      * Clears the cache. | ||||
|      */ | ||||
|     public synchronized void clear() { | ||||
|         this.map.clear(); | ||||
|     } | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Returns the number of used entries in the cache. | ||||
| 	 *  | ||||
| 	 * @return the number of entries currently in the cache. | ||||
| 	 */ | ||||
| 	public synchronized int usedEntries() { | ||||
| 		return this.map.size(); | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * 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()); | ||||
| 	} | ||||
|     /** | ||||
|      * Returns the number of used entries in the cache. | ||||
|      *  | ||||
|      * @return the number of entries currently in the cache. | ||||
|      */ | ||||
|     public synchronized int usedEntries() { | ||||
|         return this.map.size(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 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 | ||||
|  | ||||
| @ -41,7 +41,7 @@ import java.util.logging.Level; | ||||
| import java.util.logging.Logger; | ||||
| 
 | ||||
| import jme3test.blender.config.ConfigDialog; | ||||
| import jme3test.blender.config.IConfigExecutable; | ||||
| import jme3test.blender.config.ConfigExecutable; | ||||
| import jme3test.blender.scene.Pivot; | ||||
| 
 | ||||
| import com.jme3.animation.AnimControl; | ||||
| @ -67,157 +67,160 @@ import com.jme3.texture.plugins.AWTLoader; | ||||
|  * @author Marcin Roguski (Kaelthas) | ||||
|  */ | ||||
| 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 final boolean debug; | ||||
| 	 | ||||
| 	/** | ||||
| 	 * Starting method | ||||
| 	 * @param args input parameters; the following options can be passed to the application: | ||||
| 	 * <li> -debug   : this one indicates if the application runs in debug or not (it is used under linux | ||||
| 	 * 				   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 | ||||
| 		boolean debug = false; | ||||
| 		for(String arg : args) { | ||||
| 			if("-debug".equalsIgnoreCase(arg)) { | ||||
| 				debug = true; | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 		final boolean debugMode = debug; | ||||
| 		//running the application | ||||
| 		new ConfigDialog("./src/test-data/Blender", new IConfigExecutable() { | ||||
| 			@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 | ||||
| 	 * @param debug variable that indicates if the application runs in debug mode | ||||
| 	 * (this is required on linux to show release the mouse to be used in debug mode) | ||||
| 	 */ | ||||
| 	public ManualBlenderTester(ModelKey modelKey, Level logLevel, boolean debug) { | ||||
| 		this.debug = debug; | ||||
| 		Logger.getLogger("com.jme3").setLevel(logLevel); | ||||
| 		this.modelKey = modelKey; | ||||
| 		this.showSettings = false; | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void simpleInitApp() { | ||||
| 		if(debug) { | ||||
| 			mouseInput.setCursorVisible(true); | ||||
| 		} | ||||
| 		assetManager.registerLocator(".", FileLocator.class); | ||||
| 		assetManager.registerLoader(BlenderLoader.class, "blend"); | ||||
| 		assetManager.registerLoader(AWTLoader.class, "png"); | ||||
|     private static final Logger LOGGER = Logger.getLogger(ManualBlenderTester.class.getName()); | ||||
|     private ModelKey modelKey;//the key that holds the test file configuration | ||||
|     private final boolean debug; | ||||
| 
 | ||||
| 		viewPort.setBackgroundColor(ColorRGBA.Gray); | ||||
|     /** | ||||
|      * Starting method | ||||
|      * @param args input parameters; the following options can be passed to the application: | ||||
|      * <li> -debug   : this one indicates if the application runs in debug or not (it is used under linux | ||||
|      * 				   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 | ||||
|         boolean debug = false; | ||||
|         for (String arg : args) { | ||||
|             if ("-debug".equalsIgnoreCase(arg)) { | ||||
|                 debug = true; | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|         final boolean debugMode = debug; | ||||
|         //running the application | ||||
|         new ConfigDialog("./src/test-data/Blender", new ConfigExecutable() { | ||||
| 
 | ||||
| 		flyCam.setMoveSpeed(20); | ||||
| 		cam.setFrustumFar(1000.0f); | ||||
| 		cam.setFrustumNear(1.0f); | ||||
| 		AssetInfo ai = new AssetInfo(assetManager, modelKey) { | ||||
| 			@Override | ||||
| 			public InputStream openStream() { | ||||
| 				try { | ||||
| 					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(); | ||||
| 			//setting the first animation as active | ||||
| 			if(((BlenderKey) modelKey).getAnimations()!=null) { | ||||
| 				for(Entry<String, Map<String, int[]>> animEntry : animations.entrySet()) { | ||||
| 					for(Entry<String, int[]> anim : animEntry.getValue().entrySet()) { | ||||
| 						Spatial animatedSpatial = this.findNode(blenderModel, animEntry.getKey()); | ||||
| 						animatedSpatial.getControl(AnimControl.class).createChannel().setAnim(anim.getKey()); | ||||
| 						break; | ||||
| 					} | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 		} else { | ||||
| 			this.testBlenderModelLoader(ai); | ||||
| 		} | ||||
| 		 | ||||
| 		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 | ||||
| 	 */ | ||||
| 	private Spatial findNode(Node rootNode, String name) { | ||||
| 		if(name.equals(rootNode.getName())) { | ||||
| 			return rootNode; | ||||
| 		} | ||||
| 		return rootNode.getChild(name); | ||||
| 	} | ||||
|             @Override | ||||
|             public void execute(ModelKey modelKey, Level logLevel) { | ||||
|                 new ManualBlenderTester(modelKey, logLevel, debugMode).start(); | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
| 	/** | ||||
| 	 * This method loads the model using blenderLoader. | ||||
| 	 * @param assetInfo | ||||
| 	 *        the asset info | ||||
| 	 * @return the loaded model | ||||
| 	 */ | ||||
| 	private Node testBlenderLoader(AssetInfo assetInfo) { | ||||
| 		Node blenderModel = null; | ||||
| 		BlenderLoader blenderLoader = new BlenderLoader(); | ||||
| 		try { | ||||
| 			LoadingResults loadingResults = blenderLoader.load(assetInfo); | ||||
| 			for(Node object : loadingResults.getObjects()) { | ||||
| 				this.rootNode.attachChild(object); | ||||
| 				blenderModel = object; | ||||
| 			} | ||||
| 			for(Light light : loadingResults.getLights()) { | ||||
| 				this.rootNode.addLight(light); | ||||
| 			} | ||||
| 			for(Camera camera : loadingResults.getCameras()) { | ||||
| 				LOGGER.info(camera.toString()); | ||||
| 			} | ||||
| 		} catch(IOException e) { | ||||
| 			LOGGER.log(Level.SEVERE, e.getMessage(), e); | ||||
| 		} | ||||
| 		return blenderModel; | ||||
| 	} | ||||
|     /** | ||||
|      * Constructor stores the given key and disables the settings screen. | ||||
|      * @param modelKey the key to be stored | ||||
|      * @param logLevel the jme logger log level | ||||
|      * @param debug variable that indicates if the application runs in debug mode | ||||
|      * (this is required on linux to show release the mouse to be used in debug mode) | ||||
|      */ | ||||
|     public ManualBlenderTester(ModelKey modelKey, Level logLevel, boolean debug) { | ||||
|         this.debug = debug; | ||||
|         Logger.getLogger("com.jme3").setLevel(logLevel); | ||||
|         this.modelKey = modelKey; | ||||
|         this.showSettings = false; | ||||
|     } | ||||
| 
 | ||||
| 	/** | ||||
| 	 * This method loads the model using blenderModelLoader. | ||||
| 	 * @param assetInfo | ||||
| 	 *        the asset info | ||||
| 	 * @return the loaded model | ||||
| 	 */ | ||||
| 	private Node testBlenderModelLoader(AssetInfo assetInfo) { | ||||
| 		BlenderModelLoader blenderLoader = new BlenderModelLoader(); | ||||
| 		try { | ||||
| 			Spatial loadingResults = blenderLoader.load(assetInfo); | ||||
| 			this.rootNode.attachChild(loadingResults); | ||||
| 			if(loadingResults instanceof Node) { | ||||
| 				return (Node)loadingResults; | ||||
| 			} | ||||
| 		} catch(IOException e) { | ||||
| 			LOGGER.log(Level.SEVERE, e.getMessage(), e); | ||||
| 		} | ||||
| 		return null; | ||||
| 	} | ||||
|     @Override | ||||
|     public void simpleInitApp() { | ||||
|         if (debug) { | ||||
|             mouseInput.setCursorVisible(true); | ||||
|         } | ||||
|         assetManager.registerLocator(".", FileLocator.class); | ||||
|         assetManager.registerLoader(BlenderLoader.class, "blend"); | ||||
|         assetManager.registerLoader(AWTLoader.class, "png"); | ||||
| 
 | ||||
|         viewPort.setBackgroundColor(ColorRGBA.Gray); | ||||
| 
 | ||||
|         flyCam.setMoveSpeed(20); | ||||
|         cam.setFrustumFar(1000.0f); | ||||
|         cam.setFrustumNear(1.0f); | ||||
|         AssetInfo ai = new AssetInfo(assetManager, modelKey) { | ||||
| 
 | ||||
|             @Override | ||||
|             public InputStream openStream() { | ||||
|                 try { | ||||
|                     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(); | ||||
|             //setting the first animation as active | ||||
|             if (((BlenderKey) modelKey).getAnimations() != null) { | ||||
|                 for (Entry<String, Map<String, int[]>> animEntry : animations.entrySet()) { | ||||
|                     for (Entry<String, int[]> anim : animEntry.getValue().entrySet()) { | ||||
|                         Spatial animatedSpatial = this.findNode(blenderModel, animEntry.getKey()); | ||||
|                         animatedSpatial.getControl(AnimControl.class).createChannel().setAnim(anim.getKey()); | ||||
|                         break; | ||||
|                     } | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|         } else { | ||||
|             this.testBlenderModelLoader(ai); | ||||
|         } | ||||
| 
 | ||||
|         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 | ||||
|      */ | ||||
|     private Spatial findNode(Node rootNode, String 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 | ||||
|      */ | ||||
|     private Node testBlenderLoader(AssetInfo assetInfo) { | ||||
|         Node blenderModel = null; | ||||
|         BlenderLoader blenderLoader = new BlenderLoader(); | ||||
|         try { | ||||
|             LoadingResults loadingResults = blenderLoader.load(assetInfo); | ||||
|             for (Node object : loadingResults.getObjects()) { | ||||
|                 this.rootNode.attachChild(object); | ||||
|                 blenderModel = object; | ||||
|             } | ||||
|             for (Light light : loadingResults.getLights()) { | ||||
|                 this.rootNode.addLight(light); | ||||
|             } | ||||
|             for (Camera camera : loadingResults.getCameras()) { | ||||
|                 LOGGER.info(camera.toString()); | ||||
|             } | ||||
|         } 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 | ||||
|      */ | ||||
|     private Node testBlenderModelLoader(AssetInfo assetInfo) { | ||||
|         BlenderModelLoader blenderLoader = new BlenderModelLoader(); | ||||
|         try { | ||||
|             Spatial loadingResults = blenderLoader.load(assetInfo); | ||||
|             this.rootNode.attachChild(loadingResults); | ||||
|             if (loadingResults instanceof Node) { | ||||
|                 return (Node) loadingResults; | ||||
|             } | ||||
|         } 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) | ||||
|  */ | ||||
| public abstract class AbstractConfigDialog extends JFrame { | ||||
| 	private static final long serialVersionUID = -3677493125861310310L; | ||||
| 	private static final Logger LOGGER = Logger.getLogger(AbstractConfigDialog.class.getName()); | ||||
| 	 | ||||
| 	protected JComboBox jComboBoxVersionSelection; | ||||
| 	protected JList jListBlenderFiles; | ||||
| 	protected JTable jTableProperties; | ||||
| 	protected JTable jTableAnimations; | ||||
| 	protected JButton jButtonAddAnimation; | ||||
| 	protected JButton jButtonRemoveAnimation; | ||||
| 	protected JCheckBox jCheckBoxUseModelKey; | ||||
| 	protected JButton jButtonOK; | ||||
| 	protected JButton jButtonCancel; | ||||
| 	 | ||||
| 	/** | ||||
| 	 * Cionstructor initializes the gui. | ||||
| 	 */ | ||||
| 	public AbstractConfigDialog() { | ||||
| 		this.init(); | ||||
| 	} | ||||
| 	 | ||||
| 	/** | ||||
| 	 * This method initializes the window. | ||||
| 	 */ | ||||
| 	private void init() { | ||||
| 		try {//setting the system Look And Feel | ||||
| 			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); | ||||
| 		} catch (ClassNotFoundException e) { | ||||
| 			LOGGER.log(Level.SEVERE, e.getMessage(), e); | ||||
| 		} catch (InstantiationException e) { | ||||
| 			LOGGER.log(Level.SEVERE, e.getMessage(), e); | ||||
| 		} catch (IllegalAccessException e) { | ||||
| 			LOGGER.log(Level.SEVERE, e.getMessage(), e); | ||||
| 		} catch (UnsupportedLookAndFeelException e) { | ||||
| 			LOGGER.log(Level.SEVERE, e.getMessage(), e); | ||||
| 		} | ||||
| 		this.setLayout(new BorderLayout()); | ||||
| 		 | ||||
| 		this.add(this.prepareBlenderFilesAndLogLevelPanel(), BorderLayout.WEST); | ||||
| 		this.add(this.prepareFilePropertiesPanel(), BorderLayout.CENTER); | ||||
| 		this.add(this.prepareButtonsPanel(), BorderLayout.SOUTH); | ||||
| 		 | ||||
| 		this.pack(); | ||||
| 		this.setLocationRelativeTo(null); | ||||
| 		this.setVisible(true); | ||||
| 		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); | ||||
| 	} | ||||
| 	 | ||||
| 	/** | ||||
| 	 * This method prepares a swing panel containing the list of blender files | ||||
| 	 * and log level chooser. | ||||
| 	 * @return prepared swing panel | ||||
| 	 */ | ||||
| 	private JPanel prepareBlenderFilesAndLogLevelPanel() { | ||||
| 		JPanel jPanelBlenderFilesListAndLogLevel = new JPanel(); | ||||
| 		jPanelBlenderFilesListAndLogLevel.setBorder(new TitledBorder("Blender test files")); | ||||
| 		jPanelBlenderFilesListAndLogLevel.setLayout(new BorderLayout()); | ||||
| 		 | ||||
| 		//blender version selection combo box | ||||
| 		jComboBoxVersionSelection = new JComboBox(new DefaultComboBoxModel()); | ||||
| 		jComboBoxVersionSelection.setEditable(false); | ||||
| 		jPanelBlenderFilesListAndLogLevel.add(jComboBoxVersionSelection, BorderLayout.NORTH); | ||||
| 		 | ||||
| 		//blender list files | ||||
| 		jListBlenderFiles = new JList(new DefaultListModel()); | ||||
| 		jListBlenderFiles.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); | ||||
| 		JScrollPane listScroller = new JScrollPane(jListBlenderFiles); | ||||
| 		jPanelBlenderFilesListAndLogLevel.add(listScroller, BorderLayout.CENTER); | ||||
| 		 | ||||
| 		//Log Level list | ||||
| 		Box box = Box.createVerticalBox(); | ||||
| 		box.add(new Label("Log level:")); | ||||
| 		ButtonGroup buttonGroup = new ButtonGroup(); | ||||
| 		 | ||||
| 		Level[] levels = new Level[] {Level.OFF, Level.SEVERE, Level.WARNING, Level.INFO,  | ||||
| 									  Level.CONFIG, Level.FINE, Level.FINER, Level.FINEST, Level.ALL}; | ||||
| 		for(Level level : levels) { | ||||
| 			JRadioButtonLevel jRadioButtonLevel = new JRadioButtonLevel(level); | ||||
| 			buttonGroup.add(jRadioButtonLevel); | ||||
| 			box.add(jRadioButtonLevel); | ||||
| 		} | ||||
| 		jPanelBlenderFilesListAndLogLevel.add(box, BorderLayout.SOUTH); | ||||
| 		 | ||||
| 		return jPanelBlenderFilesListAndLogLevel; | ||||
| 	} | ||||
| 	 | ||||
| 	/** | ||||
| 	 * This method prepares a swing panel containing the file's animations. | ||||
| 	 * @return prepared swing panel | ||||
| 	 */ | ||||
| 	protected JPanel prepareFilePropertiesPanel() { | ||||
| 		//properties table | ||||
| 		JPanel jPanelProperties = new JPanel(); | ||||
| 		jPanelProperties.setBorder(new EmptyBorder(new Insets(0, 5, 0, 5))); | ||||
| 		jPanelProperties.setLayout(new BorderLayout()); | ||||
| 		jPanelProperties.add(new JLabel("Properties"), BorderLayout.NORTH); | ||||
| 		 | ||||
| 		jTableProperties = new JTable(); | ||||
| 		jTableProperties.setSelectionMode(DefaultListSelectionModel.SINGLE_SELECTION); | ||||
| 		jTableProperties.setModel(new BlenderTableModel(new Object[] {"Name", "Value"})); | ||||
| 		jTableProperties.getColumnModel().getColumn(1).setCellEditor(new BlenderTableCellEditor()); | ||||
| 		JScrollPane jScrollPaneProperties = new JScrollPane(jTableProperties); | ||||
| 		jTableProperties.setFillsViewportHeight(true); | ||||
| 		 | ||||
| 		jPanelProperties.add(jScrollPaneProperties, BorderLayout.CENTER); | ||||
| 		 | ||||
| 		//animations table | ||||
| 		JPanel jPanelAnimations = new JPanel(); | ||||
| 		jPanelAnimations.setBorder(new EmptyBorder(new Insets(0, 5, 0, 5))); | ||||
| 		jPanelAnimations.setLayout(new BorderLayout()); | ||||
| 		jPanelAnimations.add(new JLabel("Animations"), BorderLayout.NORTH); | ||||
| 		 | ||||
| 		jTableAnimations = new JTable(); | ||||
| 		jTableAnimations.setSelectionMode(DefaultListSelectionModel.SINGLE_SELECTION); | ||||
| 		jTableAnimations.setModel(new DefaultTableModel(new Object[] {"Object", "Name", "Start frame", "Stop frame"}, 0)); | ||||
| 		for(int i=0;i<jTableAnimations.getColumnModel().getColumnCount();++i) { | ||||
| 			jTableAnimations.getColumnModel().getColumn(i).setCellEditor(new BlenderTableCellEditor()); | ||||
| 		} | ||||
| 		JScrollPane jScrollPaneAnimations = new JScrollPane(jTableAnimations); | ||||
| 		jTableAnimations.setFillsViewportHeight(true); | ||||
| 		 | ||||
| 		JPanel jPanelTableButtons = new JPanel(); | ||||
| 		jPanelTableButtons.setLayout(new FlowLayout(FlowLayout.LEFT)); | ||||
| 		jButtonAddAnimation = new JButton("Add animation"); | ||||
| 		jButtonAddAnimation.setEnabled(false); | ||||
| 		jButtonRemoveAnimation = new JButton("Remove animation"); | ||||
| 		jButtonRemoveAnimation.setEnabled(false); | ||||
| 		jPanelTableButtons.add(jButtonAddAnimation); | ||||
| 		jPanelTableButtons.add(jButtonRemoveAnimation); | ||||
| 		 | ||||
| 		jPanelAnimations.add(jScrollPaneAnimations, BorderLayout.CENTER); | ||||
| 		jPanelAnimations.add(jPanelTableButtons, BorderLayout.SOUTH); | ||||
| 		 | ||||
| 		//model key check-box | ||||
| 		jCheckBoxUseModelKey = new JCheckBox(); | ||||
| 		jCheckBoxUseModelKey.setText("Use ModelKey to start the test"); | ||||
| 		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!"); | ||||
| 		 | ||||
| 		//building the result panel | ||||
| 		JPanel jPanelResult = new JPanel(); | ||||
| 		jPanelResult.setBorder(new TitledBorder("Loading properties")); | ||||
| 		jPanelResult.setLayout(new BorderLayout()); | ||||
| 		 | ||||
| 		jPanelResult.add(jPanelProperties, BorderLayout.WEST); | ||||
| 		jPanelResult.add(jPanelAnimations, BorderLayout.CENTER); | ||||
| 		jPanelResult.add(jCheckBoxUseModelKey, BorderLayout.SOUTH); | ||||
| 		return jPanelResult; | ||||
| 	} | ||||
| 	 | ||||
| 	/** | ||||
| 	 * This method prepares a swing panel containing the buttons. | ||||
| 	 * @return prepared swing panel | ||||
| 	 */ | ||||
| 	protected JPanel prepareButtonsPanel() { | ||||
| 		JPanel jPanelButtons = new JPanel(); | ||||
| 		jButtonOK = new JButton("OK"); | ||||
| 		jButtonOK.setEnabled(false); | ||||
| 		jPanelButtons.add(jButtonOK); | ||||
| 		jButtonCancel = new JButton("Cancel"); | ||||
| 		jPanelButtons.add(jButtonCancel); | ||||
| 		return jPanelButtons; | ||||
| 	} | ||||
| 	 | ||||
| 	/** | ||||
| 	 * This class was made only to make the selection of a level radio button easier. | ||||
| 	 * @author Marcin Roguski | ||||
| 	 */ | ||||
| 	protected static class JRadioButtonLevel extends JRadioButton { | ||||
| 		private static final long serialVersionUID = 8874525909060993518L; | ||||
| 		private static Level selectedLevel; | ||||
| 		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. | ||||
| 		 * @param level the level of log info | ||||
| 		 */ | ||||
| 		public JRadioButtonLevel(Level level) { | ||||
| 			super(level.getName()); | ||||
| 			this.level = level; | ||||
| 			radioButtons.put(level, this); | ||||
| 			this.addActionListener(new ActionListener() { | ||||
| 				@Override | ||||
| 				public void actionPerformed(ActionEvent e) { | ||||
| 					JRadioButtonLevel.selectedLevel = JRadioButtonLevel.this.level; | ||||
| 				} | ||||
| 			}); | ||||
| 		} | ||||
| 		 | ||||
| 		/** | ||||
| 		 * This method returns the currently selected info level. | ||||
| 		 * @return currently selected info level | ||||
| 		 */ | ||||
| 		public static Level getSelectedLevel() { | ||||
| 			return selectedLevel; | ||||
| 		} | ||||
| 		 | ||||
| 		/** | ||||
| 		 * This method sets the current info level. | ||||
| 		 * @param level the current info level | ||||
| 		 */ | ||||
| 		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) | ||||
| 	 */ | ||||
| 	protected static class FileListItem { | ||||
| 		private File file;				//the file to be stored | ||||
| 		/** | ||||
| 		 * Constructore. Stores the given file. | ||||
| 		 * @param file the file to be stored | ||||
| 		 */ | ||||
| 		public FileListItem(File file) { | ||||
| 			this.file = file; | ||||
| 		} | ||||
| 		 | ||||
| 		/** | ||||
| 		 * This method returns the stored file. | ||||
| 		 * @return the stored file | ||||
| 		 */ | ||||
| 		public File getFile() { | ||||
| 			return file; | ||||
| 		} | ||||
| 		 | ||||
| 		@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 { | ||||
| 		private static final long serialVersionUID = -4211206550875326553L; | ||||
| 
 | ||||
| 		/** | ||||
| 		 * Constructor only calls super-constuctor. | ||||
| 		 * @param columnNames the names of table columns | ||||
| 		 */ | ||||
| 		public BlenderTableModel(Object[] columnNames) { | ||||
| 			super(columnNames, 0); | ||||
| 		} | ||||
| 		 | ||||
| 		@Override | ||||
| 		public void addRow(Object[] rowData) { | ||||
| 			for(int i=0;i<rowData.length;++i) { | ||||
| 				if(rowData[i]==null) { | ||||
| 					rowData[i] = ""; | ||||
| 				} | ||||
| 			} | ||||
| 			super.addRow(rowData); | ||||
| 		} | ||||
| 		 | ||||
| 		@Override | ||||
| 		public boolean isCellEditable(int row, int column) { | ||||
| 			return column>0; | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	/** | ||||
| 	 * A cell editor tah improves data input to the table. | ||||
| 	 * @author Marcin Roguski (Kaelthas) | ||||
| 	 */ | ||||
| 	protected static class BlenderTableCellEditor extends AbstractCellEditor implements TableCellEditor { | ||||
| 		private static final long serialVersionUID = -8601975203921608519L; | ||||
| 		private JCheckBox jCheckBox		= new JCheckBox(); | ||||
| 		private JTextField jTextField	= new JTextField(); | ||||
| 		private JComboBox jComboBox		= new JComboBox(); | ||||
| 		private Object lastValue; | ||||
| 		 | ||||
| 		@Override | ||||
| 		public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { | ||||
| 			this.lastValue = value; | ||||
| 			if(value instanceof Boolean) { | ||||
| 				jCheckBox.setSelected(((Boolean) value).booleanValue()); | ||||
| 				return jCheckBox; | ||||
| 			} else if(value instanceof String || value instanceof Number || value instanceof Character) { | ||||
| 				jTextField.setText(value.toString()); | ||||
| 				return jTextField; | ||||
| 			} else if(value instanceof Enum<?>) { | ||||
| 				DefaultComboBoxModel defaultComboBoxModel = (DefaultComboBoxModel)jComboBox.getModel(); | ||||
| 				defaultComboBoxModel.removeAllElements(); | ||||
| 				for(Object object : value.getClass().getEnumConstants()) { | ||||
| 					defaultComboBoxModel.addElement(object); | ||||
| 				} | ||||
| 				return jComboBox; | ||||
| 			} | ||||
| 			else { | ||||
| 				jTextField.setText(value==null ? "" : value.toString()); | ||||
| 				return jTextField; | ||||
| 			} | ||||
| 		} | ||||
|     private static final long serialVersionUID = -3677493125861310310L; | ||||
|     private static final Logger LOGGER = Logger.getLogger(AbstractConfigDialog.class.getName()); | ||||
|     protected JComboBox jComboBoxVersionSelection; | ||||
|     protected JList jListBlenderFiles; | ||||
|     protected JTable jTableProperties; | ||||
|     protected JTable jTableAnimations; | ||||
|     protected JButton jButtonAddAnimation; | ||||
|     protected JButton jButtonRemoveAnimation; | ||||
|     protected JCheckBox jCheckBoxUseModelKey; | ||||
|     protected JButton jButtonOK; | ||||
|     protected JButton jButtonCancel; | ||||
| 
 | ||||
| 		@Override | ||||
| 		public Object getCellEditorValue() { | ||||
| 			if(lastValue instanceof Boolean) { | ||||
| 				return Boolean.valueOf(jCheckBox.isSelected()); | ||||
| 			} else if(lastValue instanceof String) { | ||||
| 				return jTextField.getText(); | ||||
| 			} else if(lastValue instanceof Character) { | ||||
| 				return Character.valueOf(jTextField.getText().charAt(0)); | ||||
| 			} else if(lastValue instanceof Byte) { | ||||
| 				return Byte.valueOf(jTextField.getText()); | ||||
| 			} else if(lastValue instanceof Short) { | ||||
| 				return Short.valueOf(jTextField.getText()); | ||||
| 			} else if(lastValue instanceof Integer) { | ||||
| 				return Integer.valueOf(jTextField.getText()); | ||||
| 			} else if(lastValue instanceof Long) { | ||||
| 				return Long.valueOf(jTextField.getText()); | ||||
| 			} else if(lastValue instanceof Float) { | ||||
| 				return Float.valueOf(jTextField.getText()); | ||||
| 			} else if(lastValue instanceof Double) { | ||||
| 				return Double.valueOf(jTextField.getText()); | ||||
| 			} else if(lastValue instanceof Enum<?>) { | ||||
| 				return jComboBox.getSelectedItem(); | ||||
| 			} | ||||
| 			//TODO: savable objects | ||||
| 			return null; | ||||
| 		} | ||||
| 	} | ||||
|     /** | ||||
|      * Cionstructor initializes the gui. | ||||
|      */ | ||||
|     public AbstractConfigDialog() { | ||||
|         this.init(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * This method initializes the window. | ||||
|      */ | ||||
|     private void init() { | ||||
|         try {//setting the system Look And Feel | ||||
|             UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); | ||||
|         } catch (ClassNotFoundException e) { | ||||
|             LOGGER.log(Level.SEVERE, e.getMessage(), e); | ||||
|         } catch (InstantiationException e) { | ||||
|             LOGGER.log(Level.SEVERE, e.getMessage(), e); | ||||
|         } catch (IllegalAccessException e) { | ||||
|             LOGGER.log(Level.SEVERE, e.getMessage(), e); | ||||
|         } catch (UnsupportedLookAndFeelException e) { | ||||
|             LOGGER.log(Level.SEVERE, e.getMessage(), e); | ||||
|         } | ||||
|         this.setLayout(new BorderLayout()); | ||||
| 
 | ||||
|         this.add(this.prepareBlenderFilesAndLogLevelPanel(), BorderLayout.WEST); | ||||
|         this.add(this.prepareFilePropertiesPanel(), BorderLayout.CENTER); | ||||
|         this.add(this.prepareButtonsPanel(), BorderLayout.SOUTH); | ||||
| 
 | ||||
|         this.pack(); | ||||
|         this.setLocationRelativeTo(null); | ||||
|         this.setVisible(true); | ||||
|         this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * This method prepares a swing panel containing the list of blender files | ||||
|      * and log level chooser. | ||||
|      * @return prepared swing panel | ||||
|      */ | ||||
|     private JPanel prepareBlenderFilesAndLogLevelPanel() { | ||||
|         JPanel jPanelBlenderFilesListAndLogLevel = new JPanel(); | ||||
|         jPanelBlenderFilesListAndLogLevel.setBorder(new TitledBorder("Blender test files")); | ||||
|         jPanelBlenderFilesListAndLogLevel.setLayout(new BorderLayout()); | ||||
| 
 | ||||
|         //blender version selection combo box | ||||
|         jComboBoxVersionSelection = new JComboBox(new DefaultComboBoxModel()); | ||||
|         jComboBoxVersionSelection.setEditable(false); | ||||
|         jPanelBlenderFilesListAndLogLevel.add(jComboBoxVersionSelection, BorderLayout.NORTH); | ||||
| 
 | ||||
|         //blender list files | ||||
|         jListBlenderFiles = new JList(new DefaultListModel()); | ||||
|         jListBlenderFiles.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); | ||||
|         JScrollPane listScroller = new JScrollPane(jListBlenderFiles); | ||||
|         jPanelBlenderFilesListAndLogLevel.add(listScroller, BorderLayout.CENTER); | ||||
| 
 | ||||
|         //Log Level list | ||||
|         Box box = Box.createVerticalBox(); | ||||
|         box.add(new Label("Log level:")); | ||||
|         ButtonGroup buttonGroup = new ButtonGroup(); | ||||
| 
 | ||||
|         Level[] levels = new Level[]{Level.OFF, Level.SEVERE, Level.WARNING, Level.INFO, | ||||
|             Level.CONFIG, Level.FINE, Level.FINER, Level.FINEST, Level.ALL}; | ||||
|         for (Level level : levels) { | ||||
|             JRadioButtonLevel jRadioButtonLevel = new JRadioButtonLevel(level); | ||||
|             buttonGroup.add(jRadioButtonLevel); | ||||
|             box.add(jRadioButtonLevel); | ||||
|         } | ||||
|         jPanelBlenderFilesListAndLogLevel.add(box, BorderLayout.SOUTH); | ||||
| 
 | ||||
|         return jPanelBlenderFilesListAndLogLevel; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * This method prepares a swing panel containing the file's animations. | ||||
|      * @return prepared swing panel | ||||
|      */ | ||||
|     protected JPanel prepareFilePropertiesPanel() { | ||||
|         //properties table | ||||
|         JPanel jPanelProperties = new JPanel(); | ||||
|         jPanelProperties.setBorder(new EmptyBorder(new Insets(0, 5, 0, 5))); | ||||
|         jPanelProperties.setLayout(new BorderLayout()); | ||||
|         jPanelProperties.add(new JLabel("Properties"), BorderLayout.NORTH); | ||||
| 
 | ||||
|         jTableProperties = new JTable(); | ||||
|         jTableProperties.setSelectionMode(DefaultListSelectionModel.SINGLE_SELECTION); | ||||
|         jTableProperties.setModel(new BlenderTableModel(new Object[]{"Name", "Value"})); | ||||
|         jTableProperties.getColumnModel().getColumn(1).setCellEditor(new BlenderTableCellEditor()); | ||||
|         JScrollPane jScrollPaneProperties = new JScrollPane(jTableProperties); | ||||
|         jTableProperties.setFillsViewportHeight(true); | ||||
| 
 | ||||
|         jPanelProperties.add(jScrollPaneProperties, BorderLayout.CENTER); | ||||
| 
 | ||||
|         //animations table | ||||
|         JPanel jPanelAnimations = new JPanel(); | ||||
|         jPanelAnimations.setBorder(new EmptyBorder(new Insets(0, 5, 0, 5))); | ||||
|         jPanelAnimations.setLayout(new BorderLayout()); | ||||
|         jPanelAnimations.add(new JLabel("Animations"), BorderLayout.NORTH); | ||||
| 
 | ||||
|         jTableAnimations = new JTable(); | ||||
|         jTableAnimations.setSelectionMode(DefaultListSelectionModel.SINGLE_SELECTION); | ||||
|         jTableAnimations.setModel(new DefaultTableModel(new Object[]{"Object", "Name", "Start frame", "Stop frame"}, 0)); | ||||
|         for (int i = 0; i < jTableAnimations.getColumnModel().getColumnCount(); ++i) { | ||||
|             jTableAnimations.getColumnModel().getColumn(i).setCellEditor(new BlenderTableCellEditor()); | ||||
|         } | ||||
|         JScrollPane jScrollPaneAnimations = new JScrollPane(jTableAnimations); | ||||
|         jTableAnimations.setFillsViewportHeight(true); | ||||
| 
 | ||||
|         JPanel jPanelTableButtons = new JPanel(); | ||||
|         jPanelTableButtons.setLayout(new FlowLayout(FlowLayout.LEFT)); | ||||
|         jButtonAddAnimation = new JButton("Add animation"); | ||||
|         jButtonAddAnimation.setEnabled(false); | ||||
|         jButtonRemoveAnimation = new JButton("Remove animation"); | ||||
|         jButtonRemoveAnimation.setEnabled(false); | ||||
|         jPanelTableButtons.add(jButtonAddAnimation); | ||||
|         jPanelTableButtons.add(jButtonRemoveAnimation); | ||||
| 
 | ||||
|         jPanelAnimations.add(jScrollPaneAnimations, BorderLayout.CENTER); | ||||
|         jPanelAnimations.add(jPanelTableButtons, BorderLayout.SOUTH); | ||||
| 
 | ||||
|         //model key check-box | ||||
|         jCheckBoxUseModelKey = new JCheckBox(); | ||||
|         jCheckBoxUseModelKey.setText("Use ModelKey to start the test"); | ||||
|         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!"); | ||||
| 
 | ||||
|         //building the result panel | ||||
|         JPanel jPanelResult = new JPanel(); | ||||
|         jPanelResult.setBorder(new TitledBorder("Loading properties")); | ||||
|         jPanelResult.setLayout(new BorderLayout()); | ||||
| 
 | ||||
|         jPanelResult.add(jPanelProperties, BorderLayout.WEST); | ||||
|         jPanelResult.add(jPanelAnimations, BorderLayout.CENTER); | ||||
|         jPanelResult.add(jCheckBoxUseModelKey, BorderLayout.SOUTH); | ||||
|         return jPanelResult; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * This method prepares a swing panel containing the buttons. | ||||
|      * @return prepared swing panel | ||||
|      */ | ||||
|     protected JPanel prepareButtonsPanel() { | ||||
|         JPanel jPanelButtons = new JPanel(); | ||||
|         jButtonOK = new JButton("OK"); | ||||
|         jButtonOK.setEnabled(false); | ||||
|         jPanelButtons.add(jButtonOK); | ||||
|         jButtonCancel = new JButton("Cancel"); | ||||
|         jPanelButtons.add(jButtonCancel); | ||||
|         return jPanelButtons; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * This class was made only to make the selection of a level radio button easier. | ||||
|      * @author Marcin Roguski | ||||
|      */ | ||||
|     protected static class JRadioButtonLevel extends JRadioButton { | ||||
| 
 | ||||
|         private static final long serialVersionUID = 8874525909060993518L; | ||||
|         private static Level selectedLevel; | ||||
|         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. | ||||
|          * @param level the level of log info | ||||
|          */ | ||||
|         public JRadioButtonLevel(Level level) { | ||||
|             super(level.getName()); | ||||
|             this.level = level; | ||||
|             radioButtons.put(level, this); | ||||
|             this.addActionListener(new ActionListener() { | ||||
| 
 | ||||
|                 @Override | ||||
|                 public void actionPerformed(ActionEvent e) { | ||||
|                     JRadioButtonLevel.selectedLevel = JRadioButtonLevel.this.level; | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
| 
 | ||||
|         /** | ||||
|          * This method returns the currently selected info level. | ||||
|          * @return currently selected info level | ||||
|          */ | ||||
|         public static Level getSelectedLevel() { | ||||
|             return selectedLevel; | ||||
|         } | ||||
| 
 | ||||
|         /** | ||||
|          * This method sets the current info level. | ||||
|          * @param level the current info level | ||||
|          */ | ||||
|         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) | ||||
|      */ | ||||
|     protected static class FileListItem { | ||||
| 
 | ||||
|         private File file;				//the file to be stored | ||||
| 
 | ||||
|         /** | ||||
|          * Constructore. Stores the given file. | ||||
|          * @param file the file to be stored | ||||
|          */ | ||||
|         public FileListItem(File file) { | ||||
|             this.file = file; | ||||
|         } | ||||
| 
 | ||||
|         /** | ||||
|          * This method returns the stored file. | ||||
|          * @return the stored file | ||||
|          */ | ||||
|         public File getFile() { | ||||
|             return file; | ||||
|         } | ||||
| 
 | ||||
|         @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 { | ||||
| 
 | ||||
|         private static final long serialVersionUID = -4211206550875326553L; | ||||
| 
 | ||||
|         /** | ||||
|          * Constructor only calls super-constuctor. | ||||
|          * @param columnNames the names of table columns | ||||
|          */ | ||||
|         public BlenderTableModel(Object[] columnNames) { | ||||
|             super(columnNames, 0); | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public void addRow(Object[] rowData) { | ||||
|             for (int i = 0; i < rowData.length; ++i) { | ||||
|                 if (rowData[i] == null) { | ||||
|                     rowData[i] = ""; | ||||
|                 } | ||||
|             } | ||||
|             super.addRow(rowData); | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public boolean isCellEditable(int row, int column) { | ||||
|             return column > 0; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * A cell editor tah improves data input to the table. | ||||
|      * @author Marcin Roguski (Kaelthas) | ||||
|      */ | ||||
|     protected static class BlenderTableCellEditor extends AbstractCellEditor implements TableCellEditor { | ||||
| 
 | ||||
|         private static final long serialVersionUID = -8601975203921608519L; | ||||
|         private JCheckBox jCheckBox = new JCheckBox(); | ||||
|         private JTextField jTextField = new JTextField(); | ||||
|         private JComboBox jComboBox = new JComboBox(); | ||||
|         private Object lastValue; | ||||
| 
 | ||||
|         @Override | ||||
|         public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { | ||||
|             this.lastValue = value; | ||||
|             if (value instanceof Boolean) { | ||||
|                 jCheckBox.setSelected(((Boolean) value).booleanValue()); | ||||
|                 return jCheckBox; | ||||
|             } else if (value instanceof String || value instanceof Number || value instanceof Character) { | ||||
|                 jTextField.setText(value.toString()); | ||||
|                 return jTextField; | ||||
|             } else if (value instanceof Enum<?>) { | ||||
|                 DefaultComboBoxModel defaultComboBoxModel = (DefaultComboBoxModel) jComboBox.getModel(); | ||||
|                 defaultComboBoxModel.removeAllElements(); | ||||
|                 for (Object object : value.getClass().getEnumConstants()) { | ||||
|                     defaultComboBoxModel.addElement(object); | ||||
|                 } | ||||
|                 return jComboBox; | ||||
|             } else { | ||||
|                 jTextField.setText(value == null ? "" : value.toString()); | ||||
|                 return jTextField; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public Object getCellEditorValue() { | ||||
|             if (lastValue instanceof Boolean) { | ||||
|                 return Boolean.valueOf(jCheckBox.isSelected()); | ||||
|             } else if (lastValue instanceof String) { | ||||
|                 return jTextField.getText(); | ||||
|             } else if (lastValue instanceof Character) { | ||||
|                 return Character.valueOf(jTextField.getText().charAt(0)); | ||||
|             } else if (lastValue instanceof Byte) { | ||||
|                 return Byte.valueOf(jTextField.getText()); | ||||
|             } else if (lastValue instanceof Short) { | ||||
|                 return Short.valueOf(jTextField.getText()); | ||||
|             } else if (lastValue instanceof Integer) { | ||||
|                 return Integer.valueOf(jTextField.getText()); | ||||
|             } else if (lastValue instanceof Long) { | ||||
|                 return Long.valueOf(jTextField.getText()); | ||||
|             } else if (lastValue instanceof Float) { | ||||
|                 return Float.valueOf(jTextField.getText()); | ||||
|             } else if (lastValue instanceof Double) { | ||||
|                 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) | ||||
|  */ | ||||
| public class ConfigDialog extends AbstractConfigDialog { | ||||
| 	private static final long serialVersionUID = 2863364888664674247L; | ||||
| 	private static final Logger LOGGER = Logger.getLogger(ConfigDialog.class.getName()); | ||||
| 	 | ||||
| 	private String baseFolderName; | ||||
| 	private File configFile;								//the config file | ||||
| 	private Map<String, BlenderKeyConfiguration> configMap;	//the blender key configuration map | ||||
| 	private BlenderKeyConfiguration blenderKeyConfiguration;//the configuration for the files | ||||
| 	private IConfigExecutable		configExecutable;		//this is called after clicking the 'OK' button | ||||
| 	 | ||||
| 	/** | ||||
| 	 * Constructor. Builds the whole window and stores its data. | ||||
| 	 * @param testAssetsFolderName the path to test files folder | ||||
| 	 */ | ||||
| 	public ConfigDialog(String baseFolderName, IConfigExecutable configExecutable) { | ||||
| 		if(baseFolderName==null) { | ||||
| 			throw new IllegalArgumentException("No test asset folder given!"); | ||||
| 		} | ||||
| 		if(configExecutable==null) { | ||||
| 			throw new IllegalArgumentException("No config executable given!"); | ||||
| 		} | ||||
| 		this.baseFolderName = baseFolderName; | ||||
| 		this.configExecutable = configExecutable; | ||||
| 		this.configMap = new HashMap<String, ConfigDialog.BlenderKeyConfiguration>(); | ||||
| 		 | ||||
| 		//setting up version selection (as a folder list in a compo box) | ||||
| 		File baseFolder = new File(baseFolderName); | ||||
| 		if(!baseFolder.exists() || !baseFolder.isDirectory()) { | ||||
| 			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() { | ||||
| 			@Override | ||||
| 			public boolean accept(File file) { | ||||
| 				return file.isDirectory() && file.getName().charAt(0)!='.'; | ||||
| 			} | ||||
| 		}); | ||||
| 		for(File folder : folders) { | ||||
| 			((DefaultComboBoxModel)jComboBoxVersionSelection.getModel()).addElement(folder.getName()); | ||||
| 			configMap.put(folder.getName(), null); | ||||
| 		} | ||||
| 		this.initListeners(); | ||||
| 		 | ||||
| 		jComboBoxVersionSelection.setSelectedIndex(0); | ||||
| 	} | ||||
| 	 | ||||
| 	/** | ||||
| 	 * This method returns the selected blender key. | ||||
| 	 * @return the selected blender key | ||||
| 	 */ | ||||
| 	public BlenderKey getSelectedBlenderKey() { | ||||
| 		return blenderKeyConfiguration.lastUsedKey; | ||||
| 	} | ||||
| 	 | ||||
| 	/** | ||||
| 	 * This method prepares the blender files' list. | ||||
| 	 * @param testAssetsFolderName the path to test files folder | ||||
| 	 * @return array of blender files | ||||
| 	 */ | ||||
| 	private File[] prepareFilesList(String testAssetsFolderName) { | ||||
| 		File testAssetsFolder = new File(testAssetsFolderName); | ||||
| 		 | ||||
| 		//loading blender files | ||||
| 		File[] blenderFiles = testAssetsFolder.listFiles(new FileFilter() { | ||||
| 			@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 | ||||
| 			public boolean accept(File file) { | ||||
| 				return file.isFile() && file.canRead() && file.getName().endsWith(".conf"); | ||||
| 			} | ||||
| 		}); | ||||
| 		if (files == null || files.length == 0) { | ||||
| 			blenderKeyConfiguration = new BlenderKeyConfiguration(blenderFiles.length); | ||||
| 			 | ||||
| 		} else { | ||||
| 			BinaryImporter jmeImporter = new BinaryImporter(); | ||||
| 			String instructionToUser = files.length==1 ? | ||||
| 					"No other config file to load! No configuration set!" : | ||||
| 					"Please choose different config file!"; | ||||
| 			do { | ||||
| 				if (files.length > 1) { | ||||
| 					configFile = (File) JOptionPane.showInputDialog(null, "Choose the config file!", "Config file selection", | ||||
| 							JOptionPane.INFORMATION_MESSAGE, null, files, files[0]); | ||||
| 				} else { | ||||
| 					configFile = files[0]; | ||||
| 				} | ||||
| 				if(configFile==null) { | ||||
| 					JOptionPane.showMessageDialog(this, "No config file selected!\nEmpty configuration will be created!", | ||||
| 							  "No configuration selected", JOptionPane.INFORMATION_MESSAGE); | ||||
| 					blenderKeyConfiguration = new BlenderKeyConfiguration(blenderFiles.length); | ||||
| 				} else { | ||||
| 					try { | ||||
| 						Savable loadedData = jmeImporter.load(configFile); | ||||
| 						if (loadedData instanceof BlenderKeyConfiguration) { | ||||
| 							blenderKeyConfiguration = (BlenderKeyConfiguration) loadedData; | ||||
| 						} else { | ||||
| 							LOGGER.warning("Cannot load data drom the given file!"); | ||||
| 							JOptionPane.showMessageDialog(this, "The data stored in the config file is of invalid type!\n" | ||||
| 																+ instructionToUser, "Config data error", JOptionPane.ERROR_MESSAGE); | ||||
| 						} | ||||
| 					} catch (IOException e) { | ||||
| 						JOptionPane.showMessageDialog(this, "Unable to load configuration! Reason: " + e.getLocalizedMessage(), | ||||
| 								  "Loading data error", JOptionPane.ERROR_MESSAGE); | ||||
| 						LOGGER.severe("Unable to load configuration"); | ||||
| 					} catch (Exception e) { | ||||
| 						JOptionPane.showMessageDialog(this, "Unable to load configuration!", | ||||
| 								  "Loading data error", JOptionPane.ERROR_MESSAGE); | ||||
| 						LOGGER.log(Level.SEVERE, "Unable to load configuration due to unpredicted error!", e); | ||||
| 					} | ||||
| 				} | ||||
| 			} while (blenderKeyConfiguration == null && files.length>1); | ||||
| 		} | ||||
| 		configFile = new File(testAssetsFolder, "test.conf"); | ||||
| 		 | ||||
| 		jCheckBoxUseModelKey.setSelected(blenderKeyConfiguration.useModelKey); | ||||
| 		 | ||||
| 		//enlisting the files in the list | ||||
| 		DefaultListModel defaultListModel = (DefaultListModel) jListBlenderFiles.getModel(); | ||||
| 		defaultListModel.removeAllElements(); | ||||
| 		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) { | ||||
| 		//setting properties | ||||
| 		BlenderTableModel propertiesModel = (BlenderTableModel) jTableProperties.getModel(); | ||||
| 		int rowCount = propertiesModel.getRowCount(); | ||||
| 		for(int i=0;i<rowCount;++i) { | ||||
| 			propertiesModel.removeRow(0); | ||||
| 		} | ||||
| 		Field[] fields = blenderKey.getClass().getDeclaredFields(); | ||||
| 		for(Field field : fields) { | ||||
| 			 | ||||
| 			field.setAccessible(true); | ||||
| 			if(!"animations".equalsIgnoreCase(field.getName()) &&  | ||||
| 			   (field.getModifiers() & Modifier.STATIC)==0) { | ||||
| 				try { | ||||
| 					propertiesModel.addRow(new Object[] {field.getName(), field.get(blenderKey)}); | ||||
| 				} 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) { | ||||
| 			animationsModel.removeRow(0); | ||||
| 		} | ||||
| 		Map<String, Map<String, int[]>> animations = blenderKey.getAnimations(); | ||||
| 		if(animations!=null) { | ||||
| 			for(Entry<String, Map<String, int[]>> animationEntry : animations.entrySet()) { | ||||
| 				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 method stores the current blender config. | ||||
| 	 * @param configuration the blender config to store | ||||
| 	 */ | ||||
| 	private void storeConfig(BlenderKeyConfiguration configuration) { | ||||
| 		if(configuration.lastUsedKey!=null) {//reading animations | ||||
| 			DefaultTableModel animationsTableModel = (DefaultTableModel)jTableAnimations.getModel(); | ||||
| 			if(configuration.lastUsedKey.getAnimations()!=null) { | ||||
| 				configuration.lastUsedKey.getAnimations().clear(); | ||||
| 			} | ||||
| 			int animCounter = 0; | ||||
| 			for(int i=0;i<animationsTableModel.getRowCount();++i) { | ||||
| 				String objectName = (String)animationsTableModel.getValueAt(i, 0); | ||||
| 				String animName = (String)animationsTableModel.getValueAt(i, 1); | ||||
| 				Number startFrame = (Number)animationsTableModel.getValueAt(i, 2); | ||||
| 				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()); | ||||
| 					++animCounter; | ||||
| 				} | ||||
| 			} | ||||
| 			if(animCounter<animationsTableModel.getRowCount()) { | ||||
| 				JOptionPane.showMessageDialog(ConfigDialog.this, "Some animations had errors!\nThey had not been added!",  | ||||
| 						"Invalid animations definitions", JOptionPane.WARNING_MESSAGE); | ||||
| 			} | ||||
| 		} | ||||
| 		//getting the key type | ||||
| 		configuration.useModelKey = jCheckBoxUseModelKey.isSelected(); | ||||
| 		configuration.logLevel = JRadioButtonLevel.getSelectedLevel(); | ||||
| 		 | ||||
| 		//storing the config | ||||
| 		JmeExporter jmeExporter = new BinaryExporter(); | ||||
| 		try { | ||||
| 			if(!jmeExporter.save(configuration, configFile)) { | ||||
| 				JOptionPane.showMessageDialog(ConfigDialog.this, "Unable to save the config data!", "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 | ||||
| 		jComboBoxVersionSelection.addActionListener(new ActionListener() { | ||||
| 			@Override | ||||
| 			public void actionPerformed(ActionEvent evt) { | ||||
| 				//save the previous congifuration | ||||
| 				if(blenderKeyConfiguration!=null) { | ||||
| 					ConfigDialog.this.storeConfig(blenderKeyConfiguration); | ||||
| 					blenderKeyConfiguration = null; | ||||
| 				} | ||||
| 				 | ||||
| 				//load new configuration | ||||
| 				File[] blenderFiles = ConfigDialog.this.prepareFilesList(baseFolderName+'/'+jComboBoxVersionSelection.getSelectedItem().toString()); | ||||
| 				if(blenderKeyConfiguration.lastUsedKey!=null) { | ||||
| 					for(int i=0;i<blenderFiles.length; ++i) { | ||||
| 						if(blenderFiles[i].getPath().equalsIgnoreCase(blenderKeyConfiguration.lastUsedKey.getName())) { | ||||
| 							jListBlenderFiles.setSelectedIndex(i); | ||||
| 							break; | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 				if(blenderKeyConfiguration.logLevel==null) { | ||||
| 					blenderKeyConfiguration.logLevel = Level.INFO; | ||||
| 				} | ||||
| 				JRadioButtonLevel.setSelectedLevel(blenderKeyConfiguration.logLevel); | ||||
| 			} | ||||
| 		}); | ||||
| 		//selection of the file changes the config on the right | ||||
| 		jListBlenderFiles.addListSelectionListener(new ListSelectionListener() { | ||||
| 			@Override | ||||
| 			public void valueChanged(ListSelectionEvent evt) { | ||||
| 				BlenderKeyConfiguration config = ConfigDialog.this.blenderKeyConfiguration; | ||||
| 				FileListItem selectedItem = (FileListItem) ConfigDialog.this.jListBlenderFiles.getSelectedValue(); | ||||
| 				if(selectedItem != null) { | ||||
| 					String fileName = selectedItem.getFile().getName(); | ||||
| 					config.lastUsedKey = config.blenderKeys.get(fileName); | ||||
| 					if(config.lastUsedKey==null) { | ||||
| 						config.lastUsedKey = new BlenderKey(selectedItem.getFile().getPath()); | ||||
| 						config.blenderKeys.put(fileName, config.lastUsedKey); | ||||
| 					} | ||||
| 					ConfigDialog.this.setBlenderKey(config.lastUsedKey); | ||||
| 				} else { | ||||
| 					config.lastUsedKey = null; | ||||
| 				} | ||||
| 			} | ||||
| 		}); | ||||
| 		jTableProperties.getModel().addTableModelListener(new TableModelListener() { | ||||
| 			@Override | ||||
| 			public void tableChanged(TableModelEvent evt) { | ||||
| 				if(evt.getType()==TableModelEvent.UPDATE) { | ||||
| 					BlenderKeyConfiguration config = ConfigDialog.this.blenderKeyConfiguration; | ||||
| 					int row = evt.getFirstRow(); | ||||
| 					String name = (String)jTableProperties.getModel().getValueAt(row, 0); | ||||
| 					Object value = jTableProperties.getModel().getValueAt(row, 1); | ||||
| 					try { | ||||
| 						Field field = config.lastUsedKey.getClass().getDeclaredField(name); | ||||
| 						field.setAccessible(true); | ||||
| 						field.set(config.lastUsedKey, value); | ||||
| 					} catch (IllegalArgumentException 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); | ||||
| 					} catch (NoSuchFieldException e) { | ||||
| 						LOGGER.log(Level.SEVERE, e.getMessage(), e); | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		}); | ||||
| 		jTableAnimations.getModel().addTableModelListener(new TableModelListener() { | ||||
| 			@Override | ||||
| 			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); | ||||
| 				} | ||||
| 			} | ||||
| 		}); | ||||
| 		jButtonAddAnimation.addActionListener(new ActionListener() { | ||||
| 			@Override | ||||
| 			public void actionPerformed(ActionEvent evt) { | ||||
| 				((DefaultTableModel)jTableAnimations.getModel()).addRow(new Object[] {"", "", Integer.valueOf(-1), Integer.valueOf(-1)}); | ||||
| 			} | ||||
| 		}); | ||||
| 		jButtonRemoveAnimation.addActionListener(new ActionListener() { | ||||
| 			@Override | ||||
| 			public void actionPerformed(ActionEvent evt) { | ||||
| 				int row = jTableAnimations.getSelectedRow(); | ||||
| 				if(row>=0) { | ||||
| 					((DefaultTableModel)jTableAnimations.getModel()).removeRow(row); | ||||
| 				} | ||||
| 			} | ||||
| 		}); | ||||
| 		 | ||||
| 		//button listeners | ||||
| 		jButtonOK.addActionListener(new ActionListener() { | ||||
| 			@Override | ||||
| 			public void actionPerformed(ActionEvent evt) { | ||||
| 				ConfigDialog.this.storeConfig(blenderKeyConfiguration); | ||||
| 				//running the test | ||||
| 				SwingUtilities.invokeLater(new Runnable() { | ||||
| 					@Override | ||||
| 					public void run() { | ||||
| 						configExecutable.execute(ConfigDialog.this.blenderKeyConfiguration.getKeyToUse(), | ||||
| 												 ConfigDialog.this.blenderKeyConfiguration.logLevel); | ||||
| 					} | ||||
| 				}); | ||||
| 				//disposing the config window | ||||
| 				ConfigDialog.this.dispose(); | ||||
| 			} | ||||
| 		}); | ||||
| 		jButtonCancel.addActionListener(new ActionListener() { | ||||
| 			@Override | ||||
| 			public void actionPerformed(ActionEvent evt) { | ||||
| 				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) | ||||
| 	 */ | ||||
| 	public static class BlenderKeyConfiguration implements Savable { | ||||
| 		private Map<String, BlenderKey> blenderKeys; | ||||
| 		private BlenderKey	lastUsedKey; | ||||
| 		private Level		logLevel; | ||||
| 		private boolean		useModelKey; | ||||
| 		 | ||||
| 		/** | ||||
| 		 * Constructor for jme serialization. | ||||
| 		 */ | ||||
| 		public BlenderKeyConfiguration() {} | ||||
| 		 | ||||
| 		/** | ||||
| 		 * Constructor that creates new empty configuration for every blender file. | ||||
| 		 * @param blenderFilesAmount the amount of blender files | ||||
| 		 */ | ||||
| 		public BlenderKeyConfiguration(int blenderFilesAmount) { | ||||
| 			blenderKeys = new HashMap<String, BlenderKey>(blenderFilesAmount); | ||||
| 		} | ||||
| 		 | ||||
| 		/** | ||||
| 		 * This method returns the key that will be used during the test. | ||||
| 		 * @return the key that will be used during the test | ||||
| 		 */ | ||||
| 		public ModelKey getKeyToUse() { | ||||
| 			return useModelKey ? new ModelKey(lastUsedKey.getName()) : lastUsedKey; | ||||
| 		} | ||||
| 		 | ||||
| 		@Override | ||||
| 		public void write(JmeExporter ex) throws IOException { | ||||
| 			OutputCapsule oc = ex.getCapsule(this); | ||||
| 			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()); | ||||
| 		} | ||||
|     private static final long serialVersionUID = 2863364888664674247L; | ||||
|     private static final Logger LOGGER = Logger.getLogger(ConfigDialog.class.getName()); | ||||
|     private String baseFolderName; | ||||
|     private File configFile;								//the config file | ||||
|     private Map<String, BlenderKeyConfiguration> configMap;	//the blender key configuration map | ||||
|     private BlenderKeyConfiguration blenderKeyConfiguration;//the configuration for the files | ||||
|     private ConfigExecutable configExecutable;		//this is called after clicking the 'OK' button | ||||
| 
 | ||||
| 		@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); | ||||
| 		} | ||||
| 	} | ||||
|     /** | ||||
|      * Constructor. Builds the whole window and stores its data. | ||||
|      * @param testAssetsFolderName the path to test files folder | ||||
|      */ | ||||
|     public ConfigDialog(String baseFolderName, ConfigExecutable configExecutable) { | ||||
|         if (baseFolderName == null) { | ||||
|             throw new IllegalArgumentException("No test asset folder given!"); | ||||
|         } | ||||
|         if (configExecutable == null) { | ||||
|             throw new IllegalArgumentException("No config executable given!"); | ||||
|         } | ||||
|         this.baseFolderName = baseFolderName; | ||||
|         this.configExecutable = configExecutable; | ||||
|         this.configMap = new HashMap<String, ConfigDialog.BlenderKeyConfiguration>(); | ||||
| 
 | ||||
|         //setting up version selection (as a folder list in a compo box) | ||||
|         File baseFolder = new File(baseFolderName); | ||||
|         if (!baseFolder.exists() || !baseFolder.isDirectory()) { | ||||
|             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() { | ||||
| 
 | ||||
|             @Override | ||||
|             public boolean accept(File file) { | ||||
|                 return file.isDirectory() && file.getName().charAt(0) != '.'; | ||||
|             } | ||||
|         }); | ||||
|         for (File folder : folders) { | ||||
|             ((DefaultComboBoxModel) jComboBoxVersionSelection.getModel()).addElement(folder.getName()); | ||||
|             configMap.put(folder.getName(), null); | ||||
|         } | ||||
|         this.initListeners(); | ||||
| 
 | ||||
|         jComboBoxVersionSelection.setSelectedIndex(0); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * This method returns the selected blender key. | ||||
|      * @return the selected blender key | ||||
|      */ | ||||
|     public BlenderKey getSelectedBlenderKey() { | ||||
|         return blenderKeyConfiguration.lastUsedKey; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * This method prepares the blender files' list. | ||||
|      * @param testAssetsFolderName the path to test files folder | ||||
|      * @return array of blender files | ||||
|      */ | ||||
|     private File[] prepareFilesList(String testAssetsFolderName) { | ||||
|         File testAssetsFolder = new File(testAssetsFolderName); | ||||
| 
 | ||||
|         //loading blender files | ||||
|         File[] blenderFiles = testAssetsFolder.listFiles(new FileFilter() { | ||||
| 
 | ||||
|             @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 | ||||
|             public boolean accept(File file) { | ||||
|                 return file.isFile() && file.canRead() && file.getName().endsWith(".conf"); | ||||
|             } | ||||
|         }); | ||||
|         if (files == null || files.length == 0) { | ||||
|             blenderKeyConfiguration = new BlenderKeyConfiguration(blenderFiles.length); | ||||
| 
 | ||||
|         } else { | ||||
|             BinaryImporter jmeImporter = new BinaryImporter(); | ||||
|             String instructionToUser = files.length == 1 | ||||
|                     ? "No other config file to load! No configuration set!" | ||||
|                     : "Please choose different config file!"; | ||||
|             do { | ||||
|                 if (files.length > 1) { | ||||
|                     configFile = (File) JOptionPane.showInputDialog(null, "Choose the config file!", "Config file selection", | ||||
|                             JOptionPane.INFORMATION_MESSAGE, null, files, files[0]); | ||||
|                 } else { | ||||
|                     configFile = files[0]; | ||||
|                 } | ||||
|                 if (configFile == null) { | ||||
|                     JOptionPane.showMessageDialog(this, "No config file selected!\nEmpty configuration will be created!", | ||||
|                             "No configuration selected", JOptionPane.INFORMATION_MESSAGE); | ||||
|                     blenderKeyConfiguration = new BlenderKeyConfiguration(blenderFiles.length); | ||||
|                 } else { | ||||
|                     try { | ||||
|                         Savable loadedData = jmeImporter.load(configFile); | ||||
|                         if (loadedData instanceof BlenderKeyConfiguration) { | ||||
|                             blenderKeyConfiguration = (BlenderKeyConfiguration) loadedData; | ||||
|                         } else { | ||||
|                             LOGGER.warning("Cannot load data drom the given file!"); | ||||
|                             JOptionPane.showMessageDialog(this, "The data stored in the config file is of invalid type!\n" | ||||
|                                     + instructionToUser, "Config data error", JOptionPane.ERROR_MESSAGE); | ||||
|                         } | ||||
|                     } catch (IOException e) { | ||||
|                         JOptionPane.showMessageDialog(this, "Unable to load configuration! Reason: " + e.getLocalizedMessage(), | ||||
|                                 "Loading data error", JOptionPane.ERROR_MESSAGE); | ||||
|                         LOGGER.severe("Unable to load configuration"); | ||||
|                     } catch (Exception e) { | ||||
|                         JOptionPane.showMessageDialog(this, "Unable to load configuration!", | ||||
|                                 "Loading data error", JOptionPane.ERROR_MESSAGE); | ||||
|                         LOGGER.log(Level.SEVERE, "Unable to load configuration due to unpredicted error!", e); | ||||
|                     } | ||||
|                 } | ||||
|             } while (blenderKeyConfiguration == null && files.length > 1); | ||||
|         } | ||||
|         configFile = new File(testAssetsFolder, "test.conf"); | ||||
| 
 | ||||
|         jCheckBoxUseModelKey.setSelected(blenderKeyConfiguration.useModelKey); | ||||
| 
 | ||||
|         //enlisting the files in the list | ||||
|         DefaultListModel defaultListModel = (DefaultListModel) jListBlenderFiles.getModel(); | ||||
|         defaultListModel.removeAllElements(); | ||||
|         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) { | ||||
|         //setting properties | ||||
|         BlenderTableModel propertiesModel = (BlenderTableModel) jTableProperties.getModel(); | ||||
|         int rowCount = propertiesModel.getRowCount(); | ||||
|         for (int i = 0; i < rowCount; ++i) { | ||||
|             propertiesModel.removeRow(0); | ||||
|         } | ||||
|         Field[] fields = blenderKey.getClass().getDeclaredFields(); | ||||
|         for (Field field : fields) { | ||||
| 
 | ||||
|             field.setAccessible(true); | ||||
|             if (!"animations".equalsIgnoreCase(field.getName()) | ||||
|                     && (field.getModifiers() & Modifier.STATIC) == 0) { | ||||
|                 try { | ||||
|                     propertiesModel.addRow(new Object[]{field.getName(), field.get(blenderKey)}); | ||||
|                 } 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) { | ||||
|             animationsModel.removeRow(0); | ||||
|         } | ||||
|         Map<String, Map<String, int[]>> animations = blenderKey.getAnimations(); | ||||
|         if (animations != null) { | ||||
|             for (Entry<String, Map<String, int[]>> animationEntry : animations.entrySet()) { | ||||
|                 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 method stores the current blender config. | ||||
|      * @param configuration the blender config to store | ||||
|      */ | ||||
|     private void storeConfig(BlenderKeyConfiguration configuration) { | ||||
|         if (configuration.lastUsedKey != null) {//reading animations | ||||
|             DefaultTableModel animationsTableModel = (DefaultTableModel) jTableAnimations.getModel(); | ||||
|             if (configuration.lastUsedKey.getAnimations() != null) { | ||||
|                 configuration.lastUsedKey.getAnimations().clear(); | ||||
|             } | ||||
|             int animCounter = 0; | ||||
|             for (int i = 0; i < animationsTableModel.getRowCount(); ++i) { | ||||
|                 String objectName = (String) animationsTableModel.getValueAt(i, 0); | ||||
|                 String animName = (String) animationsTableModel.getValueAt(i, 1); | ||||
|                 Number startFrame = (Number) animationsTableModel.getValueAt(i, 2); | ||||
|                 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()); | ||||
|                     ++animCounter; | ||||
|                 } | ||||
|             } | ||||
|             if (animCounter < animationsTableModel.getRowCount()) { | ||||
|                 JOptionPane.showMessageDialog(ConfigDialog.this, "Some animations had errors!\nThey had not been added!", | ||||
|                         "Invalid animations definitions", JOptionPane.WARNING_MESSAGE); | ||||
|             } | ||||
|         } | ||||
|         //getting the key type | ||||
|         configuration.useModelKey = jCheckBoxUseModelKey.isSelected(); | ||||
|         configuration.logLevel = JRadioButtonLevel.getSelectedLevel(); | ||||
| 
 | ||||
|         //storing the config | ||||
|         JmeExporter jmeExporter = new BinaryExporter(); | ||||
|         try { | ||||
|             if (!jmeExporter.save(configuration, configFile)) { | ||||
|                 JOptionPane.showMessageDialog(ConfigDialog.this, "Unable to save the config data!", "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 | ||||
|         jComboBoxVersionSelection.addActionListener(new ActionListener() { | ||||
| 
 | ||||
|             @Override | ||||
|             public void actionPerformed(ActionEvent evt) { | ||||
|                 //save the previous congifuration | ||||
|                 if (blenderKeyConfiguration != null) { | ||||
|                     ConfigDialog.this.storeConfig(blenderKeyConfiguration); | ||||
|                     blenderKeyConfiguration = null; | ||||
|                 } | ||||
| 
 | ||||
|                 //load new configuration | ||||
|                 File[] blenderFiles = ConfigDialog.this.prepareFilesList(baseFolderName + '/' + jComboBoxVersionSelection.getSelectedItem().toString()); | ||||
|                 if (blenderKeyConfiguration.lastUsedKey != null) { | ||||
|                     for (int i = 0; i < blenderFiles.length; ++i) { | ||||
|                         if (blenderFiles[i].getPath().equalsIgnoreCase(blenderKeyConfiguration.lastUsedKey.getName())) { | ||||
|                             jListBlenderFiles.setSelectedIndex(i); | ||||
|                             break; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|                 if (blenderKeyConfiguration.logLevel == null) { | ||||
|                     blenderKeyConfiguration.logLevel = Level.INFO; | ||||
|                 } | ||||
|                 JRadioButtonLevel.setSelectedLevel(blenderKeyConfiguration.logLevel); | ||||
|             } | ||||
|         }); | ||||
|         //selection of the file changes the config on the right | ||||
|         jListBlenderFiles.addListSelectionListener(new ListSelectionListener() { | ||||
| 
 | ||||
|             @Override | ||||
|             public void valueChanged(ListSelectionEvent evt) { | ||||
|                 BlenderKeyConfiguration config = ConfigDialog.this.blenderKeyConfiguration; | ||||
|                 FileListItem selectedItem = (FileListItem) ConfigDialog.this.jListBlenderFiles.getSelectedValue(); | ||||
|                 if (selectedItem != null) { | ||||
|                     String fileName = selectedItem.getFile().getName(); | ||||
|                     config.lastUsedKey = config.blenderKeys.get(fileName); | ||||
|                     if (config.lastUsedKey == null) { | ||||
|                         config.lastUsedKey = new BlenderKey(selectedItem.getFile().getPath()); | ||||
|                         config.blenderKeys.put(fileName, config.lastUsedKey); | ||||
|                     } | ||||
|                     ConfigDialog.this.setBlenderKey(config.lastUsedKey); | ||||
|                 } else { | ||||
|                     config.lastUsedKey = null; | ||||
|                 } | ||||
|             } | ||||
|         }); | ||||
|         jTableProperties.getModel().addTableModelListener(new TableModelListener() { | ||||
| 
 | ||||
|             @Override | ||||
|             public void tableChanged(TableModelEvent evt) { | ||||
|                 if (evt.getType() == TableModelEvent.UPDATE) { | ||||
|                     BlenderKeyConfiguration config = ConfigDialog.this.blenderKeyConfiguration; | ||||
|                     int row = evt.getFirstRow(); | ||||
|                     String name = (String) jTableProperties.getModel().getValueAt(row, 0); | ||||
|                     Object value = jTableProperties.getModel().getValueAt(row, 1); | ||||
|                     try { | ||||
|                         Field field = config.lastUsedKey.getClass().getDeclaredField(name); | ||||
|                         field.setAccessible(true); | ||||
|                         field.set(config.lastUsedKey, value); | ||||
|                     } catch (IllegalArgumentException 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); | ||||
|                     } catch (NoSuchFieldException e) { | ||||
|                         LOGGER.log(Level.SEVERE, e.getMessage(), e); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         }); | ||||
|         jTableAnimations.getModel().addTableModelListener(new TableModelListener() { | ||||
| 
 | ||||
|             @Override | ||||
|             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); | ||||
|                 } | ||||
|             } | ||||
|         }); | ||||
|         jButtonAddAnimation.addActionListener(new ActionListener() { | ||||
| 
 | ||||
|             @Override | ||||
|             public void actionPerformed(ActionEvent evt) { | ||||
|                 ((DefaultTableModel) jTableAnimations.getModel()).addRow(new Object[]{"", "", Integer.valueOf(-1), Integer.valueOf(-1)}); | ||||
|             } | ||||
|         }); | ||||
|         jButtonRemoveAnimation.addActionListener(new ActionListener() { | ||||
| 
 | ||||
|             @Override | ||||
|             public void actionPerformed(ActionEvent evt) { | ||||
|                 int row = jTableAnimations.getSelectedRow(); | ||||
|                 if (row >= 0) { | ||||
|                     ((DefaultTableModel) jTableAnimations.getModel()).removeRow(row); | ||||
|                 } | ||||
|             } | ||||
|         }); | ||||
| 
 | ||||
|         //button listeners | ||||
|         jButtonOK.addActionListener(new ActionListener() { | ||||
| 
 | ||||
|             @Override | ||||
|             public void actionPerformed(ActionEvent evt) { | ||||
|                 ConfigDialog.this.storeConfig(blenderKeyConfiguration); | ||||
|                 //running the test | ||||
|                 SwingUtilities.invokeLater(new Runnable() { | ||||
| 
 | ||||
|                     @Override | ||||
|                     public void run() { | ||||
|                         configExecutable.execute(ConfigDialog.this.blenderKeyConfiguration.getKeyToUse(), | ||||
|                                 ConfigDialog.this.blenderKeyConfiguration.logLevel); | ||||
|                     } | ||||
|                 }); | ||||
|                 //disposing the config window | ||||
|                 ConfigDialog.this.dispose(); | ||||
|             } | ||||
|         }); | ||||
|         jButtonCancel.addActionListener(new ActionListener() { | ||||
| 
 | ||||
|             @Override | ||||
|             public void actionPerformed(ActionEvent evt) { | ||||
|                 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) | ||||
|      */ | ||||
|     public static class BlenderKeyConfiguration implements Savable { | ||||
| 
 | ||||
|         private Map<String, BlenderKey> blenderKeys; | ||||
|         private BlenderKey lastUsedKey; | ||||
|         private Level logLevel; | ||||
|         private boolean useModelKey; | ||||
| 
 | ||||
|         /** | ||||
|          * Constructor for jme serialization. | ||||
|          */ | ||||
|         public BlenderKeyConfiguration() { | ||||
|         } | ||||
| 
 | ||||
|         /** | ||||
|          * Constructor that creates new empty configuration for every blender file. | ||||
|          * @param blenderFilesAmount the amount of blender files | ||||
|          */ | ||||
|         public BlenderKeyConfiguration(int blenderFilesAmount) { | ||||
|             blenderKeys = new HashMap<String, BlenderKey>(blenderFilesAmount); | ||||
|         } | ||||
| 
 | ||||
|         /** | ||||
|          * This method returns the key that will be used during the test. | ||||
|          * @return the key that will be used during the test | ||||
|          */ | ||||
|         public ModelKey getKeyToUse() { | ||||
|             return useModelKey ? new ModelKey(lastUsedKey.getName()) : lastUsedKey; | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public void write(JmeExporter ex) throws IOException { | ||||
|             OutputCapsule oc = ex.getCapsule(this); | ||||
|             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. | ||||
|  * @author Marcin Roguski (Kaelthas) | ||||
|  */ | ||||
| public interface IConfigExecutable { | ||||
| public interface ConfigExecutable { | ||||
| 	/** | ||||
| 	 * This method runs the test with the given blender key. | ||||
| 	 * @param modelKey | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -14,40 +14,41 @@ import com.jme3.scene.shape.Sphere; | ||||
|  * @author Marcin Roguski | ||||
|  */ | ||||
| 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) { | ||||
| 		Material defaultMaterial = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); | ||||
| 		defaultMaterial.setColor("Color", ColorRGBA.DarkGray); | ||||
| 		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); | ||||
|     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); | ||||
|     } | ||||
| 
 | ||||
| 			g = new Geometry("", new Sphere(3, 3, 0.05f)); | ||||
| 			g.setLocalTranslation(0, i, 0); | ||||
| 			g.setMaterial(defaultMaterial); | ||||
| 			this.attachChild(g); | ||||
|     private void assignPoints(AssetManager assetManager) { | ||||
|         Material defaultMaterial = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); | ||||
|         defaultMaterial.setColor("Color", ColorRGBA.DarkGray); | ||||
|         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.setLocalTranslation(0, 0, i); | ||||
| 			g.setMaterial(defaultMaterial); | ||||
| 			this.attachChild(g); | ||||
| 		} | ||||
| 	} | ||||
|             g = new Geometry("", new Sphere(3, 3, 0.05f)); | ||||
|             g.setLocalTranslation(0, i, 0); | ||||
|             g.setMaterial(defaultMaterial); | ||||
|             this.attachChild(g); | ||||
| 
 | ||||
| 	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; | ||||
| 	} | ||||
|             g = new Geometry("", new Sphere(3, 3, 0.05f)); | ||||
|             g.setLocalTranslation(0, 0, i); | ||||
|             g.setMaterial(defaultMaterial); | ||||
|             this.attachChild(g); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     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 | ||||
|  */ | ||||
| public class VisibleBone extends Node { | ||||
| 	private Vector3f	globalPosition; | ||||
| 
 | ||||
| 	public VisibleBone(Bone bone, Vector3f parentLocation, Quaternion parentRotation, AssetManager assetManager) { | ||||
| 		Material redMat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); | ||||
| 		redMat.setColor("Color", ColorRGBA.Red); | ||||
|     private Vector3f globalPosition; | ||||
| 
 | ||||
| 		Material whiteMat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); | ||||
| 		whiteMat.setColor("Color", ColorRGBA.White); | ||||
|     public VisibleBone(Bone bone, Vector3f parentLocation, Quaternion parentRotation, AssetManager assetManager) { | ||||
|         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)); | ||||
| 		globalPosition = bone.getLocalPosition().add(parentLocation); | ||||
| 		g.setLocalTranslation(globalPosition); | ||||
| 		g.setLocalRotation(bone.getLocalRotation().mult(parentRotation)); | ||||
| 		g.setMaterial(redMat); | ||||
| 		this.attachChild(g); | ||||
|         Material whiteMat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); | ||||
|         whiteMat.setColor("Color", ColorRGBA.White); | ||||
| 
 | ||||
| 		if(bone.getChildren() != null) { | ||||
| 			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); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|         Geometry g = new Geometry(bone.getName(), new Sphere(9, 9, 0.01f)); | ||||
|         globalPosition = bone.getLocalPosition().add(parentLocation); | ||||
|         g.setLocalTranslation(globalPosition); | ||||
|         g.setLocalRotation(bone.getLocalRotation().mult(parentRotation)); | ||||
|         g.setMaterial(redMat); | ||||
|         this.attachChild(g); | ||||
| 
 | ||||
|         if (bone.getChildren() != null) { | ||||
|             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 | ||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| 
 | ||||
| package jme3test.network; | ||||
| 
 | ||||
| import java.awt.Dimension; | ||||
| @ -38,19 +37,13 @@ import java.awt.Component; | ||||
| import java.io.IOException; | ||||
| import javax.swing.*; | ||||
| 
 | ||||
| import com.jme3.network.AbstractMessage; | ||||
| import com.jme3.network.Client; | ||||
| import com.jme3.network.HostedConnection; | ||||
| import com.jme3.network.Message; | ||||
| import com.jme3.network.MessageListener; | ||||
| 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; | ||||
| 
 | ||||
| 
 | ||||
| /** | ||||
|  *  A simple test chat server.  When SM implements a set | ||||
|  *  of standard chat classes this can become a lot simpler. | ||||
| @ -58,115 +51,108 @@ import jme3test.network.TestChatServer.ChatMessage; | ||||
|  *  @version   $Revision$ | ||||
|  *  @author    Paul Speed | ||||
|  */ | ||||
| public class TestChatClient extends JFrame | ||||
| { | ||||
| public class TestChatClient extends JFrame { | ||||
| 
 | ||||
|     private Client client; | ||||
|     private JEditorPane chatLog; | ||||
|     private StringBuilder chatMessages = new StringBuilder(); | ||||
|     private JTextField nameField; | ||||
|     private JTextField messageField;  | ||||
|      | ||||
|     public TestChatClient( String host ) throws IOException | ||||
|     { | ||||
|         super( "jME3 Test Chat Client - to:" + host ); | ||||
|          | ||||
|     private JTextField messageField; | ||||
| 
 | ||||
|     public TestChatClient(String host) throws IOException { | ||||
|         super("jME3 Test Chat Client - to:" + host); | ||||
| 
 | ||||
|         // Build out the UI        | ||||
|         setDefaultCloseOperation( DISPOSE_ON_CLOSE ); | ||||
|         setSize( 800, 600 ); | ||||
|          | ||||
|         setDefaultCloseOperation(DISPOSE_ON_CLOSE); | ||||
|         setSize(800, 600); | ||||
| 
 | ||||
|         chatLog = new JEditorPane(); | ||||
|         chatLog.setEditable(false); | ||||
|         chatLog.setContentType("text/html"); | ||||
|         chatLog.setText( "<html><body>" ); | ||||
|          | ||||
|         getContentPane().add( new JScrollPane(chatLog), "Center" ); | ||||
|   | ||||
|         chatLog.setText("<html><body>"); | ||||
| 
 | ||||
|         getContentPane().add(new JScrollPane(chatLog), "Center"); | ||||
| 
 | ||||
|         // A crude form        | ||||
|         JPanel p = new JPanel(); | ||||
|         p.setLayout( new BoxLayout(p, BoxLayout.X_AXIS) ); | ||||
|         p.add( new JLabel( "Name:" ) ); | ||||
|         nameField = new JTextField( System.getProperty( "user.name", "yourname" ) ); | ||||
|         p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS)); | ||||
|         p.add(new JLabel("Name:")); | ||||
|         nameField = new JTextField(System.getProperty("user.name", "yourname")); | ||||
|         Dimension d = nameField.getPreferredSize(); | ||||
|         nameField.setMaximumSize( new Dimension(120, d.height + 6) ); | ||||
|         p.add( nameField ); | ||||
|         p.add( new JLabel( "  Message:" ) ); | ||||
|         nameField.setMaximumSize(new Dimension(120, d.height + 6)); | ||||
|         p.add(nameField); | ||||
|         p.add(new JLabel("  Message:")); | ||||
|         messageField = new JTextField(); | ||||
|         p.add( messageField ); | ||||
|         p.add( new JButton(new SendAction(true)) );        | ||||
|         p.add( new JButton(new SendAction(false)) );        | ||||
|          | ||||
|         getContentPane().add( p, "South" ); | ||||
|          | ||||
|         client = Network.connectToServer( TestChatServer.NAME, TestChatServer.VERSION, | ||||
|                                           host, TestChatServer.PORT, TestChatServer.UDP_PORT );                                           | ||||
|         client.addMessageListener( new ChatHandler(), ChatMessage.class );                                              | ||||
|         client.start();                                                                                | ||||
|         p.add(messageField); | ||||
|         p.add(new JButton(new SendAction(true))); | ||||
|         p.add(new JButton(new SendAction(false))); | ||||
| 
 | ||||
|         getContentPane().add(p, "South"); | ||||
| 
 | ||||
|         client = Network.connectToServer(TestChatServer.NAME, TestChatServer.VERSION, | ||||
|                 host, TestChatServer.PORT, TestChatServer.UDP_PORT); | ||||
|         client.addMessageListener(new ChatHandler(), ChatMessage.class); | ||||
|         client.start(); | ||||
|     } | ||||
|   | ||||
|     public static String getString( Component owner, String title, String message, String initialValue ) | ||||
|     { | ||||
|         return (String)JOptionPane.showInputDialog( owner, message, title, JOptionPane.PLAIN_MESSAGE, | ||||
|                                                      null, null, initialValue ); | ||||
| 
 | ||||
|     public static String getString(Component owner, String title, String message, String initialValue) { | ||||
|         return (String) JOptionPane.showInputDialog(owner, message, title, JOptionPane.PLAIN_MESSAGE, | ||||
|                 null, null, initialValue); | ||||
|     } | ||||
|     | ||||
|     public static void main( String... args ) throws Exception | ||||
|     { | ||||
| 
 | ||||
|     public static void main(String... args) throws Exception { | ||||
|         TestChatServer.initializeClasses(); | ||||
| 
 | ||||
|         // Grab a host string from the user | ||||
|         String s = getString( null, "Host Info", "Enter chat host:", "localhost" ); | ||||
|         if( s == null ) { | ||||
|             System.out.println( "User cancelled." ); | ||||
|         String s = getString(null, "Host Info", "Enter chat host:", "localhost"); | ||||
|         if (s == null) { | ||||
|             System.out.println("User cancelled."); | ||||
|             return; | ||||
|         } | ||||
|      | ||||
|         TestChatClient test = new TestChatClient( s ); | ||||
|         test.setVisible( true ); | ||||
| 
 | ||||
|         TestChatClient test = new TestChatClient(s); | ||||
|         test.setVisible(true); | ||||
|     } | ||||
|   | ||||
|     private class ChatHandler implements MessageListener<Client> | ||||
|     { | ||||
|         public void messageReceived( Client source, Message m )  | ||||
|         { | ||||
|             ChatMessage chat = (ChatMessage)m; | ||||
|   | ||||
|             System.out.println( "Received:" + chat ); | ||||
|                         | ||||
| 
 | ||||
|     private class ChatHandler implements MessageListener<Client> { | ||||
| 
 | ||||
|         public void messageReceived(Client source, Message m) { | ||||
|             ChatMessage chat = (ChatMessage) m; | ||||
| 
 | ||||
|             System.out.println("Received:" + chat); | ||||
| 
 | ||||
|             // One of the least efficient ways to add text to a | ||||
|             // JEditorPane | ||||
|             chatMessages.append( "<font color='#00a000'>" + (m.isReliable() ? "TCP" : "UDP") + "</font>" ); | ||||
|             chatMessages.append( " -- <font color='#000080'><b>" + chat.getName() + "</b></font> : " );  | ||||
|             chatMessages.append( chat.getMessage() ); | ||||
|             chatMessages.append( "<br />" );  | ||||
|             String s = "<html><body>" + chatMessages + "</body></html>";  | ||||
|             chatLog.setText( s ); | ||||
|              | ||||
|             chatMessages.append("<font color='#00a000'>" + (m.isReliable() ? "TCP" : "UDP") + "</font>"); | ||||
|             chatMessages.append(" -- <font color='#000080'><b>" + chat.getName() + "</b></font> : "); | ||||
|             chatMessages.append(chat.getMessage()); | ||||
|             chatMessages.append("<br />"); | ||||
|             String s = "<html><body>" + chatMessages + "</body></html>"; | ||||
|             chatLog.setText(s); | ||||
| 
 | ||||
|             // Set selection to the end so that the scroll panel will scroll | ||||
|             // 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; | ||||
|          | ||||
|         public SendAction( boolean reliable ) | ||||
|         { | ||||
|             super( reliable ? "TCP" : "UDP" ); | ||||
| 
 | ||||
|         public SendAction(boolean reliable) { | ||||
|             super(reliable ? "TCP" : "UDP"); | ||||
|             this.reliable = reliable; | ||||
|         } | ||||
|          | ||||
|         public void actionPerformed( ActionEvent evt ) | ||||
|         { | ||||
| 
 | ||||
|         public void actionPerformed(ActionEvent evt) { | ||||
|             String name = nameField.getText(); | ||||
|             String message = messageField.getText(); | ||||
|              | ||||
|             ChatMessage chat = new ChatMessage( name, message ); | ||||
| 
 | ||||
|             ChatMessage chat = new ChatMessage(name, message); | ||||
|             chat.setReliable(reliable); | ||||
|             System.out.println( "Sending:" + chat ); | ||||
|             client.send( chat );  | ||||
|             System.out.println("Sending:" + chat); | ||||
|             client.send(chat); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -29,7 +29,6 @@ | ||||
|  * 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.Message; | ||||
| @ -41,7 +40,6 @@ import com.jme3.network.Server; | ||||
| import com.jme3.network.serializing.Serializable; | ||||
| import com.jme3.network.serializing.Serializer; | ||||
| 
 | ||||
| 
 | ||||
| /** | ||||
|  *  A simple test chat server.  When SM implements a set | ||||
|  *  of standard chat classes this can become a lot simpler. | ||||
| @ -49,105 +47,92 @@ import com.jme3.network.serializing.Serializer; | ||||
|  *  @version   $Revision$ | ||||
|  *  @author    Paul Speed | ||||
|  */ | ||||
| public class TestChatServer | ||||
| { | ||||
| public class TestChatServer { | ||||
|     // Normally these and the initialized method would | ||||
|     // be in shared constants or something. | ||||
| 
 | ||||
|     public static final String NAME = "Test Chat Server"; | ||||
|     public static final int VERSION = 1; | ||||
| 
 | ||||
|     public static final int 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 | ||||
|         // call our initialize.  | ||||
|         Serializer.registerClass(ChatMessage.class); | ||||
|     } | ||||
|      | ||||
|     public static void main( String... args ) throws Exception | ||||
|     { | ||||
| 
 | ||||
|     public static void main(String... args) throws Exception { | ||||
|         initializeClasses(); | ||||
|      | ||||
| 
 | ||||
|         // 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(); | ||||
| 
 | ||||
|         ChatHandler handler = new ChatHandler(); | ||||
|         server.addMessageListener( handler, ChatMessage.class ); | ||||
|   | ||||
|         server.addMessageListener(handler, ChatMessage.class); | ||||
| 
 | ||||
|         // Keep running basically forever | ||||
|         synchronized( NAME ) { | ||||
|         synchronized (NAME) { | ||||
|             NAME.wait(); | ||||
|         }            | ||||
|     } | ||||
|      | ||||
|     private static class ChatHandler implements MessageListener<HostedConnection> | ||||
|     { | ||||
|         public ChatHandler()  | ||||
|         { | ||||
|         } | ||||
|      | ||||
|         public void messageReceived( HostedConnection source, Message m ) | ||||
|         { | ||||
|             if( m instanceof ChatMessage ) { | ||||
|     } | ||||
| 
 | ||||
|     private static class ChatHandler implements MessageListener<HostedConnection> { | ||||
| 
 | ||||
|         public ChatHandler() { | ||||
|         } | ||||
| 
 | ||||
|         public void messageReceived(HostedConnection source, Message m) { | ||||
|             if (m instanceof ChatMessage) { | ||||
|                 // Keep track of the name just in case we  | ||||
|                 // want to know it for some other reason later and it's | ||||
|                 // a good example of session data | ||||
|                 source.setAttribute( "name", ((ChatMessage)m).getName() ); | ||||
|   | ||||
|                 System.out.println( "Broadcasting:" + m + "  reliable:" + m.isReliable() ); | ||||
|                                     | ||||
|                 source.setAttribute("name", ((ChatMessage) m).getName()); | ||||
| 
 | ||||
|                 System.out.println("Broadcasting:" + m + "  reliable:" + m.isReliable()); | ||||
| 
 | ||||
|                 // Just rebroadcast... the reliable flag will stay the | ||||
|                 // same so if it came in on UDP it will go out on that too | ||||
|                 source.getServer().broadcast( m );  | ||||
|                 source.getServer().broadcast(m); | ||||
|             } else { | ||||
|                 System.err.println( "Received odd message:" + m ); | ||||
|             }             | ||||
|                 System.err.println("Received odd message:" + m); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Serializable | ||||
|     public static class ChatMessage extends AbstractMessage  | ||||
|     { | ||||
|     public static class ChatMessage extends AbstractMessage { | ||||
| 
 | ||||
|         private String name; | ||||
|         private String message; | ||||
|   | ||||
|         public ChatMessage() | ||||
|         { | ||||
| 
 | ||||
|         public ChatMessage() { | ||||
|         } | ||||
| 
 | ||||
|         public ChatMessage( String name, String message ) | ||||
|         { | ||||
|         public ChatMessage(String name, String message) { | ||||
|             setName(name); | ||||
|             setMessage(message); | ||||
|         } | ||||
|          | ||||
|         public void setName( String name ) | ||||
|         { | ||||
| 
 | ||||
|         public void setName(String name) { | ||||
|             this.name = name; | ||||
|         } | ||||
|          | ||||
|         public String getName() | ||||
|         { | ||||
| 
 | ||||
|         public String getName() { | ||||
|             return name; | ||||
|         } | ||||
|          | ||||
|         public void setMessage( String s ) | ||||
|         { | ||||
| 
 | ||||
|         public void setMessage(String s) { | ||||
|             this.message = s; | ||||
|         } | ||||
|          | ||||
|         public String getMessage() | ||||
|         { | ||||
| 
 | ||||
|         public String getMessage() { | ||||
|             return message; | ||||
|         } | ||||
|          | ||||
|         public String toString() | ||||
|         { | ||||
| 
 | ||||
|         public String toString() { | ||||
|             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; | ||||
| 
 | ||||
| import com.jme3.network.connection.Client; | ||||
| import com.jme3.network.connection.Server; | ||||
| import com.jme3.network.events.MessageAdapter; | ||||
| import com.jme3.network.message.Message; | ||||
| import com.jme3.network.Client; | ||||
| import com.jme3.network.HostedConnection; | ||||
| import com.jme3.network.MessageListener; | ||||
| 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.Serializer; | ||||
| import com.jme3.network.sync.MovingAverage; | ||||
| import java.io.IOException; | ||||
| 
 | ||||
| public class TestLatency extends MessageAdapter { | ||||
| public class TestLatency { | ||||
| 
 | ||||
|     private static long startTime; | ||||
|     private static Client client; | ||||
| @ -56,7 +58,7 @@ public class TestLatency extends MessageAdapter { | ||||
|     } | ||||
| 
 | ||||
|     @Serializable | ||||
|     public static class TimestampMessage extends Message { | ||||
|     public static class TimestampMessage extends com.jme3.network.message.Message { | ||||
| 
 | ||||
|         long timeSent     = 0; | ||||
|         long timeReceived = 0; | ||||
| @ -73,14 +75,19 @@ public class TestLatency extends MessageAdapter { | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void messageReceived(Message msg){ | ||||
|         TimestampMessage timeMsg = (TimestampMessage) msg; | ||||
|         try { | ||||
|             if (timeMsg.timeReceived == 0){ | ||||
|                 TimestampMessage outMsg = new TimestampMessage(timeMsg.timeSent, getTime()); | ||||
|                 msg.getClient().send(outMsg); | ||||
|             }else{ | ||||
|     public static void main(String[] args) throws IOException, InterruptedException{ | ||||
|         Serializer.registerClass(TimestampMessage.class); | ||||
| 
 | ||||
|         Server server = Network.createServer(5110); | ||||
|         server.start(); | ||||
| 
 | ||||
|         client = Network.connectToServer("localhost", 5110); | ||||
|         client.start(); | ||||
|          | ||||
|         client.addMessageListener(new MessageListener<Client>(){ | ||||
|             public void messageReceived(Client source, Message m) { | ||||
|                 TimestampMessage timeMsg = (TimestampMessage) m; | ||||
| 
 | ||||
|                 long curTime = getTime(); | ||||
|                 //System.out.println("Time sent: " + timeMsg.timeSent); | ||||
|                 //System.out.println("Time received by server: " + timeMsg.timeReceived); | ||||
| @ -99,26 +106,24 @@ public class TestLatency extends MessageAdapter { | ||||
| 
 | ||||
|                 client.send(new TimestampMessage(getTime(), 0)); | ||||
|             } | ||||
|         } catch (IOException ex) { | ||||
|             ex.printStackTrace(); | ||||
|         } | ||||
|     } | ||||
|         }, TimestampMessage.class); | ||||
| 
 | ||||
|     public static void main(String[] args) throws IOException, InterruptedException{ | ||||
|         Serializer.registerClass(TimestampMessage.class); | ||||
| 
 | ||||
|         Server server = new Server(5110, 5110); | ||||
|         server.start(); | ||||
| 
 | ||||
|         client = new Client("localhost", 5110, 5110); | ||||
|         client.start(); | ||||
| 
 | ||||
|         client.addMessageListener(new TestLatency(), TimestampMessage.class); | ||||
|         server.addMessageListener(new TestLatency(), TimestampMessage.class); | ||||
|         server.addMessageListener(new MessageListener<HostedConnection>(){ | ||||
|             public void messageReceived(HostedConnection source, Message m) { | ||||
|                 TimestampMessage timeMsg = (TimestampMessage) m; | ||||
|                 TimestampMessage outMsg = new TimestampMessage(timeMsg.timeSent, getTime()); | ||||
|                 source.send(outMsg); | ||||
|             } | ||||
|         }, TimestampMessage.class); | ||||
| 
 | ||||
|         Thread.sleep(1); | ||||
| 
 | ||||
|         client.send(new TimestampMessage(getTime(), 0)); | ||||
|          | ||||
|         Object obj = new Object(); | ||||
|         synchronized(obj){ | ||||
|             obj.wait(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | ||||
| @ -32,12 +32,12 @@ | ||||
| 
 | ||||
| package jme3test.network; | ||||
| 
 | ||||
| import com.jme3.network.AbstractMessage; | ||||
| import com.jme3.network.Client; | ||||
| import com.jme3.network.HostedConnection; | ||||
| import com.jme3.network.MessageListener; | ||||
| import com.jme3.network.Network; | ||||
| import com.jme3.network.Server; | ||||
| import com.jme3.network.message.Message; | ||||
| import com.jme3.network.serializing.Serializable; | ||||
| import com.jme3.network.serializing.Serializer; | ||||
| import java.io.IOException; | ||||
| @ -45,11 +45,11 @@ import java.io.IOException; | ||||
| public class TestMessages { | ||||
| 
 | ||||
|     @Serializable | ||||
|     public static class PingMessage extends Message { | ||||
|     public static class PingMessage extends AbstractMessage { | ||||
|     } | ||||
| 
 | ||||
|     @Serializable | ||||
|     public static class PongMessage extends Message { | ||||
|     public static class PongMessage extends AbstractMessage { | ||||
|     } | ||||
| 
 | ||||
|     private static class ServerPingResponder implements MessageListener<HostedConnection> { | ||||
| @ -76,15 +76,18 @@ public class TestMessages { | ||||
|         Server server = Network.createServer(5110); | ||||
|         server.start(); | ||||
| 
 | ||||
|         Client client = Network.connectToServer("192.168.1.101", 5110, 5111); | ||||
|         Client client = Network.connectToServer("localhost", 5110); | ||||
|         client.start(); | ||||
| 
 | ||||
|         server.addMessageListener(new ServerPingResponder(), PingMessage.class); | ||||
|         client.addMessageListener(new ClientPingResponder(), PongMessage.class); | ||||
| 
 | ||||
|         Thread.sleep(100); | ||||
| 
 | ||||
|         System.out.println("Sending ping message.."); | ||||
|         System.out.println("Client: Sending ping message.."); | ||||
|         client.send(new PingMessage()); | ||||
|          | ||||
|         Object obj = new Object(); | ||||
|         synchronized (obj){ | ||||
|             obj.wait(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -32,37 +32,39 @@ | ||||
| 
 | ||||
| package jme3test.network; | ||||
| 
 | ||||
| import com.jme3.network.connection.Client; | ||||
| import com.jme3.network.connection.Server; | ||||
| import com.jme3.network.events.ConnectionAdapter; | ||||
| import com.jme3.network.Client; | ||||
| import com.jme3.network.ConnectionListener; | ||||
| import com.jme3.network.HostedConnection; | ||||
| import com.jme3.network.Network; | ||||
| import com.jme3.network.Server; | ||||
| import java.io.IOException; | ||||
| import java.util.logging.Level; | ||||
| import java.util.logging.Logger; | ||||
| 
 | ||||
| public class TestNetworkStress extends ConnectionAdapter { | ||||
| public class TestNetworkStress implements ConnectionListener { | ||||
|      | ||||
|     @Override | ||||
|     public void clientConnected(Client client) { | ||||
|         System.out.println("CLIENT CONNECTED: "+client.getClientID()); | ||||
|         try { | ||||
|             client.kick("goodbye"); | ||||
|         } catch (IOException ex) { | ||||
|             ex.printStackTrace(); | ||||
|         } | ||||
|     public void connectionAdded(Server server, HostedConnection conn) { | ||||
|         System.out.println("Client Connected: "+conn.getId()); | ||||
|         //conn.close("goodbye"); | ||||
|     } | ||||
| 
 | ||||
|     public void connectionRemoved(Server server, HostedConnection conn) { | ||||
|     } | ||||
|      | ||||
|     public static void main(String[] args) throws IOException, InterruptedException{ | ||||
|         Logger.getLogger("").getHandlers()[0].setLevel(Level.OFF); | ||||
|          | ||||
|         Server server = new Server(5110, 5110); | ||||
|         Server server = Network.createServer(5110); | ||||
|         server.start(); | ||||
|         server.addConnectionListener(new TestNetworkStress()); | ||||
| 
 | ||||
|         for (int i = 0; i < 1000; i++){ | ||||
|             Client client = new Client("localhost", 5110, 5110); | ||||
|             Client client = Network.connectToServer("localhost", 5110); | ||||
|             client.start(); | ||||
| 
 | ||||
|             Thread.sleep(10); | ||||
|              | ||||
|             client.close(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -34,25 +34,45 @@ package jme3test.network; | ||||
| 
 | ||||
| import com.jme3.app.SimpleApplication; | ||||
| import com.jme3.export.Savable; | ||||
| import com.jme3.network.connection.Client; | ||||
| import com.jme3.network.connection.Server; | ||||
| import com.jme3.network.Client; | ||||
| 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.RemoteObjectDefMessage; | ||||
| import com.jme3.network.serializing.Serializer; | ||||
| import com.jme3.network.serializing.serializers.SavableSerializer; | ||||
| import com.jme3.scene.Spatial; | ||||
| import java.io.IOException; | ||||
| import java.lang.reflect.Method; | ||||
| import java.util.concurrent.Callable; | ||||
| 
 | ||||
| public class TestRemoteCall { | ||||
| 
 | ||||
|     private static SimpleApplication serverApp; | ||||
| 
 | ||||
|     /** | ||||
|      * Interface implemented by the server, exposing | ||||
|      * RMI calls that clients can use. | ||||
|      */ | ||||
|     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 void attachChild(String model) { | ||||
|         public boolean attachChild(String model) { | ||||
|             if (model == null) | ||||
|                 throw new RuntimeException("Cannot be null. .. etc"); | ||||
| 
 | ||||
|             final String finalModel = model; | ||||
|             serverApp.enqueue(new Callable<Void>() { | ||||
|                 public Void call() throws Exception { | ||||
| @ -61,6 +81,7 @@ public class TestRemoteCall { | ||||
|                     return null; | ||||
|                 } | ||||
|             }); | ||||
|             return true; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -73,7 +94,7 @@ public class TestRemoteCall { | ||||
|         serverApp.start(); | ||||
| 
 | ||||
|         try { | ||||
|             Server server = new Server(5110, 5110); | ||||
|             Server server = Network.createServer(5110); | ||||
|             server.start(); | ||||
| 
 | ||||
|             ObjectStore store = new ObjectStore(server); | ||||
| @ -88,11 +109,12 @@ public class TestRemoteCall { | ||||
| 
 | ||||
|         createServer(); | ||||
| 
 | ||||
|         Client client = new Client("localhost", 5110, 5110); | ||||
|         Client client = Network.connectToServer("localhost", 5110); | ||||
|         client.start(); | ||||
| 
 | ||||
|         ObjectStore store = new ObjectStore(client); | ||||
|         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 | ||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| 
 | ||||
| package jme3test.network; | ||||
| 
 | ||||
| import com.jme3.network.AbstractMessage; | ||||
| import com.jme3.network.Client; | ||||
| import com.jme3.network.Message; | ||||
| import com.jme3.network.MessageConnection; | ||||
| @ -47,59 +47,64 @@ public class TestThroughput implements MessageListener<MessageConnection> { //ex | ||||
|     private static long lastTime = -1; | ||||
|     private static long counter = 0; | ||||
|     private static long total = 0; | ||||
|     private static Client client; | ||||
| 
 | ||||
|     // Change this flag to test UDP instead of TCP | ||||
|     private static boolean testReliable = false; | ||||
|      | ||||
|     private boolean isOnServer; | ||||
| 
 | ||||
|     public TestThroughput( boolean isOnServer ) { | ||||
|     public TestThroughput(boolean isOnServer) { | ||||
|         this.isOnServer = isOnServer; | ||||
|     }  | ||||
|     } | ||||
|      | ||||
|     @Serializable | ||||
|     public static class TestMessage extends AbstractMessage { | ||||
| 
 | ||||
|         public TestMessage() { | ||||
|             setReliable(testReliable); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void messageReceived( MessageConnection source, Message msg){ | ||||
|      | ||||
|         if( !isOnServer ) { | ||||
|     public void messageReceived(MessageConnection source, Message msg) { | ||||
| 
 | ||||
|         if (!isOnServer) { | ||||
|             // It's local to the client so we got it back | ||||
|             counter++; | ||||
|             total++; | ||||
|             long time = System.currentTimeMillis(); | ||||
| //System.out.println( "total:" + total + "  counter:" + counter + "  lastTime:" + lastTime + "  time:" + time ); | ||||
|             if( lastTime < 0 ) { | ||||
|             if (lastTime < 0) { | ||||
|                 lastTime = time; | ||||
|             } else if( time - lastTime > 1000 ) { | ||||
|             } else if (time - lastTime > 1000) { | ||||
|                 long delta = time - lastTime; | ||||
|                 double scale = delta / 1000.0; | ||||
|                 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; | ||||
|                 lastTime = time; | ||||
|             } | ||||
|         } else { | ||||
|             if( source == null ) { | ||||
|                 System.out.println( "Received a message from a not fully connected source, msg:"+ msg ); | ||||
|             if (source == null) { | ||||
|                 System.out.println("Received a message from a not fully connected source, msg:" + msg); | ||||
|             } else { | ||||
| //System.out.println( "sending:" + msg + " back to client:" + source ); | ||||
|                 // The 'reliable' flag is transient and the server doesn't | ||||
|                 // (yet) reset this value for us. | ||||
|                 ((com.jme3.network.message.Message)msg).setReliable(testReliable); | ||||
|                 ((com.jme3.network.Message) msg).setReliable(testReliable); | ||||
|                 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); | ||||
| 
 | ||||
|         // Use this to test the client/server name version check | ||||
|         //Server server = Network.createServer( "bad name", 42, 5110, 5110 ); | ||||
|         Server server = Network.createServer( 5110, 5110 ); | ||||
|         Server server = Network.createServer(5110, 5110); | ||||
|         server.start(); | ||||
| 
 | ||||
|         Client client = Network.connectToServer( "localhost", 5110 ); | ||||
|         Client client = Network.connectToServer("localhost", 5110); | ||||
|         client.start(); | ||||
| 
 | ||||
|         client.addMessageListener(new TestThroughput(false), TestMessage.class); | ||||
| @ -109,20 +114,11 @@ public class TestThroughput implements MessageListener<MessageConnection> { //ex | ||||
| 
 | ||||
|         TestMessage test = new TestMessage(); | ||||
| //        for( int i = 0; i < 10; i++ ) { | ||||
|         while( true ) { | ||||
|         while (true) { | ||||
| //System.out.println( "sending." ); | ||||
|             client.send(test); | ||||
|         }             | ||||
|   | ||||
|         } | ||||
| 
 | ||||
|         //Thread.sleep(5000); | ||||
|     } | ||||
| 
 | ||||
|     @Serializable | ||||
|     public static class TestMessage extends com.jme3.network.message.Message { | ||||
| 
 | ||||
|         public TestMessage(){ | ||||
|             setReliable(testReliable); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user