Home | History | Annotate | Download | only in flame
      1 package com.badlogic.gdx.tools.flame;
      2 
      3 import java.awt.Dimension;
      4 import java.awt.GridBagConstraints;
      5 import java.awt.GridBagLayout;
      6 import java.awt.Insets;
      7 import java.awt.event.ActionEvent;
      8 import java.awt.event.ActionListener;
      9 
     10 import javax.swing.DefaultComboBoxModel;
     11 import javax.swing.JButton;
     12 import javax.swing.JComboBox;
     13 import javax.swing.JPanel;
     14 import javax.swing.JScrollPane;
     15 import javax.swing.JTable;
     16 import javax.swing.ListSelectionModel;
     17 import javax.swing.event.ListSelectionEvent;
     18 import javax.swing.event.ListSelectionListener;
     19 import javax.swing.event.TableModelEvent;
     20 import javax.swing.event.TableModelListener;
     21 import javax.swing.table.DefaultTableModel;
     22 
     23 import com.badlogic.gdx.graphics.g3d.particles.ParticleController;
     24 import com.badlogic.gdx.graphics.g3d.particles.influencers.DynamicsInfluencer;
     25 import com.badlogic.gdx.graphics.g3d.particles.influencers.DynamicsModifier;
     26 import com.badlogic.gdx.graphics.g3d.particles.influencers.DynamicsModifier.BrownianAcceleration;
     27 import com.badlogic.gdx.graphics.g3d.particles.influencers.DynamicsModifier.CentripetalAcceleration;
     28 import com.badlogic.gdx.graphics.g3d.particles.influencers.DynamicsModifier.FaceDirection;
     29 import com.badlogic.gdx.graphics.g3d.particles.influencers.DynamicsModifier.PolarAcceleration;
     30 import com.badlogic.gdx.graphics.g3d.particles.influencers.DynamicsModifier.Rotational3D;
     31 import com.badlogic.gdx.graphics.g3d.particles.influencers.DynamicsModifier.TangentialAcceleration;
     32 import com.badlogic.gdx.tools.flame.FlameMain.ControllerType;
     33 import com.badlogic.gdx.utils.Array;
     34 
     35 /** @author Inferno */
     36 public class DynamicsInfluencerPanel extends InfluencerPanel<DynamicsInfluencer> {
     37 
     38 	private static final String 	VEL_TYPE_ROTATIONAL_2D = "Angular Velocity 2D",
     39 															VEL_TYPE_ROTATIONAL_3D = "Angular Velocity 3D",
     40 											VEL_TYPE_CENTRIPETAL = "Centripetal",
     41 											VEL_TYPE_TANGENTIAL = "Tangential",
     42 											VEL_TYPE_POLAR = "Polar",
     43 											VEL_TYPE_BROWNIAN = "Brownian",
     44 											VEL_TYPE_FACE = "Face";
     45 
     46 	protected class VelocityWrapper{
     47 		public DynamicsModifier velocityValue;
     48 		public boolean isActive;
     49 
     50 		public VelocityWrapper(DynamicsModifier value, boolean isActive){
     51 			this.velocityValue =  value;
     52 			this.isActive = isActive;
     53 		}
     54 	}
     55 
     56 	JComboBox velocityBox;
     57 	JTable velocityTable;
     58 	DefaultTableModel velocityTableModel;
     59 	JPanel selectedVelocityPanel;
     60 	AngularVelocityPanel angularVelocityPanel;
     61 	StrengthVelocityPanel strengthVelocityPanel;
     62 	ParticleValuePanel emptyPanel;
     63 	Array<VelocityWrapper> velocities;
     64 
     65 	public DynamicsInfluencerPanel (FlameMain editor, DynamicsInfluencer influencer) {
     66 		super(editor, influencer, "Dynamics Influencer",
     67 							"Defines how the particles dynamics (acceleration, angular velocity).");
     68 		velocities = new Array<VelocityWrapper>();
     69 		setValue(value);
     70 		set(influencer);
     71 	}
     72 
     73 	private void set (DynamicsInfluencer influencer) {
     74 		//Clear
     75 		for (int i = velocityTableModel.getRowCount() - 1; i >= 0; i--) {
     76 			velocityTableModel.removeRow(i);
     77 		}
     78 		velocities.clear();
     79 
     80 		//Add
     81 		for(int i=0, c = influencer.velocities.size; i < c; ++i){
     82 			velocities.add(new VelocityWrapper((DynamicsModifier)influencer.velocities.items[i], true));
     83 			velocityTableModel.addRow(new Object[] {"Velocity "+i, true});
     84 		}
     85 
     86 		DefaultComboBoxModel model = (DefaultComboBoxModel) velocityBox.getModel();
     87 		model.removeAllElements();
     88 		for(Object velocityObject : getAvailableVelocities(editor.getControllerType())){
     89 			model.addElement(velocityObject);
     90 		}
     91 	}
     92 
     93 	private Object[] getAvailableVelocities (ControllerType type) {
     94 		if(type == ControllerType.Billboard || type == ControllerType.PointSprite) {
     95 			return new String[]{	VEL_TYPE_ROTATIONAL_2D, VEL_TYPE_CENTRIPETAL, VEL_TYPE_TANGENTIAL,
     96 				VEL_TYPE_POLAR, VEL_TYPE_BROWNIAN};
     97 		}
     98 		else if(type == ControllerType.ModelInstance|| type == ControllerType.ParticleController) {
     99 			return new String[]{	VEL_TYPE_ROTATIONAL_3D, VEL_TYPE_CENTRIPETAL, VEL_TYPE_TANGENTIAL,
    100 				VEL_TYPE_POLAR, VEL_TYPE_BROWNIAN, VEL_TYPE_FACE};
    101 		}
    102 		return null;
    103 	}
    104 
    105 	protected void initializeComponents () {
    106 		super.initializeComponents();
    107 		JPanel velocitiesPanel = new JPanel();
    108 		velocitiesPanel.setLayout(new GridBagLayout());
    109 		{
    110 			JPanel sideButtons = new JPanel(new GridBagLayout());
    111 			velocitiesPanel.add(sideButtons, new GridBagConstraints(1, 0, 1, 1, 1, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE,
    112 				new Insets(0, 0, 0, 0), 0, 0));
    113 			{
    114 				sideButtons.add(velocityBox = new JComboBox(new DefaultComboBoxModel()),
    115 					new GridBagConstraints(0, -1, 1, 1, 0, 0, GridBagConstraints.CENTER,
    116 					GridBagConstraints.HORIZONTAL, new Insets(0, 0, 6, 0), 0, 0));
    117 			}
    118 			{
    119 				JButton newButton = new JButton("New");
    120 				sideButtons.add(newButton, new GridBagConstraints(0, -1, 1, 1, 0, 0, GridBagConstraints.CENTER,
    121 					GridBagConstraints.HORIZONTAL, new Insets(0, 0, 6, 0), 0, 0));
    122 				newButton.addActionListener(new ActionListener() {
    123 					public void actionPerformed (ActionEvent event) {
    124 						createVelocity(velocityBox.getSelectedItem());
    125 					}
    126 				});
    127 			}
    128 			{
    129 				JButton deleteButton = new JButton("Delete");
    130 				sideButtons.add(deleteButton, new GridBagConstraints(0, -1, 1, 1, 0, 0, GridBagConstraints.CENTER,
    131 					GridBagConstraints.HORIZONTAL, new Insets(0, 0, 6, 0), 0, 0));
    132 				deleteButton.addActionListener(new ActionListener() {
    133 					public void actionPerformed (ActionEvent event) {
    134 						deleteVelocity();
    135 					}
    136 				});
    137 			}
    138 		}
    139 		JScrollPane scroll = new JScrollPane();
    140 		velocitiesPanel.add(scroll, new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0,
    141 			0, 0, 6), 0, 0));
    142 		velocityTable = new JTable() {
    143 			public Class getColumnClass (int column) {
    144 				return column == 1 ? Boolean.class : super.getColumnClass(column);
    145 			}
    146 
    147 			@Override
    148 			public Dimension getPreferredScrollableViewportSize () {
    149 				Dimension dim = super.getPreferredScrollableViewportSize();
    150 				dim.height = getPreferredSize().height;
    151 				return dim;
    152 			}
    153 		};
    154 		velocityTable.getTableHeader().setReorderingAllowed(false);
    155 		velocityTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    156 		scroll.setViewportView(velocityTable);
    157 		velocityTableModel = new DefaultTableModel(new String[0][0], new String[] {"Velocity", "Active"});
    158 		velocityTable.setModel(velocityTableModel);
    159 		velocityTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
    160 			public void valueChanged (ListSelectionEvent event) {
    161 				if (event.getValueIsAdjusting()) return;
    162 				velocitySelected();
    163 			}
    164 		});
    165 		velocityTableModel.addTableModelListener(new TableModelListener() {
    166 			public void tableChanged (TableModelEvent event) {
    167 				if (event.getColumn() != 1) return;
    168 				velocityChecked(event.getFirstRow(), (Boolean)velocityTable.getValueAt(event.getFirstRow(), 1));
    169 			}
    170 		});
    171 
    172 		//Velocity values
    173 		emptyPanel = new ParticleValuePanel(editor, "", "",true, false);
    174 		strengthVelocityPanel = new StrengthVelocityPanel(editor, null, "Life", "", "");
    175 		angularVelocityPanel = new AngularVelocityPanel(editor, null, "Life", "", "");
    176 		strengthVelocityPanel.setVisible(false);
    177 		angularVelocityPanel.setVisible(false);
    178 		emptyPanel.setVisible(false);
    179 		strengthVelocityPanel.setIsAlwayShown(true);
    180 		angularVelocityPanel.setIsAlwayShown(true);
    181 		emptyPanel.setIsAlwayShown(true);
    182 		emptyPanel.setValue(null);
    183 
    184 		//Assemble
    185 		int i=0;
    186 		addContent(i++, 0, velocitiesPanel);
    187 		addContent(i++, 0, strengthVelocityPanel);
    188 		addContent(i++, 0, angularVelocityPanel);
    189 		addContent(i++, 0, emptyPanel);
    190 	}
    191 
    192 	protected void velocityChecked (int index, boolean isChecked) {
    193 		ParticleController controller = editor.getEmitter();
    194 		DynamicsInfluencer influencer = (DynamicsInfluencer)controller.findInfluencer(DynamicsInfluencer.class);
    195 		influencer.velocities.clear();
    196 		velocities.get(index).isActive = isChecked;
    197 		for(VelocityWrapper wrapper : velocities){
    198 			if(wrapper.isActive)
    199 				influencer.velocities.add(wrapper.velocityValue);
    200 		}
    201 		//Restart the effect and reinit the controller
    202 		editor.restart();
    203 	}
    204 
    205 	protected void velocitySelected () {
    206 		//Show the velocity value panel
    207 		int index = velocityTable.getSelectedRow();
    208 		if(index == -1) return;
    209 
    210 		DynamicsModifier velocityValue = velocities.get(index).velocityValue;
    211 		EditorPanel velocityPanel = getVelocityPanel(velocityValue);
    212 
    213 		//Show the selected velocity
    214 		if(selectedVelocityPanel != null && selectedVelocityPanel != velocityPanel)
    215 			selectedVelocityPanel.setVisible(false);
    216 		velocityPanel.setVisible(true);
    217 		velocityPanel.showContent(true);
    218 		selectedVelocityPanel = velocityPanel;
    219 	}
    220 
    221 	private EditorPanel getVelocityPanel (DynamicsModifier velocityValue) {
    222 		EditorPanel panel = null;
    223 		//Billboards
    224 		if(velocityValue instanceof DynamicsModifier.Rotational2D ){
    225 			strengthVelocityPanel.setValue((DynamicsModifier.Strength) velocityValue);
    226 			strengthVelocityPanel.setName("Angular Velocity");
    227 			strengthVelocityPanel.setDescription("The angular speed around the billboard facing direction, in degrees/sec .");
    228 			panel = strengthVelocityPanel;
    229 		}
    230 		else if(	velocityValue instanceof CentripetalAcceleration){
    231 			strengthVelocityPanel.setValue((DynamicsModifier.CentripetalAcceleration) velocityValue);
    232 			strengthVelocityPanel.setName("Centripetal Acceleration");
    233 			strengthVelocityPanel.setDescription("A directional acceleration, the direction is towards the origin (global), or towards the emitter position (local), in world units/sec2 .");
    234 			panel = strengthVelocityPanel;
    235 		}
    236 		else if(	velocityValue instanceof TangentialAcceleration){
    237 			angularVelocityPanel.setValue((DynamicsModifier.Angular) velocityValue);
    238 			angularVelocityPanel.setName("Tangetial Velocity");
    239 			angularVelocityPanel.setDescription("A directional acceleration (axis and magnitude), the final direction is the cross product between particle position and the axis, in world units/sec2 .");
    240 			panel = angularVelocityPanel;
    241 		}
    242 		else if(	velocityValue instanceof PolarAcceleration){
    243 			angularVelocityPanel.setValue((DynamicsModifier.Angular) velocityValue);
    244 			angularVelocityPanel.setName("Polar Velocity");
    245 			angularVelocityPanel.setDescription("A directional acceleration (axis and magnitude), in world units/sec2 .");
    246 			panel = angularVelocityPanel;
    247 		}
    248 		else if(	velocityValue instanceof BrownianAcceleration){
    249 			strengthVelocityPanel.setValue((DynamicsModifier.Strength) velocityValue);
    250 			strengthVelocityPanel.setName("Brownian Velocity");
    251 			strengthVelocityPanel.setDescription("A directional acceleration which has random direction at each update, in world units/sec2.");
    252 			panel = strengthVelocityPanel;
    253 		}
    254 		else if(velocityValue instanceof Rotational3D ){
    255 			angularVelocityPanel.setValue((DynamicsModifier.Angular) velocityValue);
    256 			angularVelocityPanel.setName("Angular Velocity");
    257 			angularVelocityPanel.setDescription("An angular velocity (axis and magnitude), in degree/sec2.");
    258 			panel = angularVelocityPanel;
    259 		}
    260 		else if(	velocityValue instanceof FaceDirection){
    261 			emptyPanel.setName("Face");
    262 			emptyPanel.setDescription("Rotates the model to face its current velocity (Do not add any other angular velocity when using this).");
    263 			panel = emptyPanel;
    264 		}
    265 
    266 		return panel;
    267 	}
    268 
    269 	private DynamicsModifier createVelocityValue (Object selectedItem) {
    270 		DynamicsModifier velocityValue = null;
    271 		if(selectedItem == VEL_TYPE_ROTATIONAL_2D) velocityValue = new DynamicsModifier.Rotational2D();
    272 		else if(selectedItem == VEL_TYPE_ROTATIONAL_3D) velocityValue = new DynamicsModifier.Rotational3D();
    273 		else if(selectedItem == VEL_TYPE_CENTRIPETAL) velocityValue = new DynamicsModifier.CentripetalAcceleration();
    274 		else if(selectedItem == VEL_TYPE_TANGENTIAL) velocityValue = new DynamicsModifier.TangentialAcceleration();
    275 		else if(selectedItem == VEL_TYPE_POLAR) velocityValue = new DynamicsModifier.PolarAcceleration();
    276 		else if(selectedItem == VEL_TYPE_BROWNIAN) velocityValue = new DynamicsModifier.BrownianAcceleration();
    277 		else if(selectedItem == VEL_TYPE_FACE) velocityValue = new DynamicsModifier.FaceDirection();
    278 		return velocityValue;
    279 	}
    280 
    281 
    282 	protected void deleteVelocity () {
    283 		int row = velocityTable.getSelectedRow();
    284 		if (row == -1) return;
    285 
    286 		//Remove the velocity from the table
    287 		ParticleController controller = editor.getEmitter();
    288 		DynamicsInfluencer influencer = (DynamicsInfluencer)controller.findInfluencer(DynamicsInfluencer.class);
    289 		influencer.velocities.removeValue(velocities.removeIndex(row).velocityValue, true);
    290 		velocityTableModel.removeRow(row);
    291 
    292 		//Restart the effect and reinit the controller
    293 		editor.restart();
    294 
    295 		selectedVelocityPanel.setVisible(false);
    296 		selectedVelocityPanel = null;
    297 	}
    298 
    299 	protected void createVelocity (Object selectedItem) {
    300 		//Add the velocity to the table and to the influencer
    301 		ParticleController controller = editor.getEmitter();
    302 		DynamicsInfluencer influencer = (DynamicsInfluencer)controller.findInfluencer(DynamicsInfluencer.class);
    303 		VelocityWrapper wrapper = new VelocityWrapper(createVelocityValue(selectedItem), true);
    304 		velocities.add(wrapper);
    305 		influencer.velocities.add(wrapper.velocityValue);
    306 		int index = velocities.size-1;
    307 		velocityTableModel.addRow(new Object[] {"Velocity "+index, true});
    308 
    309 		//Reinit
    310 		editor.restart();
    311 
    312 		//Select new velocity
    313 		velocityTable.getSelectionModel().setSelectionInterval(index, index);
    314 		revalidate();
    315 		repaint();
    316 	}
    317 
    318 }
    319