diff --git a/engine/src/core/com/jme3/shader/DefineList.java b/engine/src/core/com/jme3/shader/DefineList.java index a64214b79..498bcda66 100644 --- a/engine/src/core/com/jme3/shader/DefineList.java +++ b/engine/src/core/com/jme3/shader/DefineList.java @@ -35,13 +35,15 @@ package com.jme3.shader; import com.jme3.export.*; import java.io.IOException; import java.util.Map; -import java.util.SortedMap; import java.util.TreeMap; -public class DefineList implements Savable { +public class DefineList implements Savable, Cloneable { - private final SortedMap defines = new TreeMap(); + private static final String ONE = "1"; + + private TreeMap defines = new TreeMap(); private String compiled = null; + private int cachedHashCode = 0; public void write(JmeExporter ex) throws IOException{ OutputCapsule oc = ex.getCapsule(this); @@ -73,46 +75,66 @@ public class DefineList implements Savable { public void clear() { defines.clear(); compiled = ""; + cachedHashCode = 0; } public String get(String key){ return defines.get(key); } + + @Override + public DefineList clone() { + try { + DefineList clone = (DefineList) super.clone(); + clone.cachedHashCode = 0; + clone.compiled = null; + clone.defines = (TreeMap) defines.clone(); + return clone; + } catch (CloneNotSupportedException ex) { + throw new AssertionError(); + } + } public boolean set(String key, VarType type, Object val){ if (val == null){ defines.remove(key); compiled = null; + cachedHashCode = 0; return true; } switch (type){ case Boolean: - if ( ((Boolean) val).booleanValue() ) { - // same literal, != should work - if (defines.put(key, "1") != "1") { + if (((Boolean) val).booleanValue()) { + // same literal, != will work + if (defines.put(key, ONE) != ONE) { compiled = null; + cachedHashCode = 0; return true; } } else if (defines.containsKey(key)) { defines.remove(key); compiled = null; + cachedHashCode = 0; return true; } break; case Float: case Int: - String original = defines.put(key, val.toString()); + String newValue = val.toString(); + String original = defines.put(key, newValue); if (!val.equals(original)) { compiled = null; + cachedHashCode = 0; return true; } break; default: - // same literal, != should work - if (defines.put(key, "1") != "1") { + // same literal, != will work + if (defines.put(key, ONE) != ONE) { compiled = null; + cachedHashCode = 0; return true; } break; @@ -124,17 +146,18 @@ public class DefineList implements Savable { public boolean remove(String key){ if (defines.remove(key) != null) { compiled = null; + cachedHashCode = 0; return true; } - return false; } public void addFrom(DefineList other){ - if (other == null) + if (other == null) { return; - + } compiled = null; + cachedHashCode = 0; defines.putAll(other.defines); } @@ -150,15 +173,29 @@ public class DefineList implements Savable { return compiled; } + @Override + public boolean equals(Object obj) { + final DefineList other = (DefineList) obj; + return defines.equals(other.defines); + } + + @Override + public int hashCode() { + if (cachedHashCode == 0) { + cachedHashCode = defines.hashCode(); + } + return cachedHashCode; + } + @Override public String toString(){ StringBuilder sb = new StringBuilder(); int i = 0; for (Map.Entry entry : defines.entrySet()) { - sb.append(entry.getKey()); - if (i != defines.size() - 1) + sb.append(entry.getKey()).append("=").append(entry.getValue()); + if (i != defines.size() - 1) { sb.append(", "); - + } i++; } return sb.toString(); diff --git a/engine/src/core/com/jme3/shader/ShaderKey.java b/engine/src/core/com/jme3/shader/ShaderKey.java index c2057712b..ee6560f79 100644 --- a/engine/src/core/com/jme3/shader/ShaderKey.java +++ b/engine/src/core/com/jme3/shader/ShaderKey.java @@ -45,6 +45,7 @@ public class ShaderKey extends AssetKey { protected DefineList defines; protected String vertLanguage; protected String fragLanguage; + protected int cachedHashedCode = 0; public ShaderKey(){ } @@ -57,6 +58,14 @@ public class ShaderKey extends AssetKey { this.fragLanguage = fragLanguage; } + @Override + public ShaderKey clone() { + ShaderKey clone = (ShaderKey) super.clone(); + clone.cachedHashedCode = 0; + clone.defines = defines.clone(); + return clone; + } + @Override public String toString(){ return "V="+name + " F=" + fragName + (defines != null ? defines : ""); @@ -64,32 +73,29 @@ public class ShaderKey extends AssetKey { @Override public boolean equals(Object obj) { - if (obj == null){ - return false; - } - if (getClass() != obj.getClass()){ - return false; - } - final ShaderKey other = (ShaderKey) obj; if (name.equals(other.name) && fragName.equals(other.fragName)){ - if (defines != null && other.defines != null) - return defines.getCompiled().equals(other.defines.getCompiled()); - else if (defines != null || other.defines != null) + if (defines != null && other.defines != null) { + return defines.equals(other.defines); + } else if (defines != null || other.defines != null) { return false; - else + } else { return true; + } } return false; } @Override public int hashCode() { - int hash = 7; - hash = 41 * hash + name.hashCode(); - hash = 41 * hash + fragName.hashCode(); - hash = 41 * hash + (defines != null ? defines.getCompiled().hashCode() : 0); - return hash; + if (cachedHashedCode == 0) { + int hash = 7; + hash = 41 * hash + name.hashCode(); + hash = 41 * hash + fragName.hashCode(); + hash = 41 * hash + (defines != null ? defines.hashCode() : 0); + cachedHashedCode = hash; + } + return cachedHashedCode; } public DefineList getDefines() { @@ -126,6 +132,7 @@ public class ShaderKey extends AssetKey { OutputCapsule oc = ex.getCapsule(this); oc.write(fragName, "fragment_name", null); oc.write(vertLanguage, "language", null); + oc.write(fragLanguage, "frag_language", null); } @Override @@ -134,6 +141,7 @@ public class ShaderKey extends AssetKey { InputCapsule ic = im.getCapsule(this); fragName = ic.readString("fragment_name", null); vertLanguage = ic.readString("language", null); + fragLanguage = ic.readString("frag_language", null); } }