commit 8bfefd68074e97a3c9dbcaaf197521615ed16c8d
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Wed May 1 13:27:23 2019 +0100

    Split the DistortedNode class into two - DistortedNode and DistortedNodeData

diff --git a/src/main/java/org/distorted/library/main/Distorted.java b/src/main/java/org/distorted/library/main/Distorted.java
index 1be70e8..9f8a445 100644
--- a/src/main/java/org/distorted/library/main/Distorted.java
+++ b/src/main/java/org/distorted/library/main/Distorted.java
@@ -231,7 +231,7 @@ public class Distorted
   public static void onDestroy()
     {
     DistortedObject.onDestroy();
-    DistortedNode.onDestroy();
+    DistortedNodeData.onDestroy();
     DistortedEffects.onDestroy();
     DistortedMaster.onDestroy();
     DistortedOutputSurface.onDestroy();
diff --git a/src/main/java/org/distorted/library/main/DistortedEffects.java b/src/main/java/org/distorted/library/main/DistortedEffects.java
index de2efc6..14d8174 100644
--- a/src/main/java/org/distorted/library/main/DistortedEffects.java
+++ b/src/main/java/org/distorted/library/main/DistortedEffects.java
@@ -854,7 +854,7 @@ public class DistortedEffects
  */
   public int abortAllEffects()
     {
-    return mM.abortAll(true) + mV.abortAll(true) + mF.abortAll(true);
+    return mM.abortAll(true) + mV.abortAll(true) + mF.abortAll(true) + mP.abortAll(true);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/library/main/DistortedNode.java b/src/main/java/org/distorted/library/main/DistortedNode.java
index 0d6b654..703a088 100644
--- a/src/main/java/org/distorted/library/main/DistortedNode.java
+++ b/src/main/java/org/distorted/library/main/DistortedNode.java
@@ -25,7 +25,6 @@ import org.distorted.library.mesh.MeshBase;
 
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashMap;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 /**
@@ -45,9 +44,6 @@ public class DistortedNode implements DistortedMaster.Slave
   private static final int DETALL = 2;
   private static final int SORT   = 3;
 
-  private ArrayList<DistortedNode> mChildren;
-  private int[] mNumChildren;  // ==mChildren.length(), but we only create mChildren if the first one gets added
-
   private class Job
     {
     int type;
@@ -62,8 +58,8 @@ public class DistortedNode implements DistortedMaster.Slave
 
   private ArrayList<Job> mJobs = new ArrayList<>();
 
-  private static HashMap<ArrayList<Long>,NodeData> mMapNodeID = new HashMap<>();
-  private static long mNextNodeID =0;
+  private ArrayList<DistortedNode> mChildren;
+  private int[] mNumChildren;  // ==mChildren.length(), but we only create mChildren if the first one gets added
 
   private boolean mRenderWayOIT;
   private DistortedNode mParent;
@@ -72,49 +68,17 @@ public class DistortedNode implements DistortedMaster.Slave
   private DistortedEffects mEffects;
   private DistortedSurface mSurface;
   private DistortedRenderState mState;
-  private NodeData mData;
+  private DistortedNodeData mData;
   private int mFboW, mFboH, mFboDepthStencil;
 
-  private class NodeData
-    {
-    final long ID;
-    final ArrayList<Long> key;
-
-    int numPointingNodes;
-    long currTime;
-    DistortedFramebuffer mFBO;
-
-    NodeData(long id, ArrayList<Long> k)
-      {
-      ID              = id;
-      key             = k;
-      numPointingNodes= 1;
-      currTime        =-1;
-      mFBO            = null;
-      }
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  static synchronized void onDestroy()
-    {
-    mNextNodeID = 0;
-    mMapNodeID.clear();
-    }
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public void markForDeletion()
     {
-    if( --mData.numPointingNodes==0 )
+    if( mData.removeData() )
       {
-      mMapNodeID.remove(mData.key);
-
-      if( mData.mFBO!=null )
-        {
-        mData.mFBO.markForDeletion();
-        mData.mFBO = null;
-        }
+      mData.mFBO.markForDeletion();
+      mData.mFBO = null;
       }
 
     mEffects.removeNode(this);
@@ -164,89 +128,18 @@ public class DistortedNode implements DistortedMaster.Slave
     return ret;
     }
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// Debug - print all the Node IDs
-
-  @SuppressWarnings("unused")
-  void debug(int depth)
-    {
-    String tmp="";
-    int i;
-
-    for(i=0; i<depth; i++) tmp +="   ";
-    tmp += ("NodeID="+mData.ID+" nodes pointing: "+mData.numPointingNodes+" surfaceID="+
-            mSurface.getID()+" FBO="+(mData.mFBO==null ? "null":mData.mFBO.getID()))+
-            " parent sID="+(mParent==null ? "null": (mParent.mSurface.getID()));
-
-    android.util.Log.e("NODE", tmp);
-
-    for(i=0; i<mNumChildren[0]; i++)
-      mChildren.get(i).debug(depth+1);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// Debug - print contents of the HashMap
-
-  @SuppressWarnings("unused")
-  static void debugMap()
-    {
-    NodeData tmp;
-
-    for(ArrayList<Long> key: mMapNodeID.keySet())
-      {
-      tmp = mMapNodeID.get(key);
-      android.util.Log.e("NODE", "NodeID: "+tmp.ID+" <-- "+key);
-      }
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private NodeData retData()
-    {
-    ArrayList<Long> newList = generateIDList();
-    NodeData newData = mMapNodeID.get(newList);
-
-    if( newData!=null )
-      {
-      newData.numPointingNodes++;
-      }
-    else
-      {
-      newData = new NodeData(++mNextNodeID,newList);
-      mMapNodeID.put(newList,newData);
-      }
-
-    return newData;
-    }
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // tree isomorphism algorithm
 
   private void adjustIsomorphism()
     {
-    NodeData newData = retData();
-    boolean deleteOldFBO = false;
-    boolean createNewFBO = false;
-
-    if( --mData.numPointingNodes==0 )
-      {
-      mMapNodeID.remove(mData.key);
-      if( mData.mFBO!=null ) deleteOldFBO=true;
-      }
-    if( mNumChildren[0]>0 && newData.mFBO==null )
-      {
-      createNewFBO = true;
-      }
-    if( mNumChildren[0]==0 && newData.mFBO!=null )
-      {
-      newData.mFBO.markForDeletion();
-      android.util.Log.e("NODE", "ERROR!! this NodeData cannot possibly contain a non-null FBO!! "+newData.mFBO.getID() );
-      newData.mFBO = null;
-      }
+    DistortedNodeData newData = DistortedNodeData.returnData(generateIDList());
+    boolean deleteOldFBO = mData.removeData();
+    boolean createNewFBO = (mNumChildren[0]>0 && newData.mFBO==null);
 
     if( deleteOldFBO && createNewFBO )
       {
-      newData.mFBO = mData.mFBO;  // just copy over
+      newData.mFBO = mData.mFBO;
       }
     else if( deleteOldFBO )
       {
@@ -325,10 +218,8 @@ public class DistortedNode implements DistortedMaster.Slave
     {
     int numRenders = 0;
 
-    if( mNumChildren[0]>0 && mData.currTime!=currTime )
+    if( mNumChildren[0]>0 && mData.notRenderedYetAtThisTime(currTime) )
       {
-      mData.currTime = currTime;
-
       for (int i=0; i<mNumChildren[0]; i++)
         {
         numRenders += mChildren.get(i).renderRecursive(currTime);
@@ -413,7 +304,7 @@ public class DistortedNode implements DistortedMaster.Slave
     mFboH            = 0;  // mSurface's dimensions
     mFboDepthStencil = DistortedFramebuffer.DEPTH_NO_STENCIL;
 
-    mData = retData();
+    mData = DistortedNodeData.returnData(generateIDList());
     mEffects.newNode(this);
     }
 
@@ -482,7 +373,7 @@ public class DistortedNode implements DistortedMaster.Slave
       mNumChildren = new int[1];
       }
 
-    mData = retData();
+    mData = DistortedNodeData.returnData(generateIDList());
     mEffects.newNode(this);
     }
 
diff --git a/src/main/java/org/distorted/library/main/DistortedNodeData.java b/src/main/java/org/distorted/library/main/DistortedNodeData.java
new file mode 100644
index 0000000..8befa60
--- /dev/null
+++ b/src/main/java/org/distorted/library/main/DistortedNodeData.java
@@ -0,0 +1,119 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Copyright 2019 Leszek Koltunski                                                               //
+//                                                                                               //
+// This file is part of Distorted.                                                               //
+//                                                                                               //
+// Distorted is free software: you can redistribute it and/or modify                             //
+// it under the terms of the GNU General Public License as published by                          //
+// the Free Software Foundation, either version 2 of the License, or                             //
+// (at your option) any later version.                                                           //
+//                                                                                               //
+// Distorted is distributed in the hope that it will be useful,                                  //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
+// GNU General Public License for more details.                                                  //
+//                                                                                               //
+// You should have received a copy of the GNU General Public License                             //
+// along with Distorted.  If not, see <http://www.gnu.org/licenses/>.                            //
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+package org.distorted.library.main;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * This is a member of DistortedNode. Makes sure two isomorphic Nodes only get rendered once.
+ */
+class DistortedNodeData
+  {
+  private static HashMap<ArrayList<Long>, DistortedNodeData> mMapNodeID = new HashMap<>();
+  private static long mNextNodeID =0;
+
+  private final ArrayList<Long> key;
+  private int numPointingNodes;
+  private long currTime;
+
+  final long ID;
+  DistortedFramebuffer mFBO;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private DistortedNodeData(long id, ArrayList<Long> k)
+    {
+    ID              = id;
+    key             = k;
+    numPointingNodes= 1;
+    currTime        =-1;
+    mFBO            = null;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  static synchronized void onDestroy()
+    {
+    mNextNodeID = 0;
+    mMapNodeID.clear();
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  @SuppressWarnings("unused")
+  static void debugMap()
+    {
+    DistortedNodeData tmp;
+
+    for(ArrayList<Long> key: mMapNodeID.keySet())
+      {
+      tmp = mMapNodeID.get(key);
+      android.util.Log.e("NodeData", "NodeID: "+tmp.ID+" <-- "+key);
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  static DistortedNodeData returnData(ArrayList<Long> list)
+    {
+    DistortedNodeData newData = mMapNodeID.get(list);
+
+    if( newData!=null )
+      {
+      newData.numPointingNodes++;
+      }
+    else
+      {
+      newData = new DistortedNodeData(++mNextNodeID,list);
+      mMapNodeID.put(list,newData);
+      }
+
+    return newData;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  boolean removeData()
+    {
+    if( --numPointingNodes==0 )
+      {
+      mMapNodeID.remove(key);
+
+      if( mFBO!=null ) return true;
+      }
+
+    return false;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  boolean notRenderedYetAtThisTime(long time)
+    {
+    if( currTime!=time )
+      {
+      currTime = time;
+      return true;
+      }
+
+    return false;
+    }
+  }
diff --git a/src/main/java/org/distorted/library/main/EffectQueue.java b/src/main/java/org/distorted/library/main/EffectQueue.java
index 93b32bd..9f7aebb 100644
--- a/src/main/java/org/distorted/library/main/EffectQueue.java
+++ b/src/main/java/org/distorted/library/main/EffectQueue.java
@@ -38,8 +38,8 @@ abstract class EffectQueue implements DistortedMaster.Slave
   private static final int DETACH = 2;
   private static final int DETALL = 3;
 
-  int mNumEffects;      // 'ToBe' will be more than mNumEffects if doWork() hasn't
-  int mNumEffectsToBe;  // added them yet (or less if it hasn't removed some yet)
+  int mNumEffects;              // 'ToBe' will be more than mNumEffects if doWork() hasn't
+  private int mNumEffectsToBe;  // added them yet (or less if it hasn't removed some yet)
   float[] mUniforms;
   long[] mCurrentDuration;
   Effect[] mEffects;
@@ -101,7 +101,7 @@ abstract class EffectQueue implements DistortedMaster.Slave
 // (this is a speedup: then both queues can be applied once, which seriously speeds up stuff -
 // especially important in case of postprocessing)
 
-  void regenerateIDandSort()
+  private void regenerateIDandSort()
     {
     if( mNumEffects>0 )
       {
