소스 검색

Merge pull request #2410 from capdevon/capdevon-audio-filter

Fix #2408 - com.jme3.audio.LowPassFilter not cloneable
Ryan McDonough 4 달 전
부모
커밋
6f95af851c

+ 23 - 4
jme3-core/src/main/java/com/jme3/audio/Filter.java

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009-2020 jMonkeyEngine
+ * Copyright (c) 2009-2025 jMonkeyEngine
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -35,9 +35,12 @@ import com.jme3.export.JmeExporter;
 import com.jme3.export.JmeImporter;
 import com.jme3.export.Savable;
 import com.jme3.util.NativeObject;
+import com.jme3.util.clone.Cloner;
+import com.jme3.util.clone.JmeCloneable;
+
 import java.io.IOException;
 
-public abstract class Filter extends NativeObject implements Savable {
+public abstract class Filter extends NativeObject implements Savable, JmeCloneable {
 
     public Filter() {
         super();
@@ -49,12 +52,28 @@ public abstract class Filter extends NativeObject implements Savable {
 
     @Override
     public void write(JmeExporter ex) throws IOException {
-        // nothing to save
+        // no-op
     }
 
     @Override
     public void read(JmeImporter im) throws IOException {
-        // nothing to read
+        // no-op
+    }
+
+    /**
+     *  Called internally by com.jme3.util.clone.Cloner.  Do not call directly.
+     */
+    @Override
+    public Object jmeClone() {
+        return super.clone();
+    }
+
+    /**
+     * Called internally by com.jme3.util.clone.Cloner. Do not call directly.
+     */
+    @Override
+    public void cloneFields(Cloner cloner, Object original) {
+        // no-op
     }
 
     @Override

+ 60 - 2
jme3-core/src/main/java/com/jme3/audio/LowPassFilter.java

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009-2023 jMonkeyEngine
+ * Copyright (c) 2009-2025 jMonkeyEngine
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -36,26 +36,63 @@ import com.jme3.export.JmeExporter;
 import com.jme3.export.JmeImporter;
 import com.jme3.export.OutputCapsule;
 import com.jme3.util.NativeObject;
+
 import java.io.IOException;
 
+/**
+ * A filter that attenuates frequencies above a specified threshold, allowing lower
+ * frequencies to pass through with less attenuation. Commonly used to simulate effects
+ * such as muffling or underwater acoustics.
+ */
 public class LowPassFilter extends Filter {
 
-    protected float volume, highFreqVolume;
+    /**
+     * The overall volume scaling of the filtered sound
+     */
+    protected float volume;
+    /**
+     * The volume scaling of the high frequencies allowed to pass through. Valid values range
+     * from 0.0 to 1.0, where 0.0 completely eliminates high frequencies and 1.0 lets them pass
+     * through unchanged.
+     */
+    protected float highFreqVolume;
 
+    /**
+     * Constructs a low-pass filter.
+     *
+     * @param volume         the overall volume scaling of the filtered sound (0.0 - 1.0).
+     * @param highFreqVolume the volume scaling of high frequencies (0.0 - 1.0).
+     * @throws IllegalArgumentException if {@code volume} or {@code highFreqVolume} is out of range.
+     */
     public LowPassFilter(float volume, float highFreqVolume) {
         super();
         setVolume(volume);
         setHighFreqVolume(highFreqVolume);
     }
 
+    /**
+     * For internal cloning
+     * @param id the native object ID
+     */
     protected LowPassFilter(int id) {
         super(id);
     }
 
+    /**
+     * Retrieves the current volume scaling of high frequencies.
+     *
+     * @return the high-frequency volume scaling.
+     */
     public float getHighFreqVolume() {
         return highFreqVolume;
     }
 
+    /**
+     * Sets the high-frequency volume.
+     *
+     * @param highFreqVolume the new high-frequency volume scaling (0.0 - 1.0).
+     * @throws IllegalArgumentException if {@code highFreqVolume} is out of range.
+     */
     public void setHighFreqVolume(float highFreqVolume) {
         if (highFreqVolume < 0 || highFreqVolume > 1)
             throw new IllegalArgumentException("High freq volume must be between 0 and 1");
@@ -64,10 +101,21 @@ public class LowPassFilter extends Filter {
         this.updateNeeded = true;
     }
 
+    /**
+     * Retrieves the current overall volume scaling of the filtered sound.
+     *
+     * @return the overall volume scaling.
+     */
     public float getVolume() {
         return volume;
     }
 
+    /**
+     * Sets the overall volume.
+     *
+     * @param volume the new overall volume scaling (0.0 - 1.0).
+     * @throws IllegalArgumentException if {@code volume} is out of range.
+     */
     public void setVolume(float volume) {
         if (volume < 0 || volume > 1)
             throw new IllegalArgumentException("Volume must be between 0 and 1");
@@ -92,11 +140,21 @@ public class LowPassFilter extends Filter {
         highFreqVolume = ic.readFloat("hf_volume", 0);
     }
 
+    /**
+     * Creates a native object clone of this filter for internal usage.
+     *
+     * @return a new {@code LowPassFilter} instance with the same native ID.
+     */
     @Override
     public NativeObject createDestructableClone() {
         return new LowPassFilter(id);
     }
 
+    /**
+     * Retrieves a unique identifier for this filter. Used internally for native object management.
+     *
+     * @return a unique long identifier.
+     */
     @Override
     public long getUniqueId() {
         return ((long) OBJTYPE_FILTER << 32) | (0xffffffffL & (long) id);

+ 48 - 0
jme3-core/src/test/java/com/jme3/audio/AudioNodeTest.java

@@ -0,0 +1,48 @@
+package com.jme3.audio;
+
+import com.jme3.asset.AssetManager;
+import com.jme3.math.Vector3f;
+import com.jme3.system.JmeSystem;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Automated tests for the {@code AudioNode} class.
+ *
+ * @author capdevon
+ */
+public class AudioNodeTest {
+
+    @Test
+    public void testAudioNodeClone() {
+        AssetManager assetManager = JmeSystem.newAssetManager(AudioNodeTest.class.getResource("/com/jme3/asset/Desktop.cfg"));
+
+        AudioNode audio = new AudioNode(assetManager,
+                "Sound/Effects/Bang.wav", AudioData.DataType.Buffer);
+        audio.setDirection(new Vector3f(0, 1, 0));
+        audio.setVelocity(new Vector3f(1, 1, 1));
+        audio.setDryFilter(new LowPassFilter(1f, .1f));
+        audio.setReverbFilter(new LowPassFilter(.5f, .5f));
+
+        AudioNode clone = audio.clone();
+
+        Assert.assertNotNull(clone.previousWorldTranslation);
+        Assert.assertNotSame(audio.previousWorldTranslation, clone.previousWorldTranslation);
+        Assert.assertEquals(audio.previousWorldTranslation, clone.previousWorldTranslation);
+
+        Assert.assertNotNull(clone.getDirection());
+        Assert.assertNotSame(audio.getDirection(), clone.getDirection());
+        Assert.assertEquals(audio.getDirection(), clone.getDirection());
+
+        Assert.assertNotNull(clone.getVelocity());
+        Assert.assertNotSame(audio.getVelocity(), clone.getVelocity());
+        Assert.assertEquals(audio.getVelocity(), clone.getVelocity());
+
+        Assert.assertNotNull(clone.getDryFilter());
+        Assert.assertNotSame(audio.getDryFilter(), clone.getDryFilter());
+
+        Assert.assertNotNull(clone.getReverbFilter());
+        Assert.assertNotSame(audio.getReverbFilter(), clone.getReverbFilter());
+    }
+
+}