Quellcode durchsuchen

Changes to animations storing (not yet used in the selected blender file) and small refactoring.

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7886 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
Kae..pl vor 14 Jahren
Ursprung
Commit
e911e3299e

+ 4 - 2
engine/src/test/jme3test/blender/ManualBlenderTester.java

@@ -40,8 +40,8 @@ import java.util.Map.Entry;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
+import jme3test.blender.config.BlenderKeyConfiguration;
 import jme3test.blender.config.ConfigDialog;
-import jme3test.blender.config.ConfigDialog.BlenderKeyConfiguration;
 import jme3test.blender.scene.Pivot;
 
 import com.jme3.animation.AnimControl;
@@ -92,7 +92,9 @@ public class ManualBlenderTester extends SimpleApplication {
         //running the application
         ConfigDialog configDialog = new ConfigDialog("./src/test-data/Blender");
         BlenderKeyConfiguration bkk = configDialog.getBlenderKeyConfiguration();
-        new ManualBlenderTester(bkk, debugMode).start();
+        if(bkk != null) {
+        	new ManualBlenderTester(bkk, debugMode).start();
+        }
     }
 
     /**

+ 2 - 7
engine/src/test/jme3test/blender/config/AbstractConfigDialog.java

@@ -84,7 +84,7 @@ public abstract class AbstractConfigDialog extends JDialog {
         }
         this.setLayout(new BorderLayout());
         this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
-        this.setLocationRelativeTo(null);
+        this.setLocationByPlatform(true);
 
         this.add(this.prepareBlenderFilesAndLogLevelPanel(), BorderLayout.WEST);
         this.add(this.prepareFilePropertiesPanel(), BorderLayout.CENTER);
@@ -157,12 +157,7 @@ public abstract class AbstractConfigDialog extends JDialog {
         jPanelAnimations.setLayout(new BorderLayout());
         jPanelAnimations.add(new JLabel("Animations"), BorderLayout.NORTH);
 
-        jTableAnimations = new JTable();
-        jTableAnimations.setSelectionMode(DefaultListSelectionModel.SINGLE_SELECTION);
-        jTableAnimations.setModel(new DefaultTableModel(new Object[]{"Object", "Name", "Start frame", "Stop frame"}, 0));
-        for (int i = 0; i < jTableAnimations.getColumnModel().getColumnCount(); ++i) {
-            jTableAnimations.getColumnModel().getColumn(i).setCellEditor(new BlenderTableCellEditor());
-        }
+        jTableAnimations = new AnimationsTable();
         JScrollPane jScrollPaneAnimations = new JScrollPane(jTableAnimations);
         jTableAnimations.setFillsViewportHeight(true);
 

+ 185 - 0
engine/src/test/jme3test/blender/config/AnimationsTable.java

@@ -0,0 +1,185 @@
+package jme3test.blender.config;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Random;
+import java.util.Vector;
+
+import javax.swing.DefaultCellEditor;
+import javax.swing.DefaultListSelectionModel;
+import javax.swing.JFrame;
+import javax.swing.JRadioButton;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.JTextField;
+import javax.swing.event.TableModelEvent;
+import javax.swing.event.TableModelListener;
+import javax.swing.table.DefaultTableCellRenderer;
+import javax.swing.table.DefaultTableModel;
+
+/**
+ * Table for displaying and managing animations to import.
+ * @author Marcin Roguski (Kaelthas)
+ */
+public class AnimationsTable extends JTable {
+	private static final long serialVersionUID = 1978778634957586330L;
+
+	/**
+	 * Constructor. Creates default model. Applies basic settings.
+	 */
+	public AnimationsTable() {
+		super(new AnimationsTableModel(new Object[] {null, "Object name", "Animation name", "Start", "Stop"}));
+		this.getTableHeader().setReorderingAllowed(false);
+		this.setSelectionMode(DefaultListSelectionModel.SINGLE_SELECTION);
+		CellRenderer cellRenderer = new CellRenderer();
+		this.setDefaultRenderer(Object.class, cellRenderer);
+		this.getModel().addTableModelListener(cellRenderer);
+		this.getColumnModel().getColumn(0).setCellEditor(new RadioButtonCellEditor());
+	}
+	
+	/**
+	 * This class represents the model where all cells are editable and animations are always grouped
+	 * by object.
+	 * @author Marcin Roguski (Kaelthas)
+	 */
+	private static final class AnimationsTableModel extends DefaultTableModel {
+		private static final long serialVersionUID = 8285912542455513806L;
+
+		/**
+		 * Constructor. Creates table with given columns and no rows.
+		 * @param columnNames the names of the columns
+		 */
+		public AnimationsTableModel(Object[] columnNames) {
+			super(columnNames, 0);
+		}
+		
+		@Override
+		public boolean isCellEditable(int row, int column) {
+			return true;
+		}
+		
+		@Override
+		@SuppressWarnings("rawtypes")
+		public void addRow(Vector rowData) {
+			String objectName = (String) rowData.get(1);
+			int index = 0;
+			boolean objectFound = false;
+			for(int i=0;i<this.getRowCount();++i) {
+				String name = (String)this.getValueAt(i, 1);
+				if(name.equals(objectName)) {
+					index = i;
+					objectFound = true;
+				}
+			}
+			if(objectFound) {
+				this.insertRow(index + 1, rowData);
+			} else {
+				super.addRow(rowData);
+			}
+		}
+	}
+	
+	/**
+	 * This class renders each group (specified by object) to one of the colors so that they are
+	 * easily recognizable. It also renderes selected row with JRadioButton.
+	 * @author Marcin Roguski (Kaelthas)
+	 */
+	private static final class CellRenderer extends DefaultTableCellRenderer implements TableModelListener {
+		private static final long serialVersionUID = 3759759133199203533L;
+		
+		/** Index of the object (specifies the object's group color. */
+		private Map<String, Integer> objectIndex = new HashMap<String, Integer>();
+		/** The other color for the group (the first one is WHITE. */
+		private Color color = new Color(240, 240, 240);
+		/** Radio button to display row selection. */
+		private JRadioButton jRadioButton = new JRadioButton();
+		
+		@Override
+		public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row,
+				int column) {
+			Object objectName = table.getModel().getValueAt(row, 1);
+			Component component;
+			if(column == 0) {
+				jRadioButton.setSelected((Boolean)value);
+				component = jRadioButton;
+			} else {
+				component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
+			}
+			
+			Integer index = objectIndex.get(objectName);
+			if(index != null) {
+				if(index.intValue() % 2 == 1) {
+					component.setBackground(color);
+				} else {
+					component.setBackground(Color.WHITE);
+				}
+			}
+			return component;
+		}
+		
+		@Override
+		public void tableChanged(TableModelEvent evt) {
+			if(evt.getType() == TableModelEvent.INSERT) {
+				DefaultTableModel model = (DefaultTableModel)evt.getSource();
+				for(int i=evt.getFirstRow();i<=evt.getLastRow();++i) {
+					String objectName = (String) model.getValueAt(i, 1);
+					if(!objectIndex.containsKey(objectName)) {
+						objectIndex.put(objectName, Integer.valueOf(objectIndex.size()));
+					}
+				}
+			}
+		}
+	}
+	
+	/**
+	 * This editor is used for the first column to allow the edition of row selection.
+	 * @author Marcin Roguski (Kaelthas)
+	 */
+	private static final class RadioButtonCellEditor extends DefaultCellEditor {
+		private static final long serialVersionUID = 7697027333456874718L;
+		/** Component that allows editing. */
+		private JRadioButton jRadioButton = new JRadioButton();
+		
+		/**
+		 * Constructor.
+		 */
+		public RadioButtonCellEditor() {
+			super(new JTextField());
+		}
+		
+		@Override
+		public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
+			jRadioButton.setSelected((Boolean)value);
+			return jRadioButton;
+		}
+		
+		@Override
+		public Object getCellEditorValue() {
+			return Boolean.valueOf(jRadioButton.isSelected());
+		}
+	}
+	
+	public static void main(String[] args) {
+		JFrame frame = new JFrame();
+		frame.setLayout(new BorderLayout());
+		frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
+		
+		Random random = new Random(System.currentTimeMillis());
+		AnimationsTable table = new AnimationsTable();
+		int objectsCount = random.nextInt(5) + 1;
+		for(int i=1;i<=objectsCount;++i) {
+			int animsCount = random.nextInt(7) + 1;
+			for(int j=1;j<=animsCount;++j) {
+				((DefaultTableModel)table.getModel()).addRow(new Object[] {Boolean.FALSE, "Obiekt" + i, "Animacja" + j, "Start" + j, "Stop" + j});
+			}
+		}
+		((DefaultTableModel)table.getModel()).addRow(new Object[] {Boolean.FALSE, "Obiekt1", "xxx", "xxx", "xxx"});
+		JScrollPane jScrollPane = new JScrollPane(table, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+		frame.add(jScrollPane, BorderLayout.CENTER);
+		frame.pack();
+		frame.setVisible(true);
+	}
+}

+ 127 - 0
engine/src/test/jme3test/blender/config/BlenderKeyConfiguration.java

@@ -0,0 +1,127 @@
+package jme3test.blender.config;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.logging.Level;
+
+import com.jme3.asset.BlenderKey;
+import com.jme3.asset.ModelKey;
+import com.jme3.export.InputCapsule;
+import com.jme3.export.JmeExporter;
+import com.jme3.export.JmeImporter;
+import com.jme3.export.OutputCapsule;
+import com.jme3.export.Savable;
+
+/**
+ * This class holds the configuration for all the files.
+ * It can be saved and loaded using jme mechanisms.
+ * @author Marcin Roguski (Kaelthas)
+ */
+public class BlenderKeyConfiguration implements Savable {
+	/**
+	 * The key is a directory of blender_version_folder.
+	 * The value is the map between the blender file name and its blender key.
+	 */
+    /*package*/ Map<String, Map<String, BlenderKey>> blenderKeys;
+    /** List of selected animations for each object. An object can have one active animations.*/
+    /*package*/ Map<String, List<String[]>> selectedAnimations;
+    /** The last version of blender opened. */
+    /*package*/ String lastVersionUsed;
+    /** The last used blender key for each blender version. */
+    /*package*/ Map<String, BlenderKey> lastUsedKey;
+    /** Last used log level. */
+    /*package*/ Level logLevel;
+    /** This variable tells if the model or blender loader is used. */
+    /*package*/ boolean useModelKey;
+    
+    /**
+     * Constructor that creates new empty configuration for every blender file.
+     * Also used for jme serialization.
+     */
+    public BlenderKeyConfiguration() {
+    	blenderKeys = new HashMap<String, Map<String, BlenderKey>>();
+    	selectedAnimations = new HashMap<String, List<String[]>>();
+    	lastUsedKey = new HashMap<String, BlenderKey>();
+    	logLevel = Level.INFO;
+	}
+
+    /**
+     * This method returns the name of the last used asset folder.
+     * @return the name of the last used asset folder
+     */
+    public String getLastVersionUsed() {
+		return lastVersionUsed;
+	}
+    
+    /**
+     * This method returns the log level of jme app.
+     * @return the log level of jme app
+     */
+    public Level getLogLevel() {
+		return logLevel;
+	}
+    
+    /**
+     * This method returns the key that will be used during the test.
+     * @return the key that will be used during the test
+     */
+    public ModelKey getKeyToUse() {
+        return useModelKey ? new ModelKey(lastUsedKey.get(lastVersionUsed).getName()) : lastUsedKey.get(lastVersionUsed);
+    }
+
+    @Override
+    public void write(JmeExporter ex) throws IOException {
+        OutputCapsule oc = ex.getCapsule(this);
+        oc.write(blenderKeys.size(), "versions-count", 0);
+        int i=0;
+        for(Entry<String, Map<String, BlenderKey>> entry : blenderKeys.entrySet()) {
+        	oc.write(entry.getKey(), "key" + i, null);
+        	oc.writeStringSavableMap(entry.getValue(), "value" + i++, null);
+        }
+        oc.writeStringSavableMap(lastUsedKey, "last-key", null);
+        if(selectedAnimations==null) {
+        	oc.write(0, "selected-animations-count", 0);
+        } else {
+        	i = 0;
+        	oc.write(selectedAnimations.size(), "selected-animations-count", 0);
+        	for(Entry<String, List<String[]>> entry : selectedAnimations.entrySet()) {
+        		oc.write(entry.getKey(), "animKey" + i, null);
+        		oc.write(entry.getValue().toArray(new String[selectedAnimations.size()][]), "animVal" + i++, null);
+        	}
+        }
+        oc.write(useModelKey, "use-model-key", false);
+        oc.write(logLevel == null ? null : logLevel.getName(), "log-level", Level.INFO.getName());
+        oc.write(lastVersionUsed, "versionUsed", null);
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public void read(JmeImporter im) throws IOException {
+        InputCapsule ic = im.getCapsule(this);
+        int versionsCount = ic.readInt("versions-count", 0);
+        for(int i=0;i<versionsCount;++i) {
+        	String versionName = ic.readString("key" + i, null);
+        	Map<String, BlenderKey> versionBlenderFiles = (Map<String, BlenderKey>) ic.readStringSavableMap("value" + i, null);
+        	blenderKeys.put(versionName, versionBlenderFiles);
+        }
+        
+        int selectedAnimCount = ic.readInt("selected-animations-count", 0);
+        if(selectedAnimCount > 0) {
+        	for(int i=0;i<selectedAnimCount;++i) {
+        		String blenderKeyName = ic.readString("animKey" + i, null);
+        		String[][] selectedAnimations = ic.readStringArray2D("animVal" + i, null);
+        		List<String[]> anims = Arrays.asList(selectedAnimations);
+        		this.selectedAnimations.put(blenderKeyName, anims);
+        	}
+        }
+        lastUsedKey = (Map<String, BlenderKey>) ic.readStringSavableMap("last-key", null);
+        useModelKey = ic.readBoolean("use-model-key", false);
+        String logLevelName = ic.readString("log-level", Level.INFO.getName());
+        logLevel = logLevelName == null ? Level.INFO : Level.parse(logLevelName);
+        lastVersionUsed = ic.readString("versionUsed", null);
+    }
+}

+ 39 - 97
engine/src/test/jme3test/blender/config/ConfigDialog.java

@@ -10,7 +10,9 @@ import java.io.FileFilter;
 import java.io.IOException;
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.logging.Level;
@@ -26,11 +28,7 @@ import javax.swing.event.TableModelListener;
 import javax.swing.table.DefaultTableModel;
 
 import com.jme3.asset.BlenderKey;
-import com.jme3.asset.ModelKey;
-import com.jme3.export.InputCapsule;
 import com.jme3.export.JmeExporter;
-import com.jme3.export.JmeImporter;
-import com.jme3.export.OutputCapsule;
 import com.jme3.export.Savable;
 import com.jme3.export.binary.BinaryExporter;
 import com.jme3.export.binary.BinaryImporter;
@@ -159,6 +157,26 @@ public class ConfigDialog extends AbstractConfigDialog {
         
         //enlisting the files in the list
         this.reloadFilesList();
+        
+        //apply animations selection
+        DefaultTableModel model = (DefaultTableModel) jTableAnimations.getModel();
+        BlenderKey blenderKey = blenderKeyConfiguration.lastUsedKey.get(blenderKeyConfiguration.lastVersionUsed);
+        if(blenderKey != null) {
+	        String blenderKeyName = blenderKey.getName();
+	        List<String[]> selectedAnimations = blenderKeyConfiguration.selectedAnimations.get(blenderKeyName);
+	        if(selectedAnimations != null) {
+		        for(String[] selectedAnimation : selectedAnimations) {
+		        	for(int i=0;i<model.getRowCount();++i) {
+		        		String objectName = (String) model.getValueAt(i, 1);
+		        		String animationName = (String) model.getValueAt(i, 2);
+		        		if(selectedAnimation[0].equals(objectName) && selectedAnimation[1].equals(animationName)) {
+		        			model.setValueAt(Boolean.TRUE, i, 0);
+		        			break;
+		        		}
+		        	}
+		        }
+	        }
+        }
     }
     
     /**
@@ -227,7 +245,7 @@ public class ConfigDialog extends AbstractConfigDialog {
             for (Entry<String, Map<String, int[]>> animationEntry : animations.entrySet()) {
                 for (Entry<String, int[]> animDataEntry : animationEntry.getValue().entrySet()) {
                     int[] frames = animDataEntry.getValue();
-                    animationsModel.addRow(new Object[]{animationEntry.getKey(), animDataEntry.getKey(),
+                    animationsModel.addRow(new Object[]{Boolean.FALSE, animationEntry.getKey(), animDataEntry.getKey(),
                                 Integer.valueOf(frames[0]), Integer.valueOf(frames[1])});
                 }
             }
@@ -243,6 +261,7 @@ public class ConfigDialog extends AbstractConfigDialog {
      * @param configuration the blender config to store
      */
     private void storeConfig(BlenderKeyConfiguration configuration) {
+    	configuration.selectedAnimations.clear();
     	BlenderKey blenderKey = configuration.lastUsedKey.get(configuration.lastVersionUsed);
         if (blenderKey != null) {//reading animations
             DefaultTableModel animationsTableModel = (DefaultTableModel) jTableAnimations.getModel();
@@ -250,15 +269,23 @@ public class ConfigDialog extends AbstractConfigDialog {
             	blenderKey.getAnimations().clear();
             }
             int animCounter = 0;
+            List<String[]> selectedAnimations = new ArrayList<String[]>();
             for (int i = 0; i < animationsTableModel.getRowCount(); ++i) {
-                String objectName = (String) animationsTableModel.getValueAt(i, 0);
-                String animName = (String) animationsTableModel.getValueAt(i, 1);
-                Number startFrame = (Number) animationsTableModel.getValueAt(i, 2);
-                Number stopFrame = (Number) animationsTableModel.getValueAt(i, 3);
+            	Boolean isSelected = (Boolean) animationsTableModel.getValueAt(i, 0);
+                String objectName = (String) animationsTableModel.getValueAt(i, 1);
+                String animName = (String) animationsTableModel.getValueAt(i, 2);
+                Number startFrame = (Number) animationsTableModel.getValueAt(i, 3);
+                Number stopFrame = (Number) animationsTableModel.getValueAt(i, 4);
                 if (objectName != null && animName != null && startFrame.intValue() <= stopFrame.intValue()) {
                 	blenderKey.addAnimation(objectName, animName, startFrame.intValue(), stopFrame.intValue());
                     ++animCounter;
                 }
+                if(isSelected) {
+                	selectedAnimations.add(new String[] {objectName, animName});
+                }
+            }
+            if(selectedAnimations.size() > 0) {
+            	configuration.selectedAnimations.put(blenderKey.getName(), selectedAnimations);
             }
             if (animCounter < animationsTableModel.getRowCount()) {
                 JOptionPane.showMessageDialog(ConfigDialog.this, "Some animations had errors!\nThey had not been added!",
@@ -365,7 +392,7 @@ public class ConfigDialog extends AbstractConfigDialog {
 
             @Override
             public void actionPerformed(ActionEvent evt) {
-                ((DefaultTableModel) jTableAnimations.getModel()).addRow(new Object[]{"", "", Integer.valueOf(-1), Integer.valueOf(-1)});
+                ((DefaultTableModel) jTableAnimations.getModel()).addRow(new Object[]{Boolean.FALSE, "", "", Integer.valueOf(1), Integer.valueOf(25)});
             }
         });
         jButtonRemoveAnimation.addActionListener(new ActionListener() {
@@ -390,95 +417,10 @@ public class ConfigDialog extends AbstractConfigDialog {
 
             @Override
             public void actionPerformed(ActionEvent evt) {
+            	ConfigDialog.this.storeConfig(blenderKeyConfiguration);
+            	blenderKeyConfiguration = null;
                 ConfigDialog.this.dispose();
             }
         });
     }
-
-    /**
-     * This class holds the configuration for all the files.
-     * It can be saved and loaded using jme mechanisms.
-     * @author Marcin Roguski (Kaelthas)
-     */
-    public static class BlenderKeyConfiguration implements Savable {
-    	/**
-    	 * The key is a directory of blender_version_folder.
-    	 * The value is the map between the blender file name and its blender key.
-    	 */
-        private Map<String, Map<String, BlenderKey>> blenderKeys;
-        /** The last version of blender opened. */
-        private String lastVersionUsed;
-        /** The last used blender key for each blender version. */
-        private Map<String, BlenderKey> lastUsedKey;
-        /** Last used log level. */
-        private Level logLevel;
-        /** This variable tells if the model or blender loader is used. */
-        private boolean useModelKey;
-        
-        /**
-         * Constructor that creates new empty configuration for every blender file.
-         * Also used for jme serialization.
-         */
-        public BlenderKeyConfiguration() {
-        	blenderKeys = new HashMap<String, Map<String, BlenderKey>>();
-        	lastUsedKey = new HashMap<String, BlenderKey>();
-        	logLevel = Level.INFO;
-		}
-
-        /**
-         * This method returns the name of the last used asset folder.
-         * @return the name of the last used asset folder
-         */
-        public String getLastVersionUsed() {
-			return lastVersionUsed;
-		}
-        
-        /**
-         * This method returns the log level of jme app.
-         * @return the log level of jme app
-         */
-        public Level getLogLevel() {
-			return logLevel;
-		}
-        
-        /**
-         * This method returns the key that will be used during the test.
-         * @return the key that will be used during the test
-         */
-        public ModelKey getKeyToUse() {
-            return useModelKey ? new ModelKey(lastUsedKey.get(lastVersionUsed).getName()) : lastUsedKey.get(lastVersionUsed);
-        }
-
-        @Override
-        public void write(JmeExporter ex) throws IOException {
-            OutputCapsule oc = ex.getCapsule(this);
-            oc.write(blenderKeys.size(), "versions-count", 0);
-            int i=0;
-            for(Entry<String, Map<String, BlenderKey>> entry : blenderKeys.entrySet()) {
-            	oc.write(entry.getKey(), "key" + i, null);
-            	oc.writeStringSavableMap(entry.getValue(), "value" + i++, null);
-            }
-            oc.writeStringSavableMap(lastUsedKey, "last-key", null);
-            oc.write(useModelKey, "use-model-key", false);
-            oc.write(logLevel == null ? null : logLevel.getName(), "log-level", Level.INFO.getName());
-            oc.write(lastVersionUsed, "versionUsed", null);
-        }
-
-        @Override
-        @SuppressWarnings("unchecked")
-        public void read(JmeImporter im) throws IOException {
-            InputCapsule ic = im.getCapsule(this);
-            int versionsCount = ic.readInt("versions-count", 0);
-            for(int i=0;i<versionsCount;++i) {
-            	String versionName = ic.readString("key" + i, null);
-            	Map<String, BlenderKey> versionBlenderFiles = (Map<String, BlenderKey>) ic.readStringSavableMap("value" + i, null);
-            	blenderKeys.put(versionName, versionBlenderFiles);
-            }
-            lastUsedKey = (Map<String, BlenderKey>) ic.readStringSavableMap("last-key", null);
-            useModelKey = ic.readBoolean("use-model-key", false);
-            String logLevelName = ic.readString("log-level", Level.INFO.getName());
-            logLevel = logLevelName == null ? Level.INFO : Level.parse(logLevelName);
-            lastVersionUsed = ic.readString("versionUsed", null);
-        }
-    }
 }