Browse Source

replacing animcontrol

rickard 3 years ago
parent
commit
659a677ecc

+ 19 - 244
jme3-core/src/com/jme3/gde/core/util/SpatialUtil.java

@@ -1,22 +1,22 @@
 /*
 /*
  * Copyright (c) 2003-2012 jMonkeyEngine
  * Copyright (c) 2003-2012 jMonkeyEngine
  * All rights reserved.
  * All rights reserved.
- * 
+ *
  * Redistribution and use in source and binary forms, with or without
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
  * modification, are permitted provided that the following conditions are
  * met:
  * met:
- * 
+ *
  * * Redistributions of source code must retain the above copyright
  * * Redistributions of source code must retain the above copyright
  *   notice, this list of conditions and the following disclaimer.
  *   notice, this list of conditions and the following disclaimer.
- * 
+ *
  * * Redistributions in binary form must reproduce the above copyright
  * * Redistributions in binary form must reproduce the above copyright
  *   notice, this list of conditions and the following disclaimer in the
  *   notice, this list of conditions and the following disclaimer in the
  *   documentation and/or other materials provided with the distribution.
  *   documentation and/or other materials provided with the distribution.
- * 
+ *
  * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
  * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
  *   may be used to endorse or promote products derived from this software
  *   may be used to endorse or promote products derived from this software
  *   without specific prior written permission.
  *   without specific prior written permission.
- * 
+ *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
@@ -31,14 +31,10 @@
  */
  */
 package com.jme3.gde.core.util;
 package com.jme3.gde.core.util;
 
 
-import com.jme3.animation.AnimControl;
-import com.jme3.animation.SkeletonControl;
-import com.jme3.gde.core.scene.ApplicationLogHandler.LogLevel;
-import com.jme3.scene.Geometry;
-import com.jme3.scene.Node;
+import com.jme3.anim.AnimComposer;
 import com.jme3.scene.SceneGraphVisitor;
 import com.jme3.scene.SceneGraphVisitor;
-import com.jme3.scene.SceneGraphVisitorAdapter;
 import com.jme3.scene.Spatial;
 import com.jme3.scene.Spatial;
+
 import java.util.ArrayList;
 import java.util.ArrayList;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.logging.Level;
 import java.util.logging.Level;
@@ -54,10 +50,9 @@ import java.util.logging.Logger;
 @SuppressWarnings({"unchecked", "rawtypes"})
 @SuppressWarnings({"unchecked", "rawtypes"})
 public class SpatialUtil {
 public class SpatialUtil {
 
 
-    private static final Logger logger = Logger.getLogger(SpatialUtil.class.getName());
-    //TODO: use these variables
-    public static final String ORIGINAL_NAME = "ORIGINAL_NAME";
-    public static final String ORIGINAL_PATH = "ORIGINAL_PATH";
+    private static final Logger logger =
+            Logger.getLogger(SpatialUtil.class.getName());
+
 
 
     /**
     /**
      * Gets a "pathname" for the given Spatial, combines the Spatials and
      * Gets a "pathname" for the given Spatial, combines the Spatials and
@@ -103,10 +98,12 @@ public class SpatialUtil {
                         geomName = "null";
                         geomName = "null";
                     }
                     }
                     geom.setUserData("ORIGINAL_NAME", geomName);
                     geom.setUserData("ORIGINAL_NAME", geomName);
-                    logger.log(Level.FINE, "Set ORIGINAL_NAME for {0}", geomName);
+                    logger.log(Level.FINE, "Set ORIGINAL_NAME for {0}",
+                            geomName);
                     String id = SpatialUtil.getSpatialPath(curSpat);
                     String id = SpatialUtil.getSpatialPath(curSpat);
                     if (geomMap.contains(id)) {
                     if (geomMap.contains(id)) {
-                        logger.log(Level.WARNING, "Cannot create unique name for Spatial {0}: {1}", new Object[]{geom, id});
+                        logger.log(Level.WARNING, "Cannot create unique name " +
+                                "for Spatial {0}: {1}", new Object[]{geom, id});
                     }
                     }
                     geomMap.add(id);
                     geomMap.add(id);
                     geom.setUserData("ORIGINAL_PATH", id);
                     geom.setUserData("ORIGINAL_PATH", id);
@@ -114,231 +111,13 @@ public class SpatialUtil {
                 }
                 }
             });
             });
         } else {
         } else {
-            logger.log(Level.SEVERE, "No Spatial available when trying to add Spatial paths.");
-        }
-    }
-
-    /**
-     * Finds a previously marked spatial in the supplied root Spatial, creates
-     * the name and path to be looked for from the given needle Spatial.
-     *
-     * @param root
-     * @param needle
-     * @return
-     */
-    public static Spatial findTaggedSpatial(final Spatial root, final Spatial needle) {
-        if (needle == null) {
-            logger.log(Level.WARNING, "Trying to find null needle for {0}", root);
-            return null;
-        }
-        final String name = needle.getName();
-        final String path = getSpatialPath(needle);
-        if (name == null || path == null) {
-            logger.log(Level.WARNING, "Trying to find tagged Spatial with null name spatial for {0}.", root);
-            return null;
-        }
-        final Class clazz = needle.getClass();
-        String rootName = root.getUserData("ORIGINAL_NAME");
-        String rootPath = root.getUserData("ORIGINAL_PATH");
-        if (name.equals(rootName) && path.equals(rootPath)) {
-            return root;
-        }
-        final SpatialHolder holder = new SpatialHolder();
-        root.depthFirstTraversal(new SceneGraphVisitor() {
-            @Override
-            public void visit(Spatial spatial) {
-                String spName = spatial.getUserData("ORIGINAL_NAME");
-                String spPath = spatial.getUserData("ORIGINAL_PATH");
-                if (name.equals(spName) && path.equals(spPath) && clazz.isInstance(spatial)) {
-                    if (holder.spatial == null) {
-                        holder.spatial = spatial;
-                    } else {
-                        logger.log(Level.WARNING, "Found Spatial {0} twice in {1}", new Object[]{path, root});
-                    }
-                }
-            }
-        });
-        return holder.spatial;
-    }
-
-    /**
-     * Finds a spatial in the given Spatial tree with the specified name and
-     * path, the path and name are constructed from the given (sub-)spatial(s)
-     * and is not read from the UserData of the objects. This is mainly used to
-     * check if the original spatial still exists in the original file.
-     *
-     * @param root
-     * @param name
-     * @param path
-     */
-    public static Spatial findSpatial(final Spatial root, final String name, final String path) {
-        if (name == null || path == null) {
-            logger.log(Level.WARNING, "Trying to find Spatial with null name spatial for {0}.", root);
-            return null;
-        }
-        if (name.equals(root.getName()) && path.equals(getSpatialPath(root))) {
-            return root;
-        }
-        final SpatialHolder holder = new SpatialHolder();
-        root.depthFirstTraversal(new SceneGraphVisitor() {
-            @Override
-            public void visit(Spatial spatial) {
-                if (name.equals(spatial.getName()) && path.equals(getSpatialPath(spatial))) {
-                    if (holder.spatial == null) {
-                        holder.spatial = spatial;
-                    } else {
-                        logger.log(Level.WARNING, "Found Spatial {0} twice in {1}", new Object[]{path, root});
-                    }
-                }
-            }
-        });
-        return holder.spatial;
-    }
-
-    /**
-     * Updates the mesh data of existing objects from an original file, adds new
-     * nonexisting geometry objects to the root, including their parents if they
-     * don't exist.
-     *
-     * @param root
-     * @param original
-     */
-    public static void updateMeshDataFromOriginal(final Spatial root, final Spatial original) {
-        //loop through original to also find new geometry
-        original.depthFirstTraversal(new SceneGraphVisitorAdapter() {
-            @Override
-            public void visit(Geometry geom) {
-                //will always return same class type as 2nd param, so casting is safe
-                Geometry spat = (Geometry) findTaggedSpatial(root, geom);
-                if (spat != null) {
-                    spat.setMesh(geom.getMesh());
-                    logger.log(LogLevel.USERINFO, "Updated mesh for Geometry {0}", geom.getName());
-                } else {
-                    addLeafWithNonExistingParents(root, geom);
-                }
-            }
-        });
-    }
-
-    public static void updateMaterialDataFromOriginal(final Spatial root, final Spatial original) {
-        //loop through original to also find new geometry
-        original.depthFirstTraversal(new SceneGraphVisitorAdapter() {
-            @Override
-            public void visit(Geometry geom) {
-                //will always return same class type as 2nd param, so casting is safe
-                Geometry spat = (Geometry) findTaggedSpatial(root, geom);
-                if (spat != null && spat.getMaterial() != null && geom.getMaterial() != null) {
-                    spat.setMaterial(geom.getMaterial());
-                    logger.log(LogLevel.USERINFO, "Updated material for Geometry {0}", geom.getName());
-                }
-            }
-        });
-    }
-
-    /**
-     * Adds a leaf to a spatial, including all nonexisting parents.
-     *
-     * @param root
-     * @param original
-     */
-    private static void addLeafWithNonExistingParents(Spatial root, Spatial leaf) {
-        if (!(root instanceof Node)) {
-            logger.log(Level.WARNING, "Cannot add new Leaf {0} to {1}, is not a Node!", new Object[]{leaf.getName(), root.getName()});
-            return;
+            logger.log(Level.SEVERE, "No Spatial available when trying to add" +
+                    " Spatial paths.");
         }
         }
-        for (Spatial s = leaf; s.getParent() != null; s = s.getParent()) {
-            Spatial parent = s.getParent();
-            Spatial other = findTaggedSpatial(root, parent);
-            if (other == null) {
-                continue;
-            }
-            if (other instanceof Node) {
-                logger.log(Level.INFO, "Attaching {0} to {1} in root {2} to add leaf {3}", new Object[]{s, other, root, leaf});
-                //set original path data to leaf and new parents
-                for (Spatial spt = leaf; spt != parent; spt = spt.getParent()) {
-                    if(spt == null){
-                        return; // this is to avoid a crash when changing names of meshes externally
-                    }
-                    spt.setUserData(ORIGINAL_NAME, spt.getName());
-                    spt.setUserData(ORIGINAL_PATH, getSpatialPath(spt));
-                    spt = spt.getParent();
-                }
-                //attach to new node in own root
-                Node otherNode = (Node) other;
-                otherNode.attachChild(s);
-                logger.log(LogLevel.USERINFO, "Attached Node {0} with leaf {0}", new Object[]{other.getName(), leaf.getName()});
-                return;
-            } else {
-                logger.log(Level.WARNING, "Cannot attach leaf {0} to found spatial {1} in root {2}, not a node.", new Object[]{leaf, other, root});
-            }
-        }
-        logger.log(Level.WARNING, "Could not attach new Leaf {0}, no root node found.", leaf.getName());
-    }
-
-    public static void updateAnimControlDataFromOriginal(final Spatial root, final Spatial original) {
-        //loop through original to also find new AnimControls, we expect all nodes etc. to exist
-        //TODO: can (blender) AnimControls end up in other nodes that are not a parent of the geometry they modify?
-        removeAnimData(root);
-        original.depthFirstTraversal(new SceneGraphVisitor() {
-            @Override
-            public void visit(Spatial spat) {
-                AnimControl animControl = spat.getControl(AnimControl.class);
-                if (animControl != null) {
-                    Spatial mySpatial = findTaggedSpatial(root, spat);
-                    if (mySpatial != null) {
-                        //TODO: move attachments: have to scan through all nodes and find the ones
-                        //where UserData "AttachedBone" == Bone and move it to new Bone
-                        AnimControl myAnimControl = mySpatial.getControl(AnimControl.class);
-                        SkeletonControl mySkeletonControl = spat.getControl(SkeletonControl.class);
-                        if (mySkeletonControl != null) {
-                            mySpatial.removeControl(mySkeletonControl);
-                        }
-                        if (myAnimControl != null) {
-                            mySpatial.removeControl(myAnimControl);
-                        }
-                        AnimControl newControl = (AnimControl) animControl.cloneForSpatial(mySpatial);
-                        if (mySpatial.getControl(SkeletonControl.class) == null) {
-                            logger.log(Level.INFO, "Adding control for {0}", mySpatial.getName());
-                            mySpatial.addControl(newControl);
-                        } else {
-                            logger.log(Level.INFO, "Control for {0} was added automatically", mySpatial.getName());
-                        }
-                        if (mySpatial.getControl(SkeletonControl.class) == null) {
-                            if (animControl.getSkeleton() == null) {
-                                logger.log(Level.INFO, "Could not add a SkeletonControl for {0}, because animControl.getSkeleton() return null. Broken file? Gltf?", mySpatial.getName());
-                            } else {
-                                mySpatial.addControl(new SkeletonControl(animControl.getSkeleton()));
-                            }
-                        } else {
-                            logger.log(Level.INFO, "SkeletonControl for {0} was added by AnimControl already", mySpatial.getName());
-                        }
-                        logger.log(LogLevel.USERINFO, "Updated animation for {0}", mySpatial.getName());
-                    } else {
-                        logger.log(Level.WARNING, "Could not find sibling for {0} in root {1} when trying to apply AnimControl data", new Object[]{spat, root});
-                    }
-                }
-            }
-        });
-        //TODO: remove old AnimControls?
     }
     }
 
 
-    public static void removeAnimData(Spatial root) {
-        root.depthFirstTraversal(new SceneGraphVisitor() {
-            @Override
-            public void visit(Spatial spat) {
-                AnimControl animControl = spat.getControl(AnimControl.class);
-                if (animControl != null) {
-                    spat.removeControl(animControl);
-                    SkeletonControl skeletonControl = spat.getControl(SkeletonControl.class);
-                    if (skeletonControl != null) {
-                        spat.removeControl(skeletonControl);
-                    }
-                }
-            }
-        });
-    }
-
-    public static void clearRemovedOriginals(final Spatial root, final Spatial original) {
+    public static void clearRemovedOriginals(final Spatial root,
+                                             final Spatial original) {
         //TODO: Clear old stuff at all?
         //TODO: Clear old stuff at all?
         return;
         return;
     }
     }
@@ -352,7 +131,7 @@ public class SpatialUtil {
         final AtomicBoolean animFound = new AtomicBoolean(false);
         final AtomicBoolean animFound = new AtomicBoolean(false);
         root.depthFirstTraversal(new SceneGraphVisitor() {
         root.depthFirstTraversal(new SceneGraphVisitor() {
             public void visit(Spatial spatial) {
             public void visit(Spatial spatial) {
-                if (spatial.getControl(AnimControl.class) != null) {
+                if (spatial.getControl(AnimComposer.class) != null) {
                     animFound.set(true);
                     animFound.set(true);
                 }
                 }
             }
             }
@@ -360,8 +139,4 @@ public class SpatialUtil {
         return animFound.get();
         return animFound.get();
     }
     }
 
 
-    private static class SpatialHolder {
-
-        Spatial spatial;
-    }
 }
 }

+ 60 - 0
jme3-core/src/com/jme3/gde/core/util/TaggedSpatialFinder.java

@@ -0,0 +1,60 @@
+package com.jme3.gde.core.util;
+
+import com.jme3.scene.SceneGraphVisitor;
+import com.jme3.scene.Spatial;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Finds a previously marked spatial in the supplied root Spatial, creates
+ * the name and path to be looked for from the given needle Spatial.
+ */
+public class TaggedSpatialFinder {
+
+    private static final Logger logger =
+            Logger.getLogger(TaggedSpatialFinder.class.getName());
+
+    public Spatial find(final Spatial root, final Spatial needle) {
+        if (needle == null) {
+            logger.log(Level.WARNING, "Trying to find null needle for {0}",
+                    root);
+            return null;
+        }
+        final String name = needle.getName();
+        final String path = SpatialUtil.getSpatialPath(needle);
+        if (name == null || path == null) {
+            logger.log(Level.WARNING, "Trying to find tagged Spatial with " +
+                    "null name spatial for {0}.", root);
+            return null;
+        }
+        final Class clazz = needle.getClass();
+        String rootName = root.getUserData("ORIGINAL_NAME");
+        String rootPath = root.getUserData("ORIGINAL_PATH");
+        if (name.equals(rootName) && path.equals(rootPath)) {
+            return root;
+        }
+        final SpatialHolder holder = new SpatialHolder();
+        root.depthFirstTraversal(new SceneGraphVisitor() {
+            @Override
+            public void visit(Spatial spatial) {
+                String spName = spatial.getUserData("ORIGINAL_NAME");
+                String spPath = spatial.getUserData("ORIGINAL_PATH");
+                if (name.equals(spName) && path.equals(spPath) && clazz.isInstance(spatial)) {
+                    if (holder.spatial == null) {
+                        holder.spatial = spatial;
+                    } else {
+                        logger.log(Level.WARNING, "Found Spatial {0} twice in" +
+                                " {1}", new Object[]{path, root});
+                    }
+                }
+            }
+        });
+        return holder.spatial;
+    }
+
+    private static class SpatialHolder {
+
+        Spatial spatial;
+    }
+}

+ 99 - 0
jme3-core/src/com/jme3/gde/core/util/datatransfer/AnimationDataFromOriginal.java

@@ -0,0 +1,99 @@
+package com.jme3.gde.core.util.datatransfer;
+
+import com.jme3.anim.AnimClip;
+import com.jme3.anim.AnimComposer;
+import com.jme3.gde.core.scene.ApplicationLogHandler;
+import com.jme3.gde.core.util.TaggedSpatialFinder;
+import com.jme3.scene.SceneGraphVisitor;
+import com.jme3.scene.Spatial;
+import com.jme3.util.clone.Cloner;
+
+import java.util.Collection;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class AnimationDataFromOriginal implements SpatialDataTransferInterface {
+
+    private static final Logger logger =
+            Logger.getLogger(AnimationDataFromOriginal.class.getName());
+
+    private final TaggedSpatialFinder finder;
+
+    public AnimationDataFromOriginal(TaggedSpatialFinder finder) {
+        this.finder = finder;
+    }
+
+    @Override
+    public void update(final Spatial root, final Spatial original) {
+        //loop through original to also find new AnimControls, we expect all 
+        // nodes etc. to exist
+        //TODO: can (blender) AnimControls end up in other nodes that are not
+        // a parent of the geometry they modify?
+        removeAnimData(root);
+        original.depthFirstTraversal(new SceneGraphVisitor() {
+            @Override
+            public void visit(Spatial spat) {
+                AnimComposer animComposer = spat.getControl(AnimComposer.class);
+                if (animComposer != null) {
+                    Spatial mySpatial = finder.find(root, spat);
+                    if (mySpatial != null) {
+                        //TODO: move attachments: have to scan through all 
+                        // nodes and find the ones
+                        //where UserData "AttachedBone" == Bone and move it 
+                        // to new Bone
+                        AnimComposer myAnimControl =
+                                mySpatial.getControl(AnimComposer.class);
+
+                        if (myAnimControl != null) {
+                            mySpatial.removeControl(myAnimControl);
+                        }
+
+                        AnimComposer newControl = new AnimComposer();
+                        newControl.cloneFields(new Cloner(),
+                                animComposer.jmeClone());
+                        copyAnimClips(newControl, animComposer);
+                        if (mySpatial.getControl(AnimComposer.class) == null) {
+                            logger.log(Level.INFO, "Adding control for {0}",
+                                    mySpatial.getName());
+                            mySpatial.addControl(newControl);
+                        } else {
+                            logger.log(Level.INFO, "Control for {0} was added" +
+                                    " automatically", mySpatial.getName());
+                        }
+
+                        logger.log(ApplicationLogHandler.LogLevel.USERINFO,
+                                "Updated animation for {0}",
+                                mySpatial.getName());
+                    } else {
+                        logger.log(Level.WARNING, "Could not find sibling for" +
+                                " {0} in root {1} when trying to apply " +
+                                "AnimControl data", new Object[]{spat, root});
+                    }
+                }
+            }
+        });
+        //TODO: remove old AnimControls?
+    }
+
+    private void copyAnimClips(AnimComposer control, AnimComposer original) {
+        Collection<AnimClip> clips = original.getAnimClips();
+        for (AnimClip c : clips) {
+            control.addAnimClip(c);
+        }
+    }
+
+
+    private void removeAnimData(Spatial root) {
+        root.depthFirstTraversal(new SceneGraphVisitor() {
+            @Override
+            public void visit(Spatial spat) {
+                AnimComposer animControl = spat.getControl(AnimComposer.class);
+                if (animControl != null) {
+                    spat.removeControl(animControl);
+
+                }
+            }
+        });
+    }
+
+}

+ 40 - 0
jme3-core/src/com/jme3/gde/core/util/datatransfer/MaterialDataFromOriginal.java

@@ -0,0 +1,40 @@
+package com.jme3.gde.core.util.datatransfer;
+
+import com.jme3.gde.core.scene.ApplicationLogHandler;
+import com.jme3.gde.core.util.TaggedSpatialFinder;
+import com.jme3.scene.Geometry;
+import com.jme3.scene.SceneGraphVisitorAdapter;
+import com.jme3.scene.Spatial;
+
+import java.util.logging.Logger;
+
+public class MaterialDataFromOriginal implements SpatialDataTransferInterface {
+
+    private static final Logger logger =
+            Logger.getLogger(MaterialDataFromOriginal.class.getName());
+
+    private final TaggedSpatialFinder finder;
+
+    public MaterialDataFromOriginal(TaggedSpatialFinder finder) {
+        this.finder = finder;
+    }
+
+    @Override
+    public void update(final Spatial root, final Spatial original) {
+        //loop through original to also find new geometry
+        original.depthFirstTraversal(new SceneGraphVisitorAdapter() {
+            @Override
+            public void visit(Geometry geom) {
+                //will always return same class type as 2nd param, so casting
+                // is safe
+                Geometry spat = (Geometry) finder.find(root, geom);
+                if (spat != null && spat.getMaterial() != null && geom.getMaterial() != null) {
+                    spat.setMaterial(geom.getMaterial());
+                    logger.log(ApplicationLogHandler.LogLevel.USERINFO,
+                            "Updated material for Geometry {0}",
+                            geom.getName());
+                }
+            }
+        });
+    }
+}