commit 4f9ec5d6aa39930d77ec2055ccce5696d304d3f8
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Fri May 14 00:51:41 2021 +0200

    Make Dynamic's resetToBegin() done on the next frame.
    This is necessary if we want to reset many Dynamics at one go and have all of them start synchronized.
    Otherwise it can happen that when we reset, we do it when some objects which the Dynamics belong to are already rendered and others are not, and then some of the Dynamics will be delayed by one frame which is visible already.

diff --git a/src/main/java/org/distorted/library/type/Dynamic.java b/src/main/java/org/distorted/library/type/Dynamic.java
index 3927128..b7a32ab 100644
--- a/src/main/java/org/distorted/library/type/Dynamic.java
+++ b/src/main/java/org/distorted/library/type/Dynamic.java
@@ -19,6 +19,9 @@
 
 package org.distorted.library.type;
 
+import org.distorted.library.main.InternalMaster;
+
+import java.util.ArrayList;
 import java.util.Random;
 import java.util.Vector;
 
@@ -53,7 +56,7 @@ import java.util.Vector;
 //
 // and similarly Y(t) and Z(t).
 
-public abstract class Dynamic
+public abstract class Dynamic implements InternalMaster.Slave
   {
   /**
    * One revolution takes us from the first point to the last and back to first through the shortest path.
@@ -154,13 +157,27 @@ public abstract class Dynamic
 
   private float[] buf;
   private float[] old;
-  private static Random mRnd = new Random();
+  private static final Random mRnd = new Random();
   private static final int NUM_NOISE = 5; // used iff mNoise>0.0. Number of intermediary points between each pair of adjacent vectors
                                           // where we randomize noise factors to make the way between the two vectors not so smooth.
   private long mStartTime;
   private long mCorrectedTime;
   private static long mPausedTime;
 
+  private static final int JOB_RESET = 0;
+
+  private static class Job
+    {
+    int type;
+
+    Job(int t)
+      {
+      type  = t;
+      }
+    }
+
+  private ArrayList<Job> mJobs;
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // hide this from Javadoc
   
@@ -523,6 +540,13 @@ public abstract class Dynamic
       }
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void resetToBeginningNow()
+    {
+    mStartTime = -1;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   abstract void interpolate(float[] buffer, int offset, float time);
@@ -595,7 +619,10 @@ public abstract class Dynamic
  */
   public void resetToBeginning()
     {
-    mStartTime = -1;
+    if( mJobs==null ) mJobs = new ArrayList<>();
+
+    mJobs.add(new Job(JOB_RESET));
+    InternalMaster.newSlave(this);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -733,5 +760,23 @@ public abstract class Dynamic
     return false;
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void doWork()
+    {
+    int num = mJobs.size();
+    Job job;
+
+    for(int i=0; i<num; i++)
+      {
+      job = mJobs.remove(0);
+
+      if (job.type == JOB_RESET )
+        {
+        resetToBeginningNow();
+        }
+      }
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
   }
