Browse Source

- add Filter Explorer for editig and previewing j3f files containting post filters (WIP, only FogFilter available atm)
- add function to preview post filters in the sceneviewer

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7707 75d07b2b-3a1a-0410-a2c5-0572b91ccdca

nor..67 14 years ago
parent
commit
f9dff76380
24 changed files with 1460 additions and 2 deletions
  1. 1 1
      jme3-core/manifest.mf
  2. 2 0
      jme3-core/src/com/jme3/gde/core/Bundle.properties
  3. 12 0
      jme3-core/src/com/jme3/gde/core/FilterPostProcessorResolver.xml
  4. 58 0
      jme3-core/src/com/jme3/gde/core/assets/FilterDataObject.java
  5. BIN
      jme3-core/src/com/jme3/gde/core/filter.j3f
  6. 159 0
      jme3-core/src/com/jme3/gde/core/filters/AbstractFilterNode.java
  7. 107 0
      jme3-core/src/com/jme3/gde/core/filters/AddFilterAction.java
  8. 3 0
      jme3-core/src/com/jme3/gde/core/filters/Bundle.properties
  9. 67 0
      jme3-core/src/com/jme3/gde/core/filters/FilterExplorerTopComponent.form
  10. 222 0
      jme3-core/src/com/jme3/gde/core/filters/FilterExplorerTopComponent.java
  11. 47 0
      jme3-core/src/com/jme3/gde/core/filters/FilterNode.java
  12. 203 0
      jme3-core/src/com/jme3/gde/core/filters/FilterPostProcessorNode.java
  13. 83 0
      jme3-core/src/com/jme3/gde/core/filters/JmeFogFilter.java
  14. 63 0
      jme3-core/src/com/jme3/gde/core/filters/OpenFilterAction.java
  15. 104 0
      jme3-core/src/com/jme3/gde/core/filters/actions/AbstractNewFilterAction.java
  16. 105 0
      jme3-core/src/com/jme3/gde/core/filters/actions/AbstractNewFilterWizardAction.java
  17. 44 0
      jme3-core/src/com/jme3/gde/core/filters/actions/NewFilterAction.java
  18. 54 0
      jme3-core/src/com/jme3/gde/core/filters/actions/impl/NewFogFilterAction.java
  19. 73 0
      jme3-core/src/com/jme3/gde/core/layer.xml
  20. BIN
      jme3-core/src/com/jme3/gde/core/objects_082.gif
  21. 6 1
      jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/SceneExplorerProperty.java
  22. 2 0
      jme3-core/src/com/jme3/gde/core/sceneviewer/Bundle.properties
  23. 21 0
      jme3-core/src/com/jme3/gde/core/sceneviewer/SceneViewerTopComponent.form
  24. 24 0
      jme3-core/src/com/jme3/gde/core/sceneviewer/SceneViewerTopComponent.java

+ 1 - 1
jme3-core/manifest.mf

@@ -4,5 +4,5 @@ OpenIDE-Module-Implementation-Version: 0
 OpenIDE-Module-Install: com/jme3/gde/core/Installer.class
 OpenIDE-Module-Layer: com/jme3/gde/core/layer.xml
 OpenIDE-Module-Localizing-Bundle: com/jme3/gde/core/Bundle.properties
-OpenIDE-Module-Requires: org.netbeans.api.javahelp.Help
+OpenIDE-Module-Requires: org.netbeans.api.javahelp.Help, org.openide.windows.WindowManager
 

+ 2 - 0
jme3-core/src/com/jme3/gde/core/Bundle.properties

@@ -3,6 +3,8 @@ OpenIDE-Module-Long-Description=\
     This plugin provides the core functions of jMonkeyPlatform.
 OpenIDE-Module-Name=jMonkeyPlatform Core
 OpenIDE-Module-Short-Description=The jMonkeyPlatform Core Plugin
+Services/MIMEResolver/FilterPostProcessorResolver.xml=FilterPostProcessor Files
 Services/MIMEResolver/JMEBinaryModelResolver.xml=JMEBinaryModel Files
 Menu/Help/jmewiki.url=Browse Help online
 Menu/Help/help-main.xml=Browse Help locally
+Templates/Other/filter.j3f=Empty FilterPostProcessor file

+ 12 - 0
jme3-core/src/com/jme3/gde/core/FilterPostProcessorResolver.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+To change this template, choose Tools | Templates
+and open the template in the editor.
+-->
+<!DOCTYPE MIME-resolver PUBLIC "-//NetBeans//DTD MIME Resolver 1.0//EN" "http://www.netbeans.org/dtds/mime-resolver-1_0.dtd">
+<MIME-resolver>
+    <file>
+        <ext name="j3f"/>
+        <resolver mime="application/jme3filterpostprocessor"/>
+    </file>
+</MIME-resolver>

+ 58 - 0
jme3-core/src/com/jme3/gde/core/assets/FilterDataObject.java

@@ -0,0 +1,58 @@
+/*
+ *  Copyright (c) 2009-2010 jMonkeyEngine
+ *  All rights reserved.
+ * 
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ * 
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ *  * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ *  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ *  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jme3.gde.core.assets;
+
+import com.jme3.gde.core.filters.FilterPostProcessorNode;
+import com.jme3.post.FilterPostProcessor;
+import java.io.IOException;
+import org.openide.filesystems.FileObject;
+import org.openide.loaders.DataObjectExistsException;
+import org.openide.loaders.MultiFileLoader;
+
+/**
+ *
+ * @author normenhansen
+ */
+public class FilterDataObject extends AssetDataObject {
+
+    public FilterDataObject(FileObject pf, MultiFileLoader loader) throws DataObjectExistsException, IOException {
+        super(pf, loader);
+        getLookupContents().add(new FilterPostProcessorNode(this));
+        saveExtension = "j3f";
+        getLookup().lookup(AssetData.class).setExtension("j3f");
+    }
+
+    @Override
+    public FilterPostProcessor loadAsset() {
+        return (FilterPostProcessor) super.loadAsset();
+    }
+}

BIN
jme3-core/src/com/jme3/gde/core/filter.j3f


+ 159 - 0
jme3-core/src/com/jme3/gde/core/filters/AbstractFilterNode.java

@@ -0,0 +1,159 @@
+/*
+ *  Copyright (c) 2009-2010 jMonkeyEngine
+ *  All rights reserved.
+ * 
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ * 
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ *  * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ *  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ *  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jme3.gde.core.filters;
+
+import com.jme3.gde.core.sceneexplorer.nodes.properties.SceneExplorerProperty;
+import com.jme3.gde.core.sceneexplorer.nodes.properties.ScenePropertyChangeListener;
+import com.jme3.post.Filter;
+import java.io.IOException;
+import javax.swing.Action;
+import org.openide.actions.CopyAction;
+import org.openide.actions.CutAction;
+import org.openide.actions.DeleteAction;
+import org.openide.actions.PasteAction;
+import org.openide.actions.RenameAction;
+import org.openide.loaders.DataObject;
+import org.openide.nodes.AbstractNode;
+import org.openide.nodes.Children;
+import org.openide.nodes.Node;
+import org.openide.util.Exceptions;
+import org.openide.util.actions.SystemAction;
+
+/**
+ *
+ * @author normenhansen
+ */
+public abstract class AbstractFilterNode extends AbstractNode implements FilterNode, ScenePropertyChangeListener {
+
+    protected boolean readOnly = false;
+    protected DataObject dataObject;
+    protected Filter filter;
+
+    public AbstractFilterNode() {
+        super(Children.LEAF);
+    }
+
+    public AbstractFilterNode(Filter filter) {
+        super(Children.LEAF);
+        this.filter = filter;
+        setName(filter.getName());
+    }
+
+    @Override
+    public Action[] getActions(boolean context) {
+//        return super.getActions(context);
+        return new Action[]{
+                    SystemAction.get(DeleteAction.class)
+                };
+    }
+
+    @Override
+    public boolean canDestroy() {
+        return !readOnly;
+    }
+
+    @Override
+    public void destroy() throws IOException {
+        super.destroy();
+        FilterPostProcessorNode nod = (FilterPostProcessorNode) getParentNode();
+        nod.removeFilter(filter);
+    }
+
+    protected void fireSave(boolean modified) {
+        if (dataObject != null) {
+            dataObject.setModified(true);
+        }
+    }
+
+    /**
+     * returns the PropertySet with the given name (mostly Class.name)
+     * @param name
+     * @return The PropertySet or null if no PropertySet by that name exists
+     */
+    public PropertySet getPropertySet(String name) {
+        for (int i = 0; i < getPropertySets().length; i++) {
+            PropertySet propertySet = getPropertySets()[i];
+            if (propertySet.getName().equals(name)) {
+                return propertySet;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * @param saveCookie the saveCookie to set
+     */
+    public AbstractFilterNode setReadOnly(boolean readOnly) {
+        this.readOnly = readOnly;
+        return this;
+    }
+
+    public void refreshProperties() {
+        setSheet(createSheet());
+    }
+
+    protected Property<?> makeProperty(Object obj, Class returntype, String method, String name) {
+        Property<?> prop = null;
+        try {
+            prop = new SceneExplorerProperty(getExplorerObjectClass().cast(obj), returntype, method, null);
+            prop.setName(name);
+        } catch (NoSuchMethodException ex) {
+            Exceptions.printStackTrace(ex);
+        }
+        return prop;
+    }
+
+    protected Property<?> makeProperty(Object obj, Class returntype, String method, String setter, String name) {
+        Property<?> prop = null;
+        try {
+            if (readOnly) {
+                prop = new SceneExplorerProperty(getExplorerObjectClass().cast(obj), returntype, method, null);
+            } else {
+                prop = new SceneExplorerProperty(getExplorerObjectClass().cast(obj), returntype, method, setter, this);
+            }
+            prop.setName(name);
+
+        } catch (NoSuchMethodException ex) {
+            Exceptions.printStackTrace(ex);
+        }
+        return prop;
+    }
+
+    public void propertyChange(final String name, final Object before, final Object after) {
+        fireSave(true);
+        firePropertyChange(name, before, after);
+    }
+
+    public abstract Class<?> getExplorerObjectClass();
+
+    public abstract Node[] createNodes(Object key, DataObject dataObject, boolean readOnly);
+}

+ 107 - 0
jme3-core/src/com/jme3/gde/core/filters/AddFilterAction.java

@@ -0,0 +1,107 @@
+/*
+ *  Copyright (c) 2009-2010 jMonkeyEngine
+ *  All rights reserved.
+ * 
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ * 
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ *  * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ *  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ *  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jme3.gde.core.filters;
+
+import com.jme3.gde.core.filters.actions.NewFilterAction;
+import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit;
+import com.jme3.gde.core.undoredo.SceneUndoRedoManager;
+import com.jme3.post.Filter;
+import com.jme3.post.FilterPostProcessor;
+import java.awt.event.ActionEvent;
+import javax.swing.AbstractAction;
+import javax.swing.JMenu;
+import javax.swing.JMenuItem;
+import javax.swing.undo.CannotRedoException;
+import javax.swing.undo.CannotUndoException;
+import org.openide.util.Lookup;
+import org.openide.util.actions.Presenter;
+
+/**
+ *
+ * @author normenhansen
+ */
+public class AddFilterAction extends AbstractAction implements Presenter.Popup {
+
+    protected FilterPostProcessorNode filterNode;
+
+    public AddFilterAction(FilterPostProcessorNode node) {
+        this.filterNode = node;
+    }
+
+    public void actionPerformed(ActionEvent e) {
+    }
+
+    public JMenuItem getPopupPresenter() {
+        JMenu result = new JMenu("Add Filter..");
+        for (NewFilterAction di : Lookup.getDefault().lookupAll(NewFilterAction.class)) {
+            result.add(new JMenuItem(di.getAction(filterNode)));
+        }
+        return result;
+    }
+
+    private void addFilterUndo(final FilterPostProcessor fpp, final Filter filter) {
+        //add undo
+        if (fpp != null && filter != null) {
+            Lookup.getDefault().lookup(SceneUndoRedoManager.class).addEdit(this, new AbstractUndoableSceneEdit() {
+
+                @Override
+                public void sceneUndo() throws CannotUndoException {
+                    fpp.removeFilter(filter);
+                }
+
+                @Override
+                public void sceneRedo() throws CannotRedoException {
+                    fpp.addFilter(filter);
+                }
+
+                @Override
+                public void awtRedo() {
+                    filterNode.refresh();
+                }
+
+                @Override
+                public void awtUndo() {
+                    filterNode.refresh();
+                }
+            });
+        }
+    }
+
+    private void setModified() {
+        java.awt.EventQueue.invokeLater(new Runnable() {
+
+            public void run() {
+                filterNode.refresh();
+            }
+        });
+    }
+}

+ 3 - 0
jme3-core/src/com/jme3/gde/core/filters/Bundle.properties

@@ -0,0 +1,3 @@
+CTL_FilterExplorerAction=FilterExplorer
+CTL_FilterExplorerTopComponent=FilterExplorer Window
+HINT_FilterExplorerTopComponent=This is a FilterExplorer window

+ 67 - 0
jme3-core/src/com/jme3/gde/core/filters/FilterExplorerTopComponent.form

@@ -0,0 +1,67 @@
+<?xml version="1.1" encoding="UTF-8" ?>
+
+<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
+  <AuxValues>
+    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
+    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
+    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
+  </AuxValues>
+
+  <Layout>
+    <DimensionLayout dim="0">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Component id="jToolBar1" alignment="0" pref="400" max="32767" attributes="0"/>
+          <Component id="jScrollPane1" alignment="0" pref="400" max="32767" attributes="0"/>
+      </Group>
+    </DimensionLayout>
+    <DimensionLayout dim="1">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" alignment="0" attributes="0">
+              <Component id="jToolBar1" min="-2" pref="25" max="-2" attributes="0"/>
+              <EmptySpace max="-2" attributes="0"/>
+              <Component id="jScrollPane1" pref="267" max="32767" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+  </Layout>
+  <SubComponents>
+    <Container class="javax.swing.JScrollPane" name="jScrollPane1">
+      <AuxValues>
+        <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new BeanTreeView();"/>
+      </AuxValues>
+
+      <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
+    </Container>
+    <Container class="javax.swing.JToolBar" name="jToolBar1">
+      <Properties>
+        <Property name="floatable" type="boolean" value="false"/>
+        <Property name="rollover" type="boolean" value="true"/>
+      </Properties>
+
+      <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout"/>
+      <SubComponents>
+        <Container class="javax.swing.JPanel" name="jPanel1">
+
+          <Layout>
+            <DimensionLayout dim="0">
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <EmptySpace min="0" pref="392" max="32767" attributes="0"/>
+              </Group>
+            </DimensionLayout>
+            <DimensionLayout dim="1">
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <EmptySpace min="0" pref="21" max="32767" attributes="0"/>
+              </Group>
+            </DimensionLayout>
+          </Layout>
+        </Container>
+      </SubComponents>
+    </Container>
+  </SubComponents>
+</Form>

+ 222 - 0
jme3-core/src/com/jme3/gde/core/filters/FilterExplorerTopComponent.java

@@ -0,0 +1,222 @@
+/*
+ *  Copyright (c) 2009-2010 jMonkeyEngine
+ *  All rights reserved.
+ * 
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ * 
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ *  * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ *  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ *  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jme3.gde.core.filters;
+
+import com.jme3.gde.core.assets.FilterDataObject;
+import com.jme3.gde.core.scene.SceneApplication;
+import com.jme3.post.FilterPostProcessor;
+import java.util.concurrent.Callable;
+import java.util.logging.Logger;
+import org.openide.util.NbBundle;
+import org.openide.windows.TopComponent;
+import org.openide.windows.WindowManager;
+import org.netbeans.api.settings.ConvertAsProperties;
+import org.openide.awt.ActionID;
+import org.openide.awt.ActionReference;
+import org.openide.explorer.ExplorerManager;
+import org.openide.explorer.ExplorerUtils;
+import org.openide.explorer.view.BeanTreeView;
+import org.openide.nodes.Node;
+
+/**
+ * Top component which displays something.
+ */
+@ConvertAsProperties(dtd = "-//com.jme3.gde.core.filters//FilterExplorer//EN",
+autostore = false)
[email protected](preferredID = "FilterExplorerTopComponent",
+iconBase="com/jme3/gde/core/objects_082.gif", 
+persistenceType = TopComponent.PERSISTENCE_ALWAYS)
[email protected](mode = "navigator", openAtStartup = true)
+@ActionID(category = "Window", id = "com.jme3.gde.core.filters.FilterExplorerTopComponent")
+@ActionReference(path = "Menu/Window" /*, position = 333 */)
[email protected](displayName = "#CTL_FilterExplorerAction",
+preferredID = "FilterExplorerTopComponent")
+public final class FilterExplorerTopComponent extends TopComponent implements ExplorerManager.Provider {
+
+    private static FilterExplorerTopComponent instance;
+    private static final String PREFERRED_ID = "FilterExplorerTopComponent";
+    private transient ExplorerManager explorerManager = new ExplorerManager();
+    private FilterDataObject currentFile;
+    private FilterPostProcessorNode node;
+    private boolean added = false;
+
+    public FilterExplorerTopComponent() {
+        initComponents();
+        setName(NbBundle.getMessage(FilterExplorerTopComponent.class, "CTL_FilterExplorerTopComponent"));
+        setToolTipText(NbBundle.getMessage(FilterExplorerTopComponent.class, "HINT_FilterExplorerTopComponent"));
+        associateLookup(ExplorerUtils.createLookup(explorerManager, getActionMap()));
+    }
+
+    /** This method is called from within the constructor to
+     * initialize the form.
+     * WARNING: Do NOT modify this code. The content of this method is
+     * always regenerated by the Form Editor.
+     */
+    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
+    private void initComponents() {
+
+        jScrollPane1 = new BeanTreeView();
+        jToolBar1 = new javax.swing.JToolBar();
+        jPanel1 = new javax.swing.JPanel();
+
+        jToolBar1.setFloatable(false);
+        jToolBar1.setRollover(true);
+
+        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
+        jPanel1.setLayout(jPanel1Layout);
+        jPanel1Layout.setHorizontalGroup(
+            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGap(0, 392, Short.MAX_VALUE)
+        );
+        jPanel1Layout.setVerticalGroup(
+            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGap(0, 21, Short.MAX_VALUE)
+        );
+
+        jToolBar1.add(jPanel1);
+
+        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+        this.setLayout(layout);
+        layout.setHorizontalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addComponent(jToolBar1, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE)
+            .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE)
+        );
+        layout.setVerticalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(layout.createSequentialGroup()
+                .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 267, Short.MAX_VALUE))
+        );
+    }// </editor-fold>//GEN-END:initComponents
+    // Variables declaration - do not modify//GEN-BEGIN:variables
+    private javax.swing.JPanel jPanel1;
+    private javax.swing.JScrollPane jScrollPane1;
+    private javax.swing.JToolBar jToolBar1;
+    // End of variables declaration//GEN-END:variables
+
+    @Override
+    public void componentOpened() {
+        // TODO add custom code on component opening
+    }
+
+    @Override
+    public void componentClosed() {
+        // TODO add custom code on component closing
+        //explorerManager.setRootContext(Node.EMPTY);
+        setActivatedNodes(new Node[]{});
+    }
+
+    void writeProperties(java.util.Properties p) {
+        // better to version settings since initial version as advocated at
+        // http://wiki.apidesign.org/wiki/PropertyFiles
+        p.setProperty("version", "1.0");
+        // TODO store your settings
+    }
+
+    void readProperties(java.util.Properties p) {
+        String version = p.getProperty("version");
+        // TODO read your settings according to their version
+    }
+
+    public void loadFile(FilterDataObject object) {
+        explorerManager.setRootContext(object.getLookup().lookup(FilterPostProcessorNode.class));
+        node = object.getLookup().lookup(FilterPostProcessorNode.class);
+        setActivatedNodes(new Node[]{object.getNodeDelegate()});
+        open();
+        if (currentFile != null && added) {
+            setFilterEnabled(false);
+        }
+        currentFile = object;
+        if (added) {
+            setFilterEnabled(true);
+        }
+    }
+
+    public synchronized void setFilterEnabled(final boolean enabled) {
+        if (added == enabled) {
+            return;
+        }
+        added = enabled;
+        if (currentFile != null) {
+            final FilterPostProcessor fpp = this.node.getFilterPostProcessor();
+            SceneApplication.getApplication().enqueue(new Callable() {
+
+                public Object call() throws Exception {
+                    if (enabled) {
+                        SceneApplication.getApplication().getViewPort().removeProcessor(fpp);
+                    } else {
+                        SceneApplication.getApplication().getViewPort().addProcessor(fpp);
+                    }
+                    return null;
+                }
+            });
+
+        }
+    }
+
+    /**
+     * Gets default instance. Do not use directly: reserved for *.settings files only,
+     * i.e. deserialization routines; otherwise you could get a non-deserialized instance.
+     * To obtain the singleton instance, use {@link #findInstance}.
+     */
+    public static synchronized FilterExplorerTopComponent getDefault() {
+        if (instance == null) {
+            instance = new FilterExplorerTopComponent();
+        }
+        return instance;
+    }
+
+    /**
+     * Obtain the SceneExplorerTopComponent instance. Never call {@link #getDefault} directly!
+     */
+    public static synchronized FilterExplorerTopComponent findInstance() {
+        TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID);
+        if (win == null) {
+            Logger.getLogger(FilterExplorerTopComponent.class.getName()).warning(
+                    "Cannot find " + PREFERRED_ID + " component. It will not be located properly in the window system.");
+            return getDefault();
+        }
+        if (win instanceof FilterExplorerTopComponent) {
+            return (FilterExplorerTopComponent) win;
+        }
+        Logger.getLogger(FilterExplorerTopComponent.class.getName()).warning(
+                "There seem to be multiple components with the '" + PREFERRED_ID
+                + "' ID. That is a potential source of errors and unexpected behavior.");
+        return getDefault();
+    }
+
+    public ExplorerManager getExplorerManager() {
+        return explorerManager;
+    }
+}

+ 47 - 0
jme3-core/src/com/jme3/gde/core/filters/FilterNode.java

@@ -0,0 +1,47 @@
+/*
+ *  Copyright (c) 2009-2010 jMonkeyEngine
+ *  All rights reserved.
+ * 
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ * 
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ *  * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ *  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ *  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jme3.gde.core.filters;
+
+import org.openide.loaders.DataObject;
+import org.openide.nodes.Node;
+
+/**
+ *
+ * @author normenhansen
+ */
+public interface FilterNode{
+
+    public Class<?> getExplorerObjectClass();
+
+    public Node[] createNodes(Object key, DataObject dataObject, boolean readOnly);
+    
+}

+ 203 - 0
jme3-core/src/com/jme3/gde/core/filters/FilterPostProcessorNode.java

@@ -0,0 +1,203 @@
+/*
+ *  Copyright (c) 2009-2010 jMonkeyEngine
+ *  All rights reserved.
+ * 
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ * 
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ *  * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ *  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ *  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jme3.gde.core.filters;
+
+import com.jme3.gde.core.assets.FilterDataObject;
+import com.jme3.gde.core.scene.SceneApplication;
+import com.jme3.post.Filter;
+import com.jme3.post.FilterPostProcessor;
+import java.awt.Image;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import javax.swing.Action;
+import org.openide.actions.CopyAction;
+import org.openide.actions.CutAction;
+import org.openide.actions.DeleteAction;
+import org.openide.actions.PasteAction;
+import org.openide.actions.RenameAction;
+import org.openide.nodes.AbstractNode;
+import org.openide.nodes.Children;
+import org.openide.nodes.Node;
+import org.openide.util.Exceptions;
+import org.openide.util.ImageUtilities;
+import org.openide.util.Lookup;
+import org.openide.util.actions.SystemAction;
+
+/**
+ *
+ * @author normenhansen
+ */
+public class FilterPostProcessorNode extends AbstractNode {
+
+    private FilterDataObject dataObject;
+    private static Image smallImage =
+            ImageUtilities.loadImage("com/jme3/gde/core/objects_082.gif");
+    private FilterPostProcessor fpp;
+
+    public FilterPostProcessorNode(FilterDataObject dataObject) {
+        super(new FilterChildren(dataObject));
+        this.dataObject = dataObject;
+        setName(dataObject.getName());
+        ((FilterChildren) getChildren()).setFilterPostProcessorNode(this);
+    }
+
+    @Override
+    public Image getIcon(int type) {
+        return smallImage;
+    }
+
+    @Override
+    public Image getOpenedIcon(int type) {
+        return smallImage;
+    }
+
+    public FilterPostProcessor getFilterPostProcessor() {
+        if (fpp == null) {
+            this.fpp = dataObject.loadAsset();
+        }
+        return fpp;
+    }
+
+    public void refresh() {
+        java.awt.EventQueue.invokeLater(new Runnable() {
+
+            public void run() {
+                ((FilterChildren) getChildren()).addNotify();
+                ((FilterChildren) getChildren()).doRefresh();
+            }
+        });
+    }
+
+    public void addFilter(final Filter filter) {
+        SceneApplication.getApplication().enqueue(new Callable<Object>() {
+
+            public Object call() throws Exception {
+                getFilterPostProcessor().addFilter(filter);
+                return null;
+            }
+        });
+        setModified();
+        refresh();
+    }
+
+    public void removeFilter(final Filter filter) {
+        SceneApplication.getApplication().enqueue(new Callable<Object>() {
+
+            public Object call() throws Exception {
+                getFilterPostProcessor().removeFilter(filter);
+                return null;
+            }
+        });
+        setModified();
+        refresh();
+    }
+
+    protected void setModified() {
+        java.awt.EventQueue.invokeLater(new Runnable() {
+
+            public void run() {
+                dataObject.setModified(true);
+            }
+        });
+    }
+
+    @Override
+    public Action[] getActions(boolean context) {
+//        return super.getActions(context);
+        return new Action[]{
+                    new AddFilterAction(this)
+                };
+    }
+
+    public static class FilterChildren extends Children.Keys<Object> {
+
+        private FilterDataObject dataObject;
+        private FilterPostProcessorNode node;
+        private boolean readOnly = false;
+
+        public FilterChildren(FilterDataObject dataObject) {
+            this.dataObject = dataObject;
+        }
+
+        public void setFilterPostProcessorNode(FilterPostProcessorNode node) {
+            this.node = node;
+        }
+
+        @Override
+        protected void addNotify() {
+            super.addNotify();
+            setKeys(createKeys());
+        }
+
+        protected void doRefresh() {
+            refresh();
+        }
+
+        protected List<Object> createKeys() {
+            try {
+                return SceneApplication.getApplication().enqueue(new Callable<List<Object>>() {
+
+                    public List<Object> call() throws Exception {
+                        List<Object> keys = new LinkedList<Object>();
+                        for (Iterator it = node.getFilterPostProcessor().getFilterIterator(); it.hasNext();) {
+                            Filter filter = (Filter) it.next();
+                            keys.add(filter);
+                        }
+                        return keys;
+                    }
+                }).get();
+            } catch (InterruptedException ex) {
+                Exceptions.printStackTrace(ex);
+            } catch (ExecutionException ex) {
+                Exceptions.printStackTrace(ex);
+            }
+            return null;
+        }
+
+        @Override
+        protected Node[] createNodes(Object t) {
+            Filter filter = (Filter) t;
+            for (FilterNode di : Lookup.getDefault().lookupAll(FilterNode.class)) {
+                if (di.getExplorerObjectClass().getName().equals(filter.getClass().getName())) {
+                    Node[] ret = di.createNodes(filter, dataObject, readOnly);
+                    if (ret != null) {
+                        return ret;
+                    }
+                }
+            }
+            return new Node[]{};
+        }
+    }
+}

+ 83 - 0
jme3-core/src/com/jme3/gde/core/filters/JmeFogFilter.java

@@ -0,0 +1,83 @@
+/*
+ *  Copyright (c) 2009-2010 jMonkeyEngine
+ *  All rights reserved.
+ * 
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ * 
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ *  * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ *  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ *  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jme3.gde.core.filters;
+
+import com.jme3.math.ColorRGBA;
+import com.jme3.post.filters.FogFilter;
+import org.openide.loaders.DataObject;
+import org.openide.nodes.Node;
+import org.openide.nodes.Sheet;
+
+/**
+ *
+ * @author normenhansen
+ */
[email protected](service = FilterNode.class)
+public class JmeFogFilter extends AbstractFilterNode {
+
+    public JmeFogFilter() {
+    }
+
+    public JmeFogFilter(FogFilter filter, DataObject object, boolean readOnly) {
+        super(filter);
+        this.dataObject = object;
+        this.readOnly = readOnly;
+    }
+
+    @Override
+    protected Sheet createSheet() {
+        Sheet sheet = super.createSheet();
+        Sheet.Set set = Sheet.createPropertiesSet();
+        set.setDisplayName("Fog");
+        set.setName(Node.class.getName());
+        FogFilter obj = (FogFilter) filter;
+        if (obj == null) {
+            return sheet;
+        }
+        set.put(makeProperty(obj, float.class, "getFogDistance", "setFogDistance", "Distance"));
+        set.put(makeProperty(obj, float.class, "getFogDensity", "setFogDensity", "Density"));
+        set.put(makeProperty(obj, ColorRGBA.class, "getFogColor", "setFogColor", "Color"));
+        sheet.put(set);
+        return sheet;
+
+    }
+
+    @Override
+    public Class<?> getExplorerObjectClass() {
+        return FogFilter.class;
+    }
+
+    @Override
+    public Node[] createNodes(Object key, DataObject dataObject, boolean readOnly) {
+        return new Node[]{new JmeFogFilter((FogFilter) key, dataObject, readOnly)};
+    }
+}

+ 63 - 0
jme3-core/src/com/jme3/gde/core/filters/OpenFilterAction.java

@@ -0,0 +1,63 @@
+/*
+ *  Copyright (c) 2009-2010 jMonkeyEngine
+ *  All rights reserved.
+ * 
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ * 
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ *  * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ *  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ *  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jme3.gde.core.filters;
+
+import com.jme3.gde.core.assets.FilterDataObject;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+
+import org.openide.awt.ActionRegistration;
+import org.openide.awt.ActionReference;
+import org.openide.awt.ActionReferences;
+import org.openide.awt.ActionID;
+import org.openide.util.NbBundle.Messages;
+
+@ActionID(category = "Filters",
+id = "com.jme3.gde.core.filters.OpenFilterAction")
+@ActionRegistration(displayName = "#CTL_OpenFilterAction")
+@ActionReferences({
+    @ActionReference(path = "Loaders/application/jme3filterpostprocessor/Actions", position = 10)
+})
+@Messages("CTL_OpenFilterAction=Open Filter")
+public final class OpenFilterAction implements ActionListener {
+
+    private final FilterDataObject context;
+
+    public OpenFilterAction(FilterDataObject context) {
+        this.context = context;
+    }
+
+    public void actionPerformed(ActionEvent ev) {
+        // TODO use context
+        FilterExplorerTopComponent.findInstance().loadFile(context);
+    }
+}

+ 104 - 0
jme3-core/src/com/jme3/gde/core/filters/actions/AbstractNewFilterAction.java

@@ -0,0 +1,104 @@
+/*
+ *  Copyright (c) 2009-2010 jMonkeyEngine
+ *  All rights reserved.
+ * 
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ * 
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ *  * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ *  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ *  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jme3.gde.core.filters.actions;
+
+import com.bulletphysics.collision.broadphase.Dbvt.Node;
+import com.jme3.gde.core.filters.FilterPostProcessorNode;
+import com.jme3.gde.core.scene.SceneApplication;
+import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit;
+import com.jme3.gde.core.undoredo.SceneUndoRedoManager;
+import com.jme3.post.Filter;
+import java.awt.event.ActionEvent;
+import java.util.concurrent.Callable;
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+import javax.swing.undo.CannotRedoException;
+import javax.swing.undo.CannotUndoException;
+import org.openide.loaders.DataObject;
+import org.openide.util.Lookup;
+
+/**
+ *
+ * @author normenhansen
+ */
+public abstract class AbstractNewFilterAction implements NewFilterAction {
+
+    protected String name = "*";
+
+    protected abstract Filter doCreateFilter();
+
+    protected Action makeAction(final FilterPostProcessorNode rootNode) {
+        return new AbstractAction(name) {
+
+            public void actionPerformed(ActionEvent e) {
+                SceneApplication.getApplication().enqueue(new Callable<Void>() {
+
+                    public Void call() throws Exception {
+                        final Filter filter = doCreateFilter();
+                        if (filter != null && rootNode != null) {
+                            rootNode.addFilter(filter);
+                            SceneUndoRedoManager undoRedo = Lookup.getDefault().lookup(SceneUndoRedoManager.class);
+                            if(undoRedo==null) return null;
+                            undoRedo.addEdit(this, new AbstractUndoableSceneEdit() {
+
+                                @Override
+                                public void sceneUndo() throws CannotUndoException {
+                                    rootNode.removeFilter(filter);
+                                }
+
+                                @Override
+                                public void sceneRedo() throws CannotRedoException {
+                                    rootNode.addFilter(filter);
+                                }
+
+                                @Override
+                                public void awtRedo() {
+//                                    rootNode.refresh();
+                                }
+
+                                @Override
+                                public void awtUndo() {
+//                                    rootNode.refresh();
+                                }
+                            });
+                        }
+                        return null;
+                    }
+                });
+            }
+        };
+    }
+
+    public Action getAction(FilterPostProcessorNode rootNode) {
+        return makeAction(rootNode);
+    }
+}

+ 105 - 0
jme3-core/src/com/jme3/gde/core/filters/actions/AbstractNewFilterWizardAction.java

@@ -0,0 +1,105 @@
+/*
+ *  Copyright (c) 2009-2010 jMonkeyEngine
+ *  All rights reserved.
+ * 
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ * 
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ *  * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ *  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ *  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jme3.gde.core.filters.actions;
+
+import com.jme3.gde.core.filters.FilterPostProcessorNode;
+import com.jme3.gde.core.scene.SceneApplication;
+import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit;
+import com.jme3.gde.core.undoredo.SceneUndoRedoManager;
+import com.jme3.post.Filter;
+import com.jme3.post.FilterPostProcessor;
+import java.awt.event.ActionEvent;
+import java.util.concurrent.Callable;
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+import javax.swing.undo.CannotRedoException;
+import javax.swing.undo.CannotUndoException;
+import org.openide.util.Lookup;
+
+/**
+ *
+ * @author normenhansen
+ */
+public abstract class AbstractNewFilterWizardAction implements NewFilterAction{
+    protected String name = "*";
+
+    protected abstract Object showWizard(org.openide.nodes.Node node);
+
+    protected abstract Filter doCreateFilter(FilterPostProcessor parent, Object configuration);
+
+    protected Action makeAction(final FilterPostProcessorNode rootNode) {
+        return new AbstractAction(name) {
+
+            public void actionPerformed(ActionEvent e) {
+                final Object obj = showWizard(rootNode);
+                SceneApplication.getApplication().enqueue(new Callable<Void>() {
+
+                    public Void call() throws Exception {
+                        final Filter filter = doCreateFilter(rootNode.getFilterPostProcessor(), obj);
+                        if (filter != null) {
+                            rootNode.addFilter(filter);
+                            SceneUndoRedoManager undoRedo = Lookup.getDefault().lookup(SceneUndoRedoManager.class);
+                            if(undoRedo==null) return null;
+                            undoRedo.addEdit(this, new AbstractUndoableSceneEdit() {
+
+                                @Override
+                                public void sceneUndo() throws CannotUndoException {
+                                    rootNode.removeFilter(filter);
+                                }
+
+                                @Override
+                                public void sceneRedo() throws CannotRedoException {
+                                    rootNode.addFilter(filter);
+                                }
+
+                                @Override
+                                public void awtRedo() {
+//                                    rootNode.refresh();
+                                }
+
+                                @Override
+                                public void awtUndo() {
+//                                    rootNode.refresh();
+                                }
+                            });
+                        }
+                        return null;                    }
+                });
+            }
+
+        };
+    }
+
+    public Action getAction(FilterPostProcessorNode rootNode) {
+        return makeAction(rootNode);
+    }    
+}

+ 44 - 0
jme3-core/src/com/jme3/gde/core/filters/actions/NewFilterAction.java

@@ -0,0 +1,44 @@
+/*
+ *  Copyright (c) 2009-2010 jMonkeyEngine
+ *  All rights reserved.
+ * 
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ * 
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ *  * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ *  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ *  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jme3.gde.core.filters.actions;
+
+import com.jme3.gde.core.filters.FilterPostProcessorNode;
+import javax.swing.Action;
+
+/**
+ *
+ * @author normenhansen
+ */
+public interface NewFilterAction {
+    
+    public Action getAction(FilterPostProcessorNode rootNode);
+}

+ 54 - 0
jme3-core/src/com/jme3/gde/core/filters/actions/impl/NewFogFilterAction.java

@@ -0,0 +1,54 @@
+/*
+ *  Copyright (c) 2009-2010 jMonkeyEngine
+ *  All rights reserved.
+ * 
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ * 
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ *  * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ *  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ *  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jme3.gde.core.filters.actions.impl;
+
+import com.jme3.gde.core.filters.actions.AbstractNewFilterAction;
+import com.jme3.gde.core.filters.actions.NewFilterAction;
+import com.jme3.post.Filter;
+import com.jme3.post.filters.FogFilter;
+
+/**
+ *
+ * @author normenhansen
+ */
[email protected](service = NewFilterAction.class)
+public class NewFogFilterAction extends AbstractNewFilterAction {
+
+    public NewFogFilterAction() {
+        name = "Fog Filter";
+    }
+
+    @Override
+    protected Filter doCreateFilter() {
+        return new FogFilter();
+    }
+}

+ 73 - 0
jme3-core/src/com/jme3/gde/core/layer.xml

@@ -131,6 +131,70 @@
     </folder>
     <folder name="Loaders">
         <folder name="application">
+            <folder name="jme3filterpostprocessor">
+                <folder name="Actions">
+                    <file name="org-openide-actions-CopyAction.shadow">
+                        <attr name="originalFile" stringvalue="Actions/Edit/org-openide-actions-CopyAction.instance"/>
+                        <attr name="position" intvalue="300"/>
+                    </file>
+                    <file name="org-openide-actions-CutAction.shadow">
+                        <attr name="originalFile" stringvalue="Actions/Edit/org-openide-actions-CutAction.instance"/>
+                        <attr name="position" intvalue="200"/>
+                    </file>
+                    <file name="org-openide-actions-DeleteAction.shadow">
+                        <attr name="originalFile" stringvalue="Actions/Edit/org-openide-actions-DeleteAction.instance"/>
+                        <attr name="position" intvalue="500"/>
+                    </file>
+                    <file name="org-openide-actions-FileSystemAction.shadow">
+                        <attr name="originalFile" stringvalue="Actions/System/org-openide-actions-FileSystemAction.instance"/>
+                        <attr name="position" intvalue="1000"/>
+                    </file>
+                    <file name="org-openide-actions-PropertiesAction.shadow">
+                        <attr name="originalFile" stringvalue="Actions/System/org-openide-actions-PropertiesAction.instance"/>
+                        <attr name="position" intvalue="1300"/>
+                    </file>
+                    <file name="org-openide-actions-RenameAction.shadow">
+                        <attr name="originalFile" stringvalue="Actions/System/org-openide-actions-RenameAction.instance"/>
+                        <attr name="position" intvalue="600"/>
+                    </file>
+                    <file name="org-openide-actions-SaveAsTemplateAction.shadow">
+                        <attr name="originalFile" stringvalue="Actions/System/org-openide-actions-SaveAsTemplateAction.instance"/>
+                        <attr name="position" intvalue="800"/>
+                    </file>
+                    <file name="org-openide-actions-ToolsAction.shadow">
+                        <attr name="originalFile" stringvalue="Actions/System/org-openide-actions-ToolsAction.instance"/>
+                        <attr name="position" intvalue="1200"/>
+                    </file>
+                    <file name="sep-1.instance">
+                        <attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
+                        <attr name="position" intvalue="100"/>
+                    </file>
+                    <file name="sep-2.instance">
+                        <attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
+                        <attr name="position" intvalue="400"/>
+                    </file>
+                    <file name="sep-3.instance">
+                        <attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
+                        <attr name="position" intvalue="700"/>
+                    </file>
+                    <file name="sep-4.instance">
+                        <attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
+                        <attr name="position" intvalue="900"/>
+                    </file>
+                    <file name="sep-5.instance">
+                        <attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
+                        <attr name="position" intvalue="1100"/>
+                    </file>
+                </folder>
+                <folder name="Factories">
+                    <file name="FilterPostProcessorDataLoader.instance">
+                        <attr name="SystemFileSystem.icon" urlvalue="nbresloc:/com/jme3/gde/core/objects_082.gif"/>
+                        <attr name="dataObjectClass" stringvalue="com.jme3.gde.core.assets.FilterDataObject"/>
+                        <attr name="instanceCreate" methodvalue="org.openide.loaders.DataLoaderPool.factory"/>
+                        <attr name="mimeType" stringvalue="application/jme3filterpostprocessor"/>
+                    </file>
+                </folder>
+            </folder>
             <folder name="jme3model">
                 <folder name="Actions">
                     <file name="org-openide-actions-CopyAction.shadow">
@@ -220,6 +284,12 @@
         </folder>
     </folder>
     <folder name="Templates">
+        <folder name="Filters">
+            <file name="filter.j3f" url="filter.j3f">
+                <attr name="displayName" bundlevalue="com.jme3.gde.core.Bundle#Templates/Other/filter.j3f"/>
+                <attr name="template" boolvalue="true"/>
+            </file>
+        </folder>
         <folder name="Project">
             <folder name="Samples">
                 <file name="Standard_hidden"/>
@@ -238,6 +308,9 @@
             <file name="org-netbeans-modules-java-helpset.xml_hidden"/>
         </folder>
         <folder name="MIMEResolver">
+            <file name="FilterPostProcessorResolver.xml" url="FilterPostProcessorResolver.xml">
+                <attr name="displayName" bundlevalue="com.jme3.gde.core.Bundle#Services/MIMEResolver/FilterPostProcessorResolver.xml"/>
+            </file>
             <file name="JMEBinaryModelResolver.xml" url="JMEBinaryModelResolver.xml">
                 <attr name="displayName" bundlevalue="com.jme3.gde.core.Bundle#Services/MIMEResolver/JMEBinaryModelResolver.xml"/>
             </file>

BIN
jme3-core/src/com/jme3/gde/core/objects_082.gif


+ 6 - 1
jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/properties/SceneExplorerProperty.java

@@ -161,7 +161,12 @@ public class SceneExplorerProperty<T> extends PropertySupport.Reflection<T> {
     }
 
     protected void addUndo(final Object before, final Object after) {
-        Lookup.getDefault().lookup(SceneUndoRedoManager.class).addEdit(this, new AbstractUndoableSceneEdit() {
+        SceneUndoRedoManager undoRedo=Lookup.getDefault().lookup(SceneUndoRedoManager.class);
+        if(undoRedo==null){
+            Logger.getLogger(SceneExplorerProperty.class.getName()).log(Level.WARNING, "Cannot access SceneUndoRedoManager");
+            return;
+        }
+        undoRedo.addEdit(this, new AbstractUndoableSceneEdit() {
 
             @Override
             public void sceneUndo() {

+ 2 - 0
jme3-core/src/com/jme3/gde/core/sceneviewer/Bundle.properties

@@ -7,3 +7,5 @@ SceneViewerTopComponent.enableWireframe.toolTipText=Toggle wireframe mode
 SceneViewerTopComponent.enableWireframe.text=
 SceneViewerTopComponent.enableStats.toolTipText=Display Stats
 SceneViewerTopComponent.enableStats.text=
+SceneViewerTopComponent.jToggleButton1.text=
+SceneViewerTopComponent.jToggleButton1.toolTipText=show post filter effects

+ 21 - 0
jme3-core/src/com/jme3/gde/core/sceneviewer/SceneViewerTopComponent.form

@@ -50,6 +50,27 @@
             <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="enableCamLightActionPerformed"/>
           </Events>
         </Component>
+        <Component class="javax.swing.JToggleButton" name="jToggleButton1">
+          <Properties>
+            <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
+              <Image iconType="3" name="/com/jme3/gde/core/objects_082.gif"/>
+            </Property>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="com/jme3/gde/core/sceneviewer/Bundle.properties" key="SceneViewerTopComponent.jToggleButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+            <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="com/jme3/gde/core/sceneviewer/Bundle.properties" key="SceneViewerTopComponent.jToggleButton1.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+            <Property name="focusable" type="boolean" value="false"/>
+            <Property name="horizontalTextPosition" type="int" value="0"/>
+            <Property name="verticalTextPosition" type="int" value="3"/>
+          </Properties>
+          <Events>
+            <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jToggleButton1ActionPerformed"/>
+          </Events>
+        </Component>
+        <Component class="javax.swing.JToolBar$Separator" name="jSeparator1">
+        </Component>
         <Component class="javax.swing.JToggleButton" name="enableWireframe">
           <Properties>
             <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">

+ 24 - 0
jme3-core/src/com/jme3/gde/core/sceneviewer/SceneViewerTopComponent.java

@@ -31,6 +31,7 @@
  */
 package com.jme3.gde.core.sceneviewer;
 
+import com.jme3.gde.core.filters.FilterExplorerTopComponent;
 import com.jme3.gde.core.scene.SceneApplication;
 import com.jme3.system.JmeCanvasContext;
 import java.awt.Canvas;
@@ -92,6 +93,8 @@ public final class SceneViewerTopComponent extends TopComponent {
 
         jToolBar1 = new javax.swing.JToolBar();
         enableCamLight = new javax.swing.JToggleButton();
+        jToggleButton1 = new javax.swing.JToggleButton();
+        jSeparator1 = new javax.swing.JToolBar.Separator();
         enableWireframe = new javax.swing.JToggleButton();
         jPanel1 = new javax.swing.JPanel();
         enableStats = new javax.swing.JToggleButton();
@@ -115,6 +118,20 @@ public final class SceneViewerTopComponent extends TopComponent {
         });
         jToolBar1.add(enableCamLight);
 
+        jToggleButton1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/core/objects_082.gif"))); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(jToggleButton1, org.openide.util.NbBundle.getMessage(SceneViewerTopComponent.class, "SceneViewerTopComponent.jToggleButton1.text")); // NOI18N
+        jToggleButton1.setToolTipText(org.openide.util.NbBundle.getMessage(SceneViewerTopComponent.class, "SceneViewerTopComponent.jToggleButton1.toolTipText")); // NOI18N
+        jToggleButton1.setFocusable(false);
+        jToggleButton1.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
+        jToggleButton1.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
+        jToggleButton1.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                jToggleButton1ActionPerformed(evt);
+            }
+        });
+        jToolBar1.add(jToggleButton1);
+        jToolBar1.add(jSeparator1);
+
         enableWireframe.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/core/sceneviewer/icons/box_color.gif"))); // NOI18N
         org.openide.awt.Mnemonics.setLocalizedText(enableWireframe, org.openide.util.NbBundle.getMessage(SceneViewerTopComponent.class, "SceneViewerTopComponent.enableWireframe.text")); // NOI18N
         enableWireframe.setToolTipText(org.openide.util.NbBundle.getMessage(SceneViewerTopComponent.class, "SceneViewerTopComponent.enableWireframe.toolTipText")); // NOI18N
@@ -162,11 +179,18 @@ public final class SceneViewerTopComponent extends TopComponent {
     private void enableStatsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_enableStatsActionPerformed
         app.enableStats(enableStats.isSelected());
     }//GEN-LAST:event_enableStatsActionPerformed
+
+    private void jToggleButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jToggleButton1ActionPerformed
+        FilterExplorerTopComponent.findInstance().setFilterEnabled(jToggleButton1.isSelected());
+    }//GEN-LAST:event_jToggleButton1ActionPerformed
+
     // Variables declaration - do not modify//GEN-BEGIN:variables
     private javax.swing.JToggleButton enableCamLight;
     private javax.swing.JToggleButton enableStats;
     private javax.swing.JToggleButton enableWireframe;
     private javax.swing.JPanel jPanel1;
+    private javax.swing.JToolBar.Separator jSeparator1;
+    private javax.swing.JToggleButton jToggleButton1;
     private javax.swing.JToolBar jToolBar1;
     private javax.swing.JPanel oGLPanel;
     // End of variables declaration//GEN-END:variables