Browse Source

You can now directly edit shader node's code inside the shader node editor and benefit from a live reload feature of the shader.

Nehon 10 years ago
parent
commit
1036626821

+ 1 - 1
jme3-materialeditor/src/com/jme3/gde/materialdefinition/dialog/AddNodeDialog.java

@@ -28,7 +28,7 @@ import javax.swing.tree.TreeSelectionModel;
 
 /**
  *
- * @author m327836
+ * @author Nehon
  */
 public class AddNodeDialog extends javax.swing.JDialog {
 

+ 5 - 0
jme3-materialeditor/src/com/jme3/gde/materialdefinition/editor/Bundle.properties

@@ -0,0 +1,5 @@
+ShaderEditPanel.closeButton.text=
+ShaderEditPanel.shaderEditorPane.text=
+ShaderEditPanel.closeButton.toolTipText=Close this panel
+ShaderEditPanel.jToggleButton1.text=jToggleButton1
+ShaderEditPanel.headerText.text=jLabel1

+ 5 - 1
jme3-materialeditor/src/com/jme3/gde/materialdefinition/editor/Diagram.java

@@ -134,7 +134,11 @@ public class Diagram extends JPanel implements MouseListener, MouseMotionListene
         }
         repaint();
     }
-
+    
+    protected void showEdit(NodePanel node) {                
+        parent.showShaderEditor(node.getName(),node.getType(),node.filePaths);        
+    }
+    
     public void notifyMappingCreation(Connection conn) {
         parent.makeMapping(conn);
     }

+ 2 - 2
jme3-materialeditor/src/com/jme3/gde/materialdefinition/editor/DraggablePanel.java

@@ -11,7 +11,7 @@ import javax.swing.JPanel;
 
 /**
  *
- * @author m327836
+ * @author Nehon
  */
 public class DraggablePanel extends JPanel implements MouseListener, MouseMotionListener {
 
@@ -44,7 +44,7 @@ public class DraggablePanel extends JPanel implements MouseListener, MouseMotion
         svdey = e.getYOnScreen();
         e.consume();
     }
-
+    
     @Override
     public void mouseReleased(MouseEvent e) {
     }

+ 53 - 20
jme3-materialeditor/src/com/jme3/gde/materialdefinition/editor/MatDefEditorlElement.form

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 
-<Form version="1.4" maxVersion="1.8" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
+<Form version="1.9" maxVersion="1.9" 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"/>
@@ -16,39 +16,72 @@
   <Layout>
     <DimensionLayout dim="0">
       <Group type="103" groupAlignment="0" attributes="0">
-          <Component id="jScrollPane1" alignment="0" max="32767" attributes="0"/>
+          <Component id="jSplitPane" alignment="0" pref="470" max="32767" attributes="0"/>
       </Group>
     </DimensionLayout>
     <DimensionLayout dim="1">
       <Group type="103" groupAlignment="0" attributes="0">
-          <Component id="jScrollPane1" alignment="0" max="32767" attributes="0"/>
+          <Component id="jSplitPane" alignment="1" pref="333" max="32767" attributes="0"/>
       </Group>
     </DimensionLayout>
   </Layout>
   <SubComponents>
-    <Container class="javax.swing.JScrollPane" name="jScrollPane1">
+    <Container class="javax.swing.JSplitPane" name="jSplitPane">
+      <Properties>
+        <Property name="dividerLocation" type="int" value="1"/>
+        <Property name="dividerSize" type="int" value="6"/>
+      </Properties>
 
-      <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
+      <Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
       <SubComponents>
-        <Container class="com.jme3.gde.materialdefinition.editor.Diagram" name="diagram1">
+        <Component class="com.jme3.gde.materialdefinition.editor.ShaderEditPanel" name="shaderEditPanel1">
           <Properties>
-            <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
-              <Color blue="99" green="99" red="99" type="rgb"/>
+            <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+              <Dimension value="[0, 0]"/>
             </Property>
           </Properties>
+          <Constraints>
+            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
+              <JSplitPaneConstraints position="left"/>
+            </Constraint>
+          </Constraints>
+        </Component>
+        <Container class="javax.swing.JScrollPane" name="jScrollPane1">
+          <Properties>
+            <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+              <Dimension value="[0, 0]"/>
+            </Property>
+            <Property name="name" type="java.lang.String" value="" noResource="true"/>
+          </Properties>
+          <Constraints>
+            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
+              <JSplitPaneConstraints position="right"/>
+            </Constraint>
+          </Constraints>
+
+          <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
+          <SubComponents>
+            <Container class="com.jme3.gde.materialdefinition.editor.Diagram" name="diagram1">
+              <Properties>
+                <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
+                  <Color blue="99" green="99" red="99" type="rgb"/>
+                </Property>
+              </Properties>
 
-          <Layout>
-            <DimensionLayout dim="0">
-              <Group type="103" groupAlignment="0" attributes="0">
-                  <EmptySpace min="0" pref="398" max="32767" attributes="0"/>
-              </Group>
-            </DimensionLayout>
-            <DimensionLayout dim="1">
-              <Group type="103" groupAlignment="0" attributes="0">
-                  <EmptySpace min="0" pref="298" max="32767" attributes="0"/>
-              </Group>
-            </DimensionLayout>
-          </Layout>
+              <Layout>
+                <DimensionLayout dim="0">
+                  <Group type="103" groupAlignment="0" attributes="0">
+                      <EmptySpace min="0" pref="1591" max="32767" attributes="0"/>
+                  </Group>
+                </DimensionLayout>
+                <DimensionLayout dim="1">
+                  <Group type="103" groupAlignment="0" attributes="0">
+                      <EmptySpace min="0" pref="782" max="32767" attributes="0"/>
+                  </Group>
+                </DimensionLayout>
+              </Layout>
+            </Container>
+          </SubComponents>
         </Container>
       </SubComponents>
     </Container>

+ 70 - 6
jme3-materialeditor/src/com/jme3/gde/materialdefinition/editor/MatDefEditorlElement.java

@@ -56,6 +56,7 @@ import java.awt.Point;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.beans.PropertyVetoException;
+import java.io.File;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
@@ -69,6 +70,8 @@ import org.netbeans.core.spi.multiview.CloseOperationState;
 import org.netbeans.core.spi.multiview.MultiViewElement;
 import org.netbeans.core.spi.multiview.MultiViewElementCallback;
 import org.openide.awt.UndoRedo;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
 import org.openide.nodes.Children;
 import org.openide.nodes.Node;
 import org.openide.util.Exceptions;
@@ -103,13 +106,16 @@ public final class MatDefEditorlElement extends JPanel implements MultiViewEleme
         metaData = lkp.lookup(MatDefMetaData.class);
         assert obj != null;
         final EditableMatDefFile file = obj.getEditableFile();
-        reload(file, lkp);
+        shaderEditPanel1.setVisible(false);
+        shaderEditPanel1.setParent(this);
+        reload(file, lkp);        
     }
 
     private void initDiagram(Lookup lkp) throws NumberFormatException {
+       
         diagram1.clear();
         diagram1.setParent(this);
-
+        
         Material mat = lkp.lookup(Material.class);
 
         ProjectAssetManager manager = obj.getLookup().lookup(ProjectAssetManager.class);
@@ -260,6 +266,45 @@ public final class MatDefEditorlElement extends JPanel implements MultiViewEleme
             Exceptions.printStackTrace(ex);
         }
     }
+    
+    public void refresh() {
+
+        Lookup.Result<Material> resMat = obj.getLookup().lookupResult(Material.class);
+        Collection<? extends Material> col = (Collection<? extends Material>) resMat.allInstances();
+        if (!col.isEmpty()) {
+            Material material = col.iterator().next();
+            diagram1.refreshPreviews(material);
+        }
+
+    }
+    
+    public void setModified(){
+        obj.setModified(true);        
+    }
+    
+    public ProjectAssetManager getAssetManager(){
+        return obj.getLookup().lookup(ProjectAssetManager.class);
+    }
+    
+    public void showShaderEditor(String nodeName,NodePanel.NodeType type,List<String>pathList){
+        
+        List<FileObject> fos = new ArrayList<FileObject>();
+        for (String path : pathList) {            
+            FileObject text = FileUtil.toFileObject(new File(getAssetManager().getAbsoluteAssetPath(path)));
+            fos.add(text);
+        }
+        shaderEditPanel1.setFiles(nodeName, type, fos);
+        shaderEditPanel1.revalidate();
+        if(!shaderEditPanel1.isVisible() || jSplitPane.getDividerLocation() == jSplitPane.getMinimumDividerLocation()){
+            shaderEditPanel1.setVisible(true);
+            jSplitPane.setDividerLocation(650);
+        }
+        
+    }
+    
+    public ShaderEditPanel getShaderEditor(){
+        return shaderEditPanel1;
+    }
 
     private Node findNode(Node root, String key) {
         if (root instanceof Selectable) {
@@ -289,38 +334,53 @@ public final class MatDefEditorlElement extends JPanel implements MultiViewEleme
     // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
     private void initComponents() {
 
+        jSplitPane = new javax.swing.JSplitPane();
+        shaderEditPanel1 = new com.jme3.gde.materialdefinition.editor.ShaderEditPanel();
         jScrollPane1 = new javax.swing.JScrollPane();
         diagram1 = new com.jme3.gde.materialdefinition.editor.Diagram();
 
+        jSplitPane.setDividerLocation(1);
+        jSplitPane.setDividerSize(6);
+
+        shaderEditPanel1.setMinimumSize(new java.awt.Dimension(0, 0));
+        jSplitPane.setLeftComponent(shaderEditPanel1);
+
+        jScrollPane1.setMinimumSize(new java.awt.Dimension(0, 0));
+        jScrollPane1.setName(""); // NOI18N
+
         diagram1.setBackground(new java.awt.Color(153, 153, 153));
 
         javax.swing.GroupLayout diagram1Layout = new javax.swing.GroupLayout(diagram1);
         diagram1.setLayout(diagram1Layout);
         diagram1Layout.setHorizontalGroup(
             diagram1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGap(0, 398, Short.MAX_VALUE)
+            .addGap(0, 1591, Short.MAX_VALUE)
         );
         diagram1Layout.setVerticalGroup(
             diagram1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGap(0, 298, Short.MAX_VALUE)
+            .addGap(0, 782, Short.MAX_VALUE)
         );
 
         jScrollPane1.setViewportView(diagram1);
 
+        jSplitPane.setRightComponent(jScrollPane1);
+
         javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
         this.setLayout(layout);
         layout.setHorizontalGroup(
             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addComponent(jScrollPane1)
+            .addComponent(jSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 470, Short.MAX_VALUE)
         );
         layout.setVerticalGroup(
             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addComponent(jScrollPane1)
+            .addComponent(jSplitPane, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 333, Short.MAX_VALUE)
         );
     }// </editor-fold>//GEN-END:initComponents
     // Variables declaration - do not modify//GEN-BEGIN:variables
     private com.jme3.gde.materialdefinition.editor.Diagram diagram1;
     private javax.swing.JScrollPane jScrollPane1;
+    private javax.swing.JSplitPane jSplitPane;
+    private com.jme3.gde.materialdefinition.editor.ShaderEditPanel shaderEditPanel1;
     // End of variables declaration//GEN-END:variables
 
     @Override
@@ -572,6 +632,10 @@ public final class MatDefEditorlElement extends JPanel implements MultiViewEleme
         metaData.setProperty(diagram1.getCurrentTechniqueName() + "/" + key, x + "," + y);
 
     }
+    
+    public void reload(){
+          reload(obj.getEditableFile(), obj.getLookup());
+    }
 
     private void reload(final EditableMatDefFile file, final Lookup lkp) throws NumberFormatException {
         if (file.isLoaded()) {

+ 18 - 0
jme3-materialeditor/src/com/jme3/gde/materialdefinition/editor/NodePanel.java

@@ -5,6 +5,7 @@
 package com.jme3.gde.materialdefinition.editor;
 
 import com.jme3.gde.materialdefinition.fileStructure.ShaderNodeBlock;
+import com.jme3.gde.materialdefinition.fileStructure.leaves.DefinitionBlock;
 import com.jme3.gde.materialdefinition.fileStructure.leaves.InputMappingBlock;
 import com.jme3.gde.materialdefinition.fileStructure.leaves.OutputMappingBlock;
 import com.jme3.gde.materialdefinition.icons.Icons;
@@ -51,6 +52,7 @@ public class NodePanel extends DraggablePanel implements Selectable, PropertyCha
     private Color color;
     private String name;
     private String techName;
+    protected List<String> filePaths= new ArrayList<String>();
 
 //    private List listeners = Collections.synchronizedList(new LinkedList());
 //
@@ -106,6 +108,9 @@ public class NodePanel extends DraggablePanel implements Selectable, PropertyCha
         this.addPropertyChangeListener(WeakListeners.propertyChange(node, this));
         refresh(node);
         addKeyListener(this);
+        this.filePaths.addAll(def.getShadersPath());
+        String defPath = ((DefinitionBlock)node.getContents().get(0)).getPath();
+        this.filePaths.add(defPath);
     }
 
     /**
@@ -311,6 +316,19 @@ public class NodePanel extends DraggablePanel implements Selectable, PropertyCha
         header.addMouseMotionListener(labelMouseMotionListener);
         header.setHorizontalAlignment(SwingConstants.LEFT);
         header.setFont(new Font("Tahoma", Font.BOLD, 11));
+        header.addMouseListener(new MouseAdapter() {
+
+            @Override
+            public void mouseClicked(MouseEvent e) {
+                //if(e.getClickCount()==2){
+                    if (type==NodeType.Fragment || type == NodeType.Vertex) {
+                      diagram.showEdit(NodePanel.this);
+                    }            
+                //}
+            }
+                
+        });
+        
         content = new JPanel();
         content.setOpaque(false);
         GroupLayout contentLayout = new GroupLayout(content);

+ 1 - 1
jme3-materialeditor/src/com/jme3/gde/materialdefinition/editor/OutBusPanel.java

@@ -25,7 +25,7 @@ import javax.swing.SwingUtilities;
 
 /**
  *
- * @author m327836
+ * @author Nehon
  */
 public class OutBusPanel extends DraggablePanel implements ComponentListener, Selectable, InOut {
 

+ 1 - 1
jme3-materialeditor/src/com/jme3/gde/materialdefinition/editor/Selectable.java

@@ -6,7 +6,7 @@ package com.jme3.gde.materialdefinition.editor;
 
 /**
  *
- * @author m327836
+ * @author Nehon
  */
 public interface Selectable {
     

+ 162 - 0
jme3-materialeditor/src/com/jme3/gde/materialdefinition/editor/ShaderEditPanel.form

@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
+  <NonVisualComponents>
+    <Component class="javax.swing.ButtonGroup" name="buttonGroup1">
+    </Component>
+  </NonVisualComponents>
+  <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="header" alignment="0" max="32767" attributes="0"/>
+          <Component id="jScrollPane1" alignment="0" pref="645" max="32767" attributes="0"/>
+          <Group type="102" alignment="1" attributes="0">
+              <Component id="buttonPanel" max="32767" attributes="0"/>
+              <EmptySpace max="-2" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+    <DimensionLayout dim="1">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" alignment="1" attributes="0">
+              <Component id="header" min="-2" max="-2" attributes="0"/>
+              <EmptySpace max="-2" attributes="0"/>
+              <Component id="buttonPanel" min="-2" pref="21" max="-2" attributes="0"/>
+              <EmptySpace max="-2" attributes="0"/>
+              <Component id="jScrollPane1" pref="492" max="32767" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+  </Layout>
+  <SubComponents>
+    <Container class="javax.swing.JScrollPane" name="jScrollPane1">
+      <Properties>
+        <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+          <Dimension value="[0, 0]"/>
+        </Property>
+      </Properties>
+      <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.JEditorPane" name="shaderEditorPane">
+          <Properties>
+            <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+              <Border info="null"/>
+            </Property>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="com/jme3/gde/materialdefinition/editor/Bundle.properties" key="ShaderEditPanel.shaderEditorPane.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+        </Component>
+      </SubComponents>
+    </Container>
+    <Container class="javax.swing.JPanel" name="header">
+      <Properties>
+        <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
+          <Color blue="d1" green="b4" id="Active Caption" palette="2" red="99" type="palette"/>
+        </Property>
+        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+          <Border info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
+            <EtchetBorder/>
+          </Border>
+        </Property>
+      </Properties>
+
+      <Layout>
+        <DimensionLayout dim="0">
+          <Group type="103" groupAlignment="0" attributes="0">
+              <Group type="102" alignment="0" attributes="0">
+                  <Component id="headerText" max="32767" attributes="0"/>
+                  <EmptySpace max="-2" attributes="0"/>
+                  <Component id="closeButton" min="-2" max="-2" attributes="0"/>
+              </Group>
+          </Group>
+        </DimensionLayout>
+        <DimensionLayout dim="1">
+          <Group type="103" groupAlignment="0" attributes="0">
+              <Group type="103" alignment="0" groupAlignment="3" attributes="0">
+                  <Component id="headerText" alignment="3" min="-2" pref="19" max="-2" attributes="0"/>
+                  <Component id="closeButton" alignment="3" min="-2" pref="19" max="-2" attributes="0"/>
+              </Group>
+          </Group>
+        </DimensionLayout>
+      </Layout>
+      <SubComponents>
+        <Component class="javax.swing.JLabel" name="headerText">
+          <Properties>
+            <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
+              <Font name="Tahoma" size="11" style="1"/>
+            </Property>
+            <Property name="horizontalAlignment" type="int" value="0"/>
+            <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
+              <Image iconType="3" name="/com/jme3/gde/materialdefinition/icons/fragment.png"/>
+            </Property>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="com/jme3/gde/materialdefinition/editor/Bundle.properties" key="ShaderEditPanel.headerText.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+        </Component>
+        <Component class="javax.swing.JButton" name="closeButton">
+          <Properties>
+            <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
+              <Color blue="d1" green="b4" id="Active Caption" palette="2" red="99" type="palette"/>
+            </Property>
+            <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
+              <Font name="Tahoma" size="8" style="1"/>
+            </Property>
+            <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
+              <Image iconType="3" name="/com/jme3/gde/materialdefinition/icons/out.png"/>
+            </Property>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="com/jme3/gde/materialdefinition/editor/Bundle.properties" key="ShaderEditPanel.closeButton.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/materialdefinition/editor/Bundle.properties" key="ShaderEditPanel.closeButton.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+            <Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
+              <Insets value="[0, 0, 0, 0]"/>
+            </Property>
+          </Properties>
+          <Events>
+            <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="closeButtonActionPerformed"/>
+          </Events>
+        </Component>
+      </SubComponents>
+    </Container>
+    <Container class="javax.swing.JPanel" name="buttonPanel">
+      <Properties>
+        <Property name="alignmentX" type="float" value="0.0"/>
+        <Property name="alignmentY" type="float" value="0.0"/>
+        <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+          <Dimension value="[73, 29]"/>
+        </Property>
+      </Properties>
+
+      <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout"/>
+      <SubComponents>
+        <Component class="javax.swing.JToggleButton" name="jToggleButton1">
+          <Properties>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="com/jme3/gde/materialdefinition/editor/Bundle.properties" key="ShaderEditPanel.jToggleButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+        </Component>
+      </SubComponents>
+    </Container>
+  </SubComponents>
+</Form>

+ 244 - 0
jme3-materialeditor/src/com/jme3/gde/materialdefinition/editor/ShaderEditPanel.java

@@ -0,0 +1,244 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.jme3.gde.materialdefinition.editor;
+
+import com.jme3.gde.materialdefinition.icons.Icons;
+import com.jme3.shader.Shader;
+import java.awt.Component;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.util.List;
+import javax.swing.JPanel;
+import javax.swing.JToggleButton;
+import javax.swing.text.EditorKit;
+import org.openide.filesystems.FileObject;
+import org.openide.loaders.DataObject;
+import org.openide.loaders.DataObjectNotFoundException;
+import org.openide.text.CloneableEditorSupport;
+import org.openide.util.Exceptions;
+
+/**
+ *
+ * @author Nehon
+ */
+public class ShaderEditPanel extends JPanel {
+
+    private DataObject currentDataObject = null;
+    private MatDefEditorlElement parent = null;
+
+    /**
+     * Creates new form ShaderEditPanel
+     */
+    public ShaderEditPanel() {
+        initComponents();
+        String mime = "text/x-glsl";
+        EditorKit ek = CloneableEditorSupport.getEditorKit(mime);
+        shaderEditorPane.setEditorKit(ek);
+        shaderEditorPane.setContentType(mime);
+        shaderEditorPane.addKeyListener(new KeyListener() {
+
+            public void keyTyped(KeyEvent e) {
+                currentDataObject.setModified(true);
+            }
+
+            public void keyPressed(KeyEvent e) {
+                if ((e.getKeyCode() == KeyEvent.VK_S) && ((e.getModifiers() & KeyEvent.CTRL_MASK) != 0)) {
+                    saveCurrent();
+                }
+            }
+
+            public void keyReleased(KeyEvent e) {
+            }
+        });
+    }
+
+    public void setParent(MatDefEditorlElement parent) {
+        this.parent = parent;
+    }
+
+    public void setFiles(String title, NodePanel.NodeType type, List<FileObject> fos) {
+
+        headerText.setText(title);
+        headerText.setIcon(Icons.getIconForShaderType(type));
+        boolean firstItem = true;
+        for (Component component : buttonPanel.getComponents()) {
+            buttonGroup1.remove((JToggleButton) component);
+        }
+        buttonPanel.removeAll();
+        buttonPanel.repaint();
+
+        for (FileObject fo : fos) {
+            final Tab b = new Tab();
+            b.setText(fo.getNameExt());
+            buttonGroup1.add(b);
+            try {
+                b.dataObject = DataObject.find(fo);
+                b.addActionListener(new ActionListener() {
+                    public void actionPerformed(ActionEvent e) {
+                        saveCurrent();
+                        try {
+                            shaderEditorPane.setText(b.dataObject.getPrimaryFile().asText());
+                        } catch (IOException ex) {
+                            Exceptions.printStackTrace(ex);
+                        }
+                        currentDataObject = b.dataObject;
+                    }
+
+                });
+                if (firstItem) {
+                    shaderEditorPane.setText(fo.asText());
+                    currentDataObject = b.dataObject;
+                    b.setSelected(true);
+                    firstItem = false;                    
+                }
+            } catch (IOException ex) {
+                Exceptions.printStackTrace(ex);
+            }
+
+            buttonPanel.add(b);
+        }
+
+    }
+
+    public void saveCurrent() {
+        if (currentDataObject != null && currentDataObject.isModified()) {
+            try {
+                OutputStreamWriter out = new OutputStreamWriter(currentDataObject.getPrimaryFile().getOutputStream());
+                out.write(shaderEditorPane.getText(), 0, shaderEditorPane.getText().length());
+                out.close();
+                currentDataObject.setModified(false);
+                if(currentDataObject.getPrimaryFile().getExt().equalsIgnoreCase("j3sn")){
+                    parent.reload();                            
+                }                   
+                parent.refresh();
+            } catch (DataObjectNotFoundException ex) {
+                Exceptions.printStackTrace(ex);
+            } catch (IOException ex) {
+                Exceptions.printStackTrace(ex);
+            }
+        }
+    }
+
+    private class Tab extends JToggleButton {
+
+        DataObject dataObject;      
+    }
+
+    /**
+     * 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() {
+
+        buttonGroup1 = new javax.swing.ButtonGroup();
+        jScrollPane1 = new javax.swing.JScrollPane();
+        shaderEditorPane = new javax.swing.JEditorPane();
+        header = new javax.swing.JPanel();
+        headerText = new javax.swing.JLabel();
+        closeButton = new javax.swing.JButton();
+        buttonPanel = new javax.swing.JPanel();
+        jToggleButton1 = new javax.swing.JToggleButton();
+
+        jScrollPane1.setMinimumSize(new java.awt.Dimension(0, 0));
+
+        shaderEditorPane.setBorder(null);
+        shaderEditorPane.setText(org.openide.util.NbBundle.getMessage(ShaderEditPanel.class, "ShaderEditPanel.shaderEditorPane.text")); // NOI18N
+        jScrollPane1.setViewportView(shaderEditorPane);
+
+        header.setBackground(java.awt.SystemColor.activeCaption);
+        header.setBorder(javax.swing.BorderFactory.createEtchedBorder());
+
+        headerText.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
+        headerText.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
+        headerText.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/materialdefinition/icons/fragment.png"))); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(headerText, org.openide.util.NbBundle.getMessage(ShaderEditPanel.class, "ShaderEditPanel.headerText.text")); // NOI18N
+
+        closeButton.setBackground(java.awt.SystemColor.activeCaption);
+        closeButton.setFont(new java.awt.Font("Tahoma", 1, 8)); // NOI18N
+        closeButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/materialdefinition/icons/out.png"))); // NOI18N
+        org.openide.awt.Mnemonics.setLocalizedText(closeButton, org.openide.util.NbBundle.getMessage(ShaderEditPanel.class, "ShaderEditPanel.closeButton.text")); // NOI18N
+        closeButton.setToolTipText(org.openide.util.NbBundle.getMessage(ShaderEditPanel.class, "ShaderEditPanel.closeButton.toolTipText")); // NOI18N
+        closeButton.setMargin(new java.awt.Insets(0, 0, 0, 0));
+        closeButton.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                closeButtonActionPerformed(evt);
+            }
+        });
+
+        javax.swing.GroupLayout headerLayout = new javax.swing.GroupLayout(header);
+        header.setLayout(headerLayout);
+        headerLayout.setHorizontalGroup(
+            headerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(headerLayout.createSequentialGroup()
+                .addComponent(headerText, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(closeButton))
+        );
+        headerLayout.setVerticalGroup(
+            headerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(headerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                .addComponent(headerText, javax.swing.GroupLayout.PREFERRED_SIZE, 19, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addComponent(closeButton, javax.swing.GroupLayout.PREFERRED_SIZE, 19, javax.swing.GroupLayout.PREFERRED_SIZE))
+        );
+
+        buttonPanel.setAlignmentX(0.0F);
+        buttonPanel.setAlignmentY(0.0F);
+        buttonPanel.setPreferredSize(new java.awt.Dimension(73, 29));
+        buttonPanel.setLayout(new javax.swing.BoxLayout(buttonPanel, javax.swing.BoxLayout.LINE_AXIS));
+
+        org.openide.awt.Mnemonics.setLocalizedText(jToggleButton1, org.openide.util.NbBundle.getMessage(ShaderEditPanel.class, "ShaderEditPanel.jToggleButton1.text")); // NOI18N
+        buttonPanel.add(jToggleButton1);
+
+        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+        this.setLayout(layout);
+        layout.setHorizontalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addComponent(header, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+            .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 645, Short.MAX_VALUE)
+            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
+                .addComponent(buttonPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+                .addContainerGap())
+        );
+        layout.setVerticalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
+                .addComponent(header, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(buttonPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 21, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 492, Short.MAX_VALUE))
+        );
+    }// </editor-fold>//GEN-END:initComponents
+
+    private void closeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_closeButtonActionPerformed
+        setVisible(false);
+
+        saveCurrent();
+
+
+    }//GEN-LAST:event_closeButtonActionPerformed
+
+
+    // Variables declaration - do not modify//GEN-BEGIN:variables
+    private javax.swing.ButtonGroup buttonGroup1;
+    private javax.swing.JPanel buttonPanel;
+    private javax.swing.JButton closeButton;
+    private javax.swing.JPanel header;
+    private javax.swing.JLabel headerText;
+    private javax.swing.JScrollPane jScrollPane1;
+    private javax.swing.JToggleButton jToggleButton1;
+    private javax.swing.JEditorPane shaderEditorPane;
+    // End of variables declaration//GEN-END:variables
+}

+ 10 - 0
jme3-materialeditor/src/com/jme3/gde/materialdefinition/icons/Icons.java

@@ -4,6 +4,7 @@
  */
 package com.jme3.gde.materialdefinition.icons;
 
+import com.jme3.gde.materialdefinition.editor.NodePanel;
 import javax.swing.ImageIcon;
 
 /**
@@ -27,4 +28,13 @@ public class Icons {
     public final static ImageIcon tech = new ImageIcon(Icons.class.getResource("tech.png"));
     public final static ImageIcon in = new ImageIcon(Icons.class.getResource("in.png"));
     public final static ImageIcon out = new ImageIcon(Icons.class.getResource("out.png"));
+    public final static ImageIcon error = new ImageIcon(Icons.class.getResource("error.png"));
+
+    public static ImageIcon getIconForShaderType(NodePanel.NodeType type) {
+        if (type == NodePanel.NodeType.Fragment) {
+            return frag;
+        } else {
+            return vert;
+        }
+    }
 }

BIN
jme3-materialeditor/src/com/jme3/gde/materialdefinition/icons/error.png


+ 1 - 1
jme3-materialeditor/src/com/jme3/gde/materialdefinition/utils/DocFormatter.java

@@ -17,7 +17,7 @@ import javax.swing.text.StyledDocument;
 
 /**
  *
- * @author m327836
+ * @author Nehon
  */
 public class DocFormatter {
 

+ 12 - 0
jme3-materialeditor/src/com/jme3/gde/materials/MaterialPreviewRenderer.java

@@ -11,6 +11,7 @@ import com.jme3.gde.core.scene.PreviewRequest;
 import com.jme3.gde.core.scene.SceneApplication;
 import com.jme3.gde.core.scene.SceneListener;
 import com.jme3.gde.core.scene.SceneRequest;
+import com.jme3.gde.materialdefinition.icons.Icons;
 import com.jme3.material.MatParam;
 import com.jme3.material.Material;
 import com.jme3.math.FastMath;
@@ -111,6 +112,11 @@ public class MaterialPreviewRenderer implements SceneListener {
                                     SceneApplication.getApplication().createPreview(request);
                                 }
                             } catch (Exception e) {
+                                java.awt.EventQueue.invokeLater(new Runnable() {
+                                    public void run() {
+                                        label.setIcon(Icons.error);
+                                    }
+                                });
                                 Logger.getLogger(MaterialPreviewRenderer.class.getName()).log(Level.SEVERE, "Error rendering material{0}", e.getMessage());
                             }
                         }
@@ -148,6 +154,12 @@ public class MaterialPreviewRenderer implements SceneListener {
             //the following code will output the error
             //System.err.println(e.getMessage());
             Logger.getLogger(MaterialDebugAppState.class.getName()).log(Level.SEVERE, e.getMessage());
+            
+            java.awt.EventQueue.invokeLater(new Runnable() {
+                public void run() {
+                    label.setIcon(Icons.error);
+                }
+            });
             return null;
         }