com.badlogic.gdx.tools.particleeditor.EffectPanel Maven / Gradle / Ivy
The newest version!
/*******************************************************************************
* Copyright 2011 See AUTHORS file.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package com.badlogic.gdx.tools.particleeditor;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileWriter;
import java.io.Writer;
import java.net.URI;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableModel;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.g2d.ParticleEffect;
import com.badlogic.gdx.graphics.g2d.ParticleEmitter;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.StreamUtils;
class EffectPanel extends JPanel {
ParticleEditor editor;
JTable emitterTable;
DefaultTableModel emitterTableModel;
int editIndex;
String lastDir;
public EffectPanel (ParticleEditor editor) {
this.editor = editor;
initializeComponents();
}
public ParticleEmitter newEmitter (String name, boolean select) {
final ParticleEmitter emitter = new ParticleEmitter();
emitter.getDuration().setLow(1000);
emitter.getEmission().setHigh(50);
emitter.getLife().setHigh(500);
emitter.getXScale().setHigh(32, 32);
emitter.getTint().setColors(new float[] {1, 0.12156863f, 0.047058824f});
emitter.getTransparency().setHigh(1);
emitter.setMaxParticleCount(25);
emitter.setImagePaths(new Array(new String[] {ParticleEditor.DEFAULT_PARTICLE}));
addEmitter(name, select, emitter);
return emitter;
}
public ParticleEmitter newExampleEmitter (String name, boolean select) {
final ParticleEmitter emitter = new ParticleEmitter();
emitter.getDuration().setLow(3000);
emitter.getEmission().setHigh(250);
emitter.getLife().setHigh(500, 1000);
emitter.getLife().setTimeline(new float[] {0, 0.66f, 1});
emitter.getLife().setScaling(new float[] {1, 1, 0.3f});
emitter.getXScale().setHigh(32, 32);
emitter.getRotation().setLow(1, 360);
emitter.getRotation().setHigh(180, 180);
emitter.getRotation().setTimeline(new float[] {0, 1});
emitter.getRotation().setScaling(new float[] {0, 1});
emitter.getRotation().setRelative(true);
emitter.getAngle().setHigh(45, 135);
emitter.getAngle().setLow(90);
emitter.getAngle().setTimeline(new float[] {0, 0.5f, 1});
emitter.getAngle().setScaling(new float[] {1, 0, 0});
emitter.getAngle().setActive(true);
emitter.getVelocity().setHigh(30, 300);
emitter.getVelocity().setActive(true);
emitter.getTint().setColors(new float[] {1, 0.12156863f, 0.047058824f});
emitter.getTransparency().setHigh(1, 1);
emitter.getTransparency().setTimeline(new float[] {0, 0.2f, 0.8f, 1});
emitter.getTransparency().setScaling(new float[] {0, 1, 0.75f, 0});
emitter.setMaxParticleCount(200);
emitter.setImagePaths(new Array(new String[] {ParticleEditor.DEFAULT_PARTICLE}));
addEmitter(name, select, emitter);
return emitter;
}
private void addEmitter (String name, boolean select, final ParticleEmitter emitter) {
Array emitters = editor.effect.getEmitters();
if (emitters.size == 0)
emitter.setPosition(editor.worldCamera.viewportWidth / 2, editor.worldCamera.viewportHeight / 2);
else {
ParticleEmitter p = emitters.get(0);
emitter.setPosition(p.getX(), p.getY());
}
emitters.add(emitter);
emitterTableModel.addRow(new Object[] {name, true});
if (select) {
editor.reloadRows();
int row = emitterTableModel.getRowCount() - 1;
emitterTable.getSelectionModel().setSelectionInterval(row, row);
}
}
void emitterSelected () {
int row = emitterTable.getSelectedRow();
if (row <= -1 || row >= emitterTableModel.getRowCount()) {
// During move up/down row can be -1 because called from modifyValue callback in table
// No selection update should be made while swapping rows
return;
}
if (row == editIndex) return;
editIndex = row;
editor.reloadRows();
}
void openEffect (boolean mergeIntoCurrent) {
FileDialog dialog = new FileDialog(editor, "Open Effect", FileDialog.LOAD);
if (lastDir != null) dialog.setDirectory(lastDir);
dialog.setVisible(true);
final String file = dialog.getFile();
final String dir = dialog.getDirectory();
if (dir == null || file == null || file.trim().length() == 0) return;
lastDir = dir;
ParticleEffect effect = new ParticleEffect();
try {
File effectFile = new File(dir, file);
effect.loadEmitters(Gdx.files.absolute(effectFile.getAbsolutePath()));
if (mergeIntoCurrent) {
for (ParticleEmitter emitter : effect.getEmitters()) {
addEmitter(emitter.getName(), false, emitter);
}
} else {
editor.effect = effect;
editor.effectFile = effectFile;
}
emitterTableModel.getDataVector().removeAllElements();
editor.particleData.clear();
} catch (Exception ex) {
System.out.println("Error loading effect: " + new File(dir, file).getAbsolutePath());
ex.printStackTrace();
JOptionPane.showMessageDialog(editor, "Error opening effect.");
return;
}
for (ParticleEmitter emitter : new Array.ArrayIterator<>(editor.effect.getEmitters())) {
emitter.setPosition(editor.worldCamera.viewportWidth / 2, editor.worldCamera.viewportHeight / 2);
emitterTableModel.addRow(new Object[] {emitter.getName(), true});
}
editIndex = 0;
emitterTable.getSelectionModel().setSelectionInterval(editIndex, editIndex);
editor.reloadRows();
}
void saveEffect () {
FileDialog dialog = new FileDialog(editor, "Save Effect", FileDialog.SAVE);
if (lastDir != null) dialog.setDirectory(lastDir);
dialog.setVisible(true);
String file = dialog.getFile();
String dir = dialog.getDirectory();
if (dir == null || file == null || file.trim().length() == 0) return;
lastDir = dir;
int index = 0;
File effectFile = new File(dir, file);
// save each image path as relative path to effect file directory
URI effectDirUri = effectFile.getParentFile().toURI();
for (ParticleEmitter emitter : editor.effect.getEmitters()) {
emitter.setName((String)emitterTableModel.getValueAt(index++, 0));
Array imagePaths = emitter.getImagePaths();
for (int i = 0; i < imagePaths.size; i++) {
String imagePath = imagePaths.get(i);
if ((imagePath.contains("/") || imagePath.contains("\\")) && !imagePath.contains("..")) {
// it's absolute, make it relative:
URI imageUri = new File(imagePath).toURI();
imagePaths.set(i, effectDirUri.relativize(imageUri).getPath());
}
}
}
File outputFile = new File(dir, file);
Writer fileWriter = null;
try {
fileWriter = new FileWriter(outputFile);
editor.effect.save(fileWriter);
} catch (Exception ex) {
System.out.println("Error saving effect: " + outputFile.getAbsolutePath());
ex.printStackTrace();
JOptionPane.showMessageDialog(editor, "Error saving effect.");
} finally {
StreamUtils.closeQuietly(fileWriter);
}
}
void duplicateEmitter () {
int row = emitterTable.getSelectedRow();
if (row == -1) return;
String name = (String)emitterTableModel.getValueAt(row, 0);
addEmitter(name, true, new ParticleEmitter(editor.effect.getEmitters().get(row)));
}
void deleteEmitter () {
if (editor.effect.getEmitters().size == 1) return;
int row = emitterTable.getSelectedRow();
if (row == -1) return;
if (row <= editIndex) {
int oldEditIndex = editIndex;
editIndex = Math.max(0, editIndex - 1);
if (oldEditIndex == row) editor.reloadRows();
}
editor.effect.getEmitters().removeIndex(row);
emitterTableModel.removeRow(row);
emitterTable.getSelectionModel().setSelectionInterval(editIndex, editIndex);
}
void move (int direction) {
if (direction < 0 && editIndex <= 0) return;
Array emitters = editor.effect.getEmitters();
if (direction > 0 && editIndex >= emitters.size - 1) return;
int insertIndex = editIndex + direction;
Object name = emitterTableModel.getValueAt(editIndex, 0);
Boolean active = (Boolean)emitterTableModel.getValueAt(editIndex, 1);
emitterTableModel.removeRow(editIndex);
ParticleEmitter emitter = emitters.removeIndex(editIndex);
emitterTableModel.insertRow(insertIndex, new Object[] {name, active});
emitters.insert(insertIndex, emitter);
editIndex = insertIndex;
emitterTable.getSelectionModel().setSelectionInterval(editIndex, editIndex);
}
void emitterChecked (int index, boolean checked) {
editor.setEnabled(editor.effect.getEmitters().get(index), checked);
editor.effect.start();
}
private void initializeComponents () {
setLayout(new GridBagLayout());
{
JPanel sideButtons = new JPanel(new GridBagLayout());
add(sideButtons, new GridBagConstraints(1, 0, 1, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.BOTH,
new Insets(0, 0, 0, 0), 0, 0));
{
JButton newButton = new JButton("New");
sideButtons.add(newButton, new GridBagConstraints(0, -1, 1, 1, 0, 0, GridBagConstraints.CENTER,
GridBagConstraints.HORIZONTAL, new Insets(0, 0, 6, 0), 0, 0));
newButton.addActionListener(new ActionListener() {
public void actionPerformed (ActionEvent event) {
newEmitter("Untitled", true);
}
});
}
{
JButton newButton = new JButton("Duplicate");
sideButtons.add(newButton, new GridBagConstraints(0, -1, 1, 1, 0, 0, GridBagConstraints.CENTER,
GridBagConstraints.HORIZONTAL, new Insets(0, 0, 6, 0), 0, 0));
newButton.addActionListener(new ActionListener() {
public void actionPerformed (ActionEvent event) {
duplicateEmitter();
}
});
}
{
JButton deleteButton = new JButton("Delete");
sideButtons.add(deleteButton, new GridBagConstraints(0, -1, 1, 1, 0, 0, GridBagConstraints.CENTER,
GridBagConstraints.HORIZONTAL, new Insets(0, 0, 6, 0), 0, 0));
deleteButton.addActionListener(new ActionListener() {
public void actionPerformed (ActionEvent event) {
deleteEmitter();
}
});
}
{
sideButtons.add(new JSeparator(JSeparator.HORIZONTAL), new GridBagConstraints(0, -1, 1, 1, 0, 0,
GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 6, 0), 0, 0));
}
{
JButton saveButton = new JButton("Save");
sideButtons.add(saveButton, new GridBagConstraints(0, -1, 1, 1, 0, 0, GridBagConstraints.CENTER,
GridBagConstraints.HORIZONTAL, new Insets(0, 0, 6, 0), 0, 0));
saveButton.addActionListener(new ActionListener() {
public void actionPerformed (ActionEvent event) {
saveEffect();
}
});
}
{
JButton openButton = new JButton("Open");
sideButtons.add(openButton, new GridBagConstraints(0, -1, 1, 1, 0, 0, GridBagConstraints.CENTER,
GridBagConstraints.HORIZONTAL, new Insets(0, 0, 6, 0), 0, 0));
openButton.addActionListener(new ActionListener() {
public void actionPerformed (ActionEvent event) {
openEffect(false);
}
});
}
{
JButton mergeButton = new JButton("Merge");
sideButtons.add(mergeButton, new GridBagConstraints(0, -1, 1, 1, 0, 0, GridBagConstraints.CENTER,
GridBagConstraints.HORIZONTAL, new Insets(0, 0, 6, 0), 0, 0));
mergeButton.addActionListener(new ActionListener() {
public void actionPerformed (ActionEvent event) {
openEffect(true);
}
});
}
{
JButton upButton = new JButton("Up");
sideButtons.add(upButton, new GridBagConstraints(0, -1, 1, 1, 0, 1, GridBagConstraints.SOUTH,
GridBagConstraints.HORIZONTAL, new Insets(0, 0, 6, 0), 0, 0));
upButton.addActionListener(new ActionListener() {
public void actionPerformed (ActionEvent event) {
move(-1);
}
});
}
{
JButton downButton = new JButton("Down");
sideButtons.add(downButton, new GridBagConstraints(0, -1, 1, 1, 0, 0, GridBagConstraints.CENTER,
GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
downButton.addActionListener(new ActionListener() {
public void actionPerformed (ActionEvent event) {
move(1);
}
});
}
}
{
JScrollPane scroll = new JScrollPane();
add(scroll, new GridBagConstraints(0, 0, 1, 1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH,
new Insets(0, 0, 0, 6), 0, 0));
{
emitterTable = new JTable() {
public Class getColumnClass (int column) {
return column == 1 ? Boolean.class : super.getColumnClass(column);
}
};
emitterTable.getTableHeader().setReorderingAllowed(false);
emitterTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
scroll.setViewportView(emitterTable);
emitterTableModel = new DefaultTableModel(new String[0][0], new String[] {"Emitter", "Active"});
emitterTable.setModel(emitterTableModel);
emitterTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
public void valueChanged (ListSelectionEvent event) {
if (event.getValueIsAdjusting()) return;
emitterSelected();
}
});
emitterTableModel.addTableModelListener(new TableModelListener() {
public void tableChanged (TableModelEvent event) {
if (event.getColumn() != 1) return;
emitterChecked(event.getFirstRow(), (Boolean)emitterTable.getValueAt(event.getFirstRow(), 1));
}
});
}
}
}
}