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
3.0
Kae..pl 14 years ago
parent 06264e69bf
commit e911e3299e
  1. 4
      engine/src/test/jme3test/blender/ManualBlenderTester.java
  2. 9
      engine/src/test/jme3test/blender/config/AbstractConfigDialog.java
  3. 185
      engine/src/test/jme3test/blender/config/AnimationsTable.java
  4. 127
      engine/src/test/jme3test/blender/config/BlenderKeyConfiguration.java
  5. 136
      engine/src/test/jme3test/blender/config/ConfigDialog.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,8 +92,10 @@ public class ManualBlenderTester extends SimpleApplication {
//running the application
ConfigDialog configDialog = new ConfigDialog("./src/test-data/Blender");
BlenderKeyConfiguration bkk = configDialog.getBlenderKeyConfiguration();
if(bkk != null) {
new ManualBlenderTester(bkk, debugMode).start();
}
}
/**
* Constructor stores the given key and disables the settings screen.

@ -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);

@ -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);
}
}

@ -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);
}
}

@ -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);
}
}
}

Loading…
Cancel
Save