/******************************************************************************* * 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.BorderLayout; import java.awt.Component; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.io.File; import java.net.MalformedURLException; import java.net.URL; import java.util.HashMap; import javax.swing.BorderFactory; import javax.swing.ImageIcon; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.border.CompoundBorder; import com.badlogic.gdx.backends.lwjgl.LwjglAWTCanvas; import com.badlogic.gdx.graphics.OrthographicCamera; import com.badlogic.gdx.graphics.g2d.ParticleEffect; import com.badlogic.gdx.graphics.g2d.ParticleEmitter; import com.badlogic.gdx.graphics.g2d.ParticleEmitter.NumericValue; public class ParticlePanel extends JPanel { private static final long serialVersionUID = 1L; JPanel rowsPanel; JPanel editRowsPanel; EffectPanel effectPanel; private JSplitPane splitPane; OrthographicCamera worldCamera; OrthographicCamera textCamera; NumericValue pixelsPerMeter; NumericValue zoomLevel; NumericValue deltaMultiplier; float pixelsPerMeterPrev; float zoomLevelPrev; ParticleEffect effect = new ParticleEffect(); final HashMap<ParticleEmitter, ParticleData> particleData = new HashMap<ParticleEmitter, ParticleData>(); public ParticleRenderer particleRenderer; public ParticlePanel() { super(new BorderLayout()); setVisible(true); } void reloadRows () { EventQueue.invokeLater(new Runnable() { public void run () { editRowsPanel.removeAll(); addEditorRow(new NumericPanel(pixelsPerMeter, "Pixels per meter", "")); addEditorRow(new NumericPanel(zoomLevel, "Zoom level", "")); addEditorRow(new NumericPanel(deltaMultiplier, "Delta multiplier", "")); rowsPanel.removeAll(); ParticleEmitter emitter = getEmitter(); addRow(new ImagePanel(ParticlePanel.this, "Image", "")); addRow(new CountPanel(ParticlePanel.this, "Count", "Min number of particles at all times, max number of particles allowed.")); addRow(new RangedNumericPanel(emitter.getDelay(), "Delay", "Time from beginning of effect to emission start, in milliseconds.")); addRow(new RangedNumericPanel(emitter.getDuration(), "Duration", "Time particles will be emitted, in milliseconds.")); addRow(new ScaledNumericPanel(emitter.getEmission(), "Duration", "Emission", "Number of particles emitted per second.")); addRow(new ScaledNumericPanel(emitter.getLife(), "Duration", "Life", "Time particles will live, in milliseconds.")); addRow(new ScaledNumericPanel(emitter.getLifeOffset(), "Duration", "Life Offset", "Particle starting life consumed, in milliseconds.")); addRow(new RangedNumericPanel(emitter.getXOffsetValue(), "X Offset", "Amount to offset a particle's starting X location, in world units.")); addRow(new RangedNumericPanel(emitter.getYOffsetValue(), "Y Offset", "Amount to offset a particle's starting Y location, in world units.")); addRow(new SpawnPanel(ParticlePanel.this, emitter.getSpawnShape(), "Spawn", "Shape used to spawn particles.")); addRow(new ScaledNumericPanel(emitter.getSpawnWidth(), "Duration", "Spawn Width", "Width of the spawn shape, in world units.")); addRow(new ScaledNumericPanel(emitter.getSpawnHeight(), "Duration", "Spawn Height", "Height of the spawn shape, in world units.")); addRow(new ScaledNumericPanel(emitter.getScale(), "Life", "Size", "Particle size, in world units.")); addRow(new ScaledNumericPanel(emitter.getVelocity(), "Life", "Velocity", "Particle speed, in world units per second.")); addRow(new ScaledNumericPanel(emitter.getAngle(), "Life", "Angle", "Particle emission angle, in degrees.")); addRow(new ScaledNumericPanel(emitter.getRotation(), "Life", "Rotation", "Particle rotation, in degrees.")); addRow(new ScaledNumericPanel(emitter.getWind(), "Life", "Wind", "Wind strength, in world units per second.")); addRow(new ScaledNumericPanel(emitter.getGravity(), "Life", "Gravity", "Gravity strength, in world units per second.")); addRow(new GradientPanel(emitter.getTint(), "Tint", "")); addRow(new PercentagePanel(emitter.getTransparency(), "Life", "Transparency", "")); addRow(new OptionsPanel(ParticlePanel.this, "Options", "")); for (Component component : rowsPanel.getComponents()) if (component instanceof EditorPanel) ((EditorPanel)component).update(ParticlePanel.this); rowsPanel.repaint(); } }); } void addEditorRow (JPanel row) { row.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, java.awt.Color.black)); editRowsPanel.add(row, new GridBagConstraints(0, -1, 1, 1, 1, 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); } void addRow (JPanel row) { row.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, java.awt.Color.black)); rowsPanel.add(row, new GridBagConstraints(0, -1, 1, 1, 1, 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); } public void setVisible (String name, boolean visible) { for (Component component : rowsPanel.getComponents()) if (component instanceof EditorPanel && ((EditorPanel)component).getName().equals(name)) component.setVisible(visible); } public ParticleEmitter getEmitter () { return effect.getEmitters().get(effectPanel.editIndex); } public ImageIcon getIcon (ParticleEmitter emitter) { ParticleData data = particleData.get(emitter); if (data == null) particleData.put(emitter, data = new ParticleData()); String imagePath = emitter.getImagePath(); if (data.icon == null && imagePath != null) { try { URL url; File file = new File(imagePath); if (file.exists()) url = file.toURI().toURL(); else { url = ParticlePanel.class.getResource(imagePath); if (url == null) return null; } data.icon = new ImageIcon(url); } catch (MalformedURLException ex) { ex.printStackTrace(); } } return data.icon; } public void setIcon (ParticleEmitter emitters, ImageIcon icon) { ParticleData data = particleData.get(emitters); if (data == null) particleData.put(emitters, data = new ParticleData()); data.icon = icon; } public void setEnabled (ParticleEmitter emitter, boolean enabled) { ParticleData data = particleData.get(emitter); if (data == null) particleData.put(emitter, data = new ParticleData()); data.enabled = enabled; emitter.reset(); } public boolean isEnabled (ParticleEmitter emitter) { ParticleData data = particleData.get(emitter); if (data == null) return true; return data.enabled; } public void initializeComponents (LwjglAWTCanvas canvas) { canvas.getCanvas().setPreferredSize(new Dimension(300, 250)); // Left JPanel propertiesPanel = new JPanel(new BorderLayout()); propertiesPanel.setBorder(new CompoundBorder(BorderFactory.createEmptyBorder(3, 0, 6, 6), BorderFactory .createTitledBorder("Editor Properties"))); editRowsPanel = new JPanel(new GridBagLayout()); propertiesPanel.add(editRowsPanel, BorderLayout.CENTER); // Center JPanel spacer = new JPanel(new BorderLayout()); spacer.setBorder(new CompoundBorder(BorderFactory.createEmptyBorder(3, 0, 6, 6), BorderFactory .createTitledBorder("Particle Effect"))); spacer.add(canvas.getCanvas(), BorderLayout.CENTER); // Right JPanel emittersPanel = new JPanel(new BorderLayout()); emittersPanel.setBorder(new CompoundBorder(BorderFactory.createEmptyBorder(0, 6, 6, 0), BorderFactory .createTitledBorder("Effect Emitters"))); effectPanel = new EffectPanel(this); emittersPanel.add(effectPanel, BorderLayout.CENTER); emittersPanel.setPreferredSize(new Dimension(330, 250)); JPanel propertiesPanel2 = new JPanel(new BorderLayout()); propertiesPanel2.setBorder(new CompoundBorder(BorderFactory.createEmptyBorder(3, 0, 6, 6), BorderFactory .createTitledBorder("Emitter Properties"))); rowsPanel = new JPanel(new GridBagLayout()); propertiesPanel2.add(rowsPanel, BorderLayout.CENTER); JPanel tool = new JPanel(new BorderLayout()); tool.add(propertiesPanel, BorderLayout.WEST); tool.add(spacer, BorderLayout.CENTER); tool.add(emittersPanel, BorderLayout.EAST); splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT); splitPane.setDividerSize(4); splitPane.add(tool, JSplitPane.TOP); splitPane.add(new JScrollPane(propertiesPanel2), JSplitPane.BOTTOM); splitPane.setDividerLocation(250); add(splitPane, BorderLayout.CENTER); } static class ParticleData { public ImageIcon icon; public String imagePath; public boolean enabled = true; } }