@@ -688,13 +688,14 @@ public void ToSubGraph()
688
688
var metaKeywords = graphView . graph . keywords . Where ( x => keywordNodes . Contains ( x ) ) ;
689
689
690
690
var copyPasteGraph = new CopyPasteGraph ( graphView . selection . OfType < ShaderGroup > ( ) . Select ( x => x . userData ) ,
691
- graphView . selection . OfType < IShaderNodeView > ( ) . Where ( x => ! ( x . node is PropertyNode || x . node is SubGraphOutputNode ) ) . Select ( x => x . node ) . Where ( x => x . allowedInSubGraph ) . ToArray ( ) ,
691
+ nodes ,
692
692
graphView . selection . OfType < Edge > ( ) . Select ( x => x . userData as Graphing . Edge ) ,
693
693
graphInputs ,
694
694
metaProperties ,
695
695
metaKeywords ,
696
696
graphView . selection . OfType < StickyNote > ( ) . Select ( x => x . userData ) ,
697
- true ) ;
697
+ true ,
698
+ false ) ;
698
699
699
700
// why do we serialize and deserialize only to make copies of everything in the steps below?
700
701
// is this just to clear out all non-serialized data?
@@ -763,6 +764,7 @@ public void ToSubGraph()
763
764
// figure out what needs remapping
764
765
var externalOutputSlots = new List < Graphing . Edge > ( ) ;
765
766
var externalInputSlots = new List < Graphing . Edge > ( ) ;
767
+ var passthroughSlots = new List < Graphing . Edge > ( ) ;
766
768
foreach ( var edge in deserialized . edges )
767
769
{
768
770
var outputSlot = edge . outputSlot ;
@@ -785,6 +787,12 @@ public void ToSubGraph()
785
787
{
786
788
externalOutputSlots . Add ( edge ) ;
787
789
}
790
+ else
791
+ {
792
+ externalInputSlots . Add ( edge ) ;
793
+ externalOutputSlots . Add ( edge ) ;
794
+ passthroughSlots . Add ( edge ) ;
795
+ }
788
796
}
789
797
790
798
// Find the unique edges coming INTO the graph
@@ -800,6 +808,9 @@ public void ToSubGraph()
800
808
const int subtractHeight = 20 ;
801
809
var propPos = new Vector2 ( 0 , - ( ( amountOfProps / 2 ) + height ) - subtractHeight ) ;
802
810
811
+ var passthroughSlotRefLookup = new Dictionary < SlotReference , SlotReference > ( ) ;
812
+
813
+ var passedInProperties = new Dictionary < AbstractShaderProperty , AbstractShaderProperty > ( ) ;
803
814
foreach ( var group in uniqueIncomingEdges )
804
815
{
805
816
var sr = group . slotRef ;
@@ -812,68 +823,78 @@ public void ToSubGraph()
812
823
: null ;
813
824
814
825
AbstractShaderProperty prop ;
815
- switch ( fromSlot . concreteValueType )
826
+ if ( fromProperty != null && passedInProperties . TryGetValue ( fromProperty , out prop ) )
816
827
{
817
- case ConcreteSlotValueType . Texture2D :
818
- prop = new Texture2DShaderProperty ( ) ;
819
- break ;
820
- case ConcreteSlotValueType . Texture2DArray :
821
- prop = new Texture2DArrayShaderProperty ( ) ;
822
- break ;
823
- case ConcreteSlotValueType . Texture3D :
824
- prop = new Texture3DShaderProperty ( ) ;
825
- break ;
826
- case ConcreteSlotValueType . Cubemap :
827
- prop = new CubemapShaderProperty ( ) ;
828
- break ;
829
- case ConcreteSlotValueType . Vector4 :
830
- prop = new Vector4ShaderProperty ( ) ;
831
- break ;
832
- case ConcreteSlotValueType . Vector3 :
833
- prop = new Vector3ShaderProperty ( ) ;
834
- break ;
835
- case ConcreteSlotValueType . Vector2 :
836
- prop = new Vector2ShaderProperty ( ) ;
837
- break ;
838
- case ConcreteSlotValueType . Vector1 :
839
- prop = new Vector1ShaderProperty ( ) ;
840
- break ;
841
- case ConcreteSlotValueType . Boolean :
842
- prop = new BooleanShaderProperty ( ) ;
843
- break ;
844
- case ConcreteSlotValueType . Matrix2 :
845
- prop = new Matrix2ShaderProperty ( ) ;
846
- break ;
847
- case ConcreteSlotValueType . Matrix3 :
848
- prop = new Matrix3ShaderProperty ( ) ;
849
- break ;
850
- case ConcreteSlotValueType . Matrix4 :
851
- prop = new Matrix4ShaderProperty ( ) ;
852
- break ;
853
- case ConcreteSlotValueType . SamplerState :
854
- prop = new SamplerStateShaderProperty ( ) ;
855
- break ;
856
- case ConcreteSlotValueType . Gradient :
857
- prop = new GradientShaderProperty ( ) ;
858
- break ;
859
- case ConcreteSlotValueType . VirtualTexture :
860
- prop = new VirtualTextureShaderProperty ( )
861
- {
862
- // also copy the VT settings over from the original property (if there is one)
863
- value = ( fromProperty as VirtualTextureShaderProperty ) ? . value ?? new SerializableVirtualTexture ( )
864
- } ;
865
- break ;
866
- default :
867
- throw new ArgumentOutOfRangeException ( ) ;
868
828
}
829
+ else
830
+ {
831
+ switch ( fromSlot . concreteValueType )
832
+ {
833
+ case ConcreteSlotValueType . Texture2D :
834
+ prop = new Texture2DShaderProperty ( ) ;
835
+ break ;
836
+ case ConcreteSlotValueType . Texture2DArray :
837
+ prop = new Texture2DArrayShaderProperty ( ) ;
838
+ break ;
839
+ case ConcreteSlotValueType . Texture3D :
840
+ prop = new Texture3DShaderProperty ( ) ;
841
+ break ;
842
+ case ConcreteSlotValueType . Cubemap :
843
+ prop = new CubemapShaderProperty ( ) ;
844
+ break ;
845
+ case ConcreteSlotValueType . Vector4 :
846
+ prop = new Vector4ShaderProperty ( ) ;
847
+ break ;
848
+ case ConcreteSlotValueType . Vector3 :
849
+ prop = new Vector3ShaderProperty ( ) ;
850
+ break ;
851
+ case ConcreteSlotValueType . Vector2 :
852
+ prop = new Vector2ShaderProperty ( ) ;
853
+ break ;
854
+ case ConcreteSlotValueType . Vector1 :
855
+ prop = new Vector1ShaderProperty ( ) ;
856
+ break ;
857
+ case ConcreteSlotValueType . Boolean :
858
+ prop = new BooleanShaderProperty ( ) ;
859
+ break ;
860
+ case ConcreteSlotValueType . Matrix2 :
861
+ prop = new Matrix2ShaderProperty ( ) ;
862
+ break ;
863
+ case ConcreteSlotValueType . Matrix3 :
864
+ prop = new Matrix3ShaderProperty ( ) ;
865
+ break ;
866
+ case ConcreteSlotValueType . Matrix4 :
867
+ prop = new Matrix4ShaderProperty ( ) ;
868
+ break ;
869
+ case ConcreteSlotValueType . SamplerState :
870
+ prop = new SamplerStateShaderProperty ( ) ;
871
+ break ;
872
+ case ConcreteSlotValueType . Gradient :
873
+ prop = new GradientShaderProperty ( ) ;
874
+ break ;
875
+ case ConcreteSlotValueType . VirtualTexture :
876
+ prop = new VirtualTextureShaderProperty ( )
877
+ {
878
+ // also copy the VT settings over from the original property (if there is one)
879
+ value = ( fromProperty as VirtualTextureShaderProperty ) ? . value ?? new SerializableVirtualTexture ( )
880
+ } ;
881
+ break ;
882
+ default :
883
+ throw new ArgumentOutOfRangeException ( ) ;
884
+ }
869
885
870
- prop . displayName = fromProperty != null
871
- ? fromProperty . displayName
872
- : fromSlot . concreteValueType . ToString ( ) ;
873
- prop . displayName = GraphUtil . SanitizeName ( subGraph . addedInputs . Select ( p => p . displayName ) , "{0} ({1})" ,
874
- prop . displayName ) ;
886
+ prop . displayName = fromProperty != null
887
+ ? fromProperty . displayName
888
+ : fromSlot . concreteValueType . ToString ( ) ;
889
+ prop . displayName = GraphUtil . SanitizeName ( subGraph . addedInputs . Select ( p => p . displayName ) , "{0} ({1})" ,
890
+ prop . displayName ) ;
891
+ subGraph . AddGraphInput ( prop ) ;
892
+ if ( fromProperty != null )
893
+ {
894
+ passedInProperties . Add ( fromProperty , prop ) ;
895
+ }
896
+ }
875
897
876
- subGraph . AddGraphInput ( prop ) ;
877
898
var propNode = new PropertyNode ( ) ;
878
899
{
879
900
var drawState = propNode . drawState ;
@@ -885,13 +906,45 @@ public void ToSubGraph()
885
906
subGraph . AddNode ( propNode ) ;
886
907
propNode . property = prop ;
887
908
909
+
910
+ Vector2 avg = Vector2 . zero ;
888
911
foreach ( var edge in group . edges )
889
912
{
890
- subGraph . Connect (
891
- new SlotReference ( propNode , PropertyNode . OutputSlotId ) ,
892
- edge . inputSlot ) ;
893
- externalInputNeedingConnection . Add ( new KeyValuePair < IEdge , AbstractShaderProperty > ( edge , prop ) ) ;
913
+ if ( passthroughSlots . Contains ( edge ) && ! passthroughSlotRefLookup . ContainsKey ( sr ) )
914
+ {
915
+ passthroughSlotRefLookup . Add ( sr , new SlotReference ( propNode , PropertyNode . OutputSlotId ) ) ;
916
+ }
917
+ else
918
+ {
919
+ subGraph . Connect (
920
+ new SlotReference ( propNode , PropertyNode . OutputSlotId ) ,
921
+ edge . inputSlot ) ;
922
+
923
+ int i ;
924
+ var inputs = edge . inputSlot . node . GetInputSlots < MaterialSlot > ( ) . ToList ( ) ;
925
+
926
+ for ( i = 0 ; i < inputs . Count ; ++ i )
927
+ {
928
+ if ( inputs [ i ] . slotReference . slotId == edge . inputSlot . slotId )
929
+ {
930
+ break ;
931
+ }
932
+ }
933
+ avg += new Vector2 ( edge . inputSlot . node . drawState . position . xMin , edge . inputSlot . node . drawState . position . center . y + 30f * i ) ;
934
+ }
935
+ //we collapse input properties so dont add edges that are already being added
936
+ if ( ! externalInputNeedingConnection . Any ( x => x . Key . outputSlot . slot == edge . outputSlot . slot && x . Value == prop ) )
937
+ {
938
+ externalInputNeedingConnection . Add ( new KeyValuePair < IEdge , AbstractShaderProperty > ( edge , prop ) ) ;
939
+ }
894
940
}
941
+ avg /= group . edges . Count ;
942
+ var pos = avg - new Vector2 ( 150f , 0f ) ;
943
+ propNode . drawState = new DrawState ( )
944
+ {
945
+ position = new Rect ( pos , propNode . drawState . position . size ) ,
946
+ expanded = propNode . drawState . expanded
947
+ } ;
895
948
}
896
949
897
950
var uniqueOutgoingEdges = externalInputSlots . GroupBy (
@@ -912,7 +965,7 @@ public void ToSubGraph()
912
965
913
966
foreach ( var edge in group . edges )
914
967
{
915
- var newEdge = subGraph . Connect ( edge . outputSlot , inputSlotRef ) ;
968
+ var newEdge = subGraph . Connect ( passthroughSlotRefLookup . TryGetValue ( edge . outputSlot , out SlotReference remap ) ? remap : edge . outputSlot , inputSlotRef ) ;
916
969
externalOutputsNeedingConnection . Add ( new KeyValuePair < IEdge , IEdge > ( edge , newEdge ) ) ;
917
970
}
918
971
}
@@ -961,10 +1014,46 @@ public void ToSubGraph()
961
1014
}
962
1015
963
1016
graphObject . graph . RemoveElements (
964
- graphView . selection . OfType < IShaderNodeView > ( ) . Select ( x => x . node ) . Where ( x => x . allowedInSubGraph ) . ToArray ( ) ,
1017
+ graphView . selection . OfType < IShaderNodeView > ( ) . Select ( x => x . node ) . Where ( x => ! ( x is PropertyNode || x is SubGraphOutputNode ) && x . allowedInSubGraph ) . ToArray ( ) ,
965
1018
new IEdge [ ] { } ,
966
1019
new GroupData [ ] { } ,
967
1020
graphView . selection . OfType < StickyNote > ( ) . Select ( x => x . userData ) . ToArray ( ) ) ;
1021
+
1022
+ List < GraphElement > moved = new List < GraphElement > ( ) ;
1023
+ foreach ( var nodeView in graphView . selection . OfType < IShaderNodeView > ( ) )
1024
+ {
1025
+ var node = nodeView . node ;
1026
+ if ( graphView . graph . removedNodes . Contains ( node ) || node is SubGraphOutputNode )
1027
+ {
1028
+ continue ;
1029
+ }
1030
+
1031
+ var edges = graphView . graph . GetEdges ( node ) ;
1032
+ int numEdges = edges . Count ( ) ;
1033
+ if ( numEdges == 0 )
1034
+ {
1035
+ graphView . graph . RemoveNode ( node ) ;
1036
+ }
1037
+ else if ( numEdges == 1 && edges . First ( ) . inputSlot . node != node ) //its an output edge
1038
+ {
1039
+ var edge = edges . First ( ) ;
1040
+ int i ;
1041
+ var inputs = edge . inputSlot . node . GetInputSlots < MaterialSlot > ( ) . ToList ( ) ;
1042
+ for ( i = 0 ; i < inputs . Count ; ++ i )
1043
+ {
1044
+ if ( inputs [ i ] . slotReference . slotId == edge . inputSlot . slotId )
1045
+ {
1046
+ break ;
1047
+ }
1048
+ }
1049
+ node . drawState = new DrawState ( )
1050
+ {
1051
+ position = new Rect ( new Vector2 ( edge . inputSlot . node . drawState . position . xMin , edge . inputSlot . node . drawState . position . center . y ) - new Vector2 ( 150f , - 30f * i ) , node . drawState . position . size ) ,
1052
+ expanded = node . drawState . expanded
1053
+ } ;
1054
+ ( nodeView as GraphElement ) . SetPosition ( node . drawState . position ) ;
1055
+ }
1056
+ }
968
1057
graphObject . graph . ValidateGraph ( ) ;
969
1058
}
970
1059
0 commit comments