* 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