Main repository of MikuMikuStudio
修訂 | 6cfd509d1a1d051619c8a3b24f12389931d630ab (tree) |
---|---|
時間 | 2013-07-07 03:55:22 |
作者 | kobayasi <kobayasi@pscn...> |
Commiter | kobayasi |
add contentEquals
@@ -250,6 +250,91 @@ public class Material implements Asset, Cloneable, Savable, Comparable<Material> | ||
250 | 250 | } |
251 | 251 | |
252 | 252 | /** |
253 | + * Compares two materials and returns true if they are equal. | |
254 | + * This methods compare definition, parameters, additional render states. | |
255 | + * Since materials are mutable objects, implementing equals() properly is not possible, | |
256 | + * hence the name contentEquals(). | |
257 | + * | |
258 | + * @param otherObj the material to compare to this material | |
259 | + * @return true if the materials are equal. | |
260 | + */ | |
261 | + public boolean contentEquals(Object otherObj) { | |
262 | + if (!(otherObj instanceof Material)) { | |
263 | + return false; | |
264 | + } | |
265 | + | |
266 | + Material other = (Material) otherObj; | |
267 | + | |
268 | + // Early exit if the material are the same object | |
269 | + if (this == other) { | |
270 | + return true; | |
271 | + } | |
272 | + | |
273 | + // Check material definition | |
274 | + if (this.getMaterialDef() != other.getMaterialDef()) { | |
275 | + return false; | |
276 | + } | |
277 | + | |
278 | + // Early exit if the size of the params is different | |
279 | + if (this.paramValues.size() != other.paramValues.size()) { | |
280 | + return false; | |
281 | + } | |
282 | + | |
283 | + // Checking technique | |
284 | + if (this.technique != null || other.technique != null) { | |
285 | + // Techniques are considered equal if their names are the same | |
286 | + // E.g. if user chose custom technique for one material but | |
287 | + // uses default technique for other material, the materials | |
288 | + // are not equal. | |
289 | + String thisDefName = this.technique != null ? this.technique.getDef().getName() : "Default"; | |
290 | + String otherDefName = other.technique != null ? other.technique.getDef().getName() : "Default"; | |
291 | + if (!thisDefName.equals(otherDefName)) { | |
292 | + return false; | |
293 | + } | |
294 | + } | |
295 | + | |
296 | + // Comparing parameters | |
297 | + for (String paramKey : paramValues.keySet()) { | |
298 | + MatParam thisParam = this.getParam(paramKey); | |
299 | + MatParam otherParam = other.getParam(paramKey); | |
300 | + | |
301 | + // This param does not exist in compared mat | |
302 | + if (otherParam == null) { | |
303 | + return false; | |
304 | + } | |
305 | + | |
306 | + if (!otherParam.equals(thisParam)) { | |
307 | + return false; | |
308 | + } | |
309 | + } | |
310 | + | |
311 | + // Comparing additional render states | |
312 | + if (additionalState == null) { | |
313 | + if (other.additionalState != null) { | |
314 | + return false; | |
315 | + } | |
316 | + } else { | |
317 | + if (!additionalState.equals(other.additionalState)) { | |
318 | + return false; | |
319 | + } | |
320 | + } | |
321 | + | |
322 | + return true; | |
323 | + } | |
324 | + | |
325 | + /** | |
326 | + * Works like {@link Object#hashCode() } except it may change together with the material as the material is mutable by definition. | |
327 | + */ | |
328 | + public int contentHashCode() { | |
329 | + int hash = 7; | |
330 | + hash = 29 * hash + (this.def != null ? this.def.hashCode() : 0); | |
331 | + hash = 29 * hash + (this.paramValues != null ? this.paramValues.hashCode() : 0); | |
332 | + hash = 29 * hash + (this.technique != null ? this.technique.getDef().getName().hashCode() : 0); | |
333 | + hash = 29 * hash + (this.additionalState != null ? this.additionalState.contentHashCode() : 0); | |
334 | + return hash; | |
335 | + } | |
336 | + | |
337 | + /** | |
253 | 338 | * Returns the currently active technique. |
254 | 339 | * <p> |
255 | 340 | * The technique is selected automatically by the {@link RenderManager} |