Browse Source

Merge origin/master

rickard 3 years ago
parent
commit
0bf8e4262f

+ 0 - 3
jme3-materialeditor/src/com/jme3/gde/materialdefinition/fileStructure/InputMappingsBlock.java

@@ -4,10 +4,7 @@
  */
 package com.jme3.gde.materialdefinition.fileStructure;
 
-import com.jme3.gde.materialdefinition.fileStructure.*;
 import com.jme3.gde.materialdefinition.fileStructure.leaves.InputMappingBlock;
-import com.jme3.gde.materialdefinition.fileStructure.leaves.MatParamBlock;
-import com.jme3.gde.materialdefinition.fileStructure.leaves.OutputMappingBlock;
 import com.jme3.util.blockparser.Statement;
 import java.util.List;
 

+ 4 - 15
jme3-materialeditor/src/com/jme3/gde/materialdefinition/fileStructure/ShaderNodeBlock.java

@@ -16,16 +16,18 @@ import java.util.ArrayList;
 import java.util.List;
 
 /**
- *
+ * A ShaderNodeBlock is a shader node in the MatDef file.
+ * 
  * @author Nehon
  */
-public class ShaderNodeBlock extends UberStatement implements Comparable<ShaderNodeBlock>, PropertyChangeListener {
+public class ShaderNodeBlock extends UberStatement implements PropertyChangeListener {
 
     public final static String POSITION = "position";
     public final static String INPUT = "input";
     public final static String OUTPUT = "output";
     public static final String ADD_MAPPING = "addMapping";
     public static final String REMOVE_MAPPING = "removeMapping";
+    public static final String VALUE = "defaultValue";
     protected String name;
     //built up data for fast sorting 
     protected int spatialOrder;
@@ -192,19 +194,6 @@ public class ShaderNodeBlock extends UberStatement implements Comparable<ShaderN
         fire(REMOVE_MAPPING, mapping, null);
     }
 
-    public int compareTo(ShaderNodeBlock o) {
-        if (inputNodes.contains(o.getName())) {
-            return 1;
-        }
-        if (o.inputNodes.contains(name)) {
-            return -1;
-        }
-        if ((globalInput && o.globalOutput) || (o.globalInput && globalOutput)) {
-            return (int) Math.signum(spatialOrder - o.spatialOrder);
-        }
-        return 0;
-    }
-
     public void propertyChange(PropertyChangeEvent evt) {
         if (evt.getPropertyName().equals(POSITION)) {
             spatialOrder = (Integer) evt.getNewValue();

+ 80 - 13
jme3-materialeditor/src/com/jme3/gde/materialdefinition/fileStructure/ShaderNodesBlock.java

@@ -8,19 +8,22 @@ import com.jme3.util.blockparser.Statement;
 import java.beans.PropertyChangeEvent;
 import java.beans.PropertyChangeListener;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.List;
 import org.openide.util.WeakListeners;
 
 /**
- *
+ * A ShaderNodesBlock is a set of shader nodes in the MatDef file, for example all frag shader nodes.
+ * 
  * @author Nehon
  */
 public class ShaderNodesBlock extends UberStatement implements PropertyChangeListener {
-    
+        
     protected ShaderNodesBlock(int lineNumber, String line) {
         super(lineNumber, line);
+        
     }
-    
+
     public ShaderNodesBlock(Statement sta) {
         this(sta.getLineNumber(), sta.getLine());
         for (Statement statement : sta.getContents()) {
@@ -29,31 +32,95 @@ public class ShaderNodesBlock extends UberStatement implements PropertyChangeLis
             addStatement(b);
         }
     }
-    
-    public List<ShaderNodeBlock> getShaderNodes() {        
+
+    public List<ShaderNodeBlock> getShaderNodes() {
         return getBlocks(ShaderNodeBlock.class);
     }
-    
+
     public void addShaderNode(ShaderNodeBlock shaderNodeBlock) {
-        addStatement(shaderNodeBlock);      
+        addStatement(shaderNodeBlock);
         shaderNodeBlock.addPropertyChangeListener(WeakListeners.propertyChange(this, shaderNodeBlock));
     }
-    
+
     public boolean removeShaderNode(ShaderNodeBlock shaderNodeBlock) {
         return contents.remove(shaderNodeBlock);
     }
-    
+
+    @Override
     public void propertyChange(PropertyChangeEvent evt) {
-        if (evt.getPropertyName().equals("order")) {
+        if (evt.getPropertyName().equals(ShaderNodeBlock.ADD_MAPPING) || evt.getPropertyName().equals("order")) {
             sort();
-        }        
+        }
     }
-    
+
     public void sort() {
         List<ShaderNodeBlock> list = getShaderNodes();
-        Collections.sort(list);        
+        int passes = 0;
+        NodeComparator nodeComparator = new NodeComparator(list);
+        while (nodeComparator.changes != 0 && passes < 10) {
+            nodeComparator.changes = 0;
+            Collections.sort(list, nodeComparator);
+            passes++;
+        }
         contents.clear();
         contents.addAll(list);
         fire("reorder", null, null);
     }
+
+    /**
+     * Sorts nodes so that they are initialized after their input dependencies.
+     * Will look higher up in hierarchy and move node incrementally. This may require several passes
+     */
+    private final class NodeComparator implements Comparator<ShaderNodeBlock> {
+
+        private final List<ShaderNodeBlock> list;
+        private int changes = -1;
+
+        public NodeComparator(List<ShaderNodeBlock> list) {
+            this.list = list;
+        }
+
+        @Override
+        public int compare(ShaderNodeBlock o1, ShaderNodeBlock o2) {
+            if (o1.name.equals(o2.name)) {
+                return 0;
+            }
+            if (hasInputConnection(o2.name, o1)) {
+                changes++;
+                return 1;
+            }
+            if (hasInputConnection(o1.name, o2)) {
+                changes++;
+                return -1;
+            }
+
+            if ((o1.globalInput && o2.globalOutput) || (o2.globalInput && o1.globalOutput)) {
+                changes++;
+                return (int) Math.signum(o1.spatialOrder - o2.spatialOrder);
+            }
+            return 0;
+        }
+
+        private ShaderNodeBlock findAncestorNode(String name) {
+            for (ShaderNodeBlock node : list) {
+                if (node.name.equals(name)) {
+                    return node;
+                }
+            }
+            return null;
+        }
+
+        private boolean hasInputConnection(String name, ShaderNodeBlock node) {
+            for (String s : node.inputNodes) {
+                if (s.equals(name)) {
+                    return true;
+                }
+                ShaderNodeBlock ancestor = findAncestorNode(s);
+                if (ancestor != null && hasInputConnection(name, ancestor)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
 }