From 0a876b04d21af0c5ebd40a805d3a9f433fcd8784 Mon Sep 17 00:00:00 2001 From: Paul Speed Date: Sun, 27 Mar 2016 06:11:41 -0400 Subject: [PATCH] Added a TestCloneSpatial example to do some basic clone testing. --- .../java/jme3test/app/TestCloneSpatial.java | 213 ++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 jme3-examples/src/main/java/jme3test/app/TestCloneSpatial.java diff --git a/jme3-examples/src/main/java/jme3test/app/TestCloneSpatial.java b/jme3-examples/src/main/java/jme3test/app/TestCloneSpatial.java new file mode 100644 index 0000000000..b55262a96d --- /dev/null +++ b/jme3-examples/src/main/java/jme3test/app/TestCloneSpatial.java @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2016 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package jme3test.app; + +import java.lang.reflect.*; +import java.util.*; + +import com.jme3.light.*; +import com.jme3.material.*; +import com.jme3.math.*; +import com.jme3.scene.*; +import com.jme3.scene.control.*; +import com.jme3.scene.shape.*; +import com.jme3.util.clone.*; + + +/** + * + * + * @author Paul Speed + */ +public class TestCloneSpatial { + + public static void main( String... args ) throws Exception { + + // Setup a test node with some children, controls, etc. + Node root = new Node("rootNode"); + + // A root light + DirectionalLight rootLight = new DirectionalLight(); + root.addLight(rootLight); + + Box sharedBox = new Box(1, 1, 1); + Geometry geom1 = new Geometry("box1", sharedBox); + Material sharedMaterial = new Material(); // not a valid material, just for testing + geom1.setMaterial(sharedMaterial); + + Geometry geom2 = new Geometry("box2", sharedBox); + geom2.setMaterial(sharedMaterial); + + root.attachChild(geom1); + root.attachChild(geom2); + + // Add some controls + geom1.addControl(new BillboardControl()); + geom2.addControl(new BillboardControl()); + + // A light that will only affect the children and be controlled + // by one child + PointLight childLight = new PointLight(); + geom1.addLight(childLight); + geom2.addLight(childLight); + + geom1.addControl(new LightControl(childLight)); + + // Set some shared user data also + Vector3f sharedUserData = new Vector3f(1, 2, 3); + geom1.setUserData("shared", sharedUserData); + geom2.setUserData("shared", sharedUserData); + + dump("", root); + + System.out.println("-------- cloning spatial --------------"); + Node clone = root.clone(true); + dump("", clone); + + System.out.println("-------- cloning spatial without cloning material --------------"); + clone = root.clone(false); + dump("", clone); + } + + + /** + * Debug dump to check structure and identity + */ + public static void dump( String indent, Spatial s ) { + if( s instanceof Node ) { + dump(indent, (Node)s); + } else if( s instanceof Geometry ) { + dump(indent, (Geometry)s); + } + } + + public static void dump( String indent, Node n ) { + System.out.println(indent + objectToString(n)); + dumpSpatialProperties(indent + " ", n); + if( !n.getChildren().isEmpty() ) { + System.out.println(indent + " children:"); + for( Spatial s : n.getChildren() ) { + dump(indent + " ", s); + } + } + } + + public static void dump( String indent, Geometry g ) { + System.out.println(indent + objectToString(g)); + //System.out.println(indent + " mesh:" + objectToString(g.getMesh())); + //System.out.println(indent + " material:" + objectToString(g.getMaterial())); + dumpSpatialProperties(indent + " ", g); + } + + public static void dump( String indent, Control ctl ) { + System.out.println(indent + objectToString(ctl)); + if( ctl instanceof AbstractControl ) { + System.out.println(indent + " spatial:" + objectToString(((AbstractControl)ctl).getSpatial())); + } + } + + private static void dumpSpatialProperties( String indent, Spatial s ) { + dumpProperties(indent, s, "children"); + + if( !s.getUserDataKeys().isEmpty() ) { + System.out.println(indent + "userData:"); + for( String key : s.getUserDataKeys() ) { + System.out.println(indent + " " + key + ":" + objectToString(s.getUserData(key))); + } + } + + if( s.getNumControls() > 0 ) { + System.out.println(indent + "controls:"); + for( int i = 0; i < s.getNumControls(); i++ ) { + Control ctl = s.getControl(i); + //dump(indent + " ", ctl); + dumpObject(indent + " ", ctl); + } + } + + LightList lights = s.getLocalLightList(); + if( lights.size() > 0 ) { + System.out.println(indent + "lights:"); + for( Light l : lights ) { + dumpObject(indent + " ", l); + } + } + } + + private static void dumpObject( String indent, Object o ) { + System.out.println(indent + objectToString(o)); + dumpProperties(indent + " ", o); + } + + private static void dumpProperties( String indent, Object o, String... skip ) { + if( o == null ) { + return; + } + Set skipSet = new HashSet<>(Arrays.asList(skip)); + for( Method m : o.getClass().getMethods() ) { + if( m.getParameterTypes().length > 0 ) { + continue; + } + String name = m.getName(); + if( "getClass".equals(name) ) { + continue; + } + if( !name.startsWith("get") ) { + continue; + } + Class type = m.getReturnType(); + if( type.isPrimitive() || type.isEnum() ) { + continue; + } + name = name.substring(3); + if( skipSet.contains(name.toLowerCase()) ) { + continue; + } + try { + Object value = m.invoke(o); + System.out.println(indent + name + ":" + objectToString(value)); + } catch( Exception e ) { + throw new RuntimeException("Error with method:" + m, e); + } + } + } + + private static String objectToString( Object o ) { + if( o == null ) { + return null; + } + String s = o + "@" + System.identityHashCode(o); + s = s.replaceAll("\\r?\\n", ""); + return s; + } +}