From 259fce6ca0fa4fe92e6dc2266d442c62723eb73c Mon Sep 17 00:00:00 2001
From: Sven Göthel <sgothel@jausoft.com>
Date: Sun, 7 Jan 2024 04:44:01 +0100
Subject: GraphUI Cleanup: Simplify Shape.draw*() and
 Container.{add,remove*}Shape[s](); Remove Scene.setDebugBorderBox()

Simplify Shape/Scene
- Split scene.display()/shape.drawImpl0() and scene.displayGLSelect()/shape.drawToSelectImpl0()

Simplify Container (Scene/Group)
- {add,remove*}Shape[s](), i.e. drop unusual removeShape*() and simplify implementation

Scene
- Remove setDebugBorderBox()
---
 .../classes/com/jogamp/graph/ui/Container.java     |  29 ++--
 .../classes/com/jogamp/graph/ui/GraphShape.java    |   9 +-
 src/graphui/classes/com/jogamp/graph/ui/Group.java |  89 ++++++-------
 src/graphui/classes/com/jogamp/graph/ui/Scene.java | 147 ++++++++++-----------
 src/graphui/classes/com/jogamp/graph/ui/Shape.java |  16 ++-
 5 files changed, 143 insertions(+), 147 deletions(-)

(limited to 'src/graphui/classes')

diff --git a/src/graphui/classes/com/jogamp/graph/ui/Container.java b/src/graphui/classes/com/jogamp/graph/ui/Container.java
index dd8fe99f9..545ceec60 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/Container.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/Container.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2023 JogAmp Community. All rights reserved.
+ * Copyright 2023-2024 JogAmp Community. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without modification, are
  * permitted provided that the following conditions are met:
@@ -34,6 +34,8 @@ import java.util.List;
 import com.jogamp.graph.ui.Shape.Visitor2;
 import com.jogamp.math.geom.AABBox;
 import com.jogamp.math.util.PMVMatrix4f;
+import com.jogamp.opengl.GL2ES2;
+import com.jogamp.graph.curve.opengl.RegionRenderer;
 import com.jogamp.graph.ui.Shape.Visitor1;
 
 /**
@@ -53,25 +55,30 @@ public interface Container {
     void addShape(Shape s);
 
     /**
-     * Removes given shape, w/o {@link Shape#destroy(com.jogamp.opengl.GL2ES2, com.jogamp.graph.curve.opengl.RegionRenderer) destroying} them.
+     * Removes given shape, w/o {@link Shape#destroy(GL2ES2, RegionRenderer)}.
      * @return the removed shape or null if not contained
      */
-    Shape removeShape(Shape s);
+    Shape removeShape(final Shape s);
+
+    /** Removes all given shapes, w/o {@link Shape#destroy(GL2ES2, RegionRenderer)}. */
+    void removeShapes(Collection<? extends Shape> shapes);
 
     /**
-     * Removes shape at given index, w/o {@link Shape#destroy(com.jogamp.opengl.GL2ES2, com.jogamp.graph.curve.opengl.RegionRenderer) destroying} them.
-     * @return the removed shape
-     * @throws IndexOutOfBoundsException if index is out of bounds, i.e. (index < 0 || index >= size())
+     * Removes given shape with {@link Shape#destroy(GL2ES2, RegionRenderer)}, if contained.
+     * @param gl GL2ES2 context
+     * @param renderer
+     * @param s the shape to be removed
+     * @return true if given Shape is removed and destroyed
      */
-    Shape removeShape(final int idx);
+    boolean removeShape(final GL2ES2 gl, final RegionRenderer renderer, final Shape s);
 
     void addShapes(Collection<? extends Shape> shapes);
 
-    /** Removes all given shapes, w/o {@link Shape#destroy(com.jogamp.opengl.GL2ES2, com.jogamp.graph.curve.opengl.RegionRenderer) destroying} them. */
-    void removeShapes(Collection<? extends Shape> shapes);
+    /** Removes all given shapes with {@link Shape#destroy(GL2ES2, RegionRenderer)}. */
+    void removeShapes(final GL2ES2 gl, final RegionRenderer renderer, final Collection<? extends Shape> shapes);
 
-    /** Removes all contained shapes, w/o {@link Shape#destroy(com.jogamp.opengl.GL2ES2, com.jogamp.graph.curve.opengl.RegionRenderer) destroying} them. */
-    void removeAllShapes();
+    /** Removes all contained shapes with {@link Shape#destroy(GL2ES2, RegionRenderer)}. */
+    void removeAllShapes(final GL2ES2 gl, final RegionRenderer renderer);
 
     boolean contains(Shape s);
 
diff --git a/src/graphui/classes/com/jogamp/graph/ui/GraphShape.java b/src/graphui/classes/com/jogamp/graph/ui/GraphShape.java
index b05c2bf11..869d63ec7 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/GraphShape.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/GraphShape.java
@@ -167,9 +167,12 @@ public abstract class GraphShape extends Shape {
 
     @Override
     protected final void drawImpl0(final GL2ES2 gl, final RegionRenderer renderer, final int[] sampleCount, final Vec4f rgba) {
-        if( null != rgba ) {
-            renderer.setColorStatic(rgba);
-        }
+        renderer.setColorStatic(rgba);
+        region.draw(gl, renderer, sampleCount);
+    }
+
+    @Override
+    protected final void drawToSelectImpl0(final GL2ES2 gl, final RegionRenderer renderer, final int[] sampleCount) {
         region.draw(gl, renderer, sampleCount);
     }
 
diff --git a/src/graphui/classes/com/jogamp/graph/ui/Group.java b/src/graphui/classes/com/jogamp/graph/ui/Group.java
index b96291128..9dca781b1 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/Group.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/Group.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2023 JogAmp Community. All rights reserved.
+ * Copyright 2023-2024 JogAmp Community. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without modification, are
  * permitted provided that the following conditions are met:
@@ -123,18 +123,6 @@ public class Group extends Shape implements Container {
         markShapeDirty();
     }
 
-    /** Removes given shape, keeps it alive. */
-    @Override
-    public Shape removeShape(final Shape s) {
-        if( shapes.remove(s) ) {
-            s.setParent(null);
-            markShapeDirty();
-            return s;
-        } else {
-            return null;
-        }
-    }
-
     /**
      * Atomic replacement of the given {@link Shape} {@code remove} with {@link Shape} {@code replacement}.
      * @param remove the shape to be replaced
@@ -157,22 +145,24 @@ public class Group extends Shape implements Container {
     }
 
     @Override
-    public Shape removeShape(final int idx) {
-        final Shape r = shapes.remove(idx);
-        if( null != r ) {
-            r.setParent(null);
+    public Shape removeShape(final Shape s) {
+        if( shapes.remove(s) ) {
+            s.setParent(null);
             markShapeDirty();
+            return s;
+        } else {
+            return null;
         }
-        return r;
     }
 
-    /**
-     * Removes given shape and destroy it, if contained.
-     * @param gl GL2ES2 context
-     * @param renderer
-     * @param s the shape to be removed
-     * @return true if given Shape is removed and destroyed
-     */
+    @Override
+    public void removeShapes(final Collection<? extends Shape> shapes) {
+        for(final Shape s : shapes) {
+            removeShape(s);
+        }
+    }
+
+    @Override
     public boolean removeShape(final GL2ES2 gl, final RegionRenderer renderer, final Shape s) {
         if( shapes.remove(s) ) {
             s.setParent(null);
@@ -190,14 +180,7 @@ public class Group extends Shape implements Container {
             addShape(s);
         }
     }
-    /** Removes all given shapes, keeps them alive. */
     @Override
-    public void removeShapes(final Collection<? extends Shape> shapes) {
-        for(final Shape s : shapes) {
-            removeShape(s);
-        }
-    }
-    /** Removes all given shapes and destroys them. */
     public void removeShapes(final GL2ES2 gl, final RegionRenderer renderer, final Collection<? extends Shape> shapes) {
         for(final Shape s : shapes) {
             removeShape(gl, renderer, s);
@@ -205,14 +188,6 @@ public class Group extends Shape implements Container {
     }
 
     @Override
-    public void removeAllShapes() {
-        final int count = shapes.size();
-        for(int i=count-1; i>=0; --i) {
-            removeShape(i);
-        }
-    }
-
-    /** Removes all given shapes and destroys them. */
     public void removeAllShapes(final GL2ES2 gl, final RegionRenderer renderer) {
         final int count = shapes.size();
         for(int i=count-1; i>=0; --i) {
@@ -268,22 +243,38 @@ public class Group extends Shape implements Container {
                 shape.setTransformMv(pmv);
 
                 if( !doFrustumCulling || !pmv.getFrustum().isAABBoxOutside( shape.getBounds() ) ) {
-                    if( null == rgba ) {
-                        shape.drawToSelect(gl, renderer, sampleCount);
-                    } else {
-                        shape.draw(gl, renderer, sampleCount);
-                    }
+                    shape.draw(gl, renderer, sampleCount);
                 }
                 pmv.popMv();
             }
         }
         if( null != border ) {
-            if( null == rgba ) {
-                border.drawToSelect(gl, renderer, sampleCount);
-            } else {
-                border.draw(gl, renderer, sampleCount);
+            border.draw(gl, renderer, sampleCount);
+        }
+    }
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    @Override
+    protected final void drawToSelectImpl0(final GL2ES2 gl, final RegionRenderer renderer, final int[] sampleCount) {
+        final PMVMatrix4f pmv = renderer.getMatrix();
+        final Object[] shapesS = shapes.toArray();
+        Arrays.sort(shapesS, (Comparator)Shape.ZAscendingComparator);
+
+        final int shapeCount = shapesS.length;
+        for(int i=0; i<shapeCount; i++) {
+            final Shape shape = (Shape) shapesS[i];
+            if( shape.isVisible() ) {
+                pmv.pushMv();
+                shape.setTransformMv(pmv);
+
+                if( !doFrustumCulling || !pmv.getFrustum().isAABBoxOutside( shape.getBounds() ) ) {
+                    shape.drawToSelect(gl, renderer, sampleCount);
+                }
+                pmv.popMv();
             }
         }
+        if( null != border ) {
+            border.drawToSelect(gl, renderer, sampleCount);
+        }
     }
 
     private boolean relayoutOnDirtyShapes = true;
diff --git a/src/graphui/classes/com/jogamp/graph/ui/Scene.java b/src/graphui/classes/com/jogamp/graph/ui/Scene.java
index 101bc70e2..6d3f77971 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/Scene.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/Scene.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2010-2023 JogAmp Community. All rights reserved.
+ * Copyright 2010-2024 JogAmp Community. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without modification, are
  * permitted provided that the following conditions are met:
@@ -129,11 +129,10 @@ public final class Scene implements Container, GLEventListener {
     /** Maximum sample count {@value} for Graph Region AA {@link Region#getRenderModes() render-modes}: {@link Region#VBAA_RENDERING_BIT} or {@link Region#MSAA_RENDERING_BIT}. */
     public static final int MAX_SAMPLE_COUNT = 8;
 
-    @SuppressWarnings("unused")
     private static final boolean DEBUG = false;
 
     private final List<Shape> shapes = new CopyOnWriteArrayList<Shape>();
-    private float dbgBorderThickness = 0f;
+
     private boolean doFrustumCulling = false;
 
     private float[] clearColor = null;
@@ -272,44 +271,39 @@ public final class Scene implements Container, GLEventListener {
 
     @Override
     public void addShape(final Shape s) {
-        if( !s.hasBorder() && !FloatUtil.isZero(dbgBorderThickness) ) {
-            s.setBorder(dbgBorderThickness);
-        }
         shapes.add(s);
     }
+
     @Override
     public Shape removeShape(final Shape s) {
         if( shapes.remove(s) ) {
-            s.setBorder(0f);
             return s;
         } else {
             return null;
         }
     }
+
     @Override
-    public Shape removeShape(final int idx) {
-        final Shape r = shapes.remove(idx);
-        if( null != r ) {
-            r.setBorder(0f);
+    public void removeShapes(final Collection<? extends Shape> shapes) {
+        for(final Shape s : shapes) {
+            removeShape(s);
         }
-        return r;
     }
 
-    /**
-     * Removes given shape and destroy it, if contained.
-     * @param gl GL2ES2 context
-     * @param s the shape to be removed
-     * @return true if given Shape is removed and destroyed
-     */
-    public boolean removeShape(final GL2ES2 gl, final Shape s) {
+    @Override
+    public boolean removeShape(final GL2ES2 gl, final RegionRenderer renderer, final Shape s) {
         if( shapes.remove(s) ) {
-            s.setBorder(0f);
             s.destroy(gl, renderer);
             return true;
         } else {
             return false;
         }
     }
+
+    /** Removes given shape and destroy it, if contained - convenient call for {@link #removeShape(GL2ES2, RegionRenderer, Shape)}. */
+    public boolean removeShape(final GL2ES2 gl, final Shape s) {
+        return removeShape(gl, renderer, s);
+    }
     @Override
     public void addShapes(final Collection<? extends Shape> shapes) {
         for(final Shape s : shapes) {
@@ -317,32 +311,25 @@ public final class Scene implements Container, GLEventListener {
         }
     }
     @Override
-    public void removeShapes(final Collection<? extends Shape> shapes) {
+    public void removeShapes(final GL2ES2 gl, final RegionRenderer renderer, final Collection<? extends Shape> shapes) {
         for(final Shape s : shapes) {
-            removeShape(s);
+            removeShape(gl, renderer, s);
         }
     }
-    /** Removes all given shapes and destroys them. */
+    /** Removes all given shapes and destroys them, convenient call for {@link #removeShape(GL2ES2, RegionRenderer, Shape)} */
     public void removeShapes(final GL2ES2 gl, final Collection<? extends Shape> shapes) {
-        for(final Shape s : shapes) {
-            removeShape(gl, s);
-        }
+        removeShapes(gl, renderer, shapes);
     }
     @Override
-    public void removeAllShapes() {
+    public void removeAllShapes(final GL2ES2 gl, final RegionRenderer renderer) {
         final int count = shapes.size();
         for(int i=count-1; i>=0; --i) {
-            final Shape s = shapes.get(i);
-            s.setBorder(0f);
-            shapes.remove(s);
+            removeShape(gl, renderer, shapes.get(i));
         }
     }
-    /** Removes all given shapes and destroys them. */
+    /** Removes all given shapes and destroys them, convenient call for {@link #removeAllShapes(GL2ES2, RegionRenderer)}. */
     public void removeAllShapes(final GL2ES2 gl) {
-        final int count = shapes.size();
-        for(int i=count-1; i>=0; --i) {
-            removeShape(gl, shapes.get(i));
-        }
+        removeAllShapes(gl, renderer);
     }
 
     @Override
@@ -411,17 +398,6 @@ public final class Scene implements Container, GLEventListener {
         }
     }
 
-    /**
-     * Sets the debug {@link Shape#setBorder(float) border} thickness for all existing or added shapes, zero for no debug border (default).
-     * @param v thickness debug border, zero for no border
-     */
-    public final void setDebugBorderBox(final float v) {
-        dbgBorderThickness = v;
-        for(int i=0; i<shapes.size(); i++) {
-            shapes.get(i).setBorder(v);
-        }
-    }
-
     @Override
     public void init(final GLAutoDrawable drawable) {
         if( null == cDrawable ) {
@@ -487,64 +463,75 @@ public final class Scene implements Container, GLEventListener {
         final Object[] shapesS = shapes.toArray();
         Arrays.sort(shapesS, (Comparator)Shape.ZAscendingComparator);
 
-        display(drawable, shapesS, false);
+        display(drawable, shapesS);
     }
 
     private static final int[] sampleCountGLSelect = { -1 };
 
-    private void display(final GLAutoDrawable drawable, final Object[] shapes, final boolean glSelect) {
+    private void display(final GLAutoDrawable drawable, final Object[] shapes) {
         final GL2ES2 gl = drawable.getGL().getGL2ES2();
 
         final int[] sampleCount0;
-        if( glSelect ) {
-            gl.glClearColor(0f, 0f, 0f, 1f);
-            sampleCount0 = sampleCountGLSelect;
-            gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
-        } else {
-            if( null != clearColor ) {
-                gl.glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
-                gl.glClear(clearMask);
-            }
-            sampleCount0 = sampleCount;
+        if( null != clearColor ) {
+            gl.glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
+            gl.glClear(clearMask);
         }
+        sampleCount0 = sampleCount;
 
         final PMVMatrix4f pmv = renderer.getMatrix();
 
-        if( glSelect ) {
-            renderer.enable(gl, true, RegionRenderer.defaultBlendDisable, RegionRenderer.defaultBlendDisable);
-        } else {
-            renderer.enable(gl, true);
-        }
+        renderer.enable(gl, true);
 
-        //final int shapeCount = shapes.size();
         final int shapeCount = shapes.length;
         for(int i=0; i<shapeCount; i++) {
-            // final Shape shape = shapes.get(i);
             final Shape shape = (Shape)shapes[i];
-            // System.err.println("Id "+i+": "+uiShape);
             if( shape.isVisible() ) {
                 pmv.pushMv();
                 shape.setTransformMv(pmv);
 
                 if( !doFrustumCulling || !pmv.getFrustum().isAABBoxOutside( shape.getBounds() ) ) {
-                    if( glSelect ) {
-                        final float color = ( i + 1f ) / ( shapeCount + 2f );
-                        // FIXME
-                        // System.err.printf("drawGL: color %f, index %d of [0..%d[%n", color, i, shapeCount);
-                        renderer.setColorStatic(color, color, color, 1f);
-                        shape.drawToSelect(gl, renderer, sampleCount0);
-                    } else {
-                        shape.draw(gl, renderer, sampleCount0);
-                    }
+                    shape.draw(gl, renderer, sampleCount0);
                 }
                 pmv.popMv();
             }
         }
-        if( glSelect ) {
-            renderer.enable(gl, false, RegionRenderer.defaultBlendDisable, RegionRenderer.defaultBlendDisable);
-        } else {
-            renderer.enable(gl, false);
+        renderer.enable(gl, false);
+        synchronized ( syncDisplayedOnce ) {
+            displayedOnce = true;
+            syncDisplayedOnce.notifyAll();
+        }
+    }
+
+    private void displayGLSelect(final GLAutoDrawable drawable, final Object[] shapes) {
+        final GL2ES2 gl = drawable.getGL().getGL2ES2();
+
+        final int[] sampleCount0;
+        gl.glClearColor(0f, 0f, 0f, 1f);
+        sampleCount0 = sampleCountGLSelect;
+        gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+
+        final PMVMatrix4f pmv = renderer.getMatrix();
+
+        renderer.enable(gl, true, RegionRenderer.defaultBlendDisable, RegionRenderer.defaultBlendDisable);
+
+        final int shapeCount = shapes.length;
+        for(int i=0; i<shapeCount; i++) {
+            final Shape shape = (Shape)shapes[i];
+            if( shape.isVisible() ) {
+                pmv.pushMv();
+                shape.setTransformMv(pmv);
+
+                if( !doFrustumCulling || !pmv.getFrustum().isAABBoxOutside( shape.getBounds() ) ) {
+                    final float color = ( i + 1f ) / ( shapeCount + 2f );
+                    // FIXME
+                    // System.err.printf("drawGL: color %f, index %d of [0..%d[%n", color, i, shapeCount);
+                    renderer.setColorStatic(color, color, color, 1f);
+                    shape.drawToSelect(gl, renderer, sampleCount0);
+                }
+                pmv.popMv();
+            }
         }
+        renderer.enable(gl, false, RegionRenderer.defaultBlendDisable, RegionRenderer.defaultBlendDisable);
         synchronized ( syncDisplayedOnce ) {
             displayedOnce = true;
             syncDisplayedOnce.notifyAll();
@@ -727,7 +714,7 @@ public final class Scene implements Container, GLEventListener {
 
         final GL2ES2 gl = drawable.getGL().getGL2ES2();
 
-        display(drawable, shapesS, true);
+        displayGLSelect(drawable, shapesS);
 
         psm.setPackAlignment(gl, 4);
         // psm.setUnpackAlignment(gl, 4);
diff --git a/src/graphui/classes/com/jogamp/graph/ui/Shape.java b/src/graphui/classes/com/jogamp/graph/ui/Shape.java
index 0bdb9f985..e3a1f0e74 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/Shape.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/Shape.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2010-2023 JogAmp Community. All rights reserved.
+ * Copyright 2010-2024 JogAmp Community. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without modification, are
  * permitted provided that the following conditions are met:
@@ -583,7 +583,7 @@ public abstract class Shape {
     public void drawToSelect(final GL2ES2 gl, final RegionRenderer renderer, final int[] sampleCount) {
         synchronized ( dirtySync ) {
             validate(gl);
-            drawImpl0(gl, renderer, sampleCount, null);
+            drawToSelectImpl0(gl, renderer, sampleCount);
         }
     }
 
@@ -1751,14 +1751,22 @@ public abstract class Shape {
     protected abstract void validateImpl(final GLProfile glp, final GL2ES2 gl);
 
     /**
-     * Actual draw implementation
+     * Actual draw implementation, called by {@link #draw(GL2ES2, RegionRenderer, int[])}
      * @param gl
      * @param renderer
      * @param sampleCount
-     * @param rgba if null, caller is {@link #drawToSelect(GL2ES2, RegionRenderer, int[])}, otherwise regular {@#link #draw(GL2ES2, RegionRenderer, int[])}
+     * @param rgba
      */
     protected abstract void drawImpl0(final GL2ES2 gl, final RegionRenderer renderer, final int[] sampleCount, Vec4f rgba);
 
+    /**
+     * Actual draw implementation, called by {@link #drawToSelect(GL2ES2, RegionRenderer, int[])}
+     * @param gl
+     * @param renderer
+     * @param sampleCount
+     */
+    protected abstract void drawToSelectImpl0(final GL2ES2 gl, final RegionRenderer renderer, final int[] sampleCount);
+
     /** Custom {@link #clear(GL2ES2, RegionRenderer)} task, called 1st. */
     protected abstract void clearImpl0(final GL2ES2 gl, final RegionRenderer renderer);
 
-- 
cgit v1.2.3