to see if they've changed in the current frame. SimpleApplication will configure this by default to use asserts but the application is free to change it to throw regular exceptions or just log the error as desired.fix-openal-soft-deadlink
parent
37bb494709
commit
45b1908906
@ -0,0 +1,209 @@ |
||||
/* |
||||
* Copyright (c) 2014 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 com.jme3.app.state; |
||||
|
||||
import java.util.Arrays; |
||||
import java.util.logging.Level; |
||||
import java.util.logging.Logger; |
||||
|
||||
import com.jme3.app.Application; |
||||
import com.jme3.math.*; |
||||
import com.jme3.util.SafeArrayList; |
||||
|
||||
import static java.lang.Float.NaN; |
||||
import static java.lang.Float.POSITIVE_INFINITY; |
||||
import static java.lang.Float.NEGATIVE_INFINITY; |
||||
|
||||
/** |
||||
* Checks the various JME 'constants' for drift using either asserts |
||||
* or straight checks. The list of constants can also be configured |
||||
* but defaults to the standard JME Vector3f, Quaternion, etc. constants. |
||||
* |
||||
* @author Paul Speed |
||||
*/ |
||||
public class ConstantVerifierState extends BaseAppState { |
||||
|
||||
static final Logger log = Logger.getLogger(BaseAppState.class.getName()); |
||||
|
||||
// Note: I've used actual constructed objects for the good values
|
||||
// instead of clone just to better catch cases where the values
|
||||
// might have been corrupted even before the app state was touched. -pspeed
|
||||
public static final Checker[] DEFAULT_CHECKS = new Checker[] { |
||||
new Checker(Vector3f.ZERO, new Vector3f(0, 0, 0)), |
||||
new Checker(Vector3f.NAN, new Vector3f(NaN, NaN, NaN)), |
||||
new Checker(Vector3f.UNIT_X, new Vector3f(1, 0, 0)), |
||||
new Checker(Vector3f.UNIT_Y, new Vector3f(0, 1, 0)), |
||||
new Checker(Vector3f.UNIT_Z, new Vector3f(0, 0, 1)), |
||||
new Checker(Vector3f.UNIT_XYZ, new Vector3f(1, 1, 1)), |
||||
new Checker(Vector3f.POSITIVE_INFINITY, new Vector3f(POSITIVE_INFINITY, POSITIVE_INFINITY, POSITIVE_INFINITY)), |
||||
new Checker(Vector3f.NEGATIVE_INFINITY, new Vector3f(NEGATIVE_INFINITY, NEGATIVE_INFINITY, NEGATIVE_INFINITY)), |
||||
new Checker(Quaternion.IDENTITY, new Quaternion()), |
||||
new Checker(Quaternion.DIRECTION_Z, new Quaternion().fromAxes(Vector3f.UNIT_X, Vector3f.UNIT_Y, Vector3f.UNIT_Z)), |
||||
new Checker(Quaternion.ZERO, new Quaternion(0, 0, 0, 0)), |
||||
new Checker(Vector2f.ZERO, new Vector2f(0f, 0f)), |
||||
new Checker(Vector2f.UNIT_XY, new Vector2f(1f, 1f)), |
||||
new Checker(Vector4f.ZERO, new Vector4f(0, 0, 0, 0)), |
||||
new Checker(Vector4f.NAN, new Vector4f(NaN, NaN, NaN, NaN)), |
||||
new Checker(Vector4f.UNIT_X, new Vector4f(1, 0, 0, 0)), |
||||
new Checker(Vector4f.UNIT_Y, new Vector4f(0, 1, 0, 0)), |
||||
new Checker(Vector4f.UNIT_Z, new Vector4f(0, 0, 1, 0)), |
||||
new Checker(Vector4f.UNIT_W, new Vector4f(0, 0, 0, 1)), |
||||
new Checker(Vector4f.UNIT_XYZW, new Vector4f(1, 1, 1, 1)), |
||||
new Checker(Vector4f.POSITIVE_INFINITY, new Vector4f(POSITIVE_INFINITY, POSITIVE_INFINITY, POSITIVE_INFINITY, POSITIVE_INFINITY)), |
||||
new Checker(Vector4f.NEGATIVE_INFINITY, new Vector4f(NEGATIVE_INFINITY, NEGATIVE_INFINITY, NEGATIVE_INFINITY, NEGATIVE_INFINITY)), |
||||
new Checker(Matrix3f.ZERO, new Matrix3f(0, 0, 0, 0, 0, 0, 0, 0, 0)), |
||||
new Checker(Matrix3f.IDENTITY, new Matrix3f()), |
||||
new Checker(Matrix4f.ZERO, new Matrix4f(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)), |
||||
new Checker(Matrix4f.IDENTITY, new Matrix4f()) |
||||
}; |
||||
|
||||
public enum ErrorType { Assert, Exception, Log }; |
||||
|
||||
private SafeArrayList<Checker> checkers = new SafeArrayList<>(Checker.class); |
||||
private ErrorType errorType; |
||||
|
||||
/** |
||||
* Creates a verifier app state that will check all of the default |
||||
* constant checks using asserts. |
||||
*/ |
||||
public ConstantVerifierState() { |
||||
this(ErrorType.Assert); |
||||
} |
||||
|
||||
/** |
||||
* Creates a verifier app state that will check all of the default |
||||
* constant checks using the specified error reporting mechanism. |
||||
*/ |
||||
public ConstantVerifierState( ErrorType errorType ) { |
||||
this(errorType, DEFAULT_CHECKS); |
||||
} |
||||
|
||||
/** |
||||
* Creates a verifier app state that will check all of the specified |
||||
* checks and report errors using the specified error type. |
||||
*/ |
||||
public ConstantVerifierState( ErrorType errorType, Checker... checkers ) { |
||||
this.errorType = errorType; |
||||
this.checkers.addAll(Arrays.asList(checkers)); |
||||
} |
||||
|
||||
public void addChecker( Object constant, Object goodValue ) { |
||||
checkers.add(new Checker(constant, goodValue)); |
||||
} |
||||
|
||||
public void setErrorType( ErrorType errorType ) { |
||||
this.errorType = errorType; |
||||
} |
||||
|
||||
public ErrorType getErrorType() { |
||||
return errorType; |
||||
} |
||||
|
||||
protected SafeArrayList<Checker> getCheckers() { |
||||
return checkers; |
||||
} |
||||
|
||||
@Override |
||||
protected void initialize( Application app ) { |
||||
} |
||||
|
||||
@Override |
||||
protected void cleanup( Application app ) { |
||||
} |
||||
|
||||
@Override |
||||
protected void onEnable() { |
||||
} |
||||
|
||||
@Override |
||||
protected void onDisable() { |
||||
} |
||||
|
||||
@Override |
||||
public void postRender() { |
||||
// Check as late in the frame as possible. Subclasses can check earlier
|
||||
// if they like.
|
||||
checkValues(); |
||||
} |
||||
|
||||
protected void checkValues() { |
||||
for( Checker checker : checkers.getArray() ) { |
||||
switch( errorType ) { |
||||
default: |
||||
case Assert: |
||||
assert checker.isValid() : checker.toString(); |
||||
break; |
||||
case Exception: |
||||
if( !checker.isValid() ) { |
||||
throw new RuntimeException("Constant has changed, " + checker.toString()); |
||||
} |
||||
break; |
||||
case Log: |
||||
if( !checker.isValid() ) { |
||||
log.severe("Constant has changed, " + checker.toString()); |
||||
} |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Checks the specified 'constant' value against it's known good |
||||
* value. These should obviously be different instances for this to |
||||
* mean anything. |
||||
*/ |
||||
private static class Checker { |
||||
private Object constant; |
||||
private Object goodValue; |
||||
|
||||
public Checker( Object constant, Object goodValue ) { |
||||
if( constant == null ) { |
||||
throw new IllegalArgumentException("Constant cannot be null"); |
||||
} |
||||
if( !constant.equals(goodValue) ) { |
||||
throw new IllegalArgumentException("Constant value:" + constant + " does not match value:" + goodValue); |
||||
} |
||||
this.constant = constant; |
||||
this.goodValue = goodValue; |
||||
} |
||||
|
||||
public boolean isValid() { |
||||
return constant.equals(goodValue); |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "Constant:" + constant + ", correct value:" + goodValue + ", type:" + goodValue.getClass(); |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue