OSDN Git Service

0912d5911c888aea4829aa57f8633132ed05ff85
[mikumikustudio/MikuMikuStudio.git] / src / com / jmex / editors / swing / particles / ParticleAppearancePanel.java
1 /*
2  * Copyright (c) 2003-2009 jMonkeyEngine
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  *   notice, this list of conditions and the following disclaimer.
11  *
12  * * Redistributions in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in the
14  *   documentation and/or other materials provided with the distribution.
15  *
16  * * Neither the name of 'jMonkeyEngine' nor the names of its contributors 
17  *   may be used to endorse or promote products derived from this software 
18  *   without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 package com.jmex.editors.swing.particles;
34
35 import java.awt.Color;
36 import java.awt.Dimension;
37 import java.awt.Font;
38 import java.awt.GridBagConstraints;
39 import java.awt.GridBagLayout;
40 import java.awt.Insets;
41 import java.awt.event.ActionEvent;
42 import java.awt.event.ActionListener;
43 import java.awt.event.MouseAdapter;
44 import java.awt.event.MouseEvent;
45 import java.io.File;
46 import java.net.MalformedURLException;
47 import java.net.URL;
48 import java.util.ArrayList;
49 import java.util.Iterator;
50 import java.util.concurrent.Callable;
51 import java.util.logging.Level;
52 import java.util.logging.Logger;
53 import java.util.prefs.Preferences;
54
55 import javax.swing.AbstractAction;
56 import javax.swing.DefaultListModel;
57 import javax.swing.ImageIcon;
58 import javax.swing.JButton;
59 import javax.swing.JCheckBox;
60 import javax.swing.JComboBox;
61 import javax.swing.JFileChooser;
62 import javax.swing.JLabel;
63 import javax.swing.JList;
64 import javax.swing.JPanel;
65 import javax.swing.JScrollPane;
66 import javax.swing.ListSelectionModel;
67 import javax.swing.SwingConstants;
68 import javax.swing.event.ChangeEvent;
69 import javax.swing.event.ChangeListener;
70 import javax.swing.event.ListSelectionEvent;
71 import javax.swing.event.ListSelectionListener;
72
73 import com.jme.image.Texture;
74 import com.jme.renderer.ColorRGBA;
75 import com.jme.scene.state.BlendState;
76 import com.jme.scene.state.RenderState;
77 import com.jme.scene.state.TextureState;
78 import com.jme.system.DisplaySystem;
79 import com.jme.util.GameTaskQueue;
80 import com.jme.util.GameTaskQueueManager;
81 import com.jme.util.TextureManager;
82 import com.jmex.editors.swing.widget.ValuePanel;
83 import com.jmex.effects.particles.AnimationEntry;
84 import com.jmex.effects.particles.ParticleFactory;
85 import com.jmex.effects.particles.ParticleSystem;
86 import com.jmex.effects.particles.ParticleInfluence;
87 import com.jmex.effects.particles.ParticlePoints;
88 import com.jmex.effects.particles.RampEntry;
89 import com.jmex.effects.particles.ParticleSystem.ParticleType;
90
91 public abstract class ParticleAppearancePanel extends ParticleEditPanel {
92     private static final Logger logger = Logger
93             .getLogger(ParticleAppearancePanel.class.getName());
94     
95     private static final long serialVersionUID = 1L;
96     private static File newTexture = null;
97
98     private JCheckBox additiveBlendingBox;
99     private JComboBox geomTypeBox;
100     private JCheckBox velocityAlignedBox;
101     private JLabel imageLabel = new JLabel();
102
103     private JList rampList = null;
104     private DefaultListModel rampModel = new DefaultListModel();
105     private JButton rampAddButton = makeListButton("Add");
106     private JButton rampRemoveButton = makeListButton("Remove");
107     private JButton rampEditButton = makeListButton("Edit");
108     private JButton rampMoveUpButton = makeListButton("/\\");
109     private JButton rampMoveDownButton = makeListButton("\\/");
110
111     private JList animList = null;
112     private DefaultListModel animModel = new DefaultListModel();
113     private JButton animAddButton = makeListButton("Add");
114     private JButton animRemoveButton = makeListButton("Remove");
115     private JButton animEditButton = makeListButton("Edit");
116     private JButton animMoveUpButton = makeListButton("/\\");
117     private JButton animMoveDownButton = makeListButton("\\/");
118
119     private Preferences prefs;
120     private JFileChooser textureChooser = new JFileChooser();
121     private JPanel texturePanel;
122
123     private ValuePanel texPanel, startTexPanel;
124
125     public ParticleAppearancePanel(Preferences prefs) {
126         super();
127         this.prefs = prefs;
128         setLayout(new GridBagLayout());
129         initPanel();
130         initTextureChooser();
131     }
132
133     private JButton makeListButton(String text) {
134         JButton button = new JButton(text);
135         button.setMargin(new Insets(2, 2, 2, 2));
136         return button;
137     }
138
139     private void initPanel() {
140
141         geomTypeBox = new JComboBox(ParticleType.values());
142         geomTypeBox.addActionListener(new ActionListener() {
143             public void actionPerformed(ActionEvent e) {
144                 changeParticleType((ParticleType) geomTypeBox.getSelectedItem());
145             }
146         });
147
148         velocityAlignedBox = new JCheckBox(new AbstractAction(
149                 "Align with Velocity") {
150             private static final long serialVersionUID = 1L;
151             public void actionPerformed(ActionEvent e) {
152                 getEdittedParticles().setVelocityAligned(
153                         velocityAlignedBox.isSelected());
154             }
155         });
156         velocityAlignedBox.setFont(new Font("Arial", Font.BOLD, 13));
157
158         rampList = new JList(rampModel);
159         rampList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
160         rampList.addListSelectionListener(new ListSelectionListener() {
161             public void valueChanged(ListSelectionEvent e) {
162                 int selected = rampList.getSelectedIndex();
163                 rampRemoveButton.setEnabled(selected > 0 && selected < rampModel.getSize()-1);
164                 rampEditButton.setEnabled(selected != -1);
165                 rampMoveUpButton.setEnabled(selected > 1 && selected < rampModel.getSize()-1);
166                 rampMoveDownButton.setEnabled(selected < rampModel.getSize()-2 && selected > 0);
167             }
168         });
169         rampList.addMouseListener(new MouseAdapter() {
170             @Override
171             public void mouseClicked(MouseEvent e) {
172                 if (e.getClickCount() > 1) {
173                     rampEditButton.doClick();
174                     e.consume();
175                 }
176             }
177         });
178
179         rampAddButton.addActionListener(new ActionListener() {
180             public void actionPerformed(ActionEvent e) {
181                 new Thread() {
182                     public void run() {
183                         RampEntry entry = new RampEntry();
184                         getEdittedParticles().getRamp().addEntry(entry);
185                         showEditWindow(entry);
186                         updateRampModel();
187                         rampList.setSelectedValue(entry, true);
188                     }
189                 }.start();
190             }
191         });
192
193         rampEditButton.addActionListener(new ActionListener() {
194             public void actionPerformed(ActionEvent e) {
195                 new Thread() {
196                     public void run() {
197                         int index = rampList.getSelectedIndex();
198                         RampEntry entry = (RampEntry) rampList
199                                 .getSelectedValue();
200                         showEditWindow(entry);
201                         updateRampModel();
202                         rampList.setSelectedIndex(index);
203                     };
204                 }.start();
205             }
206         });
207
208         rampRemoveButton.addActionListener(new ActionListener() {
209             public void actionPerformed(ActionEvent e) {
210                 RampEntry entry = (RampEntry)rampList.getSelectedValue();
211                 getEdittedParticles().getRamp().removeEntry(entry);
212                 updateRampModel();
213             }
214         });
215
216         rampMoveUpButton.addActionListener(new ActionListener() {
217             public void actionPerformed(ActionEvent e) {
218                 int index = rampList.getSelectedIndex();
219                 RampEntry entry = (RampEntry)rampList.getSelectedValue();
220                 getEdittedParticles().getRamp().removeEntry(entry);
221                 getEdittedParticles().getRamp().addEntry(index-2, entry);
222                 updateRampModel();
223                 rampList.setSelectedValue(entry, true);
224             }
225         });
226
227         rampMoveDownButton.addActionListener(new ActionListener() {
228             public void actionPerformed(ActionEvent e) {
229                 int index = rampList.getSelectedIndex();
230                 RampEntry entry = (RampEntry)rampList.getSelectedValue();
231                 getEdittedParticles().getRamp().removeEntry(entry);
232                 getEdittedParticles().getRamp().addEntry(index, entry);
233                 updateRampModel();
234                 rampList.setSelectedValue(entry, true);
235             }
236         });
237         
238         rampRemoveButton.setEnabled(false);
239         rampEditButton.setEnabled(false);
240         rampMoveUpButton.setEnabled(false);
241         rampMoveDownButton.setEnabled(false);
242         
243         
244         JPanel geomPanel = new JPanel(new GridBagLayout());
245         geomPanel.setBorder(createTitledBorder("PARTICLE GEOMETRY"));
246         geomPanel.add(createBoldLabel("Type:"), new GridBagConstraints(0, 0, 1,
247                 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.NONE,
248                 new Insets(5, 5, 5, 5), 0, 0));
249         geomPanel.add(geomTypeBox, new GridBagConstraints(1, 0, 1, 1, 0, 0,
250                 GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
251                 new Insets(5, 5, 5, 5), 0, 0));
252         geomPanel.add(velocityAlignedBox, new GridBagConstraints(0, 1, 2, 1,
253                 1.0, 0, GridBagConstraints.CENTER, GridBagConstraints.NONE,
254                 new Insets(5, 5, 5, 5), 0, 0));
255
256         JPanel rampPanel = new JPanel(new GridBagLayout());
257         rampPanel.setBorder(createTitledBorder("APPEARANCE TIMELINE"));
258         rampPanel.add(new JScrollPane(rampList,
259                 JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
260                 JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED),
261                 new GridBagConstraints(1, 0, 1, 6, 1.0, 1.0,
262                         GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH,
263                         new Insets(5, 5, 5, 5), 0, 0));
264         rampPanel.add(rampAddButton, new GridBagConstraints(0, 0, 1,
265                 1, 0, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL,
266                 new Insets(5, 5, 0, 5), 0, 0));
267         rampPanel.add(rampRemoveButton, new GridBagConstraints(0, 1, 1,
268                 1, 0, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL,
269                 new Insets(5, 5, 0, 5), 0, 0));
270         rampPanel.add(rampEditButton, new GridBagConstraints(0, 2, 1,
271                 1, 0, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL,
272                 new Insets(5, 5, 0, 5), 0, 0));
273         rampPanel.add(rampMoveUpButton, new GridBagConstraints(0, 3, 1,
274                 1, 0, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL,
275                 new Insets(5, 5, 0, 5), 0, 0));
276         rampPanel.add(rampMoveDownButton, new GridBagConstraints(0, 4, 1,
277                 1, 0, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL,
278                 new Insets(5, 5, 0, 5), 0, 0));
279     
280         animList = new JList(animModel);
281         animList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
282         animList.addListSelectionListener(new ListSelectionListener() {
283             public void valueChanged(ListSelectionEvent e) {
284                 int selected = animList.getSelectedIndex();
285                 animRemoveButton.setEnabled(selected != -1);
286                 animEditButton.setEnabled(selected != -1);
287                 animMoveUpButton.setEnabled(selected > 0);
288                 animMoveDownButton.setEnabled(selected != -1 && selected < animModel.getSize()-1);
289             }
290         });
291         
292         animList.addMouseListener(new MouseAdapter() {
293             @Override
294             public void mouseClicked(MouseEvent e) {
295                 if (e.getClickCount() > 1) {
296                     animEditButton.doClick();
297                     e.consume();
298                 }
299             }
300         });
301
302         animAddButton.addActionListener(new ActionListener() {
303             public void actionPerformed(ActionEvent e) {
304                 new Thread() {
305                     public void run() {
306                         AnimationEntry entry = new AnimationEntry();
307                         getEdittedParticles().getTexAnimation().addEntry(entry);
308                         showEditWindow(entry);
309                         updateAnimModel();
310                         animList.setSelectedValue(entry, true);
311                     }
312                 }.start();
313             }
314         });
315
316         animEditButton.addActionListener(new ActionListener() {
317             public void actionPerformed(ActionEvent e) {
318                 new Thread() {
319                     public void run() {
320                         int index = animList.getSelectedIndex();
321                         AnimationEntry entry = (AnimationEntry) animList
322                                 .getSelectedValue();
323                         showEditWindow(entry);
324                         updateAnimModel();
325                         animList.setSelectedIndex(index);
326                     };
327                 }.start();
328             }
329         });
330
331         animRemoveButton.addActionListener(new ActionListener() {
332             public void actionPerformed(ActionEvent e) {
333                 AnimationEntry entry = (AnimationEntry)animList.getSelectedValue();
334                 getEdittedParticles().getTexAnimation().removeEntry(entry);
335                 updateAnimModel();
336             }
337         });
338
339         animMoveUpButton.addActionListener(new ActionListener() {
340             public void actionPerformed(ActionEvent e) {
341                 int index = animList.getSelectedIndex();
342                 AnimationEntry entry = (AnimationEntry)animList.getSelectedValue();
343                 getEdittedParticles().getTexAnimation().removeEntry(entry);
344                 getEdittedParticles().getTexAnimation().addEntry(index-1, entry);
345                 updateAnimModel();
346                 animList.setSelectedValue(entry, true);
347             }
348         });
349
350         animMoveDownButton.addActionListener(new ActionListener() {
351             public void actionPerformed(ActionEvent e) {
352                 int index = animList.getSelectedIndex();
353                 AnimationEntry entry = (AnimationEntry)animList.getSelectedValue();
354                 getEdittedParticles().getTexAnimation().removeEntry(entry);
355                 getEdittedParticles().getTexAnimation().addEntry(index+1, entry);
356                 updateAnimModel();
357                 animList.setSelectedValue(entry, true);
358             }
359         });
360         
361         animRemoveButton.setEnabled(false);
362         animEditButton.setEnabled(false);
363         animMoveUpButton.setEnabled(false);
364         animMoveDownButton.setEnabled(false);
365         
366         JPanel animPanel = new JPanel(new GridBagLayout());
367         animPanel.setBorder(createTitledBorder("ANIMATION TIMELINE"));
368         animPanel.add(new JScrollPane(animList,
369                 JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
370                 JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED),
371                 new GridBagConstraints(1, 0, 1, 6, 1.0, 1.0,
372                         GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH,
373                         new Insets(5, 5, 5, 5), 0, 0));
374         animPanel.add(animAddButton, new GridBagConstraints(0, 0, 1,
375                 1, 0, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL,
376                 new Insets(5, 5, 0, 5), 0, 0));
377         animPanel.add(animRemoveButton, new GridBagConstraints(0, 1, 1,
378                 1, 0, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL,
379                 new Insets(5, 5, 0, 5), 0, 0));
380         animPanel.add(animEditButton, new GridBagConstraints(0, 2, 1,
381                 1, 0, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL,
382                 new Insets(5, 5, 0, 5), 0, 0));
383         animPanel.add(animMoveUpButton, new GridBagConstraints(0, 3, 1,
384                 1, 0, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL,
385                 new Insets(5, 5, 0, 5), 0, 0));
386         animPanel.add(animMoveDownButton, new GridBagConstraints(0, 4, 1,
387                 1, 0, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL,
388                 new Insets(5, 5, 0, 5), 0, 0));
389
390
391         additiveBlendingBox = new JCheckBox(new AbstractAction(
392                 "Additive Blending") {
393             private static final long serialVersionUID = 1L;
394
395             public void actionPerformed(ActionEvent e) {
396                 updateBlendState(additiveBlendingBox.isSelected());
397             }
398         });
399         additiveBlendingBox.setFont(new Font("Arial", Font.BOLD, 13));
400
401         JPanel blendPanel = new JPanel(new GridBagLayout());
402         blendPanel.setBorder(createTitledBorder("PARTICLE BLENDING"));
403         blendPanel.add(additiveBlendingBox, new GridBagConstraints(0, 0, 1, 1,
404                 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE,
405                 new Insets(5, 5, 5, 5), 0, 0));
406
407         JLabel textureLabel = createBoldLabel("Texture Image:");
408         JButton changeTextureButton = new JButton(new AbstractAction(
409                 "Browse...") {
410             private static final long serialVersionUID = 1L;
411
412             public void actionPerformed(ActionEvent e) {
413                 changeTexture();
414             }
415         });
416         changeTextureButton.setFont(new Font("Arial", Font.BOLD, 12));
417         changeTextureButton.setMargin(new Insets(2, 2, 2, 2));
418
419         JButton clearTextureButton = new JButton(new AbstractAction("Clear") {
420             private static final long serialVersionUID = 1L;
421
422             public void actionPerformed(ActionEvent e) {
423                 ((TextureState) getEdittedParticles().getRenderState(RenderState.StateType.Texture)).setTexture(null);
424                 imageLabel.setIcon(null);
425             }
426         });
427         clearTextureButton.setFont(new Font("Arial", Font.BOLD, 12));
428         clearTextureButton.setMargin(new Insets(2, 2, 2, 2));
429
430         imageLabel.setBackground(Color.lightGray);
431         imageLabel.setMaximumSize(new Dimension(128, 128));
432         imageLabel.setMinimumSize(new Dimension(0, 0));
433         imageLabel.setHorizontalAlignment(SwingConstants.CENTER);
434         imageLabel.setOpaque(false);
435
436         texturePanel = new JPanel(new GridBagLayout());
437         texturePanel.setBorder(createTitledBorder("PARTICLE TEXTURE"));
438         texturePanel.add(textureLabel, new GridBagConstraints(0, 0, 1, 1, 0.0,
439                 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE,
440                 new Insets(5, 5, 5, 5), 0, 0));
441         texturePanel.add(changeTextureButton, new GridBagConstraints(0, 1, 1,
442                 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.HORIZONTAL,
443                 new Insets(0, 5, 5, 5), 0, 0));
444         texturePanel.add(clearTextureButton, new GridBagConstraints(0, 2, 1, 1,
445                 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.HORIZONTAL,
446                 new Insets(0, 5, 5, 5), 0, 0));
447         texturePanel.add(imageLabel, new GridBagConstraints(1, 0, 1, 3, 1.0,
448                 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE,
449                 new Insets(5, 5, 5, 5), 0, 0));
450
451         texPanel = new ValuePanel("Sub Images: ", "", 1, Integer.MAX_VALUE, 1);
452         texPanel.addChangeListener(new ChangeListener() {
453             public void stateChanged(ChangeEvent e) {
454                 getEdittedParticles().setTexQuantity(texPanel.getIntValue());
455             }
456         });
457
458         texturePanel.add(texPanel, new GridBagConstraints(0, 3, 2, 1, 1.0, 0.0,
459                 GridBagConstraints.NORTHWEST, GridBagConstraints.NONE,
460                 new Insets(5, 5, 5, 5), 0, 0));
461         
462
463         startTexPanel = new ValuePanel("Start Index: ", "", 0, Integer.MAX_VALUE, 1);
464         startTexPanel.addChangeListener(new ChangeListener() {
465             public void stateChanged(ChangeEvent e) {
466                 getEdittedParticles().setStartTexIndex(startTexPanel.getIntValue());
467             }
468         });
469
470         texturePanel.add(startTexPanel, new GridBagConstraints(0, 4, 2, 1, 1.0, 0.0,
471                 GridBagConstraints.NORTHWEST, GridBagConstraints.NONE,
472                 new Insets(5, 5, 5, 5), 0, 0));
473         
474         
475
476         add(geomPanel, new GridBagConstraints(0, 1, 1, 1, 1.0, 0.0,
477                 GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
478                 new Insets(5, 5, 5, 10), 0, 0));
479         add(texturePanel, new GridBagConstraints(0, 2, 1, 1, 1.0, 0.0,
480                 GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
481                 new Insets(5, 10, 5, 10), 0, 0));
482         add(blendPanel, new GridBagConstraints(0, 3, 1, 1, 1.0, 0.0,
483                 GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
484                 new Insets(5, 10, 5, 10), 0, 0));
485         add(rampPanel, new GridBagConstraints(0, 4, 1, 1, 1.0, 1.0,
486                 GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL,
487                 new Insets(5, 10, 5, 10), 0, 0));
488         add(animPanel, new GridBagConstraints(0, 5, 1, 1, 1.0, 1.0,
489                 GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL,
490                 new Insets(5, 10, 5, 10), 0, 0));
491     }
492
493     protected void showEditWindow(final RampEntry entry) {
494         RampEntryEditDialog dialog = new RampEntryEditDialog(entry);
495         dialog.setLocationRelativeTo(ParticleAppearancePanel.this);
496         dialog.setModal(true);
497         dialog.setVisible(true);
498         dialog.toFront();
499     }
500
501     protected void showEditWindow(final AnimationEntry entry) {
502         AnimationEntryEditDialog dialog = new AnimationEntryEditDialog(entry);
503         dialog.setLocationRelativeTo(ParticleAppearancePanel.this);
504         dialog.setModal(true);
505         dialog.setVisible(true);
506         dialog.toFront();
507     }
508
509     protected void updateRampModel() {
510         rampModel.clear();
511         rampModel.addElement(new StartRamp(getEdittedParticles()));
512         Iterator<RampEntry> it = getEdittedParticles().getRamp().getEntries();
513         while (it.hasNext()) {
514             RampEntry e = it.next();
515             rampModel.addElement(e);
516         }
517         rampModel.addElement(new EndRamp(getEdittedParticles()));
518     }
519
520     protected void updateAnimModel() {
521         animModel.clear();
522         Iterator<AnimationEntry> it = getEdittedParticles().getTexAnimation().getEntries();
523         while (it.hasNext()) {
524             AnimationEntry e = it.next();
525             animModel.addElement(e);
526         }
527     }
528
529     private void changeParticleType(ParticleType newType) {
530         ParticleType oldType = getEdittedParticles().getParticleType();
531         if (newType == oldType) {
532             return;
533         }
534         ParticleSystem oldGeom = getEdittedParticles(), newGeom;
535         if (newType == ParticleSystem.ParticleType.Point) {
536             ParticlePoints pPoints = ParticleFactory.buildPointParticles(oldGeom.getName(),
537                     oldGeom.getNumParticles());
538             newGeom = pPoints;
539             pPoints.setPointSize(5);
540             pPoints.setAntialiased(true);
541         } else if (newType == ParticleSystem.ParticleType.Line) {
542             newGeom = ParticleFactory.buildLineParticles(oldGeom.getName(),
543                 oldGeom.getNumParticles());
544         } else {
545             newGeom = ParticleFactory.buildParticles(oldGeom.getName(),
546                 oldGeom.getNumParticles(), newType);
547         }
548         // copy appearance parameters
549         newGeom.setVelocityAligned(oldGeom.isVelocityAligned());
550         newGeom.setStartColor(oldGeom.getStartColor().clone());
551         newGeom.setEndColor(oldGeom.getEndColor().clone());
552         newGeom.setStartTexIndex(oldGeom.getStartTexIndex());
553         newGeom.setStartSize(oldGeom.getStartSize());
554         newGeom.setEndSize(oldGeom.getEndSize());
555         newGeom.setStartMass(oldGeom.getStartMass());
556         newGeom.setEndMass(oldGeom.getEndMass());
557         newGeom.setStartSpin(oldGeom.getStartSpin());
558         newGeom.setEndSpin(oldGeom.getEndSpin());
559         newGeom.setRamp(oldGeom.getRamp());
560         newGeom.setTexQuantity(oldGeom.getTexQuantity());
561         
562         // copy origin parameters
563         newGeom.setLocalTranslation(oldGeom.getLocalTranslation());
564         newGeom.setLocalRotation(oldGeom.getLocalRotation());
565         newGeom.setLocalScale(oldGeom.getLocalScale());
566         newGeom.setOriginOffset(oldGeom.getOriginOffset());
567         newGeom.setGeometry(oldGeom.getLine());
568         newGeom.setGeometry(oldGeom.getRectangle());
569         newGeom.setGeometry(oldGeom.getRing());
570         newGeom.setEmitType(oldGeom.getEmitType());
571         
572         // copy emission parameters
573         newGeom.setRotateWithScene(oldGeom.isRotateWithScene());
574         newGeom.setEmissionDirection(oldGeom.getEmissionDirection());
575         newGeom.setMinimumAngle(oldGeom.getMinimumAngle());
576         newGeom.setMaximumAngle(oldGeom.getMaximumAngle());
577         newGeom.setInitialVelocity(oldGeom.getInitialVelocity());
578         
579         // copy flow parameters
580         newGeom.setControlFlow(oldGeom.getParticleController().isControlFlow());
581         newGeom.setReleaseRate(oldGeom.getReleaseRate());
582         newGeom.setReleaseVariance(oldGeom.getReleaseVariance());
583         newGeom.setRepeatType(oldGeom.getParticleController().getRepeatType());
584         
585         // copy world parameters
586         newGeom.setSpeed(oldGeom.getParticleController().getSpeed());
587         newGeom.setMinimumLifeTime(oldGeom.getMinimumLifeTime());
588         newGeom.setMaximumLifeTime(oldGeom.getMaximumLifeTime());
589         newGeom.getParticleController().setPrecision(
590                 oldGeom.getParticleController().getPrecision());
591         
592         // copy influence parameters
593         ArrayList<ParticleInfluence> infs = oldGeom.getInfluences();
594         if (infs != null) {
595             for (ParticleInfluence inf : infs) {
596                 newGeom.addInfluence(inf);
597             }
598         }
599         
600         // copy render states
601         for (RenderState.StateType type : RenderState.StateType.values()) {
602             RenderState rs = oldGeom.getRenderState(type);
603             if (rs != null) {
604                 newGeom.setRenderState(rs);
605             }
606         }
607         
608         requestParticleSystemOverwrite(newGeom);
609     }
610     
611     protected abstract void requestParticleSystemOverwrite(ParticleSystem newParticles);
612
613     private void changeTexture() {
614         try {
615             int result = textureChooser.showOpenDialog(this);
616             if (result == JFileChooser.CANCEL_OPTION) {
617                 return;
618             }
619             File textFile = textureChooser.getSelectedFile();
620             prefs.put("texture_dir", textFile.getParent());
621
622             newTexture = textFile;
623             
624             GameTaskQueueManager.getManager().getQueue(GameTaskQueue.RENDER).enqueue(new Callable<Object>() {
625                 public Object call() throws Exception{
626                     loadApplyTexture();
627                     return null;
628                 }
629             });
630
631             ImageIcon icon = new ImageIcon(
632                 getToolkit().createImage(textFile.getAbsolutePath()));
633             imageLabel.setIcon(icon);
634             validate();
635         } catch (Exception ex) {
636             logger.logp(Level.SEVERE, this.getClass().toString(), "changeTexture()", "Exception",
637                     ex);
638         }
639     }
640
641     private void initTextureChooser() {
642         String tdir = prefs.get("texture_dir", null);
643         if (tdir != null) {
644             textureChooser.setCurrentDirectory(new File(tdir));
645         }
646     }
647
648     private void loadApplyTexture() throws MalformedURLException {
649         TextureState ts = (TextureState)getEdittedParticles().getRenderState(RenderState.StateType.Texture);
650         TextureManager.clearCache();
651         ts.setTexture(
652                 TextureManager.loadTexture(
653                         newTexture.toURI().toURL(),
654                         Texture.MinificationFilter.BilinearNearestMipMap,
655                         Texture.MagnificationFilter.Bilinear));
656         ts.setEnabled(true);
657         getEdittedParticles().setRenderState(ts);
658         getEdittedParticles().updateRenderState();
659         newTexture = null;
660     }
661
662     private void updateBlendState(boolean additive) {
663         BlendState as = (BlendState)getEdittedParticles().getRenderState(RenderState.StateType.Blend);
664         if (as == null) {
665             as = DisplaySystem.getDisplaySystem().getRenderer().createBlendState();
666             as.setBlendEnabled(true);
667             as.setSourceFunction(BlendState.SourceFunction.SourceAlpha);
668             as.setTestEnabled(true);
669             as.setTestFunction(BlendState.TestFunction.GreaterThan);
670             getEdittedParticles().setRenderState(as);
671             getEdittedParticles().updateRenderState();
672         }
673         as.setDestinationFunction(additive ?
674             BlendState.DestinationFunction.One : BlendState.DestinationFunction.OneMinusSourceAlpha);
675     }
676
677     @Override
678     public void updateWidgets() {
679         updateRampModel();
680         
681         ParticleSystem system = getEdittedParticles();
682         geomTypeBox.setSelectedItem(system.getParticleType());
683         velocityAlignedBox.setSelected(system.isVelocityAligned());
684         texPanel.setValue(system.getTexQuantity());
685         startTexPanel.setValue(system.getStartTexIndex());
686
687         BlendState as = (BlendState)system.getRenderState(RenderState.StateType.Blend);
688         additiveBlendingBox.setSelected(as == null ||
689             as.getDestinationFunctionRGB() == BlendState.DestinationFunction.One);
690         if (getTexturePanel().isVisible()) {
691             Texture tex = null;
692             try {
693                 tex = ((TextureState)system.getRenderState(RenderState.StateType.Texture)).getTexture();
694                 if (tex != null) {
695                     if (tex.getTextureKey() != null && tex.getTextureKey().getLocation() != null)
696                         imageLabel.setIcon(
697                                 new ImageIcon(tex.getTextureKey().getLocation()));
698                     else
699                         imageLabel.setIcon(
700                             new ImageIcon(new URL(tex.getImageLocation())));
701                 } else {
702                     imageLabel.setIcon(null);
703                 }
704             } catch (Exception e) {
705                 logger.warning("image: "+tex+" : "+ tex != null ? tex.getImageLocation() : "");
706             }
707         }
708     }
709
710     public JCheckBox getAdditiveBlendingBox() {
711         return additiveBlendingBox;
712     }
713
714     public JPanel getTexturePanel() {
715         return texturePanel;
716     }
717     
718     public class StartRamp extends RampEntry {
719
720         private ParticleSystem particles;
721
722         public StartRamp(ParticleSystem particles) {
723             super(-1);
724             this.particles = particles;
725             setColor(particles.getStartColor());
726             setSize(particles.getStartSize());
727             setMass(particles.getStartMass());
728             setSpin(particles.getStartSpin());
729         }
730         
731         @Override
732         public String toString() {
733             return "START: "+super.toString();
734         }
735         
736         @Override
737         public void setSize(float size) {
738             super.setSize(size);
739             particles.setStartSize(size);
740         }
741         
742         @Override
743         public void setMass(float mass) {
744             super.setMass(mass);
745             particles.setStartMass(mass);
746         }
747         
748         @Override
749         public void setSpin(float spin) {
750             super.setSpin(spin);
751             particles.setStartSpin(spin);
752         }
753         
754         @Override
755         public void setColor(ColorRGBA color) {
756             super.setColor(color);
757             particles.setStartColor(color);
758         }
759     }
760     
761     public class EndRamp extends RampEntry {
762
763         private ParticleSystem particles;
764
765         public EndRamp(ParticleSystem particles) {
766             super(-1);
767             this.particles = particles;
768             setColor(particles.getEndColor());
769             setSize(particles.getEndSize());
770             setMass(particles.getEndMass());
771             setSpin(particles.getEndSpin());
772         }
773         
774         @Override
775         public String toString() {
776             return "END: "+super.toString();
777         }
778         
779         @Override
780         public void setSize(float size) {
781             super.setSize(size);
782             particles.setEndSize(size);
783         }
784         
785         @Override
786         public void setMass(float mass) {
787             super.setMass(mass);
788             particles.setEndMass(mass);
789         }
790         
791         @Override
792         public void setSpin(float spin) {
793             super.setSpin(spin);
794             particles.setEndSpin(spin);
795         }
796         
797         @Override
798         public void setColor(ColorRGBA color) {
799             super.setColor(color);
800             particles.setEndColor(color);
801         }
802     }
803 }