From 1af7d3700724834e40ad8636bc9a56cdc3b19b15 Mon Sep 17 00:00:00 2001
From: Normand Briere <nbriere@noware.ca>
Date: Sat, 27 Jul 2019 11:52:38 -0400
Subject: [PATCH] New layout icons

---
 Object3D.java | 1872 +++++++++++++++++++++++++++++-----------------------------
 1 files changed, 930 insertions(+), 942 deletions(-)

diff --git a/Object3D.java b/Object3D.java
index 8a39641..b4b1eb5 100644
--- a/Object3D.java
+++ b/Object3D.java
@@ -5,6 +5,7 @@
 import java.util.Vector;
 
 import javax.media.j3d.Transform3D;
+import javax.media.opengl.GL;
 import javax.vecmath.Vector3d;
 
 import javax.imageio.ImageIO;
@@ -13,12 +14,24 @@
 import //weka.core.
         matrix.Matrix;
 
+import java.util.UUID;
+
 //import net.sourceforge.sizeof.SizeOf;
 public class Object3D extends Vector<Object3D> implements java.io.Serializable, iSendInfo //, aurelienribon.tweenengine.TweenAccessor<Object3D>
 {
     //static final long serialVersionUID = -607422624994562685L;
     static final long serialVersionUID = 5022536242724664900L;
     
+    private UUID uuid = UUID.randomUUID();
+    
+    // TEMPORARY for mocap undo. No need to be transient.
+    mocap.reader.BVHReader.BVHResult savebvh;
+    Object3D saveskeleton;
+    //
+    
+    byte[] versions[];
+    int versionindex = -1;    
+        
     ScriptNode scriptnode;
 
         void InitOthers()
@@ -99,64 +112,178 @@
     
 //    transient boolean reduced; // for morph reduction
     
-transient com.bulletphysics.linearmath.Transform cache; // for fast merge
-transient com.bulletphysics.linearmath.Transform cache_1; // for fast merge
+    transient com.bulletphysics.linearmath.Transform cache; // for fast merge
+    transient com.bulletphysics.linearmath.Transform cache_1; // for fast merge
 
-transient Object3D transientsupport; // for cloning
-transient boolean transientlink2master;
+    transient Object3D transientsupport; // for cloning
+    transient boolean transientlink2master;
 
-void SaveSupports()
-{
-    if (blockloop)
-        return;
-
-    transientsupport = support;
-    transientlink2master = link2master;
-    
-    support = null;
-    link2master = false;
-    
-    if (bRep != null)
+    void SaveSupports()
     {
-        bRep.SaveSupports();
+        if (blockloop)
+            return;
+
+        transientsupport = support;
+        transientlink2master = link2master;
+
+        support = null;
+        link2master = false;
+
+        if (bRep != null)
+        {
+            bRep.SaveSupports();
+        }
+
+        for (int i = 0; i < Size(); i++)
+        {
+            Object3D child = (Object3D) get(i);
+            if (child == null)
+                continue;
+            blockloop = true;
+            child.SaveSupports();
+            blockloop = false;
+        }
     }
-    
-    for (int i = 0; i < Size(); i++)
+
+    void RestoreSupports()
     {
-        Object3D child = (Object3D) get(i);
-        if (child == null)
-            continue;
+        if (blockloop)
+            return;
+
+        support = transientsupport;
+        link2master = transientlink2master;
+        transientsupport = null;
+        transientlink2master = false;
+
+        if (bRep != null)
+        {
+            bRep.RestoreSupports();
+        }
+
+        for (int i = 0; i < Size(); i++)
+        {
+            Object3D child = (Object3D) get(i);
+            if (child == null)
+                continue;
+            blockloop = true;
+            child.RestoreSupports();
+            blockloop = false;
+        }
+    }
+
+    void ExtractBigData(java.util.Hashtable<java.util.UUID, Object3D> hashtable)
+    {
+        Object3D o;
+        
+        if (hashtable.containsKey(GetUUID()))
+        {
+            o = hashtable.get(GetUUID());
+
+            Grafreed.Assert(this.bRep == o.bRep);
+            //if (this.bRep != null)
+            //    assert(this.bRep.support == o.transientrep);
+            if (this.support != null)
+                assert(this.support.bRep == o.transientrep);
+        }
+        else
+        {
+            o = new Object3D("copy of " + this.name);
+
+            hashtable.put(GetUUID(), o);
+        }
+
+        if (!blockloop)
+        {
+            blockloop = true;
+
+            for (int i=0; i<Size(); i++)
+            {
+                get(i).ExtractBigData(hashtable);
+            }
+
+            blockloop = false;
+        }
+        
+        ExtractBigData(o);
+    }
+
+    void ExtractBigData(Object3D o)
+    {
+        if (o.bRep != null)
+            Grafreed.Assert(o.bRep == this.bRep);
+        
+        o.bRep = this.bRep;
+// July 2019       if (this.bRep != null)
+//        {
+//            o.transientrep = this.bRep.support;
+//            o.bRep.support = null;
+//        }
+        o.selection = this.selection;
+        o.versions = this.versions;
+        o.versionindex = this.versionindex;
+        
+        if (this.support != null)
+        {
+            if (o.transientrep != null)
+                Grafreed.Assert(o.transientrep == this.support.bRep);
+
+            o.transientrep = this.support.bRep;
+            this.support.bRep = null;
+        }
+        
+        //    o.support = this.support;
+        //    o.fileparent = this.fileparent;
+        //    if (this.bRep != null)
+        //        o.bRep = this.bRep.support;
+        
+        this.bRep = null;
+    //    if (this.bRep != null)
+    //        this.bRep.support = null;
+    //    this.support = null;
+    //    this.fileparent = null;
+    }
+
+    void RestoreBigData(java.util.Hashtable<java.util.UUID, Object3D> hashtable)
+    {
+        if (!hashtable.containsKey(GetUUID()))
+            return;
+
+        Object3D o = hashtable.get(GetUUID());
+
+        RestoreBigData(o);
+
+        if (blockloop)
+            return;
+
         blockloop = true;
-        child.SaveSupports();
+
+        //hashtable.remove(GetUUID());
+
+        for (int i=0; i<Size(); i++)
+        {
+            get(i).RestoreBigData(hashtable);
+        }
+        
         blockloop = false;
     }
-}
 
-void RestoreSupports()
-{
-    if (blockloop)
-        return;
-
-    support = transientsupport;
-    link2master = transientlink2master;
-    transientsupport = null;
-    transientlink2master = false;
-    
-    if (bRep != null)
+    void RestoreBigData(Object3D o)
     {
-        bRep.RestoreSupports();
+        this.bRep = o.bRep;
+        if (this.support != null && o.transientrep != null)
+        {
+            this.support.bRep = o.transientrep;
+        }
+        
+        this.selection = o.selection;
+        
+        this.versions = o.versions;
+        this.versionindex = o.versionindex;
+// July 2019        if (this.bRep != null)
+//            this.bRep.support = o.transientrep;
+    //    this.support = o.support;
+    //    this.fileparent = o.fileparent;
     }
-    
-    for (int i = 0; i < Size(); i++)
-    {
-        Object3D child = (Object3D) get(i);
-        if (child == null)
-            continue;
-        blockloop = true;
-        child.RestoreSupports();
-        blockloop = false;
-    }
-}
 
 // MOCAP SUPPORT
     double tx,ty,tz,rx,ry,rz;
@@ -299,6 +426,8 @@
         }
         
     boolean live = false;
+    transient boolean keepdontselect;
+    boolean dontselect = false;
     boolean hide = false;
     boolean link2master = false; // performs reset support/master at each frame
     boolean marked = false; // animation node
@@ -430,16 +559,16 @@
     {
         Object3D copy = this;
         
-            Camera parentcam = CameraPane.theRenderer.manipCamera;
+            Camera parentcam = Globals.theRenderer.ManipCamera();
             
-            if (CameraPane.theRenderer.manipCamera == CameraPane.theRenderer.cameras[0])
+            if (Globals.theRenderer.ManipCamera() == Globals.theRenderer.Cameras()[0])
             {
-                parentcam = CameraPane.theRenderer.cameras[1];
+                parentcam = Globals.theRenderer.Cameras()[1];
             }
             
-            if (CameraPane.theRenderer.manipCamera == CameraPane.theRenderer.cameras[1])
+            if (Globals.theRenderer.ManipCamera() == Globals.theRenderer.Cameras()[1])
             {
-                parentcam = CameraPane.theRenderer.cameras[0];
+                parentcam = Globals.theRenderer.Cameras()[0];
             }
         
         if (this == parentcam)
@@ -447,7 +576,7 @@
             //assert(this instanceof Camera);
             
             for (int count = parentcam.GetTransformCount(); --count>=0;)
-                LA.xformPos(CameraPane.theRenderer.targetLookAt, parentcam.toParent, CameraPane.theRenderer.targetLookAt);
+                LA.xformPos(Globals.theRenderer.TargetLookAt(), parentcam.toParent, Globals.theRenderer.TargetLookAt());
         }
         
         copy.marked ^= true;
@@ -467,7 +596,7 @@
             //assert(this instanceof Camera);
             
             for (int count = parentcam.GetTransformCount(); --count>=0;)
-                LA.xformPos(CameraPane.theRenderer.targetLookAt, parentcam.fromParent, CameraPane.theRenderer.targetLookAt);
+                LA.xformPos(Globals.theRenderer.TargetLookAt(), parentcam.fromParent, Globals.theRenderer.TargetLookAt());
         }
 
         copy.Touch(); // display list issue
@@ -480,12 +609,14 @@
             toParent = LA.newMatrix();
             fromParent = LA.newMatrix();
         }
+        
         if (toParentMarked == null)
         {
             if (maxcount != 1)
             {
                 new Exception().printStackTrace();
             }
+            
             toParentMarked = LA.newMatrix();
             fromParentMarked = LA.newMatrix();
         }
@@ -602,7 +733,7 @@
             return;
         }
         
-        if (CameraPane.fromscript)
+        if (Globals.fromscript)
         {
             transformcount = 0;
             return;
@@ -760,7 +891,7 @@
     
     int GetTransformCount()
     {
-        // marde pour serialization de Texture
+        // patch pour serialization de Texture
         resetmaxcount();
         resettransformcount();
         resetstep();
@@ -773,7 +904,7 @@
         if (step == 0)
             step = 1;
         if (maxcount == 0)
-            maxcount = 2048; // 4;
+            maxcount = 128; // 2048; // 4;
 //        if (acceleration == 0)
 //            acceleration = 10;
         if (delay == 0) // serial
@@ -794,12 +925,12 @@
 //            factor = CameraPane.STEP;
 //        }
         
-        if (marked && CameraPane.isLIVE() && live &&
+        if (marked && Globals.isLIVE() && live &&
                 //TEMP21aug2018
-                CameraPane.drawMode == CameraPane.SHADOW &&
-                currentframe != CameraPane.framecount)
+                (Globals.DrawMode() == iCameraPane.SHADOW || !Globals.RENDERSHADOW || !Globals.COMPUTESHADOWWHENLIVE) &&
+                currentframe != Globals.framecount)
         {
-            currentframe = CameraPane.framecount;
+            currentframe = Globals.framecount;
             
 //            System.err.println("transformcount = " + transformcount);
 //            System.err.println("factor = " + factor);
@@ -808,7 +939,8 @@
             
             boolean changedir = random && Math.random() < 0.01; // && !link2master;
 
-            if (transformcount*factor > maxcount || (step == 1 && changedir))
+            if (transformcount*factor >= maxcount && (rewind || random) ||
+                    (step == 1 && changedir))
             {
                 countdown = 1;
                 delay = speedup?8:1;
@@ -880,6 +1012,7 @@
         if (material == null || material.multiply)
             return true;
         
+        // Transparent objects are dynamic because we have to sort the triangles.
         return material.opacity > 0.99;
     }
     
@@ -911,6 +1044,11 @@
         fromParent = null; // LA.newMatrix();
         bRep = null; // new BoundaryRep();
 
+        if (oname != null && oname.equals("LeftHand"))
+        {
+            name = oname;
+        }
+        
         /*
         float hue = (float)Math.random();
         Color col;
@@ -953,7 +1091,7 @@
 
     public Object clone()
     {
-        return GrafreeD.clone(this);
+        return Grafreed.clone(this);
     }
 
     Object3D copyExpand()
@@ -1275,6 +1413,7 @@
                     toParent = LA.newMatrix();
                     fromParent = LA.newMatrix();
                 }
+                
                 LA.matCopy(other.toParent, toParent);
                 LA.matCopy(other.fromParent, fromParent);
                 
@@ -1469,7 +1608,7 @@
             BoundaryRep.SEUIL = other.material.cameralight;
 
             // Set default to 0.1
-            BoundaryRep.SEUIL /= 2;
+            BoundaryRep.SEUIL /= 4; // 2;
             System.out.println("SEUIL = " + BoundaryRep.SEUIL);
         }
         
@@ -1728,7 +1867,7 @@
             Object3D o = new Object3D((clone?"Ge:":"Li:") + this.name);
             o.bRep = transientrep;
             if (clone)
-                o.bRep = (BoundaryRep) GrafreeD.clone(transientrep);
+                o.bRep = (BoundaryRep) Grafreed.clone(transientrep);
             o.CreateMaterial();
             o.SetAttributes(this, -1);
             //parent
@@ -1741,7 +1880,7 @@
             Object3D o = new Object3D((clone?"Ge:":"Li:") + this.name);
             o.bRep = bRep;
             if (clone)
-                o.bRep = (BoundaryRep) GrafreeD.clone(bRep);
+                o.bRep = (BoundaryRep) Grafreed.clone(bRep);
             o.CreateMaterial();
             //o.overwriteThis(this, -1);
             o.SetAttributes(this, -1);
@@ -1828,12 +1967,15 @@
             if (obj.name == null)
                 continue; // can't be a null one
             
+            // Try perfect match first.
             if (n.equals(obj.name))
             {
                 theobj = obj;
                 count++;
             }
         }
+        
+        // not needed: n = n.split(":")[0]; // Poser generates a count
         
     if (count != 1)
         for (int i=Size(); --i>=0;)
@@ -2293,12 +2435,17 @@
         }
          */
         }
+        else
+        {
+            //((ObjEditor)editWindow).SetupUI2(null);
+        }
     }
 
     void createEditWindow(GroupEditor callee, boolean newWindow) //, boolean root)
     {
         if (newWindow)
         {
+                new Exception().printStackTrace();
             System.exit(0);
             if (parent != null)
             {
@@ -2333,6 +2480,14 @@
         {
             editWindow.refreshContents();
         }
+        else
+        {
+            if (manipWindow != null)
+            {
+                manipWindow.refreshContents();
+            }
+        }
+                
     //if (parent != null)
     //parent.refreshEditWindow();
     }
@@ -2412,7 +2567,8 @@
     private static final int editSelf = 1;
     private static final int editChild = 2;
     
-    void drawEditHandles(ClickInfo info, int level)
+    void drawEditHandles(//ClickInfo info,
+            int level)
     {
         if (level == 0)
         {
@@ -2420,7 +2576,8 @@
                 return;
             
             Object3D selectee;
-            for (java.util.Enumeration e = selection.elements(); e.hasMoreElements(); selectee.drawEditHandles(info, level + 1))
+            for (java.util.Enumeration e = selection.elements(); e.hasMoreElements(); selectee.drawEditHandles(//info,
+                                                                                                        level + 1))
             {
                 selectee = (Object3D) e.nextElement();
             }
@@ -2428,19 +2585,22 @@
         } else
         {
             //super.
-                    drawEditHandles0(info, level + 1);
+                    drawEditHandles0(//info,
+                            level + 1);
         }
     }
 
-    boolean doEditClick(ClickInfo info, int level)
+    boolean doEditClick(//ClickInfo info,
+            int level)
     {
         doSomething = 0;
         if (level == 0)
         {
-            return doParentClick(info);
+            return doParentClick(); //info);
         }
         if (//super.
-                doEditClick0(info, level))
+                doEditClick0(//info,
+                    level))
         {
             doSomething = 1;
             return true;
@@ -2450,7 +2610,7 @@
         }
     }
 
-    boolean doParentClick(ClickInfo info)
+    boolean doParentClick() //ClickInfo info)
     {
         if (selection == null)
         {
@@ -2463,7 +2623,8 @@
         for (java.util.Enumeration e = selection.elements(); e.hasMoreElements();)
         {
             Object3D selectee = (Object3D) e.nextElement();
-            if (selectee.doEditClick(info, 1))
+            if (selectee.doEditClick(//info,
+                    1))
             {
                 childToDrag = selectee;
                 doSomething = 2;
@@ -2475,13 +2636,15 @@
         return retval;
     }
 
-    void doEditDrag(ClickInfo info)
+    void doEditDrag(//ClickInfo clickInfo,
+            boolean opposite)
     {
         switch (doSomething)
         {
             case 1: // '\001'
                 //super.
-                        doEditDrag0(info);
+                        doEditDrag0(//clickInfo,
+                                opposite);
                 break;
 
             case 2: // '\002'
@@ -2494,11 +2657,13 @@
                     {
                         //sel.hitSomething = childToDrag.hitSomething;
                         //childToDrag.doEditDrag(info);
-                        sel.doEditDrag(info);
+                        sel.doEditDrag(//clickInfo,
+                                opposite);
                     } else
                     {
                         //super.
-                                doEditDrag0(info);
+                                doEditDrag0(//clickInfo,
+                                        opposite);
                     }
                 }
                 break;
@@ -2516,6 +2681,9 @@
         {
             deselectAll();
         }
+        
+        new Exception().printStackTrace();
+        
         ClickInfo newInfo = new ClickInfo();
         newInfo.flags = info.flags;
         newInfo.bounds = info.bounds;
@@ -2608,6 +2776,18 @@
     void GenNormalsS(boolean crease)
     {
         selection.GenNormals(crease);
+//        for (int i=0; i<selection.size(); i++)
+//        {
+//            Object3D selectee = (Object3D) selection.elementAt(i);
+//            selectee.GenNormals(crease);
+//        }
+
+        //Touch();
+    }
+
+    void GenNormalsMeshS()
+    {
+        selection.GenNormalsMesh();
 //        for (int i=0; i<selection.size(); i++)
 //        {
 //            Object3D selectee = (Object3D) selection.elementAt(i);
@@ -2748,6 +2928,24 @@
             if (child == null)
                 continue;
             child.GenNormals(crease);
+//            Children().release(i);
+        }
+        blockloop = false;
+    }
+
+    void GenNormalsMesh()
+    {
+        if (blockloop)
+            return;
+        
+        blockloop = true;
+        GenNormalsMesh0();
+        for (int i = 0; i < Children().Size(); i++)
+        {
+            Object3D child = (Object3D) Children().get(i); // reserve(i);
+            if (child == null)
+                continue;
+            child.GenNormalsMesh();
 //            Children().release(i);
         }
         blockloop = false;
@@ -2905,7 +3103,8 @@
     {
         if (bRep != null)
         {
-            bRep.GenUV();
+            bRep.GenUV(); //1);
+            //bRep.UnfoldUV();
             Touch();
         }
     }
@@ -2919,11 +3118,20 @@
         }
     }
 
+    void GenNormalsMesh0()
+    {
+        if (bRep != null)
+        {
+            bRep.GenerateNormalsMesh();
+            Touch();
+        }
+    }
+
     void GenNormalsMINE0()
     {
         if (bRep != null)
         {
-            bRep.GenerateNormalsMINE();
+            bRep.MergeNormals(); //.GenerateNormalsMINE();
             Touch();
         }
     }
@@ -2980,6 +3188,33 @@
     blockloop = false;
 }
             
+    void TransformChildren()
+    {
+        if (toParent != null)
+        {
+            for (int i=Size(); --i>=0;)
+            {
+                Object3D v = get(i);
+
+                if (v.toParent == null)
+                {
+                    v.toParent = LA.newMatrix();
+                    v.fromParent = LA.newMatrix();
+                }
+
+//                LA.matConcat(v.toParent, toParent, v.toParent);
+//                LA.matConcat(fromParent, v.fromParent, v.fromParent);
+                LA.matConcat(toParent, v.toParent, v.toParent);
+                LA.matConcat(v.fromParent, fromParent, v.fromParent);
+            }
+
+            toParent = null; // LA.matIdentity(toParent);
+            fromParent = null; // LA.matIdentity(fromParent);
+
+            Touch();
+        }
+    }
+    
     void TransformGeometry()
     {
         Object3D obj = this;
@@ -3201,9 +3436,11 @@
         
         BoundaryRep sup = bRep.support;
         bRep.support = null;
-        BoundaryRep temprep = (BoundaryRep) GrafreeD.clone(bRep);
+        BoundaryRep temprep = (BoundaryRep) Grafreed.clone(bRep);
 //            bRep.SplitInTwo(onlyone); // thread...
-            temprep.SplitInTwo(reduction34, onlyone);
+        
+        while(temprep.SplitInTwo(reduction34, onlyone));
+        
             bRep = temprep;
             bRep.support = sup;
             Touch();
@@ -3340,7 +3577,8 @@
         if (blockloop)
             return;
         
-        if (marked || (bRep != null && material != null)) // borderline...
+        if (//marked || // does not make sense
+                (bRep != null || material != null)) // borderline...
             live = h;
         
         for (int i = 0; i < Size(); i++)
@@ -3361,7 +3599,8 @@
             return;
         
         //if (bRep != null)
-        if (marked || (bRep != null && material != null)) // borderline...
+        if (//marked || // does not make sense
+                (bRep != null || material != null)) // borderline...
             link2master = h;
         
         for (int i = 0; i < Size(); i++)
@@ -3381,7 +3620,8 @@
         if (blockloop)
             return;
         
-        if (marked || (bRep != null && material != null)) // borderline...
+        if (//marked || // does not make sense
+                (bRep != null || material != null)) // borderline...
             hide = h;
         
         for (int i = 0; i < Size(); i++)
@@ -3401,7 +3641,7 @@
         if (blockloop)
             return;
         
-        if (bRep != null && material != null) // borderline...
+        if (bRep != null || material != null) // borderline...
             marked = h;
         
         for (int i = 0; i < Size(); i++)
@@ -3411,6 +3651,46 @@
                 continue;
             blockloop = true;
             child.MarkLeaves(h);
+            blockloop = false;
+         //   release(i);
+        }
+    }
+    
+    void RewindLeaves(boolean h)
+    {
+        if (blockloop)
+            return;
+        
+        if (bRep != null || material != null) // borderline...
+            rewind = h;
+        
+        for (int i = 0; i < Size(); i++)
+        {
+            Object3D child = (Object3D) get(i); // reserve(i);
+            if (child == null)
+                continue;
+            blockloop = true;
+            child.RewindLeaves(h);
+            blockloop = false;
+         //   release(i);
+        }
+    }
+    
+    void RandomLeaves(boolean h)
+    {
+        if (blockloop)
+            return;
+        
+        if (bRep != null || material != null) // borderline...
+            random = h;
+        
+        for (int i = 0; i < Size(); i++)
+        {
+            Object3D child = (Object3D) get(i); // reserve(i);
+            if (child == null)
+                continue;
+            blockloop = true;
+            child.RandomLeaves(h);
             blockloop = false;
          //   release(i);
         }
@@ -3725,7 +4005,7 @@
             if (child == null)
                 continue;
             
-            if (GrafreeD.RENDERME > 0)
+            if (Grafreed.RENDERME > 0)
             {
                 if (child instanceof Merge)
                     ((Merge)child).renderme();
@@ -3876,7 +4156,7 @@
                 if (child == null)
                     continue;
                 
-                if (GrafreeD.RENDERME > 0)
+                if (Grafreed.RENDERME > 0)
                 {
                     if (child instanceof Merge)
                         ((Merge)child).renderme();
@@ -4071,7 +4351,7 @@
                 if (child == null)
                     continue;
                 
-                if (GrafreeD.RENDERME > 0)
+                if (Grafreed.RENDERME > 0)
                 {
                     if (child instanceof Merge)
                         ((Merge)child).renderme();
@@ -4184,6 +4464,55 @@
         {               
                 blockloop = true;
             get(i).RepairShadow();
+                blockloop = false;
+        }
+    }
+    
+    void RepairSOV()
+    {
+        if (blockloop)
+            return;
+
+        String texname = this.GetPigmentTexture();
+        
+        if (texname.startsWith("sov"))
+        {
+            String[] s = texname.split("/");
+
+            String[] sname = s[1].split("Color.pn");
+            
+            texname = sname[0];
+            
+            if (sname.length > 1)
+            {
+                texname += "Color.jpg";
+            }
+            
+            this.SetPigmentTexture("sov/" + texname);
+        }
+                
+        texname = this.GetBumpTexture();
+        
+        if (texname.startsWith("sov"))
+        {
+            String[] s = texname.split("/");
+
+            String[] sname = s[1].split("Bump.pn");
+            
+            texname = sname[0];
+            
+            if (sname.length > 1)
+            {
+                texname += "Bump.jpg";
+            }
+            
+            this.SetBumpTexture("sov/" + texname);
+        }
+                
+        for (int i=0; i<Size(); i++)
+        {               
+                blockloop = true;
+            get(i).RepairSOV();
                 blockloop = false;
         }
     }
@@ -4678,7 +5007,7 @@
 
     cTreePath SelectLeaf(int indexcount, boolean deselect)
     {
-        if (hide)
+        if (hide || dontselect)
             return null;
         
         if (count <= 0)
@@ -4702,9 +5031,17 @@
         }
     }
     
+    ObjEditor GetWindow()
+    {
+        if (editWindow != null)
+            return editWindow;
+        
+        return manipWindow;
+    }
+    
     cTreePath Select(int indexcount, boolean deselect)
     {
-        if (hide)
+        if (hide || dontselect)
             return null;
             
         if (count <= 0)
@@ -4738,10 +5075,11 @@
                 if (leaf != null)
                 {
                     cTreePath tp = new cTreePath(this, leaf);
-                    if (editWindow != null)
+                    ObjEditor window = GetWindow();
+                    if (window != null)
                     {
                         //System.out.println("editWindow = " + editWindow + " vs " + this);
-                        editWindow.Select(tp, deselect, true);
+                        window.Select(tp, deselect, true);
                     }
 
                     return tp;
@@ -4758,6 +5096,7 @@
 
             if (child == null)
                 continue;
+            
             if (child.HasTransparency() && child.size() != 0)
             {
                 cTreePath leaf = child.Select(indexcount, deselect);
@@ -4767,9 +5106,10 @@
                 if (leaf != null)
                 {
                     cTreePath tp = new cTreePath(this, leaf);
-                    if (editWindow != null)
+                    ObjEditor window = GetWindow();
+                    if (window != null)
                     {
-                        editWindow.Select(tp, deselect, true);
+                        window.Select(tp, deselect, true);
                     }
 
                     return tp;
@@ -4854,7 +5194,7 @@
         return globalTransform;
     }
 
-    void PreprocessOcclusion(CameraPane cp)
+    void PreprocessOcclusion(iCameraPane cp)
     {
         /*
         if (AOdone)
@@ -5001,7 +5341,8 @@
         } else //
         if (editWindow != null)
         {
-            editWindow.cameraView.lighttouched = true;
+            //editWindow.cameraView.lighttouched = true;
+            Globals.lighttouched = true;
         }
     }
 
@@ -5093,6 +5434,51 @@
         blockloop = false;
     }
 
+    void ResetSelectable()
+    {
+        if (blockloop)
+            return;
+        
+        blockloop = true;
+
+        keepdontselect = dontselect;
+        dontselect = true;
+        
+        Object3D child;
+        int nb = Size();
+        for (int i = 0; i < nb; i++)
+        {
+            child = (Object3D) get(i);
+            if (child == null)
+                continue;
+            child.ResetSelectable();
+        }
+        
+        blockloop = false;
+    }
+
+    void RestoreSelectable()
+    {
+        if (blockloop)
+            return;
+        
+        blockloop = true;
+
+        dontselect = keepdontselect;
+        
+        Object3D child;
+        int nb = Size();
+        for (int i = 0; i < nb; i++)
+        {
+            child = (Object3D) get(i);
+            if (child == null)
+                continue;
+            child.RestoreSelectable();
+        }
+        
+        blockloop = false;
+    }
+
     boolean IsSelected()
     {
         if (parent == null)
@@ -5155,10 +5541,34 @@
         
    //     System.out.println("Fullname = " + fullname);
         
-        if (fullname.name.indexOf(":") == -1)
-            return fullname.name;
+        // Does not work on Windows due to C:
+//        if (fullname.name.indexOf(":") == -1)
+//            return fullname.name;
+//        
+//        return fullname.name.substring(0,fullname.name.indexOf(":"));
         
-        return fullname.name.substring(0,fullname.name.indexOf(":"));
+        String[] split = fullname.name.split(":");
+        
+        if (split.length == 0)
+        {
+                return "";
+        }
+        
+        if (split.length <= 2)
+        {
+                if (fullname.name.endsWith(":"))
+                {
+                        // Windows
+                        return fullname.name.substring(0, fullname.name.length()-1);
+                }
+                
+                return split[0];
+        }
+        
+        // Windows
+        assert(split.length == 4);
+        
+        return split[0] + ":" + split[1];
     }
     
     static String GetBump(cTexture fullname)
@@ -5167,10 +5577,38 @@
             return "";
         
   //      System.out.println("Fullname = " + fullname);
-        if (fullname.name.indexOf(":") == -1)
-            return "";
-
-        return fullname.name.substring(fullname.name.indexOf(":")+1,fullname.name.length());
+        // Does not work on Windows due to C:
+//        if (fullname.name.indexOf(":") == -1)
+//            return "";
+//
+//        return fullname.name.substring(fullname.name.indexOf(":")+1,fullname.name.length());
+        String[] split = fullname.name.split(":");
+        
+        if (split.length == 0)
+        {
+                return "";
+        }
+        
+        if (split.length == 1)
+        {
+                return "";
+        }
+        
+        if (split.length == 2)
+        {
+                if (fullname.name.endsWith(":"))
+                {
+                        // Windows
+                        return "";
+                }
+                
+                return split[1];
+        }
+        
+        // Windows
+        assert(split.length == 4);
+        
+        return split[2] + ":" + split[3];
     }
     
     String GetPigmentTexture()
@@ -5244,7 +5682,7 @@
         System.out.print("; textures = " + textures);
         System.out.println("; usedtextures = " + usedtextures);
         
-        if (GetTextures() == null)
+        if (GetTextures() == null) // What is that??
             GetTextures().name = ":";
         
         String texname = tex;
@@ -5275,6 +5713,43 @@
             child.ResetPigmentTexture();
             blockloop = false;
         }
+    }
+    
+    UUID GetUUID()
+    {
+        if (uuid == null)
+        {
+            // Serial
+            uuid = UUID.randomUUID();
+        }
+        
+        return uuid;
+    }
+    
+    Object3D GetObject(UUID uid)
+    {
+        if (blockloop)
+            return null;
+        
+        if (GetUUID().equals(uid))
+            return this;
+        
+        int nb = Size();
+        for (int i = 0; i < nb; i++)
+        {
+            Object3D child = (Object3D) get(i);
+
+            if (child == null)
+                continue;
+
+            blockloop = true;
+            Object3D obj = child.GetObject(uid);
+            blockloop = false;
+            if (obj != null)
+                return obj;
+        }
+        
+        return null;
     }
     
     void SetBumpTexture(String tex)
@@ -5313,25 +5788,65 @@
         }
     }
     
-    void draw(CameraPane display, Object3D /*Composite*/ root, boolean selected, boolean blocked)
+    void EmbedTextures(boolean embed)
+    {
+        if (blockloop)
+            return;
+        
+        //if (GetTextures() != null)
+        if (embed)
+            CameraPane.EmbedTextures(GetTextures());
+        else
+        {
+            GetTextures().pigmentdata = null;
+            GetTextures().bumpdata = null;
+            GetTextures().pw = 0;
+            GetTextures().ph = 0;
+            GetTextures().bw = 0;
+            GetTextures().bh = 0;
+        }
+        
+        int nb = Size();
+        for (int i = 0; i < nb; i++)
+        {
+            Object3D child = (Object3D) get(i);
+
+            if (child == null)
+                continue;
+
+            blockloop = true;
+            child.EmbedTextures(embed);
+            blockloop = false;
+        }
+    }
+    
+    void draw(iCameraPane display, Object3D /*Composite*/ root, boolean selected, boolean blocked)
     {
         Draw(display, root, selected, blocked);
     }
     
-    static cMaterial[] materialstack = new cMaterial[65536];
-    static boolean[] selectedstack = new boolean[65536];
-    static int materialdepth = 0;
-
     boolean NeedSupport()
     {
         return
-                CameraPane.SUPPORT && !CameraPane.movingcamera && link2master && /*live &&*/ support != null
+                CameraPane.SUPPORT && (!CameraPane.movingcamera || (!Globals.FREEZEONMOVE && Globals.isLIVE())) && link2master && /*live &&*/ support != null
                  // PROBLEM with CROWD!!
-                    && (CameraPane.drawMode == CameraPane.SHADOW || CameraPane.CROWD);
+                    && (Globals.DrawMode() == iCameraPane.SHADOW || !Globals.RENDERSHADOW || Globals.CROWD);
     }
     
+    static boolean DEBUG_SELECTION = false;
     
-    void Draw(CameraPane display, Object3D /*Composite*/ root, boolean selected, boolean blocked)
+    boolean IsLive()
+    {
+        if (live)
+            return true;
+        
+        if (parent == null)
+            return false;
+        
+        return parent.IsLive();
+    }
+    
+    void Draw(iCameraPane display, Object3D /*Composite*/ root, boolean selected, boolean blocked)
     {
         Invariants(); // june 2013
             
@@ -5340,8 +5855,8 @@
         //    System.err.println("Draw " + this + " Frame # " + ((Mocap)((Merge)support).object).frame);
         }
         
-        if (display.drawMode == CameraPane.SELECTION &&
-                hide)
+        if (display.DrawMode() == iCameraPane.SELECTION &&
+                (hide || dontselect))
             return;
 
         if (name != null && name.contains("sclera"))
@@ -5359,7 +5874,7 @@
         if (this instanceof Checker)
             return;
         
-        if (display.drawMode == display.SHADOW && PASSTEST)
+        if (display.DrawMode() == display.SHADOW && PASSTEST)
             return;
         
         if (count <= 0)
@@ -5367,13 +5882,13 @@
             return;
         }
 
-        if ((//display.drawMode == CameraPane.SHADOW ||
-                display.drawMode == CameraPane.SELECTION || CameraPane.DEBUG_SELECTION) && HasTransparency())
+        if ((//display.DrawMode() == CameraPane.SHADOW ||
+                display.DrawMode() == iCameraPane.SELECTION || display.IsDebugSelection()) && HasTransparency())
         {
             return;
         }
         
-        javax.media.opengl.GL gl = display.GetGL();
+        //javax.media.opengl.GL gl = display.GetGL();
 
         /*
         if (touched)
@@ -5392,7 +5907,7 @@
             support = support;
         
         //boolean usecalllists = IsStatic() && GetBRep() != null && (!CameraPane.SUPPORT || support == null || !link2master); // !(this instanceof cSpring) && !(this instanceof BezierPatch);
-        boolean usecalllists = false; // IsStatic() && GetBRep() != null && (!CameraPane.SUPPORT || support == null) && !link2master; // !(this instanceof cSpring) && !(this instanceof BezierPatch);
+        boolean usecalllists = false; //!IsLive(); // IsStatic() && GetBRep() != null && (!CameraPane.SUPPORT || support == null) && !link2master; // !(this instanceof cSpring) && !(this instanceof BezierPatch);
         
         if (!usecalllists && bRep != null && bRep.displaylist > 0)
         {
@@ -5409,15 +5924,17 @@
 
         boolean compiled = false;
 
-        boolean selectmode = display.drawMode == display.SELECTION || CameraPane.DEBUG_SELECTION;
+        boolean selectmode = display.DrawMode() == display.SELECTION || display.IsDebugSelection();
         
-        if (!selectmode && //display.drawMode != display.SELECTION &&
-                (touched || (bRep != null && bRep.displaylist <= 0)))
+        if (!selectmode && //display.DrawMode() != display.SELECTION &&
+                //(touched || (bRep != null && bRep.displaylist <= 0)))
+                (Globals.isLIVE() && Globals.COMPUTESHADOWWHENLIVE || touched && Globals.COMPUTESHADOWWHENLIVE)) // || (bRep != null && bRep.displaylist <= 0)))
         {
-            display.lighttouched = true;
+            Globals.lighttouched = true;
         } // all panes...
-        //if (usecalllists && display.drawMode != display.SELECTION && display.drawMode != display.SHADOW &&
-        if (bRep != null && usecalllists && !selectmode && // june 2013 display.drawMode != display.SHADOW &&
+        
+        //if (usecalllists && display.DrawMode() != display.SELECTION && display.DrawMode() != display.SHADOW &&
+        if (bRep != null && usecalllists && !selectmode && // june 2013 display.DrawMode() != display.SHADOW &&
                 (touched || (bRep != null && bRep.displaylist <= 0)))
         {
             if (!(this instanceof Composite))
@@ -5425,7 +5942,7 @@
             //if (displaylist == -1 && usecalllists)
             if ((bRep != null && bRep.displaylist <= 0) && usecalllists) // june 2013
             {
-                bRep.displaylist = gl.glGenLists(1);
+                bRep.displaylist = display.GenList();
                 assert(bRep.displaylist != 0);
 //        System.err.println("glGenLists: " + bRep.displaylist + " for " + this);
                 //System.out.println("\tgen list " + list);
@@ -5437,18 +5954,20 @@
             if (usecalllists)
             {
 //            System.err.println("new list " + bRep.displaylist + " for " + this);
-                gl.glNewList(bRep.displaylist, gl.GL_COMPILE); //_AND_EXECUTE);
+                display.NewList(bRep.displaylist);
             }
+            
             CallList(display, root, selected, blocked);
+            
           //  compiled = true;
             if (usecalllists)
             {
 //            System.err.println("end list " + bRep.displaylist + " for " + this);
-                gl.glEndList();
+                display.EndList();
             }
             //gl.glDrawBuffer(gl.GL_BACK);
             // XXX touched = false;
-            display.lighttouched = true; // all panes...
+            Globals.lighttouched = true; // all panes...
         }
 
         touched = GetBRep() == null; // this instanceof Composite || this instanceof FileObject; // false;
@@ -5487,12 +6006,12 @@
         
         // frustum culling
         if (CameraPane.FRUSTUM && !blocked && !IsInfinite() && GetBRep() != null // && GetBRep().VertexCount() != 1260 // default grid
-                && display.drawMode != CameraPane.SELECTION)
+                && display.DrawMode() != iCameraPane.SELECTION)
         {
-            if (display.drawMode == CameraPane.SHADOW)
+            if (display.DrawMode() == iCameraPane.SHADOW)
             {
                 if (!link2master // tricky to cull in shadow mode.
-                         && GetBRep().FrustumCull(this, gl, display.lightCamera, true))
+                         && GetBRep().FrustumCull(this, null, display.LightCamera(), true))
                 {
                     //System.out.print("CULLED");
                     culled = true;
@@ -5500,7 +6019,7 @@
             }
             else
                 //GetBRep().getBounds(v0, v1, this);
-                if (GetBRep().FrustumCull(this, gl, display.renderCamera, false))
+                if (GetBRep().FrustumCull(this, null, display.RenderCamera(), false))
                     culled = true;
             
 //            LA.xformPos(v0, display.renderCamera.toScreen, v0);
@@ -5536,11 +6055,12 @@
 
 
         if (!culled)
-        if (display.drawMode == display.SELECTION || CameraPane.DEBUG_SELECTION)
+        if (display.DrawMode() == display.SELECTION || display.IsDebugSelection())
         {
             if (GetBRep() != null)
             {
-                CameraPane.NextIndex(this, gl);
+                display.NextIndex();
+                
                 // vertex color conflict : gl.glCallList(list);
                 DrawNode(display, root, selected);
                 if (this instanceof BezierPatch)
@@ -5562,55 +6082,7 @@
             color[2] /= 2;
             gl.glMaterialfv(gl.GL_BACK, gl.GL_AMBIENT_AND_DIFFUSE, color, 0);
              */
-            if (material != null)
-            {
-                materialstack[materialdepth] = material;
-                selectedstack[materialdepth] = selected;
-                cStatic.objectstack[materialdepth++] = this;
-                //System.out.println("material " + material);
-                //Applet3D.tracein(this, selected);
-                display.vector2buffer = projectedVertices;
-                if (this instanceof Camera)
-                {
-                    display.options1[0] = material.shift;
-                //System.out.println("shift " + material.shift);
-                    display.options1[1] = material.lightarea;
-                    display.options1[2] = material.shadowbias;
-                    display.options1[3] = material.aniso;
-                    display.options1[4] = material.anisoV;
-                    display.options2[0] = material.opacity;
-                    display.options2[1] = material.diffuse;
-                    display.options2[2] = material.factor;
-
-                    cColor.HSBtoRGB(material.color, material.modulation, 1, display.options3);
-                    display.options4[0] = material.cameralight/0.2f;
-                    display.options4[1] = material.subsurface;
-                    display.options4[2] = material.sheen;
-                    
-                 //   if (display.CURRENTANTIALIAS > 0)
-                 //       display.options3[3] /= 4;
-
-                    /*
-                    System.out.println("Focus = " + display.options1[0]);
-                    System.out.println("Aperture = " + display.options1[1]);
-                    System.out.println("ShadowBlur = " + display.options1[2]);
-                    System.out.println("Antialiasing = " + display.options1[3]);
-                    System.out.println("Fog = " + display.options2[0]);
-                    System.out.println("Intensity = " + display.options2[1]);
-                    System.out.println("Elevation = " + display.options2[2]);
-                /**/
-                } else
-                {
-                    material.Draw(display, selected);
-                }
-            } else
-            {
-                if (selected && CameraPane.flash)
-                {
-                    display.modelParams4[1] = 100;
-                    gl.glProgramEnvParameter4fvARB(gl.GL_FRAGMENT_PROGRAM_ARB, 4, display.modelParams4, 0);
-                }
-            }
+                display.PushMaterial(this, selected);
 
             //System.out.println("call list " + list);
             //System.out.println();
@@ -5629,7 +6101,28 @@
         tex = GetTextures();
     }
 
-    display.BindTextures(tex, texres);
+    boolean failedPigment = false;
+    boolean failedBump = false;
+    
+    try
+    {
+        display.BindPigmentTexture(tex, texres);
+    }
+    catch (Exception e)
+    {
+        System.err.println("FAILED: " + this);
+        failedPigment = true;
+    }
+           
+    try
+    {
+        display.BindBumpTexture(tex, texres);
+    }
+    catch (Exception e)
+    {
+        //System.err.println("FAILED: " + this);
+        failedBump = true;
+    }
            
             if (!compiled)
             {
@@ -5645,30 +6138,19 @@
                         
 //        System.err.println("glCallList: " + bRep.displaylist + " for " + this);
                         assert(bRep.displaylist != 0);
-                        gl.glCallList(bRep.displaylist);
+                        display.CallList(bRep.displaylist);
 // june 2013            drawSelf(display, root, selected);
                     }
                 }
             }
 
-    display.ReleaseTextures(tex);
-     
-            //if (parent != null && parent.GetMaterial() != null)
-            //	parent.GetMaterial().Draw(display, parent.IsSelected(this));
-            if (material != null)
-            {
-                materialdepth -= 1;
-                if (materialdepth > 0)
-                {
-                    display.vector2buffer = cStatic.objectstack[materialdepth - 1].projectedVertices;
-                    materialstack[materialdepth - 1].Draw(display, selectedstack[materialdepth - 1]);
-                }
-            //Applet3D.traceout("selected ", (stackdepth>0)?selectedstack[stackdepth-1]:"???");
-            } else if (selected && CameraPane.flash && GetMaterial() != null)
-            {
-                display.modelParams4[1] = GetMaterial().cameralight;
-                gl.glProgramEnvParameter4fvARB(gl.GL_FRAGMENT_PROGRAM_ARB, 4, display.modelParams4, 0);
-            }
+    if (!failedBump)
+        display.ReleaseBumpTexture(tex);
+
+    if (!failedPigment)
+        display.ReleasePigmentTexture(tex);
+
+    display.PopMaterial(this, selected);
         }
 
         if (this instanceof Texture || this instanceof TextureNode)
@@ -5710,7 +6192,7 @@
 //            resetMasterNode();
     }
 
-    void CallList(CameraPane display, Object3D /*Composite*/ root, boolean selected, boolean blocked)
+    void CallList(iCameraPane display, Object3D /*Composite*/ root, boolean selected, boolean blocked)
     {
         if (GetBRep() == null)
         {
@@ -5793,8 +6275,11 @@
     boolean flipV = false; // true;
     int texres = 0; // 0 = low, 1 = normal, 2 = high res texture
     
-    void drawSelf(CameraPane display, Object3D /*Composite*/ root, boolean selected, boolean blocked)
+    void drawSelf(iCameraPane display, Object3D /*Composite*/ root, boolean selected, boolean blocked)
     {
+        if (display.DrawMode() == iCameraPane.SELECTION && dontselect)
+            return;
+        
         if (hide)
             return;
         // shadow optimisation
@@ -5852,16 +6337,7 @@
 //  // ???????????????????????????          Touch();
 //        }
 
-        if (material != null)
-        {
-            materialstack[materialdepth] = material;
-            selectedstack[materialdepth] = selected;
-            cStatic.objectstack[materialdepth++] = this;
-            //System.out.println("material " + material);
-            //Applet3D.tracein("selected ", selected);
-            display.vector2buffer = projectedVertices;
-            material.Draw(display, selected);
-        }
+display.PushMaterial2(this, selected);
 
         Object3D child;
         boolean sel;
@@ -5913,19 +6389,7 @@
          */
         //depth += 1;
 
-        if (material != null)
-        {
-            materialdepth -= 1;
-            if (materialdepth > 0)
-            {
-                display.vector2buffer = cStatic.objectstack[materialdepth - 1].projectedVertices;
-                materialstack[materialdepth - 1].Draw(display, selectedstack[materialdepth - 1]);
-            }
-        //Applet3D.traceout("selected ", (stackdepth>0)?selectedstack[stackdepth-1]:"???");
-        //else
-        //material.Draw(display, false);
-        }
-        
+display.PopMaterial2(this);        
 /*
         display.ReleaseTextures(tex);
  */
@@ -5936,10 +6400,13 @@
 
     //static cVector min,max;
     
-    void DrawNode(CameraPane display, Object3D /*Composite*/ root, boolean selected)
+    void DrawNode(iCameraPane display, Object3D /*Composite*/ root, boolean selected)
     {
-        if (display.drawMode == display.SHADOW && projectedVertices != null && projectedVertices.length > 2 && projectedVertices[2].y >= 10000)
+        if (display.DrawMode() == display.SHADOW && projectedVertices != null && projectedVertices.length > 2 && projectedVertices[2].y >= 10000)
             return; // no shadow for transparent objects
+        
+        if (display.DrawMode() == iCameraPane.SELECTION && dontselect)
+            return;
         
         if (hide)
             return;
@@ -5981,9 +6448,10 @@
             return;
         }
         
+        //bRep.GenUV(1/material.diffuseness);
 //        bRep.lock = true;
 
-        javax.media.opengl.GL gl = display.GetGL();
+        //javax.media.opengl.GL gl = display.GetGL();
 
         if (CameraPane.BOXMODE && !selected) // || CameraPane.movingcamera)
         {
@@ -6000,23 +6468,7 @@
 
                 bRep.getMinMax(min, max, 100);
                 
-                gl.glBegin(gl.GL_LINES);
-                
-                gl.glVertex3d(min.x, min.y, min.z);
-                gl.glVertex3d(min.x, min.y, max.z);
-                gl.glVertex3d(min.x, min.y, min.z);
-                gl.glVertex3d(min.x, max.y, min.z);
-                gl.glVertex3d(min.x, min.y, min.z);
-                gl.glVertex3d(max.x, min.y, min.z);
-                
-                gl.glVertex3d(max.x, max.y, max.z);
-                gl.glVertex3d(min.x, max.y, max.z);
-                gl.glVertex3d(max.x, max.y, max.z);
-                gl.glVertex3d(max.x, min.y, max.z);
-                gl.glVertex3d(max.x, max.y, max.z);
-                gl.glVertex3d(max.x, max.y, min.z);
-                
-                gl.glEnd();
+                display.DrawBox(min, max);
                 
                 return;
             }
@@ -6060,7 +6512,7 @@
         {
             //throw new Error();
 
-            boolean selectmode = display.drawMode == display.SELECTION || CameraPane.DEBUG_SELECTION;
+            boolean selectmode = display.DrawMode() == display.SELECTION || display.IsDebugSelection();
 
             int[] strips = bRep.getRawIndices();
 
@@ -6070,178 +6522,19 @@
                 new Exception().printStackTrace();
                 return;
             }
-
-            // TRIANGLE STRIP ARRAY
-            if (bRep.trimmed)
+            
+            if (dontselect)
             {
-                float[] v = bRep.getRawVertices();
-                float[] n = bRep.getRawNormals();
-                float[] c = bRep.getRawColors();
-                float[] uv = bRep.getRawUVMap();
-
-                int count2 = 0;
-                int count3 = 0;
-
-                if (n.length > 0)
-                {
-                    for (int i = 0; i < strips.length; i++)
-                    {
-                        gl.glBegin(gl.GL_TRIANGLE_STRIP);
-
-                        /*
-                boolean locked = false;
-                float eps = 0.1f;
-                boolean wrap = CameraPane.UVWRAP; // true; // UV WRAP TEXTURE ISSUE: true = artifacts, false = nice
-
-                int dot = 0;
-
-                if ((dot&1) == 0)
-                    dot |= (Math.abs(qv.s - pv.s) < eps && Math.abs(qv.t - pv.t) < eps) ? 3 : 1;
-
-                if (wrap || (dot&2) != 0) // Math.abs(qv.s - pv.s) < eps && Math.abs(qv.t - pv.t) < eps)
-                    gl.glTexCoord2f((float) qv.s, (float) qv.t);
-                else
-                {
-                    locked = true;
-                    gl.glTexCoord2f((float) pv.s, (float) pv.t);
-                }
-                //System.out.println("vertexq = " + qv.x + ", " + qv.y + ", " + qv.z);
-                gl.glVertex3f((float) qv.x, (float) qv.y, (float) qv.z);
-                if (hasnorm)
-                {
-                    //System.out.println("normalr = " + rv.norm.x + ", " + rv.norm.y + ", " + rv.norm.z);
-                    gl.glNormal3f((float) rv.norm.x, (float) rv.norm.y, (float) rv.norm.z);
-                }
-
-                if ((dot&4) == 0)
-                    dot |= (Math.abs(rv.s - pv.s) < eps && Math.abs(rv.t - pv.t) < eps) ? 12 : 4;
-
-                if (wrap || !locked && (dot&8) != 0)
-                    gl.glTexCoord2f((float) rv.s, (float) rv.t);
-                else
-                    gl.glTexCoord2f((float) pv.s, (float) pv.t);
-
-                f.dot = dot;
-                */
-
-                        if (!selectmode)
-                        {
-                            if (n[count3] != 0 || n[count3 + 1] != 0 || n[count3 + 2] != 0)
-                            {
-                                gl.glNormal3f(n[count3], n[count3 + 1], n[count3 + 2]);
-                            } else
-                            {
-                                gl.glNormal3f(0, 0, 1);
-                            }
-
-                            if (c != null)
-                            //System.out.println("glcolor = " + c[count3] + ", " + c[count3+1] + ", " + c[count3+2]);
-                            {
-                                gl.glColor4f(c[count3/3], c[count3/3 /* + 1*/], c[count3/3 /* + 2*/], 1);
-                            }
-                        }
-                        if (flipV)
-                            gl.glTexCoord2f(uv[count2], 1-uv[count2 + 1]);
-                        else
-                            gl.glTexCoord2f(uv[count2], uv[count2 + 1]);
-                        //System.out.println("vertex1 = " + v[count3] + ", " + v[count3+1] + ", " + v[count3+2]);
-                        gl.glVertex3f(v[count3], v[count3 + 1], v[count3 + 2]);
-
-                        count2 += 2;
-                        count3 += 3;
-                        if (!selectmode)
-                        {
-                            if (n[count3] != 0 || n[count3 + 1] != 0 || n[count3 + 2] != 0)
-                            {
-                                gl.glNormal3f(n[count3], n[count3 + 1], n[count3 + 2]);
-                            } else
-                            {
-                                gl.glNormal3f(0, 0, 1);
-                            }
-                            if (c != null)
-                            {
-                                gl.glColor4f(c[count3/3], c[count3/3 /* + 1*/], c[count3/3 /* + 2*/], 1);
-                            }
-                        }
-                        if (flipV)
-                            gl.glTexCoord2f(uv[count2], 1-uv[count2 + 1]);
-                        else
-                            gl.glTexCoord2f(uv[count2], uv[count2 + 1]);
-                        //System.out.println("vertex2 = " + v[count3] + ", " + v[count3+1] + ", " + v[count3+2]);
-                        gl.glVertex3f(v[count3], v[count3 + 1], v[count3 + 2]);
-
-                        count2 += 2;
-                        count3 += 3;
-                        for (int j = 0; j < strips[i] - 2; j++)
-                        {
-                            //gl.glTexCoord2d(...);
-                            if (!selectmode)
-                            {
-                                if (n[count3] != 0 || n[count3 + 1] != 0 || n[count3 + 2] != 0)
-                                {
-                                    gl.glNormal3f(n[count3], n[count3 + 1], n[count3 + 2]);
-                                } else
-                                {
-                                    gl.glNormal3f(0, 0, 1);
-                                }
-                                if (c != null)
-                                {
-                                    gl.glColor4f(c[count3/3], c[count3/3 /* + 1*/], c[count3/3 /* + 2*/], 1);
-                                }
-                            }
-
-                            if (flipV)
-                                gl.glTexCoord2f(uv[count2], 1-uv[count2 + 1]);
-                            else
-                                gl.glTexCoord2f(uv[count2], uv[count2 + 1]);
-                            //System.out.println("coord3 = " + uv[count2] + ", " + uv[count2+1]);
-                            gl.glVertex3f(v[count3], v[count3 + 1], v[count3 + 2]);
-                            count2 += 2;
-                            count3 += 3;
-                        }
-
-                        gl.glEnd();
-                    }
-                }
-
-                assert count3 == v.length;
+                //bRep.GenerateNormalsMINE();
             }
-            else // !trimmed
-            {
-                int count = 0;
-                for (int i = 0; i < strips.length; i++)
-                {
-                    gl.glBegin(gl.GL_TRIANGLE_STRIP);
-                    
-                    Vertex p = bRep.GetVertex(bRep.indices[count++]);
-                    Vertex q = bRep.GetVertex(bRep.indices[count++]);
-                    
-                    drawVertex(gl, p, selectmode);
-                    drawVertex(gl, q, selectmode);
-                    
-                    for (int j = 0; j < strips[i] - 2; j++)
-                    {
-                        Vertex r = bRep.GetVertex(bRep.indices[count++]);
-
-//                        if (j%2 == 0)
-//                            drawFace(p, q, r, display, null);
-//                        else
-//                            drawFace(p, r, q, display, null);
-                        
-//                        p = q;
-//                        q = r;
-                        drawVertex(gl, r, selectmode);
-                    }
-
-                    gl.glEnd();
-                }
-            }
+            
+            display.DrawGeometry(bRep, flipV, selectmode);
         } else // catch (Error e)
         {
             // TRIANGLE ARRAY
             if (IsOpaque()) // Static())
             {
-                gl.glBegin(gl.GL_TRIANGLES);
+                    display.StartTriangles();
                 int facecount = bRep.FaceCount();
                 for (int i = 0; i < facecount; i++)
                 {
@@ -6304,9 +6597,9 @@
 //               //         r.norm.dot(v3) > -0.5)
 //               //         continue;
 
-                    drawFace(p, q, r, display, face);
+                    display.DrawFace(this, p, q, r, face);
                 }
-                gl.glEnd();
+                    display.EndTriangles();
             }
             else
             {
@@ -6335,8 +6628,8 @@
                 //System.out.println("SORT");
                 
                 java.util.Arrays.sort(facescompare);
-                
-                gl.glBegin(gl.GL_TRIANGLES);
+
+                display.StartTriangles();
                 for (int i = 0; i < facecount; i++)
                 {
                     Face face = bRep.GetFace(facescompare[i].index);
@@ -6348,13 +6641,14 @@
                     Vertex q = bRep.GetVertex(face.q);
                     Vertex r = bRep.GetVertex(face.r);
 
-                    drawFace(p, q, r, display, face);
+                    display.DrawFace(this, p, q, r, face);
                 }
-                gl.glEnd();
+                display.EndTriangles();
             }
             
             if (false) // live && support != null && support.bRep != null) // debug weights
             {
+                    /*
                 gl.glDisable(gl.GL_LIGHTING);
                 float[] colorV = new float[3];
                 
@@ -6433,6 +6727,7 @@
 //                        gl.glEnd();
                     }
                 }
+                     */
             }
         }
 
@@ -6477,7 +6772,7 @@
                 center.add(r);
                 center.mul(1.0/3);
                 
-                center.sub(CameraPane.theRenderer.eyeCamera.location);
+                center.sub(Globals.theRenderer.EyeCamera().location);
                 
                 distance = center.dot(center);
             }
@@ -6488,390 +6783,11 @@
     
     transient FaceCompare[] facescompare = null;
     
-    void SetColor(CameraPane display, Vertex p0)
-    {
-        if (display.RENDERPROGRAM == 0)
-        {
-            float r = 0;
-            if (bRep != null)
-            {
-                if (bRep.stripified)
-                {
-                    r = 1;
-                }
-            }
-            float g = 0;
-            if (bRep != null)
-            {
-                if (bRep.trimmed)
-                {
-                    g = 1;
-                }
-            }
-            float b = 0;
-            if (support != null && link2master)
-            {
-                b = 1;
-            }
-            display.GetGL().glColor3f(r*p0.AO, g*p0.AO, b*p0.AO);
-            return;
-        }
-        
-        if (display.drawMode != CameraPane.SHADOW)
-            return;
-        
-        javax.media.opengl.GL gl = display.GetGL();
-//        if (true) return;
-//        float ao = p.AO;
-//        
-//    //    if (ao == 0 && !bRep.AOdone) // transient problem!
-//    //        ao = 1;
-//        
-//        gl.glColor4f(ao, ao, ao, 1);
-        
-//        CameraPane.selectedpoint.
-//            getAverage(cStatic.point1, true);
-        if (CameraPane.pointflow == null) // !random) // live)
-        {
-            return;
-        }
-        
-        cStatic.point1.set(0,0,0);
-        LA.xformPos(cStatic.point1, CameraPane.selectedpoint.toParent, cStatic.point1);
-
-        cStatic.point1.sub(p0);
-
-
-//        if (marked && (p0.vertexlinks == null || support == null || support.bRep == null)) // no position delta?
-//        {
-//            return;
-//        }
-        
-        //if (true)
-        if (cStatic.point1.dot(cStatic.point1) > 0.000001)
-        {
-            return;
-        }
-        
-        float[] colorV = new float[3];
-        
-        if (false) // marked)
-        {
-            // debug rigging weights
-            for (int object = 0; object < p0.vertexlinks.length; object++)
-            {
-                float weight = p0.weights[object] / p0.totalweight;
-
-    //            if (weight < 0.1)
-    //            {
-    //                assert(weight == 0);
-    //                continue;
-    //            }
-
-                if (p0.vertexlinks[object] == -1)
-                    continue;
-
-                Vertex q = support.bRep.GetVertex(p0.vertexlinks[object]);
-
-                int color = //1 << object; //
-                            //p.vertexlinks.length;
-                        support.bRep.supports[p0.closestsupport].links[object];
-                colorV[2] += (color & 1) * weight;
-                colorV[1] += ((color & 2) >> 1) * weight;
-                colorV[0] += ((color & 4) >> 2) * weight;
-            }
-        }
-        else
-        {
-            if (drawingstarted)
-            {
-                // find next point
-                if (bRep.GetVertex(0).faceindices == null)
-                {
-                    bRep.InitFaceIndices();
-                }
-                
-                double ymin = p0.y;
-                
-                Vertex newp = p0;
-
-                for (int fii = 0; fii < p0.faceindices.length; fii++)
-                {
-                    int fi = p0.faceindices[fii];
-
-                    if (fi == -1)
-                        break;
-
-                    Face f = bRep.GetFace(fi);
-
-                    Vertex p = bRep.GetVertex(f.p);
-                    Vertex q = bRep.GetVertex(f.q);
-                    Vertex r = bRep.GetVertex(f.r);
-                    
-                    int swap = (int)(Math.random()*3);
-                    
-//                    for (int s=swap; --s>=0;)
-//                    {
-//                        Vertex t = p;
-//                        p = q;
-//                        q = r;
-//                        r = t;
-//                    }
-                    if (ymin > p.y)
-                    {
-                        ymin = p.y;
-                        newp = p;
-//                        break;
-                    }
-                    if (ymin > q.y)
-                    {
-                        ymin = q.y;
-                        newp = q;
-//                        break;
-                    }
-                    if (ymin > r.y)
-                    {
-                        ymin = r.y;
-                        newp = r;
-//                        break;
-                    }
-                }
-             
-                CameraPane.selectedpoint.toParent[3][0] = newp.x;
-                CameraPane.selectedpoint.toParent[3][1] = newp.y;
-                CameraPane.selectedpoint.toParent[3][2] = newp.z;
-                
-                drawingstarted = false;
-                
-               // return;
-            }
-            
-            if (false) // CameraPane.DRAW
-            {
-                p0.AO = colorV[0] = 2;
-                colorV[1] = 2;
-                colorV[2] = 2;
-            }
-            
-            CameraPane.pointflow.add(p0);
-            CameraPane.pointflow.Touch();
-        }
-        
-//        gl.glColor3f(colorV[0], colorV[1], colorV[2]);
-//        gl.glMaterialfv(gl.GL_FRONT, gl.GL_DIFFUSE, colorV, 0);
-//        gl.glMaterialfv(gl.GL_BACK, gl.GL_DIFFUSE, colorV, 0);
-    }
-    
     void Print(Vertex v)
     {
         //System.err.println("(" + v.x + ", " + v.y + ", " + v.z + ")");
     }
     
-    void drawVertex(javax.media.opengl.GL gl, Vertex pv, boolean selectmode)
-    {
-        if (!selectmode)
-        {
-            gl.glNormal3f((float) pv.norm.x, (float) pv.norm.y, (float) pv.norm.z);
-            gl.glColor4f(pv.AO, pv.AO, pv.AO, 1);
-            
-            if (flipV)
-                gl.glTexCoord2f((float) pv.s, 1-(float) pv.t);
-            else
-                gl.glTexCoord2f((float) pv.s, (float) pv.t);
-        }
-
-        gl.glVertex3f((float) pv.x, (float) pv.y, (float) pv.z);
-    }
-    
-    void drawFace(Vertex pv, Vertex qv, Vertex rv,
-                  CameraPane display, Face face)
-    {
-        if (pv.y == -10000 ||
-            qv.y == -10000 ||
-            rv.y == -10000)
-            return;
-            
-//        float b = f.nbiterations & 1;
-//        float g = (f.nbiterations>>1) & 1;
-//        float r = (f.nbiterations>>2) & 1;
-//
-//        //if (f.weight == 10000)
-//        //{
-//        //    r = 1; g = b = 0;
-//        //}
-//        //else
-//        //{
-//        //    assert(f.weight < 10000);
-//            r = g = b = (float)bRep.FaceWeight(f)*100;
-//            if (r<0)
-//            assert(r>=0);
-//        //}
-        
-        javax.media.opengl.GL gl = display.GetGL();
-        
-        boolean selectmode = display.drawMode == display.SELECTION || CameraPane.DEBUG_SELECTION;
-        
-        //System.out.println("p = " + pv + "; q = " + qv + "; r = " + rv);
-        if (!selectmode) // display.drawMode != display.SELECTION) // && display.drawMode != display.SHADOW) // (attributes & FILL) != 0)
-        {
-            //gl.glBegin(gl.GL_TRIANGLES);
-            boolean hasnorm = pv.norm != null; // && (pv.norm.x != 0 || pv.norm.y != 0 || pv.norm.z != 0);
-            if (!hasnorm)
-            {
-           //     System.out.println("FUCK!!");
-                LA.vecSub(pv/*.pos*/, qv/*.pos*/, v0);
-                LA.vecSub(pv/*.pos*/, rv/*.pos*/, v1);
-                LA.vecCross(v0, v1, v2);
-                LA.vecNormalize(v2);
-                gl.glNormal3f((float) v2.x, (float) v2.y, (float) v2.z);
-            }
-
-            // P
-            float x = (float)pv.x;
-            float y = (float)pv.y;
-            float z = (float)pv.z;
-            
-            if (hasnorm)
-            {
-//            if (!pv.norm.normalized())
-//                assert(pv.norm.normalized());
-            
-                //System.out.println("normalp = " + pv.norm.x + ", " + pv.norm.y + ", " + pv.norm.z);
-                    float nx = (float)pv.norm.x;
-                    float ny = (float)pv.norm.y;
-                    float nz = (float)pv.norm.z;
-                    
-                x += nx * NORMALPUSH;
-                y += ny * NORMALPUSH;
-                z += nz * NORMALPUSH;
-                
-                gl.glNormal3f(nx, ny, nz);
-            }
-            gl.glColor4f(pv.AO, pv.AO, pv.AO, 1);
-            SetColor(display, pv);
-            //gl.glColor4f(r, g, b, 1);
-    //gl.glColor4f(pv.boundary, pv.boundary, pv.boundary, 1);
-            if (flipV)
-                gl.glTexCoord2f((float) pv.s, 1-(float) pv.t);
-            else
-                gl.glTexCoord2f((float) pv.s, (float) pv.t);
-            //System.out.println("vertexp = " + pv.x + ", " + pv.y + ", " + pv.z);
-            
-            gl.glVertex3f(x, y, z);
-            
-            // Q
-            x = (float)qv.x;
-            y = (float)qv.y;
-            z = (float)qv.z;
-            
-//            Print(pv);
-            if (hasnorm)
-            {
-//            assert(qv.norm.normalized());
-                //System.out.println("normalq = " + qv.norm.x + ", " + qv.norm.y + ", " + qv.norm.z);
-                    float nx = (float)qv.norm.x;
-                    float ny = (float)qv.norm.y;
-                    float nz = (float)qv.norm.z;
-                    
-                x += nx * NORMALPUSH;
-                y += ny * NORMALPUSH;
-                z += nz * NORMALPUSH;
-                
-                gl.glNormal3f(nx, ny, nz);
-            }
-            //System.out.println("vertexq = " + qv.s + ", " + qv.t);
-        //    boolean locked = false;
-        //    float eps = 0.1f;
-        //    boolean wrap = CameraPane.UVWRAP; // true; // UV WRAP TEXTURE ISSUE: true = artifacts, false = nice
-            
-        //    int dot = 0; //*/ (int)f.dot;
-            
-        //    if ((dot&1) == 0)
-        //        dot |= (Math.abs(qv.s - pv.s) < eps && Math.abs(qv.t - pv.t) < eps) ? 3 : 1;
-            
-        //    if (wrap || (dot&2) != 0) // Math.abs(qv.s - pv.s) < eps && Math.abs(qv.t - pv.t) < eps)
-            if (flipV)
-                gl.glTexCoord2f((float) qv.s, 1-(float) qv.t);
-            else
-                gl.glTexCoord2f((float) qv.s, (float) qv.t);
-        //    else
-        //    {
-        //        locked = true;
-        //        gl.glTexCoord2f((float) pv.s, (float) pv.t);
-        //    }
-            gl.glColor4f(qv.AO, qv.AO, qv.AO, 1);
-            SetColor(display, qv);
-            
-            gl.glVertex3f(x, y, z);
-            //gl.glColor4f(r, g, b, 1);
-   //gl.glColor4f(qv.boundary, qv.boundary, qv.boundary, 1);
-            //System.out.println("vertexq = " + qv.x + ", " + qv.y + ", " + qv.z);
-//            Print(qv);
-
-            // R
-            x = (float)rv.x;
-            y = (float)rv.y;
-            z = (float)rv.z;
-            
-            if (hasnorm)
-            {
-//            assert(rv.norm.normalized());
-                //System.out.println("normalr = " + rv.norm.x + ", " + rv.norm.y + ", " + rv.norm.z);
-                    float nx = (float)rv.norm.x;
-                    float ny = (float)rv.norm.y;
-                    float nz = (float)rv.norm.z;
-                    
-                x += nx * NORMALPUSH;
-                y += ny * NORMALPUSH;
-                z += nz * NORMALPUSH;
-                
-                gl.glNormal3f(nx, ny, nz);
-            }
-            
-        //    if ((dot&4) == 0)
-        //        dot |= (Math.abs(rv.s - pv.s) < eps && Math.abs(rv.t - pv.t) < eps) ? 12 : 4;
-            
-        //    if (wrap || !locked && (dot&8) != 0)
-            if (flipV)
-                gl.glTexCoord2f((float) rv.s, 1-(float) rv.t);
-            else
-                gl.glTexCoord2f((float) rv.s, (float) rv.t);
-        //    else
-        //        gl.glTexCoord2f((float) pv.s, (float) pv.t);
-            
-        //    f.dot = dot;
-            
-            gl.glColor4f(rv.AO, rv.AO, rv.AO, 1);
-            SetColor(display, rv);
-            //gl.glColor4f(r, g, b, 1);
-   //gl.glColor4f(rv.boundary, rv.boundary, rv.boundary, 1);
-            //System.out.println("vertexr = " + rv.x + ", " + rv.y + ", " + rv.z);
-            gl.glVertex3f(x, y, z);
-//            Print(rv);
-        //gl.glEnd();
-        }
-        else
-        {
-            gl.glVertex3f((float) pv.x, (float) pv.y, (float) pv.z);
-            gl.glVertex3f((float) qv.x, (float) qv.y, (float) qv.z);
-            gl.glVertex3f((float) rv.x, (float) rv.y, (float) rv.z);
-            
-        }
-
-        if (false) // (attributes & WIREFRAME) != 0)
-        {
-            gl.glDisable(gl.GL_LIGHTING);
-
-            gl.glBegin(gl.GL_LINE_LOOP);
-            gl.glVertex3d(pv./*pos.*/x, pv./*pos.*/y, pv./*pos.*/z);
-            gl.glVertex3d(qv./*pos.*/x, qv./*pos.*/y, qv./*pos.*/z);
-            gl.glVertex3d(rv./*pos.*/x, rv./*pos.*/y, rv./*pos.*/z);
-            gl.glEnd();
-
-            gl.glEnable(gl.GL_LIGHTING);
-        }
-    }
-
     void drawSelf(ClickInfo info, int level, boolean select)
     {
         if (bRep == null)
@@ -7395,20 +7311,23 @@
         }
     }
 
-    protected void calcHotSpot(cVector in, ClickInfo info, Point outPt, Rectangle outRec)
+    static ClickInfo clickInfo = new ClickInfo();
+        
+    protected void calcHotSpot(cVector in, //ClickInfo clickInfo,
+            Point outPt, Rectangle outRec)
     {
-        int hc = info.bounds.x + info.bounds.width / 2;
-        int vc = info.bounds.y + info.bounds.height / 2;
-        double[][] toscreen = info.toScreen;
+        int hc = clickInfo.bounds.x + clickInfo.bounds.width / 2;
+        int vc = clickInfo.bounds.y + clickInfo.bounds.height / 2;
+        double[][] toscreen = clickInfo.toScreen;
         if (toscreen == null)
         {
-            toscreen = new Camera(info.camera.viewCode).toScreen;
+            toscreen = new Camera(clickInfo.camera.viewCode).toScreen;
         }
         cVector vec = in;
         LA.xformPos(in, toscreen, in);
         //System.out.println("Distance = " + info.camera.Distance());
-        vec.x *= 100 * info.camera.SCALE / info.camera.Distance();
-        vec.y *= 100 * info.camera.SCALE / info.camera.Distance();
+        vec.x *= 100 * clickInfo.camera.SCALE / clickInfo.camera.Distance();
+        vec.y *= 100 * clickInfo.camera.SCALE / clickInfo.camera.Distance();
         outPt.x = hc + (int) vec.x;
         outPt.y = vc - (int) vec.y;
         outRec.x = outPt.x - 3;
@@ -7416,15 +7335,18 @@
         outRec.width = outRec.height = 6;
     }
 
-    protected Rectangle calcHotSpot(cVector in, ClickInfo info)
+    protected Rectangle calcHotSpot(cVector in//, ClickInfo clickInfo
+            )
     {
         Point pt = new Point(0, 0);
         Rectangle rec = new Rectangle();
-        calcHotSpot(in, info, pt, rec);
+        calcHotSpot(in, //clickInfo,
+                pt, rec);
         return rec;
     }
 
-    void drawEditHandles0(ClickInfo info, int level)
+    void drawEditHandles0(//ClickInfo clickInfo,
+            int level)
     {
         if (level == 0)
         {
@@ -7433,98 +7355,103 @@
         {
             cVector origin = new cVector();
             //LA.xformPos(origin, toParent, origin);
-            Rectangle spot = calcHotSpot(origin, info);
+            if (this.clickInfo == null)
+                this.clickInfo = new ClickInfo();
+            
+            Rectangle spot = calcHotSpot(origin); //, clickInfo);
             Rectangle boundary = new Rectangle();
             boundary.x = spot.x - 30;
             boundary.y = spot.y - 30;
             boundary.width = spot.width + 60;
             boundary.height = spot.height + 60;
-            info.g.setColor(Color.red);
+            clickInfo.g.setColor(Color.red);
             int spotw = spot.x + spot.width;
             int spoth = spot.y + spot.height;
-            info.g.fillRect(spot.x, spot.y, spot.width, spot.height);
-            if (CameraPane.Xmin > spot.x)
-            {
-                CameraPane.Xmin = spot.x;
-            }
-            if (CameraPane.Xmax < spotw)
-            {
-                CameraPane.Xmax = spotw;
-            }
-            if (CameraPane.Ymin > spot.y)
-            {
-                CameraPane.Ymin = spot.y;
-            }
-            if (CameraPane.Ymax < spoth)
-            {
-                CameraPane.Ymax = spoth;
-            }
+            clickInfo.g.fillRect(spot.x, spot.y, spot.width, spot.height);
+//            if (CameraPane.Xmin > spot.x)
+//            {
+//                CameraPane.Xmin = spot.x;
+//            }
+//            if (CameraPane.Xmax < spotw)
+//            {
+//                CameraPane.Xmax = spotw;
+//            }
+//            if (CameraPane.Ymin > spot.y)
+//            {
+//                CameraPane.Ymin = spot.y;
+//            }
+//            if (CameraPane.Ymax < spoth)
+//            {
+//                CameraPane.Ymax = spoth;
+//            }
             spot.translate(32, 32);
             spotw = spot.x + spot.width;
             spoth = spot.y + spot.height;
-            info.g.setColor(Color.blue);
-            info.g.fillRect(spot.x, spot.y, spot.width, spot.height);
-            if (CameraPane.Xmin > spot.x)
-            {
-                CameraPane.Xmin = spot.x;
-            }
-            if (CameraPane.Xmax < spotw)
-            {
-                CameraPane.Xmax = spotw;
-            }
-            if (CameraPane.Ymin > spot.y)
-            {
-                CameraPane.Ymin = spot.y;
-            }
-            if (CameraPane.Ymax < spoth)
-            {
-                CameraPane.Ymax = spoth;
-            }
-            info.g.drawLine(spotw, spoth, spotw, spoth - 15);
-            info.g.drawLine(spotw, spoth, spotw - 15, spoth);
+            clickInfo.g.setColor(Color.cyan);
+            clickInfo.g.fillRect(spot.x, spot.y, spot.width, spot.height);
+//            if (CameraPane.Xmin > spot.x)
+//            {
+//                CameraPane.Xmin = spot.x;
+//            }
+//            if (CameraPane.Xmax < spotw)
+//            {
+//                CameraPane.Xmax = spotw;
+//            }
+//            if (CameraPane.Ymin > spot.y)
+//            {
+//                CameraPane.Ymin = spot.y;
+//            }
+//            if (CameraPane.Ymax < spoth)
+//            {
+//                CameraPane.Ymax = spoth;
+//            }
+            // bonhommes info.g.drawLine(spotw, spoth, spotw, spoth - boundary.height/2); // 15
+            //info.g.drawLine(spotw, spoth, spotw - boundary.width/2, spoth); // 15
             spot.translate(0, -32);
-            info.g.setColor(Color.green);
-            info.g.fillRect(spot.x, spot.y, spot.width, spot.height);
-            if (CameraPane.Xmin > spot.x)
-            {
-                CameraPane.Xmin = spot.x;
-            }
-            if (CameraPane.Xmax < spotw)
-            {
-                CameraPane.Xmax = spotw;
-            }
-            if (CameraPane.Ymin > spot.y)
-            {
-                CameraPane.Ymin = spot.y;
-            }
-            if (CameraPane.Ymax < spoth)
-            {
-                CameraPane.Ymax = spoth;
-            }
-            info.g.drawArc(boundary.x, boundary.y,
-                    boundary.width, boundary.height, 0, 360);
+            clickInfo.g.setColor(Color.yellow);
+            clickInfo.g.fillRect(spot.x, spot.y, spot.width, spot.height);
+            clickInfo.g.setColor(Color.green);
+//            if (CameraPane.Xmin > spot.x)
+//            {
+//                CameraPane.Xmin = spot.x;
+//            }
+//            if (CameraPane.Xmax < spotw)
+//            {
+//                CameraPane.Xmax = spotw;
+//            }
+//            if (CameraPane.Ymin > spot.y)
+//            {
+//                CameraPane.Ymin = spot.y;
+//            }
+//            if (CameraPane.Ymax < spoth)
+//            {
+//                CameraPane.Ymax = spoth;
+//            }
+            clickInfo.g.drawArc(boundary.x + clickInfo.DX, boundary.y + clickInfo.DY,
+                    (int)(boundary.width * clickInfo.W), (int)(boundary.height * clickInfo.W), 0, 360);
             //info.g.drawArc(spot.x, spotw, spot.width/2, boundary.height/2, 0, 360);
-            if (CameraPane.Xmin > boundary.x)
-            {
-                CameraPane.Xmin = boundary.x;
-            }
-            if (CameraPane.Xmax < boundary.x + boundary.width)
-            {
-                CameraPane.Xmax = boundary.x + boundary.width;
-            }
-            if (CameraPane.Ymin > boundary.y)
-            {
-                CameraPane.Ymin = boundary.y;
-            }
-            if (CameraPane.Ymax < boundary.y + boundary.height)
-            {
-                CameraPane.Ymax = boundary.y + boundary.height;
-            }
+//            if (CameraPane.Xmin > boundary.x)
+//            {
+//                CameraPane.Xmin = boundary.x;
+//            }
+//            if (CameraPane.Xmax < boundary.x + boundary.width)
+//            {
+//                CameraPane.Xmax = boundary.x + boundary.width;
+//            }
+//            if (CameraPane.Ymin > boundary.y)
+//            {
+//                CameraPane.Ymin = boundary.y;
+//            }
+//            if (CameraPane.Ymax < boundary.y + boundary.height)
+//            {
+//                CameraPane.Ymax = boundary.y + boundary.height;
+//            }
             return;
         }
     }
 
-    boolean doEditClick0(ClickInfo info, int level)
+    boolean doEditClick0(//ClickInfo clickInfo, 
+                int level)
     {
         if (level == 0)
         {
@@ -7533,10 +7460,10 @@
 
         boolean retval = false;
 
-        startX = info.x;
-        startY = info.y;
+        startX = clickInfo.x;
+        startY = clickInfo.y;
 
-        hitSomething = 0;
+        hitSomething = -1;
         cVector origin = new cVector();
         //LA.xformPos(origin, toParent, origin);
         Rectangle spot = new Rectangle();
@@ -7544,22 +7471,51 @@
         {
             centerPt = new Point(0, 0);
         }
-        calcHotSpot(origin, info, centerPt, spot);
-        if (spot.contains(info.x, info.y))
+        calcHotSpot(origin, //info,
+                centerPt, spot);
+        if (spot.contains(clickInfo.x, clickInfo.y))
         {
             hitSomething = hitCenter;
             retval = true;
         }
         spot.translate(32, 0);
-        if (spot.contains(info.x, info.y))
+        if (spot.contains(clickInfo.x, clickInfo.y))
         {
             hitSomething = hitRotate;
             retval = true;
         }
         spot.translate(0, 32);
-        if (spot.contains(info.x, info.y))
+        if (spot.contains(clickInfo.x, clickInfo.y))
         {
             hitSomething = hitScale;
+            
+        double scale = 0.005f * clickInfo.camera.Distance();
+                double hScale = (double) (clickInfo.x /*- centerPt.x*/) / 32;
+                double sign = 1;
+                if (hScale < 0)
+                {
+                    sign = -1;
+                }
+                hScale = sign*Math.pow(sign*hScale, scale * 50);
+                if (hScale < 0.01)
+                {
+                    //hScale = 0.01;
+                }
+                
+                double vScale = (double) (clickInfo.y /*- centerPt.y*/) / 32;
+                sign = 1;
+                if (vScale < 0)
+                {
+                    sign = -1;
+                }
+                vScale = sign*Math.pow(sign*vScale, scale * 50);
+                if (vScale < 0.01)
+                {
+                    //vScale = 0.01;
+                }
+                
+                clickInfo.scale = Math.sqrt(hScale*hScale + vScale*vScale);
+                
             retval = true;
         }
 
@@ -7569,7 +7525,7 @@
         }
 
         //System.out.println("info.modifiers = " + info.modifiers);
-        modified = (info.modifiers & CameraPane.META) != 0;
+        modified = (clickInfo.modifiers & CameraPane.SHIFT) != 0; // Was META
         //System.out.println("modified = " + modified);
         //new Exception().printStackTrace();
         //viewCode = info.pane.renderCamera.viewCode;
@@ -7597,7 +7553,8 @@
         return true;
     }
 
-    void doEditDrag0(ClickInfo info)
+    void doEditDrag0(//ClickInfo info,
+            boolean opposite)
     {
         if (hitSomething == 0)
         {
@@ -7611,7 +7568,8 @@
 
         //System.out.println("hitSomething = " + hitSomething);
 
-        double scale = 0.005f * info.camera.Distance();
+        double scale = 0.005f * clickInfo.camera.Distance();
+        
         cVector xlate = new cVector();
         //cVector xlate2 = new cVector();
         switch (hitSomething)
@@ -7622,9 +7580,9 @@
 
             case hitCenter: // Translate
                 
-                scale *= 0.05f * info.pane.theRenderer.renderCamera.Distance();
+                scale *= 0.05f * Globals.theRenderer.RenderCamera().Distance();
                 
-                if (modified)
+                if (modified || opposite)
                 {
                     //assert(false);
                             /*
@@ -7644,8 +7602,8 @@
                     toParent[3][i] = xlate.get(i);
                     LA.matInvert(toParent, fromParent);
                      */
-                    cVector delta = LA.newVector(0, 0, startY - info.y);
-                    LA.xformDir(delta, new Camera(info.camera.viewCode).fromScreen, delta);
+                    cVector delta = LA.newVector(0, 0, startY - clickInfo.y);
+                    LA.xformDir(delta, new Camera(clickInfo.camera.viewCode).fromScreen, delta);
 
                     LA.matCopy(startMat, toParent);
                     LA.matTranslate(toParent, delta.x * scale, delta.y * scale, delta.z * scale);
@@ -7654,7 +7612,7 @@
                 } else
                 {
                     //LA.xformDir(delta, info.camera.fromScreen, delta);
-                    cVector up = new cVector(info.camera.up);
+                    cVector up = new cVector(clickInfo.camera.up);
                     cVector away = new cVector();
                     //cVector right2 = new cVector();
                     //LA.vecCross(up, cVector.Z, right);
@@ -7670,20 +7628,20 @@
                     }
                     LA.xformDir(up, ClickInfo.matbuffer, up);
     //                if (!CameraPane.LOCALTRANSFORM)
-                        LA.xformDir(up, info.pane.theRenderer.renderCamera.toScreen, up);
-                    LA.xformDir(info.camera.away, ClickInfo.matbuffer, away);
+                        LA.xformDir(up, Globals.theRenderer.RenderCamera().toScreen, up);
+                    LA.xformDir(clickInfo.camera.away, ClickInfo.matbuffer, away);
     //                if (!CameraPane.LOCALTRANSFORM)
-                        LA.xformDir(away, info.pane.theRenderer.renderCamera.toScreen, away);
+                        LA.xformDir(away, Globals.theRenderer.RenderCamera().toScreen, away);
                     //LA.vecCross(up, cVector.Z, right2);
 
-                    cVector delta = LA.newVector(info.x - startX, startY - info.y, 0);
+                    cVector delta = LA.newVector(clickInfo.x - startX, startY - clickInfo.y, 0);
 
                     //System.out.println("DELTA0 = " + delta);
                     //System.out.println("AWAY = " + info.camera.away);
                     //System.out.println("UP = " + info.camera.up);
                     if (away.z > 0)
                     {
-                        if (info.camera.up.x == 0) // LA.vecDot(right, right2)<0)
+                        if (clickInfo.camera.up.x == 0) // LA.vecDot(right, right2)<0)
                         {
                             delta.x = -delta.x;
                         } else
@@ -7698,7 +7656,7 @@
                     //System.out.println("DELTA1 = " + delta);
                     LA.xformDir(delta, ClickInfo.matbuffer, delta);
                     //System.out.println("DELTA2 = " + delta);
-                    LA.xformDir(delta, new Camera(info.camera.viewCode).fromScreen, delta);
+                    LA.xformDir(delta, new Camera(clickInfo.camera.viewCode).fromScreen, delta);
                     LA.matCopy(startMat, toParent);
                     //System.out.println("DELTA3 = " + delta);
                     LA.matTranslate(toParent, delta.x * scale, delta.y * scale, delta.z * scale);
@@ -7708,8 +7666,8 @@
                 break;
 
             case hitRotate: // rotate
-                int dx = info.x - centerPt.x;
-                int dy = -(info.y - centerPt.y);
+                int dx = clickInfo.x - centerPt.x;
+                int dy = -(clickInfo.y - centerPt.y);
                 double angle = (double) Math.atan2(dx, dy);
                 angle = -(1.570796 - angle);
 
@@ -7718,6 +7676,7 @@
 
                 if (modified)
                 {
+                    // Rotate 90 degrees
                     angle /= (Math.PI / 4);
                     angle = Math.floor(angle + 0.5);
                     angle *= (Math.PI / 4);
@@ -7731,7 +7690,7 @@
                 }
                 /**/
 
-                switch (info.pane.renderCamera.viewCode)
+                switch (clickInfo.pane.RenderCamera().viewCode)
                 {
                     case 1: // '\001'
                         LA.matZRotate(toParent, angle);
@@ -7758,26 +7717,30 @@
                 break;
 
             case hitScale: // scale
-                double hScale = (double) (info.x - centerPt.x) / 32;
+                double hScale = (double) (clickInfo.x /*- centerPt.x*/) / 32;
+                double sign = 1;
+                if (hScale < 0)
+                {
+                    sign = -1;
+                }
+                hScale = sign*Math.pow(sign*hScale, scale * 50);
                 if (hScale < 0.01)
                 {
-                    hScale = 0.01;
+                    //hScale = 0.01;
                 }
-                hScale = Math.pow(hScale, scale * 50);
-                if (hScale < 0.01)
+                
+                double vScale = (double) (clickInfo.y /*- centerPt.y*/) / 32;
+                sign = 1;
+                if (vScale < 0)
                 {
-                    hScale = 0.01;
+                    sign = -1;
                 }
-                double vScale = (double) (info.y - centerPt.y) / 32;
+                vScale = sign*Math.pow(sign*vScale, scale * 50);
                 if (vScale < 0.01)
                 {
-                    vScale = 0.01;
+                    //vScale = 0.01;
                 }
-                vScale = Math.pow(vScale, scale * 50);
-                if (vScale < 0.01)
-                {
-                    vScale = 0.01;
-                }
+                
                 LA.matCopy(startMat, toParent);
                 /**/
                 for (int i = 0; i < 3; i++)
@@ -7787,39 +7750,47 @@
                 }
                 /**/
 
-                switch (info.pane.renderCamera.viewCode)
+                double totalScale = Math.sqrt(hScale*hScale + vScale*vScale) / clickInfo.scale;
+                        
+                if (totalScale < 0.01)
+                {
+                    totalScale = 0.01;
+                }
+                
+                switch (clickInfo.pane.RenderCamera().viewCode)
                 {
                     case 3: // '\001'
-                        if (modified)
+                        if (modified || opposite)
                         {
                             //LA.matScale(toParent, 1, hScale, vScale);
-                            LA.matScale(toParent, vScale, 1, 1);
+                            LA.matScale(toParent, totalScale, 1, 1);
                         } // vScale, 1);
                         else
                         {
-                            LA.matScale(toParent, vScale, vScale, vScale);
+                            // EXCEPTION!
+                            LA.matScale(toParent, totalScale, totalScale, totalScale);
                         } // vScale, 1);
                         break;
 
                     case 2: // '\002'
-                        if (modified)
+                        if (modified || opposite)
                         {
                             //LA.matScale(toParent, hScale, 1, vScale);
-                            LA.matScale(toParent, 1, vScale, 1);
+                            LA.matScale(toParent, 1, totalScale, 1);
                         } else
                         {
-                            LA.matScale(toParent, vScale, 1, vScale);
+                            LA.matScale(toParent, totalScale, 1, totalScale);
                         }
                         break;
 
                     case 1: // '\003'
-                        if (modified)
+                        if (modified || opposite)
                         {
                             //LA.matScale(toParent, hScale, vScale, 1);
-                            LA.matScale(toParent, 1, 1, vScale);
+                            LA.matScale(toParent, 1, 1, totalScale);
                         } else
                         {
-                            LA.matScale(toParent, vScale, vScale, 1);
+                            LA.matScale(toParent, totalScale, totalScale, 1);
                         }
                         break;
                 }
@@ -7853,7 +7824,7 @@
         } // NEW ...
         
         
-        info.pane.repaint();
+        clickInfo.pane.repaint();
     }
 
     boolean overflow = false;
@@ -7952,14 +7923,22 @@
         //return super.toString() + " (id=" + list + ")" + " (brep=" + bRep + ")";
         //return name + " (id=" + list + ")" + " (brep=" + bRep + ") " + super.toString();
         //return name + " (#tri = " + (bRep==null?0:bRep.VertexCount()) + ") " + super.toString();
+        
+        String objname;
+        
         if (false) //parent != null)
         {
-            return name + " " + System.identityHashCode(this) + " (" + parent.name + " " + System.identityHashCode(parent) + ")";
+            objname = name + " " + System.identityHashCode(this) + " (" + parent.name + " " + System.identityHashCode(parent) + ")";
         } else
         {
-            return GetName() + (Math.abs(count) == 1000 ? (count == 1000 ? " " : " * ") : (" (" + (count /*- 1*/) + ") ")) + /*(IsSelected()?"(selected) ":"") + (touched?"(touched) ":"") */ +System.identityHashCode(this);
+            objname = GetName() + (Math.abs(count) == 1000 ? (count == 1000 ? " " : " * ") : (" (" + (count - 1) + ")")) + /*(IsSelected()?"(selected) ":"") + (touched?"(touched) ":"") */ "";
         } //  + super.toString();
     //return name + " (" + (SizeOf.deepSizeOf(this)/1024) + "K) " + this.getClass().getName();
+        
+        if (!Globals.ADVANCED)
+            return objname;
+        
+        return objname + " " + System.identityHashCode(this);
     }
 
     public int hashCode()
@@ -8015,6 +7994,7 @@
             objectUI.closeUI();
             if (editWindow != null)
             {
+                editWindow.ctrlPanel.FlushUI();
                 editWindow.refreshContents();
             } // ? new
             objectUI = null;
@@ -8023,6 +8003,10 @@
         {
             editWindow = null;
         } // ?
+        }
+        else
+        {
+            //editWindow.closeUI();
         }
     }
     
@@ -8035,7 +8019,7 @@
 	/*transient*/ cVector2[] projectedVertices = new cVector2[0];
         
     Object3D /*Composite*/ parent;
-    Object3D /*Composite*/ fileparent;
+    Object3D /*Composite*/ fileparent; // In the case of FileObject
     
     double[][] toParent; // dynamic matrix
     double[][] fromParent;
@@ -8150,7 +8134,7 @@
         {
             assert(bRep != null);
             if (!(support instanceof GenericJoint)) // support.bRep != null)
-                GrafreeD.Assert(support.bRep == bRep.support);
+                Grafreed.Assert(support.bRep == bRep.support);
         }
         else
         {
@@ -8181,6 +8165,10 @@
     }
     
     transient ObjEditor editWindow;
+    transient ObjEditor manipWindow;
+    
+    transient boolean pinned;
+    
     transient ObjectUI objectUI;
     public static int povDepth = 0;
     private static cVector tbMin = new cVector();
@@ -8199,9 +8187,9 @@
     private static cVector edge2 = new cVector();
     //private static cVector norm = new cVector();
     /*transient private*/ int hitSomething;
-    private static final int hitCenter = 1;
-    private static final int hitScale = 2;
-    private static final int hitRotate = 3;
+    static final int hitCenter = 1;
+    static final int hitScale = 2;
+    static final int hitRotate = 3;
     /*transient*/ /*private*/ int viewCode; // Now used for transparency cache flag
 	/*transient*/ private Point centerPt;
     /*transient*/ private int startX;

--
Gitblit v1.6.2