From ddca06e6073b4a7fe0c652c48b17a011bf286c31 Mon Sep 17 00:00:00 2001 From: "Sha..rd" Date: Wed, 11 Apr 2012 22:20:23 +0000 Subject: [PATCH] * Materials.equals() method now works correctly (checking if material will look the same if rendered, in 99.9% of cases..) * ListMap entries now implement equals method as required by spec git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9289 75d07b2b-3a1a-0410-a2c5-0572b91ccdca --- .../src/core/com/jme3/material/MatParam.java | 33 ++-- .../src/core/com/jme3/material/Material.java | 142 ++++++++---------- .../core/com/jme3/material/RenderState.java | 68 ++++++++- engine/src/core/com/jme3/renderer/Caps.java | 61 +++++--- .../jme3/renderer/queue/OpaqueComparator.java | 7 +- engine/src/core/com/jme3/scene/BatchNode.java | 2 +- engine/src/core/com/jme3/texture/Image.java | 9 +- engine/src/core/com/jme3/texture/Texture.java | 33 ++-- engine/src/core/com/jme3/util/ListMap.java | 41 ++++- 9 files changed, 259 insertions(+), 137 deletions(-) diff --git a/engine/src/core/com/jme3/material/MatParam.java b/engine/src/core/com/jme3/material/MatParam.java index b0ef117dd..c363f7588 100644 --- a/engine/src/core/com/jme3/material/MatParam.java +++ b/engine/src/core/com/jme3/material/MatParam.java @@ -328,21 +328,36 @@ When arrays can be inserted in J3M files } @Override - public boolean equals(Object other) { - if (!(other instanceof MatParam)) { + public boolean equals(Object obj) { + if (obj == null) { return false; } - - MatParam otherParam = (MatParam) other; - return otherParam.type == type - && otherParam.name.equals(name); + if (getClass() != obj.getClass()) { + return false; + } + final MatParam other = (MatParam) obj; + if (this.type != other.type) { + return false; + } + if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) { + return false; + } + if (this.value != other.value && (this.value == null || !this.value.equals(other.value))) { + return false; + } + if (this.ffBinding != other.ffBinding) { + return false; + } + return true; } @Override public int hashCode() { - int hash = 5; - hash = 17 * hash + (this.type != null ? this.type.hashCode() : 0); - hash = 17 * hash + (this.name != null ? this.name.hashCode() : 0); + int hash = 7; + hash = 59 * hash + (this.type != null ? this.type.hashCode() : 0); + hash = 59 * hash + (this.name != null ? this.name.hashCode() : 0); + hash = 59 * hash + (this.value != null ? this.value.hashCode() : 0); + hash = 59 * hash + (this.ffBinding != null ? this.ffBinding.hashCode() : 0); return hash; } diff --git a/engine/src/core/com/jme3/material/Material.java b/engine/src/core/com/jme3/material/Material.java index dd20d8b32..0989a0aaf 100644 --- a/engine/src/core/com/jme3/material/Material.java +++ b/engine/src/core/com/jme3/material/Material.java @@ -29,7 +29,7 @@ */ package com.jme3.material; -import com.jme3.asset.Asset; +import com.jme3.asset.CloneableSmartAsset; import com.jme3.asset.AssetKey; import com.jme3.asset.AssetManager; import com.jme3.export.*; @@ -63,9 +63,10 @@ import java.util.logging.Logger; * Setting the parameters can modify the behavior of a * shader. *

+ * * @author Kirill Vainer */ -public class Material implements Asset, Cloneable, Savable, Comparable { +public class Material implements CloneableSmartAsset, Cloneable, Savable { // Version #2: Fixed issue with RenderState.apply*** flags not getting exported public static final int SAVABLE_VERSION = 2; @@ -139,7 +140,7 @@ public class Material implements Asset, Cloneable, Savable, Comparable public String getName() { return name; } - + /** * This method sets the name of the material. * The name is not the same as the asset name. @@ -188,27 +189,6 @@ public class Material implements Asset, Cloneable, Savable, Comparable return sortingId; } - /** - * Uses the sorting ID for each material to compare them. - * - * @param m The other material to compare to. - * - * @return zero if the materials are equal, returns a negative value - * if this has a lower sorting ID than m, - * otherwise returns a positive value. - */ - public int compareTo(Material m) { - return m.getSortId() - getSortId(); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof Material) { - return ((Material) obj).compareTo(this) == 0; - } - return super.equals(obj); - } - /** * Clones this material. The result is returned. */ @@ -237,77 +217,84 @@ public class Material implements Asset, Cloneable, Savable, Comparable /** * Compares two materials and returns true if they are equal. - * This methods compare definition, params, additional render states - * The difference with the equals method is that it's truely comaring the objects. (equals compare the sort ids for geometry sorting) - * @param mat the material to cmpare to this material + * This methods compare definition, parameters, additional render states + * + * @param otherObj the material to compare to this material * @return true if the materials are equal. */ - public boolean isEqual(Material mat) { - //early exit if the material are the same object - if (this == mat) { + @Override + public boolean equals(Object otherObj) { + if (!(otherObj instanceof Material)) { + return false; + } + + Material other = (Material) otherObj; + + // Early exit if the material are the same object + if (this == other) { return true; } - - //comparing matrial definition - if (this.getMaterialDef() != mat.getMaterialDef()) { + // Check material definition + if (this.getMaterialDef() != other.getMaterialDef()) { return false; } - //early exit if the size of the params is different - if (paramValues.size() != mat.paramValues.size()) { + // Early exit if the size of the params is different + if (this.paramValues.size() != other.paramValues.size()) { return false; } - - //comparing params - for (String paramKey : paramValues.keySet()) { - MatParam paramOrig = getParam(paramKey); - MatParam param = mat.getParam(paramKey); - //this param does not exist in compared mat - if (param == null) { + + // Checking technique + if (this.technique != null || other.technique != null) { + // Techniques are considered equal if their names are the same + // E.g. if user chose custom technique for one material but + // uses default technique for other material, the materials + // are not equal. + String thisDefName = this.technique != null ? this.technique.getDef().getName() : null; + String otherDefName = other.technique != null ? other.technique.getDef().getName() : null; + if (!thisDefName.equals(otherDefName)) { return false; } + } + + // Comparing parameters + for (String paramKey : paramValues.keySet()) { + MatParam thisParam = this.getParam(paramKey); + MatParam otherParam = other.getParam(paramKey); - //params exist in both materials but they not of the same type - if (param.type != paramOrig.type) { + // This param does not exist in compared mat + if (otherParam == null) { return false; } - if (param instanceof MatParamTexture) { - MatParamTexture tex = (MatParamTexture) param; - MatParamTexture texOrig = (MatParamTexture) paramOrig; - //comparing textures - if (getTextureId(tex) != getTextureId(texOrig)) { - return false; - } - } else { - if (!param.getValue().equals(paramOrig.getValue())) { - return false; - } + if (!otherParam.equals(thisParam)) { + return false; } } - - //comparing additional render states + // Comparing additional render states if (additionalState == null) { - if (mat.additionalState != null) { + if (other.additionalState != null) { return false; } } else { - if (!additionalState.equals(mat.additionalState)) { + if (!additionalState.equals(other.additionalState)) { return false; } } - - + return true; } - private int getTextureId(MatParamTexture param) { - if (param.getTextureValue() != null && param.getTextureValue().getImage() != null) { - return param.getTextureValue().getImage().getId(); - } - return -1; + @Override + public int hashCode() { + int hash = 7; + hash = 29 * hash + (this.def != null ? this.def.hashCode() : 0); + hash = 29 * hash + (this.paramValues != null ? this.paramValues.hashCode() : 0); + hash = 29 * hash + (this.technique != null ? this.technique.getDef().getName().hashCode() : 0); + hash = 29 * hash + (this.additionalState != null ? this.additionalState.hashCode() : 0); + return hash; } /** @@ -701,18 +688,17 @@ public class Material implements Asset, Cloneable, Savable, Comparable } /** - * Uploads the lights in the light list as two uniform arrays.

- * *

- * uniform vec4 g_LightColor[numLights];
- * // g_LightColor.rgb is the diffuse/specular color of the light.
- * // g_Lightcolor.a is the type of light, 0 = Directional, 1 = Point,
- * // 2 = Spot.
- *
- * uniform vec4 g_LightPosition[numLights];
- * // g_LightPosition.xyz is the position of the light (for point lights)
- * // or the direction of the light (for directional lights).
- * // g_LightPosition.w is the inverse radius (1/r) of the light (for attenuation)
- *

+ * Uploads the lights in the light list as two uniform arrays.

* + *

+ * uniform vec4 g_LightColor[numLights];
// + * g_LightColor.rgb is the diffuse/specular color of the light.
// + * g_Lightcolor.a is the type of light, 0 = Directional, 1 = Point,
// + * 2 = Spot.

+ * uniform vec4 g_LightPosition[numLights];
// + * g_LightPosition.xyz is the position of the light (for point lights)
+ * // or the direction of the light (for directional lights).
// + * g_LightPosition.w is the inverse radius (1/r) of the light (for + * attenuation)

*/ protected void updateLightListUniforms(Shader shader, Geometry g, int numLights) { if (numLights == 0) { // this shader does not do lighting, ignore. diff --git a/engine/src/core/com/jme3/material/RenderState.java b/engine/src/core/com/jme3/material/RenderState.java index 23e368a95..4dc4d112b 100644 --- a/engine/src/core/com/jme3/material/RenderState.java +++ b/engine/src/core/com/jme3/material/RenderState.java @@ -304,6 +304,7 @@ public class RenderState implements Cloneable, Savable { StencilOperation backStencilDepthPassOperation = StencilOperation.Keep; TestFunction frontStencilFunction = TestFunction.Always; TestFunction backStencilFunction = TestFunction.Always; + int cachedHashCode = -1; public void write(JmeExporter ex) throws IOException { OutputCapsule oc = ex.getCapsule(this); @@ -505,6 +506,7 @@ public class RenderState implements Cloneable, Savable { public void setPointSprite(boolean pointSprite) { applyPointSprite = true; this.pointSprite = pointSprite; + cachedHashCode = -1; } /** @@ -522,6 +524,7 @@ public class RenderState implements Cloneable, Savable { public void setAlphaFallOff(float alphaFallOff) { applyAlphaFallOff = true; this.alphaFallOff = alphaFallOff; + cachedHashCode = -1; } /** @@ -539,6 +542,7 @@ public class RenderState implements Cloneable, Savable { public void setAlphaTest(boolean alphaTest) { applyAlphaTest = true; this.alphaTest = alphaTest; + cachedHashCode = -1; } /** @@ -553,6 +557,7 @@ public class RenderState implements Cloneable, Savable { public void setColorWrite(boolean colorWrite) { applyColorWrite = true; this.colorWrite = colorWrite; + cachedHashCode = -1; } /** @@ -570,6 +575,7 @@ public class RenderState implements Cloneable, Savable { public void setFaceCullMode(FaceCullMode cullMode) { applyCullMode = true; this.cullMode = cullMode; + cachedHashCode = -1; } /** @@ -589,6 +595,7 @@ public class RenderState implements Cloneable, Savable { public void setBlendMode(BlendMode blendMode) { applyBlendMode = true; this.blendMode = blendMode; + cachedHashCode = -1; } /** @@ -604,6 +611,7 @@ public class RenderState implements Cloneable, Savable { public void setDepthTest(boolean depthTest) { applyDepthTest = true; this.depthTest = depthTest; + cachedHashCode = -1; } /** @@ -618,6 +626,7 @@ public class RenderState implements Cloneable, Savable { public void setDepthWrite(boolean depthWrite) { applyDepthWrite = true; this.depthWrite = depthWrite; + cachedHashCode = -1; } /** @@ -632,6 +641,7 @@ public class RenderState implements Cloneable, Savable { public void setWireframe(boolean wireframe) { applyWireFrame = true; this.wireframe = wireframe; + cachedHashCode = -1; } /** @@ -651,6 +661,7 @@ public class RenderState implements Cloneable, Savable { offsetEnabled = true; offsetFactor = factor; offsetUnits = units; + cachedHashCode = -1; } /** @@ -699,6 +710,7 @@ public class RenderState implements Cloneable, Savable { this.backStencilDepthPassOperation = _backStencilDepthPassOperation; this.frontStencilFunction = _frontStencilFunction; this.backStencilFunction = _backStencilFunction; + cachedHashCode = -1; } /** @@ -1032,6 +1044,36 @@ public class RenderState implements Cloneable, Savable { return applyWireFrame; } + @Override + public int hashCode() { + if (cachedHashCode == -1){ + int hash = 7; + hash = 79 * hash + (this.pointSprite ? 1 : 0); + hash = 79 * hash + (this.wireframe ? 1 : 0); + hash = 79 * hash + (this.cullMode != null ? this.cullMode.hashCode() : 0); + hash = 79 * hash + (this.depthWrite ? 1 : 0); + hash = 79 * hash + (this.depthTest ? 1 : 0); + hash = 79 * hash + (this.colorWrite ? 1 : 0); + hash = 79 * hash + (this.blendMode != null ? this.blendMode.hashCode() : 0); + hash = 79 * hash + (this.alphaTest ? 1 : 0); + hash = 79 * hash + Float.floatToIntBits(this.alphaFallOff); + hash = 79 * hash + Float.floatToIntBits(this.offsetFactor); + hash = 79 * hash + Float.floatToIntBits(this.offsetUnits); + hash = 79 * hash + (this.offsetEnabled ? 1 : 0); + hash = 79 * hash + (this.stencilTest ? 1 : 0); + hash = 79 * hash + (this.frontStencilStencilFailOperation != null ? this.frontStencilStencilFailOperation.hashCode() : 0); + hash = 79 * hash + (this.frontStencilDepthFailOperation != null ? this.frontStencilDepthFailOperation.hashCode() : 0); + hash = 79 * hash + (this.frontStencilDepthPassOperation != null ? this.frontStencilDepthPassOperation.hashCode() : 0); + hash = 79 * hash + (this.backStencilStencilFailOperation != null ? this.backStencilStencilFailOperation.hashCode() : 0); + hash = 79 * hash + (this.backStencilDepthFailOperation != null ? this.backStencilDepthFailOperation.hashCode() : 0); + hash = 79 * hash + (this.backStencilDepthPassOperation != null ? this.backStencilDepthPassOperation.hashCode() : 0); + hash = 79 * hash + (this.frontStencilFunction != null ? this.frontStencilFunction.hashCode() : 0); + hash = 79 * hash + (this.backStencilFunction != null ? this.backStencilFunction.hashCode() : 0); + cachedHashCode = hash; + } + return cachedHashCode; + } + /** * Merges this state and additionalState into * the parameter state based on a specific criteria. @@ -1141,11 +1183,35 @@ public class RenderState implements Cloneable, Savable { state.frontStencilFunction = frontStencilFunction; state.backStencilFunction = backStencilFunction; } + state.cachedHashCode = -1; return state; } @Override public String toString() { - return "RenderState[\n" + "pointSprite=" + pointSprite + "\napplyPointSprite=" + applyPointSprite + "\nwireframe=" + wireframe + "\napplyWireFrame=" + applyWireFrame + "\ncullMode=" + cullMode + "\napplyCullMode=" + applyCullMode + "\ndepthWrite=" + depthWrite + "\napplyDepthWrite=" + applyDepthWrite + "\ndepthTest=" + depthTest + "\napplyDepthTest=" + applyDepthTest + "\ncolorWrite=" + colorWrite + "\napplyColorWrite=" + applyColorWrite + "\nblendMode=" + blendMode + "\napplyBlendMode=" + applyBlendMode + "\nalphaTest=" + alphaTest + "\napplyAlphaTest=" + applyAlphaTest + "\nalphaFallOff=" + alphaFallOff + "\napplyAlphaFallOff=" + applyAlphaFallOff + "\noffsetEnabled=" + offsetEnabled + "\napplyPolyOffset=" + applyPolyOffset + "\noffsetFactor=" + offsetFactor + "\noffsetUnits=" + offsetUnits + "\n]"; + return "RenderState[\n" + + "pointSprite=" + pointSprite + + "\napplyPointSprite=" + applyPointSprite + + "\nwireframe=" + wireframe + + "\napplyWireFrame=" + applyWireFrame + + "\ncullMode=" + cullMode + + "\napplyCullMode=" + applyCullMode + + "\ndepthWrite=" + depthWrite + + "\napplyDepthWrite=" + applyDepthWrite + + "\ndepthTest=" + depthTest + + "\napplyDepthTest=" + applyDepthTest + + "\ncolorWrite=" + colorWrite + + "\napplyColorWrite=" + applyColorWrite + + "\nblendMode=" + blendMode + + "\napplyBlendMode=" + applyBlendMode + + "\nalphaTest=" + alphaTest + + "\napplyAlphaTest=" + applyAlphaTest + + "\nalphaFallOff=" + alphaFallOff + + "\napplyAlphaFallOff=" + applyAlphaFallOff + + "\noffsetEnabled=" + offsetEnabled + + "\napplyPolyOffset=" + applyPolyOffset + + "\noffsetFactor=" + offsetFactor + + "\noffsetUnits=" + offsetUnits + + "\n]"; } } diff --git a/engine/src/core/com/jme3/renderer/Caps.java b/engine/src/core/com/jme3/renderer/Caps.java index 4dd1ed8af..ddf2cd9cc 100644 --- a/engine/src/core/com/jme3/renderer/Caps.java +++ b/engine/src/core/com/jme3/renderer/Caps.java @@ -203,7 +203,7 @@ public enum Caps { * Supports Format.RGB9E5 for FBO color buffers */ SharedExponentColorBuffer, - + /** * Supports Format.LATC for textures, this includes * support for ATI's 3Dc texture compression. @@ -226,7 +226,12 @@ public enum Caps { /** * Supports multisampling on the screen */ - Multisample; + Multisample, + + /** + * Supports FBO with Depth24Stencil8 image format + */ + PackedDepthStencilBuffer; /** * Returns true if given the renderer capabilities, the texture @@ -251,6 +256,8 @@ public enum Caps { Format fmt = img.getFormat(); switch (fmt){ + case Depth24Stencil8: + return caps.contains(Caps.PackedDepthStencilBuffer); case Depth32F: return caps.contains(Caps.FloatDepthBuffer); case LATC: @@ -268,6 +275,29 @@ public enum Caps { return true; } } + + private static boolean supportsColorBuffer(Collection caps, RenderBuffer colorBuf){ + Format colorFmt = colorBuf.getFormat(); + if (colorFmt.isDepthFormat()) + return false; + + if (colorFmt.isCompressed()) + return false; + + switch (colorFmt){ + case RGB111110F: + return caps.contains(Caps.PackedFloatColorBuffer); + case RGB16F_to_RGB111110F: + case RGB16F_to_RGB9E5: + case RGB9E5: + return false; + default: + if (colorFmt.isFloatingPont()) + return caps.contains(Caps.FloatColorBuffer); + + return true; + } + } /** * Returns true if given the renderer capabilities, the framebuffer @@ -285,9 +315,7 @@ public enum Caps { && !caps.contains(Caps.FrameBufferMultisample)) return false; - RenderBuffer colorBuf = fb.getColorBuffer(); RenderBuffer depthBuf = fb.getDepthBuffer(); - if (depthBuf != null){ Format depthFmt = depthBuf.getFormat(); if (!depthFmt.isDepthFormat()){ @@ -296,28 +324,15 @@ public enum Caps { if (depthFmt == Format.Depth32F && !caps.contains(Caps.FloatDepthBuffer)) return false; + + if (depthFmt == Format.Depth24Stencil8 + && !caps.contains(Caps.PackedDepthStencilBuffer)) + return false; } } - if (colorBuf != null){ - Format colorFmt = colorBuf.getFormat(); - if (colorFmt.isDepthFormat()) - return false; - - if (colorFmt.isCompressed()) + for (int i = 0; i < fb.getNumColorBuffers(); i++){ + if (!supportsColorBuffer(caps, fb.getColorBuffer(i))){ return false; - - switch (colorFmt){ - case RGB111110F: - return caps.contains(Caps.PackedFloatColorBuffer); - case RGB16F_to_RGB111110F: - case RGB16F_to_RGB9E5: - case RGB9E5: - return false; - default: - if (colorFmt.isFloatingPont()) - return caps.contains(Caps.FloatColorBuffer); - - return true; } } return true; diff --git a/engine/src/core/com/jme3/renderer/queue/OpaqueComparator.java b/engine/src/core/com/jme3/renderer/queue/OpaqueComparator.java index 85f40934d..6d4f19646 100644 --- a/engine/src/core/com/jme3/renderer/queue/OpaqueComparator.java +++ b/engine/src/core/com/jme3/renderer/queue/OpaqueComparator.java @@ -74,9 +74,8 @@ public class OpaqueComparator implements GeometryComparator { Material m1 = o1.getMaterial(); Material m2 = o2.getMaterial(); - int sortId = m1.compareTo(m2); - - if (sortId == 0){ + int compareResult = m2.getSortId() - m1.getSortId(); + if (compareResult == 0){ // use the same shader. // sort front-to-back then. float d1 = distanceToCam(o1); @@ -89,7 +88,7 @@ public class OpaqueComparator implements GeometryComparator { else return 1; }else{ - return sortId; + return compareResult; } } diff --git a/engine/src/core/com/jme3/scene/BatchNode.java b/engine/src/core/com/jme3/scene/BatchNode.java index d47118df4..c4f498ce5 100644 --- a/engine/src/core/com/jme3/scene/BatchNode.java +++ b/engine/src/core/com/jme3/scene/BatchNode.java @@ -243,7 +243,7 @@ public class BatchNode extends Node implements Savable { if (list == null) { //trying to compare materials with the isEqual method for ( Map.Entry> mat : map.entrySet()) { - if (g.getMaterial().isEqual(mat.getKey())) { + if (g.getMaterial().equals(mat.getKey())) { list = mat.getValue(); } } diff --git a/engine/src/core/com/jme3/texture/Image.java b/engine/src/core/com/jme3/texture/Image.java index 5d23522eb..2cb3f7df7 100644 --- a/engine/src/core/com/jme3/texture/Image.java +++ b/engine/src/core/com/jme3/texture/Image.java @@ -33,6 +33,7 @@ package com.jme3.texture; import com.jme3.export.*; +import com.jme3.renderer.Caps; import com.jme3.renderer.Renderer; import com.jme3.util.NativeObject; import java.io.IOException; @@ -255,7 +256,13 @@ public class Image extends NativeObject implements Savable /*, Cloneable*/ { * Luminance/grayscale texture compression. * Called BC4 in DirectX10. */ - LTC(4, false, true, false); + LTC(4, false, true, false), + + /** + * 24-bit depth with 8-bit stencil. + * Check the cap {@link Caps#PackedDepthStencilBuffer}. + */ + Depth24Stencil8(32, true, false, false); private int bpp; private boolean isDepth; diff --git a/engine/src/core/com/jme3/texture/Texture.java b/engine/src/core/com/jme3/texture/Texture.java index 1efedec14..78ecc72eb 100644 --- a/engine/src/core/com/jme3/texture/Texture.java +++ b/engine/src/core/com/jme3/texture/Texture.java @@ -32,9 +32,9 @@ package com.jme3.texture; -import com.jme3.asset.Asset; import com.jme3.asset.AssetKey; import com.jme3.asset.AssetNotFoundException; +import com.jme3.asset.CloneableSmartAsset; import com.jme3.asset.TextureKey; import com.jme3.export.*; import com.jme3.util.PlaceholderAssets; @@ -57,7 +57,7 @@ import java.util.logging.Logger; * @author Joshua Slack * @version $Id: Texture.java 4131 2009-03-19 20:15:28Z blaine.dev $ */ -public abstract class Texture implements Asset, Savable, Cloneable { +public abstract class Texture implements CloneableSmartAsset, Savable, Cloneable { public enum Type { @@ -502,7 +502,11 @@ public abstract class Texture implements Asset, Savable, Cloneable { return false; } final Texture other = (Texture) obj; - if (this.image != other.image && (this.image == null || !this.image.equals(other.image))) { + + // NOTE: Since images are generally considered unique assets in jME3, + // using the image's equals() implementation is not neccessary here + // (would be too slow) + if (this.image != other.image) { return false; } if (this.minificationFilter != other.minificationFilter) { @@ -523,7 +527,10 @@ public abstract class Texture implements Asset, Savable, Cloneable { @Override public int hashCode() { int hash = 5; - hash = 67 * hash + (this.image != null ? this.image.hashCode() : 0); + // NOTE: Since images are generally considered unique assets in jME3, + // using the image's hashCode() implementation is not neccessary here + // (would be too slow) + hash = 67 * hash + (this.image != null ? System.identityHashCode(this.image) : 0); hash = 67 * hash + (this.minificationFilter != null ? this.minificationFilter.hashCode() : 0); hash = 67 * hash + (this.magnificationFilter != null ? this.magnificationFilter.hashCode() : 0); hash = 67 * hash + (this.shadowCompareMode != null ? this.shadowCompareMode.hashCode() : 0); @@ -531,33 +538,29 @@ public abstract class Texture implements Asset, Savable, Cloneable { return hash; } - - -// public abstract Texture createSimpleClone(); - - /** Retrieve a basic clone of this Texture (ie, clone everything but the * image data, which is shared) * * @return Texture + * + * @deprecated Use {@link Texture#clone()} instead. */ + @Deprecated public Texture createSimpleClone(Texture rVal) { rVal.setMinFilter(minificationFilter); rVal.setMagFilter(magnificationFilter); rVal.setShadowCompareMode(shadowCompareMode); -// rVal.setHasBorder(hasBorder); rVal.setAnisotropicFilter(anisotropicFilter); rVal.setImage(image); // NOT CLONED. -// rVal.memReq = memReq; rVal.setKey(key); rVal.setName(name); -// rVal.setBlendColor(blendColor != null ? blendColor.clone() : null); -// if (getTextureKey() != null) { -// rVal.setTextureKey(getTextureKey()); -// } return rVal; } + /** + * @deprecated Use {@link Texture#clone()} instead. + */ + @Deprecated public abstract Texture createSimpleClone(); public void write(JmeExporter e) throws IOException { diff --git a/engine/src/core/com/jme3/util/ListMap.java b/engine/src/core/com/jme3/util/ListMap.java index c5b6de41b..93ab5cb5e 100644 --- a/engine/src/core/com/jme3/util/ListMap.java +++ b/engine/src/core/com/jme3/util/ListMap.java @@ -33,11 +33,8 @@ package com.jme3.util; import java.io.Serializable; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; import java.util.Map.Entry; -import java.util.Set; +import java.util.*; /** * Implementation of a Map that favors iteration speed rather than @@ -45,7 +42,7 @@ import java.util.Set; * * @author Kirill Vainer */ -public final class ListMap implements Map, Cloneable, Serializable { +public final class ListMap extends AbstractMap implements Cloneable, Serializable { public static void main(String[] args){ Map map = new ListMap(); @@ -89,6 +86,29 @@ public final class ListMap implements Map, Cloneable, Serializable { return new ListMapEntry(key, value); } + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final ListMapEntry other = (ListMapEntry) obj; + if (this.key != other.key && (this.key == null || !this.key.equals(other.key))) { + return false; + } + if (this.value != other.value && (this.value == null || !this.value.equals(other.value))) { + return false; + } + return true; + } + + @Override + public int hashCode() { + return (this.key != null ? this.key.hashCode() : 0) ^ + (this.value != null ? this.value.hashCode() : 0); + } } private final HashMap backingMap; @@ -115,6 +135,7 @@ public final class ListMap implements Map, Cloneable, Serializable { putAll(map); } + @Override public int size() { // return entries.size(); return backingMap.size(); @@ -135,6 +156,7 @@ public final class ListMap implements Map, Cloneable, Serializable { return entries[index].key; } + @Override public boolean isEmpty() { return size() == 0; } @@ -147,6 +169,7 @@ public final class ListMap implements Map, Cloneable, Serializable { // return a == null ? (b == null) : a.equals(b); // } + @Override public boolean containsKey(Object key) { return backingMap.containsKey( (K) key); // if (key == null) @@ -160,6 +183,7 @@ public final class ListMap implements Map, Cloneable, Serializable { // return false; } + @Override public boolean containsValue(Object value) { return backingMap.containsValue( (V) value); // for (int i = 0; i < entries.size(); i++){ @@ -169,6 +193,7 @@ public final class ListMap implements Map, Cloneable, Serializable { // return false; } + @Override public V get(Object key) { return backingMap.get( (K) key); // if (key == null) @@ -182,6 +207,7 @@ public final class ListMap implements Map, Cloneable, Serializable { // return null; } + @Override public V put(K key, V value) { if (backingMap.containsKey(key)){ // set the value on the entry @@ -222,6 +248,7 @@ public final class ListMap implements Map, Cloneable, Serializable { // return null; } + @Override public V remove(Object key) { V element = backingMap.remove( (K) key); if (element != null){ @@ -255,6 +282,7 @@ public final class ListMap implements Map, Cloneable, Serializable { // return null; } + @Override public void putAll(Map map) { for (Entry entry : map.entrySet()){ put(entry.getKey(), entry.getValue()); @@ -275,6 +303,7 @@ public final class ListMap implements Map, Cloneable, Serializable { // } } + @Override public void clear() { backingMap.clear(); // entries.clear(); @@ -287,6 +316,7 @@ public final class ListMap implements Map, Cloneable, Serializable { return clone; } + @Override public Set keySet() { return backingMap.keySet(); // HashSet keys = new HashSet(); @@ -297,6 +327,7 @@ public final class ListMap implements Map, Cloneable, Serializable { // return keys; } + @Override public Collection values() { return backingMap.values(); // ArrayList values = new ArrayList();