diff --git a/jme3-core/src/main/java/com/jme3/light/DirectionalLight.java b/jme3-core/src/main/java/com/jme3/light/DirectionalLight.java index 53528cf9d0..80d1b5fdcd 100644 --- a/jme3-core/src/main/java/com/jme3/light/DirectionalLight.java +++ b/jme3-core/src/main/java/com/jme3/light/DirectionalLight.java @@ -110,6 +110,7 @@ public final void setDirection(Vector3f dir){ if (!direction.isUnitVector()) { direction.normalizeLocal(); } + updateStates(null); } @Override diff --git a/jme3-core/src/main/java/com/jme3/light/Light.java b/jme3-core/src/main/java/com/jme3/light/Light.java index 4cbea59208..e78cc9667c 100644 --- a/jme3-core/src/main/java/com/jme3/light/Light.java +++ b/jme3-core/src/main/java/com/jme3/light/Light.java @@ -37,6 +37,7 @@ import com.jme3.math.ColorRGBA; import com.jme3.renderer.Camera; import com.jme3.scene.Spatial; +import com.jme3.util.StatefulObject; import com.jme3.util.TempVars; import java.io.IOException; @@ -45,7 +46,7 @@ *
* All light source types have a color.
*/
-public abstract class Light implements Savable, Cloneable {
+public abstract class Light extends StatefulObject implements Savable, Cloneable {
/**
* Describes the light type.
@@ -171,6 +172,7 @@ public float getLastDistance(){
*/
public void setColor(ColorRGBA color){
this.color.set(color);
+ updateStates(null);
}
@@ -189,6 +191,7 @@ public boolean isEnabled() {
*/
public void setEnabled(boolean enabled) {
this.enabled = enabled;
+ updateStates(null);
}
public boolean isFrustumCheckNeeded() {
diff --git a/jme3-core/src/main/java/com/jme3/light/PointLight.java b/jme3-core/src/main/java/com/jme3/light/PointLight.java
index 4d9f306a06..5fb6badb8e 100644
--- a/jme3-core/src/main/java/com/jme3/light/PointLight.java
+++ b/jme3-core/src/main/java/com/jme3/light/PointLight.java
@@ -136,6 +136,7 @@ public Vector3f getPosition() {
*/
public final void setPosition(Vector3f position) {
this.position.set(position);
+ updateStates(null);
}
/**
@@ -171,6 +172,7 @@ public final void setRadius(float radius) {
} else {
this.invRadius = 0;
}
+ updateStates(null);
}
/**
diff --git a/jme3-core/src/main/java/com/jme3/light/SpotLight.java b/jme3-core/src/main/java/com/jme3/light/SpotLight.java
index 417e845f0b..1ec884e090 100644
--- a/jme3-core/src/main/java/com/jme3/light/SpotLight.java
+++ b/jme3-core/src/main/java/com/jme3/light/SpotLight.java
@@ -317,6 +317,7 @@ public Vector3f getDirection() {
public final void setDirection(Vector3f direction) {
this.direction.set(direction);
+ updateStates(null);
}
public Vector3f getPosition() {
@@ -325,6 +326,7 @@ public Vector3f getPosition() {
public final void setPosition(Vector3f position) {
this.position.set(position);
+ updateStates(null);
}
public float getSpotRange() {
@@ -354,6 +356,7 @@ public void setSpotRange(float spotRange) {
} else {
this.invSpotRange = 0;
}
+ updateStates(null);
}
/**
@@ -387,6 +390,7 @@ public void setSpotInnerAngle(float spotInnerAngle) {
}
this.spotInnerAngle = spotInnerAngle;
computeAngleParameters();
+ updateStates(null);
}
/**
@@ -413,6 +417,7 @@ public void setSpotOuterAngle(float spotOuterAngle) {
}
this.spotOuterAngle = spotOuterAngle;
computeAngleParameters();
+ updateStates(null);
}
/**
diff --git a/jme3-core/src/main/java/com/jme3/renderer/Camera.java b/jme3-core/src/main/java/com/jme3/renderer/Camera.java
index eb7cca3ae4..f47b21aa35 100644
--- a/jme3-core/src/main/java/com/jme3/renderer/Camera.java
+++ b/jme3-core/src/main/java/com/jme3/renderer/Camera.java
@@ -45,6 +45,9 @@
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.math.Vector4f;
+import com.jme3.export.*;
+import com.jme3.math.*;
+import com.jme3.util.StatefulObject;
import com.jme3.util.TempVars;
import java.io.IOException;
import java.util.logging.Level;
@@ -70,7 +73,7 @@
* @author Mark Powell
* @author Joshua Slack
*/
-public class Camera implements Savable, Cloneable {
+public class Camera extends StatefulObject implements Savable, Cloneable {
private static final Logger logger = Logger.getLogger(Camera.class.getName());
@@ -1247,6 +1250,7 @@ public void updateViewProjection() {
//viewProjectionMatrix.set(viewMatrix).multLocal(projectionMatrix);
viewProjectionMatrix.set(projectionMatrix).multLocal(viewMatrix);
}
+ updateStates(null);
}
/**
diff --git a/jme3-core/src/main/java/com/jme3/scene/Node.java b/jme3-core/src/main/java/com/jme3/scene/Node.java
index 0424cea053..23f50d70e6 100644
--- a/jme3-core/src/main/java/com/jme3/scene/Node.java
+++ b/jme3-core/src/main/java/com/jme3/scene/Node.java
@@ -58,6 +58,9 @@
* @author Joshua Slack
*/
public class Node extends Spatial {
+ public enum StateUpdateHints {
+ INVALIDATE_UPDATE_LIST
+ }
private static final Logger logger = Logger.getLogger(Node.class.getName());
/**
* This node's children.
@@ -201,6 +204,7 @@ private void addUpdateChildren(SafeArrayListTimer
is the base class for a high resolution timer. It is
* created from getTimer("display system")
@@ -38,7 +40,7 @@
* @author Mark Powell
* @version $Id: Timer.java,v 1.18 2007/03/09 10:19:34 rherlitz Exp $
*/
-public abstract class Timer {
+public abstract class Timer extends StatefulObject{
/**
* Returns the current time in ticks. A tick is an arbitrary measure of time
diff --git a/jme3-core/src/main/java/com/jme3/util/NativeObject.java b/jme3-core/src/main/java/com/jme3/util/NativeObject.java
index c7ff725294..cdf044889a 100644
--- a/jme3-core/src/main/java/com/jme3/util/NativeObject.java
+++ b/jme3-core/src/main/java/com/jme3/util/NativeObject.java
@@ -42,7 +42,7 @@
* collected by the garbage collector, and then invoke the proper destructor
* on the OpenGL library to delete it from memory.
*/
-public abstract class NativeObject implements Cloneable {
+public abstract class NativeObject extends StatefulObject implements Cloneable {
public static final int INVALID_ID = -1;
@@ -130,6 +130,7 @@ public int getId(){
* and its state needs to be updated.
*/
public void setUpdateNeeded(){
+ updateStates(null);
updateNeeded = true;
}
diff --git a/jme3-core/src/main/java/com/jme3/util/StatefulObject.java b/jme3-core/src/main/java/com/jme3/util/StatefulObject.java
new file mode 100644
index 0000000000..54f4683c73
--- /dev/null
+++ b/jme3-core/src/main/java/com/jme3/util/StatefulObject.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2009-2021 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.util;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.WeakHashMap;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicLong;
+
+import com.jme3.util.functional.NoArgFunction;
+import com.jme3.util.functional.VoidFunction;
+
+
+/**
+ * StatefulObject is an object that stores one or more states
+ *
+ * @author Riccardo Balbo
+ */
+public class StatefulObject implements Cloneable{
+ private static AtomicLong globalId = new AtomicLong(Long.MIN_VALUE);
+
+ private static long getNewSnapshotID(){
+ return globalId.getAndUpdate(n->{
+ long nn=n+1;
+ if(nn==-1||n==0)nn=1;
+ return nn;
+ });
+ }
+
+ /**
+ * A state that can be updated.
+ */
+ public static abstract class State {
+ private volatile long snapshotID = 0;
+
+ /**
+ * Get unique ID of the snapshot of the current state.
+ * The ID changes after every update.
+ * @return
+ */
+ public long getSnapshotID() {
+ return snapshotID;
+ }
+
+ /**
+ * Called when the state needs to be updated
+ * @param hint Hint on what need to be updated (may be ignored)
+ */
+ public abstract void updateState(S forObject, Object hint);
+
+ private void _updateState(StatefulObject forObject, Object hint) {
+ this.updateState((S)forObject, hint);
+ }
+
+ /**
+ * Called after the update is completed.
+ * Updates the snapshot ID so that objects monitoring it can know that
+ * the state has new data.
+ */
+ public void commitUpdate() {
+ snapshotID = getNewSnapshotID(); // update the snapshot id
+ }
+
+ public abstract State cloneStateFor(S obj);
+
+ private State _cloneStateFor(StatefulObject obj) {
+ return cloneStateFor((S) obj);
+ }
+
+ /**
+ * Called after the state is attached for the first time
+ */
+ public abstract void attachedTo(S obj);
+
+ private void _attachedTo(StatefulObject obj) {
+ attachedTo((S) obj);
+ }
+ }
+
+
+
+ private transient Map