Browse Source

- move NVCompress tool to SDK

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@8875 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
nor..67 13 years ago
parent
commit
8c4f725de1

+ 415 - 0
jme3-materialeditor/src/com/jme3/gde/materials/nvcompress/NVCompress.form

@@ -0,0 +1,415 @@
+<?xml version="1.1" encoding="UTF-8" ?>
+
+<Form version="1.3" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JFrameFormInfo">
+  <NonVisualComponents>
+    <Menu class="javax.swing.JMenuBar" name="jMenuBar1">
+      <SubComponents>
+        <Menu class="javax.swing.JMenu" name="menuFile">
+          <Properties>
+            <Property name="text" type="java.lang.String" value="File"/>
+          </Properties>
+          <SubComponents>
+            <MenuItem class="javax.swing.JMenuItem" name="itemExit">
+              <Properties>
+                <Property name="accelerator" type="javax.swing.KeyStroke" editor="org.netbeans.modules.form.editors.KeyStrokeEditor">
+                  <KeyStroke key="Ctrl+Q"/>
+                </Property>
+                <Property name="text" type="java.lang.String" value="Exit"/>
+              </Properties>
+              <Events>
+                <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="itemExitActionPerformed"/>
+              </Events>
+            </MenuItem>
+          </SubComponents>
+        </Menu>
+        <Menu class="javax.swing.JMenu" name="menuHelp">
+          <Properties>
+            <Property name="text" type="java.lang.String" value="Help"/>
+          </Properties>
+          <SubComponents>
+            <MenuItem class="javax.swing.JMenuItem" name="menuAbout">
+              <Properties>
+                <Property name="text" type="java.lang.String" value="About"/>
+              </Properties>
+              <Events>
+                <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="menuAboutActionPerformed"/>
+              </Events>
+            </MenuItem>
+          </SubComponents>
+        </Menu>
+      </SubComponents>
+    </Menu>
+  </NonVisualComponents>
+  <Properties>
+    <Property name="defaultCloseOperation" type="int" value="2"/>
+    <Property name="title" type="java.lang.String" value="NVCompress GUI"/>
+  </Properties>
+  <SyntheticProperties>
+    <SyntheticProperty name="menuBar" type="java.lang.String" value="jMenuBar1"/>
+    <SyntheticProperty name="formSizePolicy" type="int" value="1"/>
+  </SyntheticProperties>
+  <Events>
+    <EventHandler event="windowClosing" listener="java.awt.event.WindowListener" parameters="java.awt.event.WindowEvent" handler="formWindowClosing"/>
+  </Events>
+  <AuxValues>
+    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
+    <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="false"/>
+    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
+    <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">
+          <Group type="102" attributes="0">
+              <EmptySpace max="-2" attributes="0"/>
+              <Group type="103" groupAlignment="0" max="-2" attributes="0">
+                  <Component id="barProgress" alignment="1" max="32767" attributes="1"/>
+                  <Component id="pnlCompressOpt" alignment="0" max="32767" attributes="1"/>
+                  <Component id="pnlExportOpt" alignment="0" max="32767" attributes="1"/>
+                  <Component id="pnlMapType" alignment="0" max="32767" attributes="1"/>
+              </Group>
+              <EmptySpace max="-2" attributes="0"/>
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <Group type="102" alignment="1" attributes="0">
+                      <Component id="btnAddFiles" min="-2" max="-2" attributes="0"/>
+                      <EmptySpace max="-2" attributes="0"/>
+                      <Component id="btnRemoveFiles" min="-2" max="-2" attributes="0"/>
+                  </Group>
+                  <Component id="sclFileList" pref="263" max="32767" attributes="0"/>
+              </Group>
+              <EmptySpace max="-2" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+    <DimensionLayout dim="1">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" alignment="0" attributes="0">
+              <EmptySpace max="-2" attributes="0"/>
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <Group type="102" attributes="0">
+                      <Component id="pnlMapType" min="-2" max="-2" attributes="0"/>
+                      <EmptySpace type="unrelated" max="-2" attributes="0"/>
+                      <Component id="pnlCompressOpt" min="-2" max="-2" attributes="0"/>
+                      <EmptySpace max="-2" attributes="0"/>
+                      <Component id="pnlExportOpt" min="-2" max="-2" attributes="0"/>
+                  </Group>
+                  <Component id="sclFileList" pref="380" max="32767" attributes="0"/>
+              </Group>
+              <EmptySpace max="-2" attributes="0"/>
+              <Group type="103" groupAlignment="3" attributes="0">
+                  <Component id="barProgress" alignment="3" pref="30" max="32767" attributes="0"/>
+                  <Component id="btnRemoveFiles" alignment="3" pref="24" max="32767" attributes="1"/>
+                  <Component id="btnAddFiles" alignment="3" max="32767" attributes="1"/>
+              </Group>
+              <EmptySpace max="-2" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+  </Layout>
+  <SubComponents>
+    <Container class="javax.swing.JPanel" name="pnlMapType">
+      <Properties>
+        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+          <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
+            <TitledBorder title="Input Options"/>
+          </Border>
+        </Property>
+      </Properties>
+
+      <Layout>
+        <DimensionLayout dim="0">
+          <Group type="103" groupAlignment="0" attributes="0">
+              <Group type="102" alignment="0" attributes="0">
+                  <EmptySpace max="-2" attributes="0"/>
+                  <Group type="103" groupAlignment="0" attributes="0">
+                      <Component id="chkRepeat" alignment="0" min="-2" max="-2" attributes="0"/>
+                      <Component id="chkMips" alignment="0" min="-2" max="-2" attributes="0"/>
+                      <Group type="102" alignment="0" attributes="0">
+                          <Component id="lblMapType" min="-2" max="-2" attributes="0"/>
+                          <EmptySpace max="-2" attributes="0"/>
+                          <Component id="cmbMapType" min="-2" max="-2" attributes="0"/>
+                      </Group>
+                  </Group>
+                  <EmptySpace pref="118" max="32767" attributes="0"/>
+              </Group>
+          </Group>
+        </DimensionLayout>
+        <DimensionLayout dim="1">
+          <Group type="103" groupAlignment="0" attributes="0">
+              <Group type="102" alignment="0" attributes="0">
+                  <Group type="103" groupAlignment="3" attributes="0">
+                      <Component id="lblMapType" alignment="3" min="-2" max="-2" attributes="0"/>
+                      <Component id="cmbMapType" alignment="3" min="-2" max="-2" attributes="0"/>
+                  </Group>
+                  <EmptySpace type="unrelated" max="-2" attributes="0"/>
+                  <Component id="chkMips" min="-2" max="-2" attributes="0"/>
+                  <EmptySpace max="-2" attributes="0"/>
+                  <Component id="chkRepeat" min="-2" max="-2" attributes="0"/>
+                  <EmptySpace max="32767" attributes="0"/>
+              </Group>
+          </Group>
+        </DimensionLayout>
+      </Layout>
+      <SubComponents>
+        <Component class="javax.swing.JComboBox" name="cmbMapType">
+          <Properties>
+            <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
+              <StringArray count="3">
+                <StringItem index="0" value="Color Map"/>
+                <StringItem index="1" value="Normal Map"/>
+                <StringItem index="2" value="Height/Convert to Normal Map"/>
+              </StringArray>
+            </Property>
+          </Properties>
+        </Component>
+        <Component class="javax.swing.JCheckBox" name="chkMips">
+          <Properties>
+            <Property name="selected" type="boolean" value="true"/>
+            <Property name="text" type="java.lang.String" value="Generate Mipmaps"/>
+          </Properties>
+        </Component>
+        <Component class="javax.swing.JLabel" name="lblMapType">
+          <Properties>
+            <Property name="text" type="java.lang.String" value="Map Type: "/>
+          </Properties>
+        </Component>
+        <Component class="javax.swing.JCheckBox" name="chkRepeat">
+          <Properties>
+            <Property name="text" type="java.lang.String" value="Repeating"/>
+          </Properties>
+        </Component>
+      </SubComponents>
+    </Container>
+    <Container class="javax.swing.JPanel" name="pnlCompressOpt">
+      <Properties>
+        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+          <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
+            <TitledBorder title="Compression Options"/>
+          </Border>
+        </Property>
+      </Properties>
+
+      <Layout>
+        <DimensionLayout dim="0">
+          <Group type="103" groupAlignment="0" attributes="0">
+              <Group type="102" attributes="0">
+                  <EmptySpace max="-2" attributes="0"/>
+                  <Group type="103" groupAlignment="0" attributes="0">
+                      <Group type="102" alignment="0" attributes="0">
+                          <Component id="chkLowQuality" min="-2" max="-2" attributes="0"/>
+                          <EmptySpace max="-2" attributes="0"/>
+                          <Component id="chkCuda" min="-2" max="-2" attributes="0"/>
+                      </Group>
+                      <Group type="102" alignment="0" attributes="0">
+                          <Component id="lblCompressType" min="-2" max="-2" attributes="0"/>
+                          <EmptySpace max="-2" attributes="0"/>
+                          <Component id="cmbCompressType" min="-2" max="-2" attributes="0"/>
+                      </Group>
+                  </Group>
+                  <EmptySpace pref="117" max="32767" attributes="0"/>
+              </Group>
+          </Group>
+        </DimensionLayout>
+        <DimensionLayout dim="1">
+          <Group type="103" groupAlignment="0" attributes="0">
+              <Group type="102" alignment="0" attributes="0">
+                  <Group type="103" groupAlignment="3" attributes="0">
+                      <Component id="chkLowQuality" alignment="3" min="-2" max="-2" attributes="0"/>
+                      <Component id="chkCuda" alignment="3" min="-2" max="-2" attributes="0"/>
+                  </Group>
+                  <EmptySpace type="unrelated" max="-2" attributes="0"/>
+                  <Group type="103" groupAlignment="3" attributes="0">
+                      <Component id="lblCompressType" alignment="3" min="-2" max="-2" attributes="0"/>
+                      <Component id="cmbCompressType" alignment="3" min="-2" max="-2" attributes="0"/>
+                  </Group>
+                  <EmptySpace max="32767" attributes="0"/>
+              </Group>
+          </Group>
+        </DimensionLayout>
+      </Layout>
+      <SubComponents>
+        <Component class="javax.swing.JComboBox" name="cmbCompressType">
+          <Properties>
+            <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
+              <StringArray count="13">
+                <StringItem index="0" value="RGBA"/>
+                <StringItem index="1" value="DXT1"/>
+                <StringItem index="2" value="DXT1nm"/>
+                <StringItem index="3" value="DXT1a"/>
+                <StringItem index="4" value="DXT3"/>
+                <StringItem index="5" value="DXT5"/>
+                <StringItem index="6" value="DXT5nm"/>
+                <StringItem index="7" value="ATI1"/>
+                <StringItem index="8" value="ATI2/3Dc"/>
+                <StringItem index="9" value="P4RGB565"/>
+                <StringItem index="10" value="P8RGB565"/>
+                <StringItem index="11" value="AWT"/>
+                <StringItem index="12" value="PNG-RGBE"/>
+              </StringArray>
+            </Property>
+          </Properties>
+          <Events>
+            <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cmbCompressTypeActionPerformed"/>
+          </Events>
+        </Component>
+        <Component class="javax.swing.JCheckBox" name="chkLowQuality">
+          <Properties>
+            <Property name="text" type="java.lang.String" value="Low Quality"/>
+          </Properties>
+        </Component>
+        <Component class="javax.swing.JLabel" name="lblCompressType">
+          <Properties>
+            <Property name="text" type="java.lang.String" value="Compression Type: "/>
+          </Properties>
+        </Component>
+        <Component class="javax.swing.JCheckBox" name="chkCuda">
+          <Properties>
+            <Property name="selected" type="boolean" value="true"/>
+            <Property name="text" type="java.lang.String" value="Use GPU Compression (faster)"/>
+          </Properties>
+        </Component>
+      </SubComponents>
+    </Container>
+    <Container class="javax.swing.JScrollPane" name="sclFileList">
+      <AuxValues>
+        <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
+      </AuxValues>
+
+      <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
+      <SubComponents>
+        <Component class="javax.swing.JList" name="lstFileList">
+          <Properties>
+            <Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
+              <Connection code="new DefaultListModel()" type="code"/>
+            </Property>
+          </Properties>
+          <Events>
+            <EventHandler event="keyTyped" listener="java.awt.event.KeyListener" parameters="java.awt.event.KeyEvent" handler="lstFileListKeyTyped"/>
+          </Events>
+        </Component>
+      </SubComponents>
+    </Container>
+    <Component class="javax.swing.JButton" name="btnAddFiles">
+      <Properties>
+        <Property name="text" type="java.lang.String" value="Add files.."/>
+      </Properties>
+      <Events>
+        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnAddFilesActionPerformed"/>
+      </Events>
+    </Component>
+    <Component class="javax.swing.JButton" name="btnRemoveFiles">
+      <Properties>
+        <Property name="text" type="java.lang.String" value="Remove Selected"/>
+      </Properties>
+      <Events>
+        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnRemoveFilesActionPerformed"/>
+      </Events>
+    </Component>
+    <Container class="javax.swing.JPanel" name="pnlExportOpt">
+      <Properties>
+        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+          <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
+            <TitledBorder title="Export Options"/>
+          </Border>
+        </Property>
+      </Properties>
+
+      <Layout>
+        <DimensionLayout dim="0">
+          <Group type="103" groupAlignment="0" attributes="0">
+              <Group type="102" attributes="0">
+                  <EmptySpace max="-2" attributes="0"/>
+                  <Group type="103" groupAlignment="0" attributes="0">
+                      <Group type="102" attributes="0">
+                          <Component id="lblTargetDir" min="-2" max="-2" attributes="0"/>
+                          <EmptySpace max="-2" attributes="0"/>
+                          <Component id="txtTargetDir" pref="217" max="32767" attributes="0"/>
+                          <EmptySpace type="unrelated" max="-2" attributes="0"/>
+                          <Component id="btnBrowse" min="-2" max="-2" attributes="0"/>
+                      </Group>
+                      <Component id="chkAsSource" alignment="0" min="-2" max="-2" attributes="0"/>
+                      <Group type="102" alignment="0" attributes="0">
+                          <Component id="btnCompress" min="-2" max="-2" attributes="0"/>
+                          <EmptySpace max="-2" attributes="0"/>
+                          <Component id="btnDecompress" min="-2" max="-2" attributes="0"/>
+                      </Group>
+                  </Group>
+                  <EmptySpace max="-2" attributes="0"/>
+              </Group>
+          </Group>
+        </DimensionLayout>
+        <DimensionLayout dim="1">
+          <Group type="103" groupAlignment="0" attributes="0">
+              <Group type="102" alignment="0" attributes="0">
+                  <Group type="103" groupAlignment="3" attributes="0">
+                      <Component id="lblTargetDir" alignment="3" min="-2" max="-2" attributes="0"/>
+                      <Component id="txtTargetDir" alignment="3" min="-2" max="-2" attributes="0"/>
+                      <Component id="btnBrowse" alignment="3" min="-2" max="-2" attributes="0"/>
+                  </Group>
+                  <EmptySpace max="-2" attributes="0"/>
+                  <Component id="chkAsSource" min="-2" max="-2" attributes="0"/>
+                  <EmptySpace min="-2" pref="7" max="-2" attributes="0"/>
+                  <Group type="103" groupAlignment="3" attributes="0">
+                      <Component id="btnCompress" alignment="3" min="-2" max="-2" attributes="0"/>
+                      <Component id="btnDecompress" alignment="3" min="-2" max="-2" attributes="0"/>
+                  </Group>
+                  <EmptySpace max="32767" attributes="0"/>
+              </Group>
+          </Group>
+        </DimensionLayout>
+      </Layout>
+      <SubComponents>
+        <Component class="javax.swing.JLabel" name="lblTargetDir">
+          <Properties>
+            <Property name="text" type="java.lang.String" value="Target Folder: "/>
+          </Properties>
+        </Component>
+        <Component class="javax.swing.JTextField" name="txtTargetDir">
+        </Component>
+        <Component class="javax.swing.JButton" name="btnBrowse">
+          <Properties>
+            <Property name="text" type="java.lang.String" value="Browse.."/>
+          </Properties>
+          <Events>
+            <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnBrowseActionPerformed"/>
+          </Events>
+        </Component>
+        <Component class="javax.swing.JCheckBox" name="chkAsSource">
+          <Properties>
+            <Property name="text" type="java.lang.String" value="Same as source"/>
+          </Properties>
+          <Events>
+            <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="chkAsSourceActionPerformed"/>
+          </Events>
+        </Component>
+        <Component class="javax.swing.JButton" name="btnCompress">
+          <Properties>
+            <Property name="text" type="java.lang.String" value="Compress"/>
+          </Properties>
+          <Events>
+            <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnCompressActionPerformed"/>
+          </Events>
+        </Component>
+        <Component class="javax.swing.JButton" name="btnDecompress">
+          <Properties>
+            <Property name="text" type="java.lang.String" value="Decompress"/>
+          </Properties>
+          <Events>
+            <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnDecompressActionPerformed"/>
+          </Events>
+        </Component>
+      </SubComponents>
+    </Container>
+    <Component class="javax.swing.JProgressBar" name="barProgress">
+      <Properties>
+        <Property name="stringPainted" type="boolean" value="true"/>
+      </Properties>
+    </Component>
+  </SubComponents>
+</Form>

+ 904 - 0
jme3-materialeditor/src/com/jme3/gde/materials/nvcompress/NVCompress.java

@@ -0,0 +1,904 @@
+/*
+ * 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.materials.nvcompress;
+
+import com.jme3.asset.AssetManager;
+import com.jme3.asset.plugins.FileLocator;
+import com.jme3.export.binary.BinaryExporter;
+import com.jme3.system.JmeSystem;
+import com.jme3.texture.Image;
+import com.jme3.texture.Texture;
+import com.jme3.texture.plugins.HDRLoader;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Cursor;
+import java.awt.event.KeyEvent;
+import java.awt.image.BufferedImage;
+import java.io.*;
+import java.util.ArrayList;
+import java.util.List;
+import javax.imageio.ImageIO;
+import javax.swing.DefaultListModel;
+import javax.swing.JFileChooser;
+import javax.swing.JOptionPane;
+import jme3tools.converters.ImageToAwt;
+import jme3tools.converters.MipMapGenerator;
+import org.openide.util.NbPreferences;
+
+public class NVCompress extends javax.swing.JFrame {
+    
+    private File texToolsPath;
+    private final String appName = "NVCompress GUI 1.00";
+    private Thread workThread = null;
+    private AssetManager manager;
+
+    public NVCompress() {
+        initComponents();
+        barProgress.setVisible(false);
+        // puts the form in the center
+        setLocationRelativeTo(null);
+        System.out.println(appName);
+        setTitle(appName);
+    }
+
+    /** 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.
+     */
+    @SuppressWarnings("unchecked")
+    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
+    private void initComponents() {
+
+        pnlMapType = new javax.swing.JPanel();
+        cmbMapType = new javax.swing.JComboBox();
+        chkMips = new javax.swing.JCheckBox();
+        lblMapType = new javax.swing.JLabel();
+        chkRepeat = new javax.swing.JCheckBox();
+        pnlCompressOpt = new javax.swing.JPanel();
+        cmbCompressType = new javax.swing.JComboBox();
+        chkLowQuality = new javax.swing.JCheckBox();
+        lblCompressType = new javax.swing.JLabel();
+        chkCuda = new javax.swing.JCheckBox();
+        sclFileList = new javax.swing.JScrollPane();
+        lstFileList = new javax.swing.JList();
+        btnAddFiles = new javax.swing.JButton();
+        btnRemoveFiles = new javax.swing.JButton();
+        pnlExportOpt = new javax.swing.JPanel();
+        lblTargetDir = new javax.swing.JLabel();
+        txtTargetDir = new javax.swing.JTextField();
+        btnBrowse = new javax.swing.JButton();
+        chkAsSource = new javax.swing.JCheckBox();
+        btnCompress = new javax.swing.JButton();
+        btnDecompress = new javax.swing.JButton();
+        barProgress = new javax.swing.JProgressBar();
+        jMenuBar1 = new javax.swing.JMenuBar();
+        menuFile = new javax.swing.JMenu();
+        itemExit = new javax.swing.JMenuItem();
+        menuHelp = new javax.swing.JMenu();
+        menuAbout = new javax.swing.JMenuItem();
+
+        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
+        setTitle("NVCompress GUI");
+        addWindowListener(new java.awt.event.WindowAdapter() {
+            public void windowClosing(java.awt.event.WindowEvent evt) {
+                formWindowClosing(evt);
+            }
+        });
+
+        pnlMapType.setBorder(javax.swing.BorderFactory.createTitledBorder("Input Options"));
+
+        cmbMapType.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Color Map", "Normal Map", "Height/Convert to Normal Map" }));
+
+        chkMips.setSelected(true);
+        chkMips.setText("Generate Mipmaps");
+
+        lblMapType.setText("Map Type: ");
+
+        chkRepeat.setText("Repeating");
+
+        javax.swing.GroupLayout pnlMapTypeLayout = new javax.swing.GroupLayout(pnlMapType);
+        pnlMapType.setLayout(pnlMapTypeLayout);
+        pnlMapTypeLayout.setHorizontalGroup(
+            pnlMapTypeLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(pnlMapTypeLayout.createSequentialGroup()
+                .addContainerGap()
+                .addGroup(pnlMapTypeLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addComponent(chkRepeat)
+                    .addComponent(chkMips)
+                    .addGroup(pnlMapTypeLayout.createSequentialGroup()
+                        .addComponent(lblMapType)
+                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                        .addComponent(cmbMapType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
+                .addContainerGap(118, Short.MAX_VALUE))
+        );
+        pnlMapTypeLayout.setVerticalGroup(
+            pnlMapTypeLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(pnlMapTypeLayout.createSequentialGroup()
+                .addGroup(pnlMapTypeLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                    .addComponent(lblMapType)
+                    .addComponent(cmbMapType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+                .addComponent(chkMips)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(chkRepeat)
+                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+        );
+
+        pnlCompressOpt.setBorder(javax.swing.BorderFactory.createTitledBorder("Compression Options"));
+
+        cmbCompressType.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "RGBA", "DXT1", "DXT1nm", "DXT1a", "DXT3", "DXT5", "DXT5nm", "ATI1", "ATI2/3Dc", "P4RGB565", "P8RGB565", "AWT", "PNG-RGBE" }));
+        cmbCompressType.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                cmbCompressTypeActionPerformed(evt);
+            }
+        });
+
+        chkLowQuality.setText("Low Quality");
+
+        lblCompressType.setText("Compression Type: ");
+
+        chkCuda.setSelected(true);
+        chkCuda.setText("Use GPU Compression (faster)");
+
+        javax.swing.GroupLayout pnlCompressOptLayout = new javax.swing.GroupLayout(pnlCompressOpt);
+        pnlCompressOpt.setLayout(pnlCompressOptLayout);
+        pnlCompressOptLayout.setHorizontalGroup(
+            pnlCompressOptLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(pnlCompressOptLayout.createSequentialGroup()
+                .addContainerGap()
+                .addGroup(pnlCompressOptLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addGroup(pnlCompressOptLayout.createSequentialGroup()
+                        .addComponent(chkLowQuality)
+                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                        .addComponent(chkCuda))
+                    .addGroup(pnlCompressOptLayout.createSequentialGroup()
+                        .addComponent(lblCompressType)
+                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                        .addComponent(cmbCompressType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
+                .addContainerGap(117, Short.MAX_VALUE))
+        );
+        pnlCompressOptLayout.setVerticalGroup(
+            pnlCompressOptLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(pnlCompressOptLayout.createSequentialGroup()
+                .addGroup(pnlCompressOptLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                    .addComponent(chkLowQuality)
+                    .addComponent(chkCuda))
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+                .addGroup(pnlCompressOptLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                    .addComponent(lblCompressType)
+                    .addComponent(cmbCompressType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+        );
+
+        lstFileList.setModel(new DefaultListModel());
+        lstFileList.addKeyListener(new java.awt.event.KeyAdapter() {
+            public void keyTyped(java.awt.event.KeyEvent evt) {
+                lstFileListKeyTyped(evt);
+            }
+        });
+        sclFileList.setViewportView(lstFileList);
+
+        btnAddFiles.setText("Add files..");
+        btnAddFiles.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                btnAddFilesActionPerformed(evt);
+            }
+        });
+
+        btnRemoveFiles.setText("Remove Selected");
+        btnRemoveFiles.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                btnRemoveFilesActionPerformed(evt);
+            }
+        });
+
+        pnlExportOpt.setBorder(javax.swing.BorderFactory.createTitledBorder("Export Options"));
+
+        lblTargetDir.setText("Target Folder: ");
+
+        btnBrowse.setText("Browse..");
+        btnBrowse.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                btnBrowseActionPerformed(evt);
+            }
+        });
+
+        chkAsSource.setText("Same as source");
+        chkAsSource.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                chkAsSourceActionPerformed(evt);
+            }
+        });
+
+        btnCompress.setText("Compress");
+        btnCompress.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                btnCompressActionPerformed(evt);
+            }
+        });
+
+        btnDecompress.setText("Decompress");
+        btnDecompress.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                btnDecompressActionPerformed(evt);
+            }
+        });
+
+        javax.swing.GroupLayout pnlExportOptLayout = new javax.swing.GroupLayout(pnlExportOpt);
+        pnlExportOpt.setLayout(pnlExportOptLayout);
+        pnlExportOptLayout.setHorizontalGroup(
+            pnlExportOptLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(pnlExportOptLayout.createSequentialGroup()
+                .addContainerGap()
+                .addGroup(pnlExportOptLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addGroup(pnlExportOptLayout.createSequentialGroup()
+                        .addComponent(lblTargetDir)
+                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                        .addComponent(txtTargetDir, javax.swing.GroupLayout.DEFAULT_SIZE, 217, Short.MAX_VALUE)
+                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+                        .addComponent(btnBrowse))
+                    .addComponent(chkAsSource)
+                    .addGroup(pnlExportOptLayout.createSequentialGroup()
+                        .addComponent(btnCompress)
+                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                        .addComponent(btnDecompress)))
+                .addContainerGap())
+        );
+        pnlExportOptLayout.setVerticalGroup(
+            pnlExportOptLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(pnlExportOptLayout.createSequentialGroup()
+                .addGroup(pnlExportOptLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                    .addComponent(lblTargetDir)
+                    .addComponent(txtTargetDir, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                    .addComponent(btnBrowse))
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(chkAsSource)
+                .addGap(7, 7, 7)
+                .addGroup(pnlExportOptLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                    .addComponent(btnCompress)
+                    .addComponent(btnDecompress))
+                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+        );
+
+        barProgress.setStringPainted(true);
+
+        menuFile.setText("File");
+
+        itemExit.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_Q, java.awt.event.InputEvent.CTRL_MASK));
+        itemExit.setText("Exit");
+        itemExit.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                itemExitActionPerformed(evt);
+            }
+        });
+        menuFile.add(itemExit);
+
+        jMenuBar1.add(menuFile);
+
+        menuHelp.setText("Help");
+
+        menuAbout.setText("About");
+        menuAbout.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                menuAboutActionPerformed(evt);
+            }
+        });
+        menuHelp.add(menuAbout);
+
+        jMenuBar1.add(menuHelp);
+
+        setJMenuBar(jMenuBar1);
+
+        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
+        getContentPane().setLayout(layout);
+        layout.setHorizontalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(layout.createSequentialGroup()
+                .addContainerGap()
+                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
+                    .addComponent(barProgress, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+                    .addComponent(pnlCompressOpt, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+                    .addComponent(pnlExportOpt, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+                    .addComponent(pnlMapType, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
+                        .addComponent(btnAddFiles)
+                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                        .addComponent(btnRemoveFiles))
+                    .addComponent(sclFileList, javax.swing.GroupLayout.DEFAULT_SIZE, 263, Short.MAX_VALUE))
+                .addContainerGap())
+        );
+        layout.setVerticalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(layout.createSequentialGroup()
+                .addContainerGap()
+                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addGroup(layout.createSequentialGroup()
+                        .addComponent(pnlMapType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+                        .addComponent(pnlCompressOpt, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                        .addComponent(pnlExportOpt, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+                    .addComponent(sclFileList, javax.swing.GroupLayout.DEFAULT_SIZE, 380, Short.MAX_VALUE))
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                    .addComponent(barProgress, javax.swing.GroupLayout.DEFAULT_SIZE, 30, Short.MAX_VALUE)
+                    .addComponent(btnRemoveFiles, javax.swing.GroupLayout.PREFERRED_SIZE, 24, Short.MAX_VALUE)
+                    .addComponent(btnAddFiles, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+                .addContainerGap())
+        );
+
+        pack();
+    }// </editor-fold>//GEN-END:initComponents
+
+    private String[] computeCompressParameters(){
+        List<String> params = new ArrayList<String>();
+
+        if (!chkCuda.isSelected())
+            params.add("-nocuda");
+        
+        switch (cmbMapType.getSelectedIndex()){
+            case 0: params.add("-color"); break;
+            case 1: params.add("-normal"); break;
+            case 2: params.add("-tonormal"); break;
+        }
+
+        if (!chkMips.isSelected())
+            params.add("-nomips");
+        if (chkRepeat.isSelected())
+            params.add("-repeat");
+        if (chkLowQuality.isSelected())
+            params.add("-fast");
+
+        switch (cmbCompressType.getSelectedIndex()){
+            case 0: params.add("-rgb"); break;
+            case 1: params.add("-bc1"); break;
+            case 2: params.add("-bc1n"); break;
+            case 3: params.add("-bc1a"); break;
+            case 4: params.add("-bc2"); break;
+            case 5: params.add("-bc3"); break;
+            case 6: params.add("-bc3n"); break;
+            case 7: params.add("-bc4"); break;
+            case 8: params.add("-bc5"); break;
+        }
+
+        return params.toArray(new String[0]);
+    }
+
+    private void updateWork(String workStatus, int percent){
+        barProgress.setString(workStatus + " - " + percent+"%");
+        barProgress.setValue(percent);
+    }
+
+    private void setComponentEnabled(Container c, boolean enabled){
+        c.setEnabled(enabled);
+        for (Component child : c.getComponents()){
+            if (child instanceof Container)
+                setComponentEnabled((Container)child, enabled);
+            else
+                child.setEnabled(enabled);
+        }
+    }
+
+    private void startWork(){
+        setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+        barProgress.setVisible(true);
+        barProgress.setValue(0);
+        barProgress.setString("Status: Working");
+
+        setComponentEnabled(pnlCompressOpt, false);
+        setComponentEnabled(pnlExportOpt, false);
+        setComponentEnabled(pnlMapType, false);
+        lstFileList.setEnabled(false);
+        btnAddFiles.setEnabled(false);
+        btnRemoveFiles.setEnabled(false);
+    }
+
+    private void endWork(){
+        workThread = null;
+
+        setCursor(null);
+        barProgress.setVisible(false);
+        barProgress.setString("Status: Done");
+
+        setComponentEnabled(pnlCompressOpt, true);
+        setComponentEnabled(pnlExportOpt, true);
+        setComponentEnabled(pnlMapType, true);
+        lstFileList.setEnabled(true);
+        btnAddFiles.setEnabled(true);
+        btnRemoveFiles.setEnabled(true);
+
+        // properly disables/enables certain components
+        chkAsSourceActionPerformed(null);
+
+        btnCompress.setText("Compress");
+        btnDecompress.setText("Decompress");
+    }
+
+    private void runJ3(File input, File output, String statusStr) throws InterruptedException{
+        updateWork(statusStr, 0);
+        if (manager == null)
+            manager = JmeSystem.newAssetManager();
+
+        manager.registerLocator(input.getParent().toString(),
+                                FileLocator.class.getName());
+
+        String format = (String) cmbCompressType.getSelectedItem();
+        if (format.equals("PNG-RGBE")){
+            HDRLoader loader = new HDRLoader(true);
+            try{
+                FileInputStream in = new FileInputStream(input);
+                Image image = loader.load(in, false);
+                in.close();
+
+                BufferedImage rgbeImage = ImageToAwt.convert(image, false, true, 0);
+                if (output == null){
+                    output = new File(input.getParent(), input.getName() + ".png");
+                }
+                ImageIO.write(rgbeImage, "png", output);
+            } catch (IOException ex){
+                ex.printStackTrace();
+            }
+        }else{
+            Texture tex = manager.loadTexture(input.getName());
+            Image image = tex.getImage();
+
+            boolean mips = chkMips.isSelected();
+            if (mips && !image.hasMipmaps()){
+                MipMapGenerator.generateMipMaps(image);
+            }
+            if (output == null){
+                output = new File(input.getParent(), input.getName() + ".j3i");
+            }
+
+            try{
+                BinaryExporter.getInstance().save(image, output);
+                BufferedImage preview = ImageToAwt.convert(image, false, true, 0);
+                ImageIO.write(preview, "png", new File(output + ".png"));
+            }catch (IOException ex){
+                ex.printStackTrace();
+            }
+        }
+    }
+
+    private void runCommand(String[] args, String statusStr) throws InterruptedException{
+        Process p = null;
+        try{
+            ProcessBuilder builder = new ProcessBuilder(args);
+            updateWork(statusStr, 0);
+            p = builder.start();
+            BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));
+            String ln;
+            while ((ln = r.readLine()) != null){
+                if (Thread.interrupted())
+                    throw new InterruptedException();
+                
+                if (ln.endsWith("%")){
+                    // show status in bar
+                    int percent = Integer.parseInt(ln.substring(0, ln.length()-1));
+                    updateWork(statusStr, percent);
+                }else if (ln.startsWith("time taken")){
+                    ln = ln.substring(12, ln.length()-7).trim();
+                    System.out.println("Time Taken: "+ln+" seconds");
+                }
+            }
+            r.close();
+            int error = p.waitFor();
+            if (error != 0){
+                System.out.println("Error Code: " + error);
+            }
+        } catch (IOException ex){
+            ex.printStackTrace();
+        } catch (InterruptedException ex){
+            // may get interrupted if user canceled work
+            if (p != null)
+                p.destroy();
+
+            // propegate exception incase caller is interested
+            throw ex;
+        }
+    }
+
+    private void runNVDecompress(final File inFile) throws InterruptedException{
+        if (!inFile.getName().toLowerCase().endsWith(".dds"))
+            return; // not a DDS file
+
+        String[] args = new String[2];
+        args[0] = new File(texToolsPath, "nvdecompress").toString();
+        args[1] = inFile.toString();
+
+        System.out.println("Decompressing file "+inFile);
+        runCommand(args, "Decompressing file "+inFile.getName());
+    }
+
+    private void runNVCompress(final File inFile, File outFile) throws InterruptedException{
+        String nvcompressCmd = new File(texToolsPath, "nvcompress").toString();
+        int argCount = 2; // nvcompressCmd & inFile are always specified
+        if (outFile != null)
+            argCount ++;
+
+        String[] params = computeCompressParameters();
+        argCount += params.length;
+
+        String[] args = new String[argCount];
+        args[0] = nvcompressCmd;
+        System.arraycopy(params, 0, args, 1, params.length);
+        args[params.length + 1] = inFile.toString();
+        if (outFile != null)
+            args[params.length + 2] = outFile.toString();
+
+        System.out.println("Converting file "+inFile);
+//        System.out.println("Arguments: ");
+//        for (String arg : args) System.out.println("   "+arg);
+
+        runCommand(args, "Converting "+inFile.getName());
+    }
+
+    private void runJ3Compress(final File inFile, File outFile) throws InterruptedException{
+        System.out.println("Converting file "+inFile);
+        runJ3(inFile, outFile, "Converting "+inFile.getName());
+    }
+
+    private Object[] compileFileList(){
+        Object[] values = lstFileList.getSelectedValues();
+        if (values == null || values.length == 0){
+            // no specific files selected, add all of them
+            DefaultListModel listModel = (DefaultListModel) lstFileList.getModel();
+            values = listModel.toArray();
+        }
+        return values;
+    }
+
+    private void runNVCompressAll(final File exportDir){
+        final Object[] fileList = compileFileList();
+        if (fileList != null && fileList.length > 0){
+            startWork();
+            workThread = new Thread(){
+                @Override
+                public void run(){
+                    for (Object val : fileList){
+                        File inFile = (File) val;
+                        File outFile = null;
+                        if (exportDir != null){
+                            String name = inFile.getName();
+                            int extPt = name.lastIndexOf(".");
+                            if (extPt > 0)
+                                name = name.substring(0, extPt);
+                            
+                            outFile = new File(exportDir, name+".dds");
+                        }
+                        try{
+                            runNVCompress(inFile, outFile);
+                        }catch (InterruptedException ex){
+                            return; // user canceled
+                        }
+                    }
+                    endWork();
+                }
+            };
+            workThread.setDaemon(true);
+            workThread.start();
+        }
+    }
+
+    private void runJ3CompressAll(final File exportDir, final String ext){
+        final Object[] fileList = compileFileList();
+        if (fileList != null && fileList.length > 0){
+            startWork();
+            workThread = new Thread(){
+                @Override
+                public void run(){
+                    for (Object val : fileList){
+                        File inFile = (File) val;
+                        File outFile = null;
+                        if (exportDir != null){
+                            String name = inFile.getName();
+                            int extPt = name.lastIndexOf(".");
+                            if (extPt > 0)
+                                name = name.substring(0, extPt);
+
+                            outFile = new File(exportDir, name+"."+ext);
+                        }
+                        try{
+                            runJ3Compress(inFile, outFile);
+                        }catch (InterruptedException ex){
+                            return; // user canceled
+                        }
+                    }
+                    endWork();
+                }
+            };
+            workThread.setDaemon(true);
+            workThread.start();
+        }
+    }
+
+    private void runNVDecompressAll(){
+        final Object[] fileList = compileFileList();
+        if (fileList != null && fileList.length > 0){
+            startWork();
+            workThread = new Thread(){
+                @Override
+                public void run(){
+                    for (Object val : fileList){
+                        File inFile = (File) val;
+                        try{
+                            runNVDecompress(inFile);
+                        }catch (InterruptedException ex){
+                            return; // user canceled
+                        }
+                    }
+                    endWork();
+                }
+            };
+            workThread.setDaemon(true);
+            workThread.start();
+        }
+    }
+
+    private void cmbCompressTypeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cmbCompressTypeActionPerformed
+
+}//GEN-LAST:event_cmbCompressTypeActionPerformed
+
+    private void btnCompressActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCompressActionPerformed
+        if (btnCompress.getText().equals("Cancel")){
+            if (workThread != null){
+                workThread.interrupt();
+                System.out.println("User canceled decompression");
+                endWork();
+            }
+        }else{
+            // find out where to export
+            File exportDir = null;
+            if (!chkAsSource.isSelected()){
+               String exportPath = txtTargetDir.getText();
+               if (exportPath != null && !exportPath.equals(""))
+                   exportDir = new File(exportPath);
+            }
+
+            String compression = (String) cmbCompressType.getSelectedItem();
+            if (compression.equals("AWT") || compression.equals("PNG-RGBE")){
+                runJ3CompressAll(exportDir, compression.equals("AWT") ? "j3i" : "pnge");
+            }else{
+                runNVCompressAll(exportDir);
+            }
+            
+            btnCompress.setEnabled(true);
+            btnCompress.setText("Cancel");
+        }
+}//GEN-LAST:event_btnCompressActionPerformed
+
+    private void btnBrowseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnBrowseActionPerformed
+        JFileChooser chooser = new JFileChooser();
+        chooser.setDialogTitle("Select export directory");
+        chooser.setMultiSelectionEnabled(false);
+        chooser.setDialogType(JFileChooser.OPEN_DIALOG);
+        chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+        if (txtTargetDir.getText() != null && !txtTargetDir.getText().equals(""))
+            chooser.setSelectedFile(new File(txtTargetDir.getText()));
+
+        if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION){
+            File f = chooser.getSelectedFile();
+            if (f != null && f.exists() && f.isDirectory())
+                txtTargetDir.setText(f.toString());
+            else
+                JOptionPane.showMessageDialog(this,
+                        "Invalid export directory specified",
+                        "Error", JOptionPane.ERROR_MESSAGE);
+        }
+    }//GEN-LAST:event_btnBrowseActionPerformed
+
+    private void chkAsSourceActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chkAsSourceActionPerformed
+        lblTargetDir.setEnabled(!chkAsSource.isSelected());
+        txtTargetDir.setEnabled(!chkAsSource.isSelected());
+        btnBrowse.setEnabled(!chkAsSource.isSelected());
+    }//GEN-LAST:event_chkAsSourceActionPerformed
+
+    private void btnAddFilesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnAddFilesActionPerformed
+        JFileChooser chooser = new JFileChooser();
+        chooser.setDialogTitle("Add input files");
+        chooser.setMultiSelectionEnabled(true);
+        chooser.setDialogType(JFileChooser.OPEN_DIALOG);
+        chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
+
+        if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION){
+            File[] files = chooser.getSelectedFiles();
+            for (File file : files){
+                if (file.exists() && !file.isDirectory()){
+                    // add to file list
+                    DefaultListModel listModel = (DefaultListModel) lstFileList.getModel();
+                    if (!listModel.contains(file))
+                        listModel.addElement(file);
+                }
+            }
+        }
+    }//GEN-LAST:event_btnAddFilesActionPerformed
+
+    private void btnRemoveFilesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRemoveFilesActionPerformed
+        Object[] selected = lstFileList.getSelectedValues();
+        DefaultListModel listModel = (DefaultListModel) lstFileList.getModel();
+        for (Object val : selected){
+            listModel.removeElement(val);
+        }
+    }//GEN-LAST:event_btnRemoveFilesActionPerformed
+
+    private void itemExitActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_itemExitActionPerformed
+        dispose();
+}//GEN-LAST:event_itemExitActionPerformed
+
+    private void menuAboutActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuAboutActionPerformed
+        String aboutText = appName+"\n"+
+                           "Created by Kirill Vainer.\n"+
+                           "\n"+
+                           "NVIDIA Texture Tools is Copyright© 2009 NVIDIA Corporation.\n"+
+                           "\n"+
+                           "Usage: \n"+
+                           "   Press \"Add Files..\" to add files to convert\n"+
+                           "   Select conversion options on the left, then\n"+
+                           "   click \"Export\" to convert files to DDS\n";
+        JOptionPane.showMessageDialog(this, aboutText, "About", JOptionPane.PLAIN_MESSAGE);
+    }//GEN-LAST:event_menuAboutActionPerformed
+
+    private void lstFileListKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_lstFileListKeyTyped
+        if (evt.getKeyCode() == KeyEvent.VK_DELETE){
+            btnRemoveFilesActionPerformed(null);
+        }
+    }//GEN-LAST:event_lstFileListKeyTyped
+
+    private void btnDecompressActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDecompressActionPerformed
+        if (btnDecompress.getText().equals("Cancel")){
+            if (workThread != null){
+                workThread.interrupt();
+                System.out.println("User canceled decompression");
+                endWork();
+            }
+        }else{
+            runNVDecompressAll();
+            btnDecompress.setEnabled(true);
+            btnDecompress.setText("Cancel");
+        }
+
+}//GEN-LAST:event_btnDecompressActionPerformed
+
+    private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing
+        if (workThread != null)
+            workThread.interrupt();
+    }//GEN-LAST:event_formWindowClosing
+
+    private  boolean verifyTexToolsPath(File path){
+        if (path.exists()){
+            File[] files = path.listFiles();
+            for (File f : files){
+                if (f.getName().startsWith("nvcompress")){
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    private  File showToolsPathChooser(File prevPath){
+        JFileChooser chooser = new JFileChooser();
+        chooser.setDialogTitle("Select directory of NVTextureTools");
+        chooser.setMultiSelectionEnabled(false);
+        chooser.setDialogType(JFileChooser.OPEN_DIALOG);
+        chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+        if (prevPath != null)
+            chooser.setSelectedFile(prevPath);
+        
+        if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION){
+            return chooser.getSelectedFile();
+        }else{
+            return null;
+        }
+    }
+
+    public  String attemptLocateToolsPath(){
+        String path = NbPreferences.forModule(this.getClass()).get("NVTextureToolsPath", null);
+        if (path == null){
+            // if texture tools has been properly installed
+            // the path is located under TEXTURE_TOOLS_DIR env var
+            path = System.getenv("TEXTURE_TOOLS_DIR");
+        }
+        return path;
+    }
+
+    public void start() {
+
+        System.out.println("Verifiying texture tools path..");
+        String path = attemptLocateToolsPath();
+        texToolsPath = path == null ? null : new File(path);
+
+        if (texToolsPath != null){
+            System.out.println("Found existing path: "+texToolsPath);
+        }
+        
+        if (texToolsPath == null || !verifyTexToolsPath(texToolsPath)){
+            while (true){
+                File f = showToolsPathChooser(texToolsPath);
+                if (f == null)
+                    return;
+
+                if (verifyTexToolsPath(f)){
+                    texToolsPath = f;
+                    NbPreferences.forModule(this.getClass()).put("NVTextureToolsPath", texToolsPath.toString());
+                    break;
+                }else{
+                    JOptionPane.showMessageDialog(null, "Directory must"+
+                                                  " contain nvcompress",
+                                                  "Error",
+                                                  JOptionPane.ERROR_MESSAGE);
+                }
+            }
+        }
+
+        java.awt.EventQueue.invokeLater(new Runnable() {
+            public void run() {
+                new NVCompress().setVisible(true);
+            }
+        });
+    }
+
+    // Variables declaration - do not modify//GEN-BEGIN:variables
+    private javax.swing.JProgressBar barProgress;
+    private javax.swing.JButton btnAddFiles;
+    private javax.swing.JButton btnBrowse;
+    private javax.swing.JButton btnCompress;
+    private javax.swing.JButton btnDecompress;
+    private javax.swing.JButton btnRemoveFiles;
+    private javax.swing.JCheckBox chkAsSource;
+    private javax.swing.JCheckBox chkCuda;
+    private javax.swing.JCheckBox chkLowQuality;
+    private javax.swing.JCheckBox chkMips;
+    private javax.swing.JCheckBox chkRepeat;
+    private javax.swing.JComboBox cmbCompressType;
+    private javax.swing.JComboBox cmbMapType;
+    private javax.swing.JMenuItem itemExit;
+    private javax.swing.JMenuBar jMenuBar1;
+    private javax.swing.JLabel lblCompressType;
+    private javax.swing.JLabel lblMapType;
+    private javax.swing.JLabel lblTargetDir;
+    private javax.swing.JList lstFileList;
+    private javax.swing.JMenuItem menuAbout;
+    private javax.swing.JMenu menuFile;
+    private javax.swing.JMenu menuHelp;
+    private javax.swing.JPanel pnlCompressOpt;
+    private javax.swing.JPanel pnlExportOpt;
+    private javax.swing.JPanel pnlMapType;
+    private javax.swing.JScrollPane sclFileList;
+    private javax.swing.JTextField txtTargetDir;
+    // End of variables declaration//GEN-END:variables
+
+}

+ 28 - 0
jme3-materialeditor/src/com/jme3/gde/materials/nvcompress/NVCompressAction.java

@@ -0,0 +1,28 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.jme3.gde.materials.nvcompress;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+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 = "Textures",
+id = "com.jme3.gde.materials.nvcompress.NVCompressAction")
+@ActionRegistration(displayName = "#CTL_NVCompress")
+@ActionReferences({
+    @ActionReference(path = "Menu/Tools/Textures", position = 100)
+})
+@Messages("CTL_NVCompress=NV Compress Tool")
+public final class NVCompressAction implements ActionListener {
+
+    public void actionPerformed(ActionEvent e) {
+        // TODO implement action body
+        new NVCompress().start();
+    }
+}