11/*
2- * Copyright (c) 2014-2021 jMonkeyEngine
2+ * Copyright (c) 2014-2025 jMonkeyEngine
33 * All rights reserved.
44 *
55 * Redistribution and use in source and binary forms, with or without
2929 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3030 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3131 */
32-
3332package com .jme3 .app .state ;
3433
35- import java .util .Arrays ;
36- import java .util .logging .Logger ;
37-
3834import com .jme3 .app .Application ;
39- import com .jme3 .math .*;
35+ import com .jme3 .math .Matrix3f ;
36+ import com .jme3 .math .Matrix4f ;
37+ import com .jme3 .math .Quaternion ;
38+ import com .jme3 .math .Vector2f ;
39+ import com .jme3 .math .Vector3f ;
40+ import com .jme3 .math .Vector4f ;
4041import com .jme3 .util .SafeArrayList ;
4142
43+ import java .util .Arrays ;
44+ import java .util .logging .Logger ;
45+
46+ import static java .lang .Float .NEGATIVE_INFINITY ;
4247import static java .lang .Float .NaN ;
4348import static java .lang .Float .POSITIVE_INFINITY ;
44- import static java .lang .Float .NEGATIVE_INFINITY ;
4549
4650/**
47- * Checks the various JME 'constants' for drift using either asserts
48- * or straight checks. The list of constants can also be configured
49- * but defaults to the standard JME Vector3f, Quaternion, etc. constants.
51+ * An AppState that periodically checks the values of various JME math constants
52+ * (e.g., `Vector3f.ZERO`, `Quaternion.IDENTITY`) against their known good values.
53+ * This is useful for detecting accidental modifications or "drift" of these
54+ * supposedly immutable constants during application runtime.
55+ * <p>
56+ * The state can be configured to report discrepancies using asserts,
57+ * throwing runtime exceptions, or logging severe messages.
58+ * The set of constants to check is configurable.
5059 *
51- * @author Paul Speed
60+ * @author Paul Speed
5261 */
5362public class ConstantVerifierState extends BaseAppState {
5463
55- private static final Logger log = Logger .getLogger (BaseAppState .class .getName ());
64+ private static final Logger log = Logger .getLogger (ConstantVerifierState .class .getName ());
5665
5766 // Note: I've used actual constructed objects for the good values
5867 // instead of clone just to better catch cases where the values
@@ -73,7 +82,14 @@ public class ConstantVerifierState extends BaseAppState {
7382 new Quaternion ().fromAxes (Vector3f .UNIT_X , Vector3f .UNIT_Y , Vector3f .UNIT_Z )),
7483 new Checker (Quaternion .ZERO , new Quaternion (0 , 0 , 0 , 0 )),
7584 new Checker (Vector2f .ZERO , new Vector2f (0f , 0f )),
85+ new Checker (Vector2f .NAN , new Vector2f (NaN , NaN )),
86+ new Checker (Vector2f .UNIT_X , new Vector2f (1 , 0 )),
87+ new Checker (Vector2f .UNIT_Y , new Vector2f (0 , 1 )),
7688 new Checker (Vector2f .UNIT_XY , new Vector2f (1f , 1f )),
89+ new Checker (Vector2f .POSITIVE_INFINITY ,
90+ new Vector2f (POSITIVE_INFINITY , POSITIVE_INFINITY )),
91+ new Checker (Vector2f .NEGATIVE_INFINITY ,
92+ new Vector2f (NEGATIVE_INFINITY , NEGATIVE_INFINITY )),
7793 new Checker (Vector4f .ZERO , new Vector4f (0 , 0 , 0 , 0 )),
7894 new Checker (Vector4f .NAN , new Vector4f (NaN , NaN , NaN , NaN )),
7995 new Checker (Vector4f .UNIT_X , new Vector4f (1 , 0 , 0 , 0 )),
@@ -91,24 +107,34 @@ public class ConstantVerifierState extends BaseAppState {
91107 new Checker (Matrix4f .IDENTITY , new Matrix4f ())
92108 };
93109
94- public enum ErrorType { Assert , Exception , Log };
110+ /**
111+ * Defines how constant value discrepancies should be reported.
112+ */
113+ public enum ErrorType {
114+ /** Causes an `assert` failure if the constant has changed. Requires assertions to be enabled. */
115+ Assert ,
116+ /** Throws a `RuntimeException` if the constant has changed. */
117+ Exception ,
118+ /** Logs a severe message if the constant has changed. */
119+ Log
120+ }
95121
96- final private SafeArrayList <Checker > checkers = new SafeArrayList <>(Checker .class );
122+ private final SafeArrayList <Checker > checkers = new SafeArrayList <>(Checker .class );
97123 private ErrorType errorType ;
98124
99125 /**
100- * Creates a verifier app state that will check all of the default
101- * constant checks using asserts .
126+ * Creates a verifier app state that will check all of the default
127+ * JME math constants using `ErrorType.Assert` .
102128 */
103129 public ConstantVerifierState () {
104130 this (ErrorType .Assert );
105131 }
106132
107133 /**
108- * Creates a verifier app state that will check all of the default
109- * constant checks using the specified error reporting mechanism.
134+ * Creates a verifier app state that will check all of the default
135+ * JME math constants using the specified error reporting mechanism.
110136 *
111- * @param errorType the mechanism to use
137+ * @param errorType The mechanism to use when a constant's value drifts.
112138 */
113139 public ConstantVerifierState (ErrorType errorType ) {
114140 this (errorType , DEFAULT_CHECKS );
@@ -126,14 +152,32 @@ private ConstantVerifierState(ErrorType errorType, Checker... checkers) {
126152 this .checkers .addAll (Arrays .asList (checkers ));
127153 }
128154
155+ /**
156+ * Adds a new constant and its expected good value to the list of items to be checked.
157+ * The `constant` and `goodValue` should be instances of the same class.
158+ *
159+ * @param constant The JME constant object to monitor for drift (e.g., `Vector3f.ZERO`).
160+ * @param goodValue An independent instance representing the expected correct value of the constant.
161+ * This instance should match the initial value of `constant`.
162+ */
129163 public void addChecker (Object constant , Object goodValue ) {
130164 checkers .add (new Checker (constant , goodValue ));
131165 }
132166
167+ /**
168+ * Sets the error reporting mechanism to be used when a constant's value drifts.
169+ *
170+ * @param errorType The desired error reporting type.
171+ */
133172 public void setErrorType (ErrorType errorType ) {
134173 this .errorType = errorType ;
135174 }
136175
176+ /**
177+ * Returns the currently configured error reporting mechanism.
178+ *
179+ * @return The current `ErrorType`.
180+ */
137181 public ErrorType getErrorType () {
138182 return errorType ;
139183 }
@@ -161,21 +205,26 @@ public void postRender() {
161205 checkValues ();
162206 }
163207
208+ /**
209+ * Iterates through all registered checkers and verifies the current values
210+ * of the constants against their known good values.
211+ * Reports any discrepancies based on the configured `ErrorType`.
212+ */
164213 protected void checkValues () {
165214 for (Checker checker : checkers .getArray ()) {
166215 switch (errorType ) {
167- default :
216+ default : // Fall through to Assert if somehow null
168217 case Assert :
169218 assert checker .isValid () : checker .toString ();
170219 break ;
171220 case Exception :
172221 if (!checker .isValid ()) {
173- throw new RuntimeException ("Constant has changed, " + checker .toString ());
222+ throw new RuntimeException ("JME Constant has changed, " + checker .toString ());
174223 }
175224 break ;
176225 case Log :
177226 if (!checker .isValid ()) {
178- log .severe ("Constant has changed, " + checker .toString ());
227+ log .severe ("JME Constant has changed, " + checker .toString ());
179228 }
180229 break ;
181230 }
@@ -188,16 +237,17 @@ protected void checkValues() {
188237 * mean anything.
189238 */
190239 private static class Checker {
191- private Object constant ;
192- private Object goodValue ;
240+
241+ private final Object constant ;
242+ private final Object goodValue ;
193243
194244 public Checker (Object constant , Object goodValue ) {
195245 if (constant == null ) {
196246 throw new IllegalArgumentException ("Constant cannot be null" );
197247 }
198248 if (!constant .equals (goodValue )) {
199249 throw new IllegalArgumentException (
200- "Constant value:" + constant + " does not match value:" + goodValue );
250+ "Constant value: " + constant + " does not match value: " + goodValue );
201251 }
202252 this .constant = constant ;
203253 this .goodValue = goodValue ;
0 commit comments