-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
VectorEffects #2577
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
VectorEffects #2577
Changes from all commits
a4dfa6c
ba6672b
9bc33ac
4121447
5adc84a
5540726
c42dfdc
f7c5fd0
dcf0f0d
40dd430
ab4c1f8
7e93369
34f536f
fba64fe
463d968
b0a095f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,105 @@ | ||
| /* | ||
| * Copyright (c) 2009-2026 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.vectoreffect; | ||
|
|
||
| import com.jme3.app.state.AppStateManager; | ||
| import java.util.ArrayList; | ||
|
|
||
| /** | ||
| * @author yaRnMcDonuts | ||
| */ | ||
|
|
||
| public abstract class AbstractVectorEffect implements VectorEffect { | ||
|
|
||
| protected VectorGroup vectorsToModify; | ||
| private final ArrayList<Runnable> onFinishedCallbacks = new ArrayList<>(); | ||
| protected boolean isFinished = false; | ||
|
|
||
| public AbstractVectorEffect(){ | ||
|
|
||
| } | ||
|
|
||
| public AbstractVectorEffect(VectorGroup vectorsToModify) { | ||
| this.vectorsToModify = vectorsToModify; | ||
| } | ||
|
|
||
| @Override | ||
| public void setIsFinished(boolean isFinished) { | ||
| this.isFinished = isFinished; | ||
| if (isFinished) { | ||
| for(Runnable r : onFinishedCallbacks) { | ||
| r.run(); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| public VectorGroup getVectorsToModify(){ | ||
| return vectorsToModify; | ||
| } | ||
|
|
||
| @Override | ||
| public boolean isFinished() { | ||
| return isFinished; | ||
| } | ||
|
|
||
|
|
||
| @Override | ||
| public void reset() { | ||
| isFinished = false; | ||
| } | ||
|
|
||
|
|
||
| public void runOnFinish(Runnable runnable) { | ||
| onFinishedCallbacks.add(runnable); | ||
| } | ||
|
|
||
| @Override | ||
| public void update(float tpf){ | ||
|
|
||
| } | ||
|
|
||
| // convenience registration method so users can avoid repeatedly writing this AppState fetching code | ||
| public void convenienceRegister(AppStateManager stateManager) { | ||
| if(stateManager != null){ | ||
| VectorEffectManagerState vectorEffectManagerState = stateManager.getState(VectorEffectManagerState.class); | ||
| if(vectorEffectManagerState != null){ | ||
| vectorEffectManagerState.registerVectorEffect(this); | ||
| } | ||
| } | ||
| } | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I do use this method in my own project, but I avoided it in the examples so that they can show the full way to fetch an appState for users who may be using the examples to learn from, and since I also want the examples to show that the effects rely on a manager state. But this convenience method does reduce appstate-fetching boiler plate code in a project that registers lots of vector effects (and prevents having to keep a reference to the VectorEffectManagerState or repeatedly fetch it in classes that make multiple registries) so I'm opting to keep it.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok then, lets call this registerTo and maybe make it append the VectorEffectManagerState if its not present in the stateManager |
||
|
|
||
|
|
||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,144 @@ | ||
| /* | ||
| * Copyright (c) 2009-2026 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.vectoreffect; | ||
|
|
||
| import com.jme3.math.EaseFunction; | ||
| import com.jme3.math.Easing; | ||
| import com.jme3.math.Vector4f; | ||
|
|
||
| /** | ||
| * | ||
| * @author yaRnMcDonuts | ||
| */ | ||
| public final class EaseVectorEffect extends AbstractVectorEffect{ | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
|
||
| private VectorGroup targetVectors; | ||
| private VectorGroup startVectors; | ||
|
|
||
| private float duration = 0f; | ||
| private float easeTimer = 0f; | ||
| private float delay = 0f; | ||
| private float delayTimer = 0f; | ||
|
|
||
| private EaseFunction easeFunction = Easing.linear; | ||
|
|
||
| private final Vector4f tempTargetVec = new Vector4f(); | ||
| private final Vector4f tempStartVec = new Vector4f(); | ||
|
|
||
| public EaseVectorEffect(VectorGroup vectorToModify) { | ||
| super(vectorToModify); | ||
| } | ||
|
|
||
| public EaseVectorEffect(VectorGroup vectorToModify, VectorGroup targetVector, float duration) { | ||
| this(vectorToModify); | ||
| setEaseToValueOverDuration(duration, targetVector); | ||
| } | ||
|
|
||
| public EaseVectorEffect(VectorGroup vectorToModify, VectorGroup targetVector, float duration, | ||
| float delay) { | ||
| this(vectorToModify); | ||
| setEaseToValueOverDuration(duration, targetVector); | ||
| setDelayTime(delay); | ||
| } | ||
|
|
||
| public EaseVectorEffect(VectorGroup vectorToModify, VectorGroup targetVector, float duration, | ||
| EaseFunction easeFunction) { | ||
| this(vectorToModify, targetVector, duration); | ||
| setEaseFunction(easeFunction); | ||
| } | ||
|
|
||
| public EaseVectorEffect(VectorGroup vectorToModify, VectorGroup targetVector, float duration, | ||
| EaseFunction easeFunction, float delay) { | ||
| this(vectorToModify, targetVector, duration); | ||
| setEaseFunction(easeFunction); | ||
| setDelayTime(delay); | ||
| } | ||
|
|
||
|
|
||
| @Override | ||
| public void update(float tpf) { | ||
| super.update(tpf); | ||
|
|
||
| if (delayTimer <= delay) { | ||
| delayTimer += tpf; | ||
| return; | ||
| } | ||
|
|
||
| if (startVectors == null) { | ||
| startVectors = vectorsToModify.clone(); | ||
| } | ||
|
|
||
| easeTimer += tpf; | ||
| float t = Math.min(easeTimer / duration, 1f); | ||
|
|
||
| float easedT = easeFunction.apply(t); | ||
|
|
||
| for(int v = 0; v < vectorsToModify.getSize(); v++){ | ||
|
|
||
| int targetIndex = Math.min(v, targetVectors.getSize() - 1); //allows multiple vectors to share a lesser number of targets if desired | ||
| targetVectors.getAsVector4(targetIndex, tempTargetVec); | ||
| startVectors.getAsVector4(v, tempStartVec); | ||
| tempTargetVec.subtractLocal(tempStartVec); | ||
| tempTargetVec.multLocal(easedT); | ||
|
|
||
| vectorsToModify.updateVectorObject(tempStartVec.addLocal(tempTargetVec), v); | ||
| } | ||
|
|
||
| if (t >= 1f) { | ||
| super.setIsFinished(true); | ||
| } | ||
| } | ||
|
|
||
| public EaseVectorEffect setEaseToValueOverDuration(float dur, VectorGroup targetVector) { | ||
| this.targetVectors = targetVector; | ||
| duration = dur; | ||
| startVectors = null; | ||
| return this; | ||
| } | ||
|
|
||
| public void setDelayTime(float delay) { | ||
| this.delay = delay; | ||
| } | ||
|
|
||
| public void setEaseFunction(EaseFunction func) { | ||
| this.easeFunction = func; | ||
| } | ||
|
|
||
| @Override | ||
| public void reset() { | ||
| delayTimer = 0; | ||
| easeTimer = 0; | ||
| startVectors = null; | ||
| super.reset(); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,105 @@ | ||
| /* | ||
| * Copyright (c) 2009-2026 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.vectoreffect; | ||
|
|
||
| import com.jme3.math.Vector4f; | ||
| import com.jme3.math.FastNoiseLite; | ||
| import com.jme3.math.FastNoiseLite.NoiseType; | ||
|
|
||
| /** | ||
| * | ||
| * @author yaRnMcDonuts | ||
| */ | ||
| public class NoiseVectorEffect extends AbstractVectorEffect { | ||
|
|
||
| private FastNoiseLite noiseGenerator; | ||
|
|
||
| private VectorGroup noiseMagnitudes; | ||
| private VectorGroup originalVectorValues; | ||
|
|
||
| private final Vector4f tempNoiseVariationVec = new Vector4f(); | ||
| private final Vector4f tempOriginalVec = new Vector4f(); | ||
|
|
||
| public float speed = 1; | ||
| private float timeAccrued = 0; | ||
|
|
||
| public NoiseVectorEffect(VectorGroup vectorObject, VectorGroup noiseMagnitude) { | ||
| this(vectorObject, noiseMagnitude, NoiseType.OpenSimplex2, 0.5f); | ||
| } | ||
|
|
||
| public NoiseVectorEffect(VectorGroup vectorObject, VectorGroup noiseMagnitude, NoiseType noiseType, | ||
| float frequency) { | ||
| super(vectorObject); | ||
|
|
||
| this.noiseMagnitudes = noiseMagnitude; | ||
| noiseGenerator = new FastNoiseLite(); | ||
| noiseGenerator.SetFrequency(frequency); | ||
| noiseGenerator.SetNoiseType(noiseType); | ||
|
|
||
| } | ||
|
|
||
| @Override | ||
| public void update(float tpf) { | ||
| super.update(tpf); | ||
|
|
||
| if(originalVectorValues == null){ | ||
| originalVectorValues = vectorsToModify.clone(); | ||
| } | ||
|
|
||
| timeAccrued += tpf; | ||
| float noiseReturnVal = noiseGenerator.GetNoise(timeAccrued * speed, 12.671f + timeAccrued * speed * 0.92173f, 19.54f + timeAccrued * speed * 0.68913f); | ||
|
|
||
| for(int v = 0; v < vectorsToModify.getSize(); v++){ | ||
| int magnitudeIndex = Math.min(v, noiseMagnitudes.getSize() - 1); //allows multiple vectors to share the same magnitude if desired | ||
| noiseMagnitudes.getAsVector4(magnitudeIndex, tempNoiseVariationVec); | ||
|
|
||
| tempNoiseVariationVec.multLocal(noiseReturnVal); | ||
| originalVectorValues.getAsVector4(v, tempOriginalVec); | ||
|
|
||
| vectorsToModify.updateVectorObject(tempOriginalVec.addLocal(tempNoiseVariationVec), v); | ||
| } | ||
| } | ||
|
|
||
| public FastNoiseLite getNoiseGenerator() { | ||
| return noiseGenerator; | ||
| } | ||
|
|
||
| public void setSpeed(float speed) { | ||
| this.speed = speed; | ||
| } | ||
|
|
||
| @Override | ||
| public void reset() { | ||
| super.reset(); | ||
| originalVectorValues = null; | ||
| } | ||
|
Comment on lines
+101
to
+104
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The @Override
public void reset() {
super.reset();
originalVectorValues = null;
timeAccrued = 0;
} |
||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
onFinishedCallbackslist is anArrayList, which is not thread-safe. IfrunOnFinish()is called from a different thread than the one callingsetIsFinished(), it could lead to aConcurrentModificationException. Using a thread-safe list, such asCopyOnWriteArrayList, would prevent this potential issue.