static StackBaseModel FindConnectedStacksCommonDescendant(INodeModel statement, HashSet <IStackModel> visited)
        {
            var            firstStack = GetConnectedStack((NodeModel)statement, 0);
            StackBaseModel desc       = statement.OutputsByDisplayOrder.Aggregate(firstStack, (stack, nextPort) =>
            {
                if (stack == null)
                {
                    return(null);
                }
                if (nextPort.PortType != PortType.Execution)
                {
                    return(firstStack);
                }
                var nextStack = GetConnectedStack(nextPort);
                if (nextStack == null)
                {
                    return(null);
                }
                if (!visited.Add(nextStack))
                {
                    return(stack);
                }
                return(FindCommonDescendant(visited, stack, nextStack));
            });

            return(desc);
        }
        // check if thisStack's descendants have been already visited and put in otherBranchSet
        // otherwise add them
        static bool Test(ref StackBaseModel thisStack,
                         HashSet <StackBaseModel> thisBranchSet,
                         HashSet <StackBaseModel> otherBranchSet,
                         Queue <StackBaseModel> thisBranchQueue)
        {
            if (thisStack == null)
            {
                return(false);
            }

            StackBaseModel connectedStack = FindConnectedStacksCommonDescendant(thisStack);

            if (!connectedStack)
            {
                return(false);
            }

            Assert.IsTrue(connectedStack.InputPorts.Count > 0, "a connected stack must have inputs");

            // small optimization: no common descendant can have less than 2 input connections
            if (connectedStack.InputPorts.Sum(c => c.ConnectionPortModels.Count()) >= 2 &&
                otherBranchSet.Contains(connectedStack))
            {
                thisStack = connectedStack;
                return(true);
            }

            if (thisBranchSet.Add(connectedStack))
            {
                thisBranchQueue.Enqueue(connectedStack);
            }

            return(false);
        }
Exemple #3
0
 void CreateStackAndLogs(out StackBaseModel stack, out FunctionCallNodeModel[] log, int logCount = 1)
 {
     stack = GraphModel.CreateFunction("F", Vector2.zero);
     log   = new FunctionCallNodeModel[logCount];
     for (int i = 0; i < logCount; i++)
     {
         log[i] = stack.CreateFunctionCallNode(k_LogMethodInfo);
     }
 }
        // This will find a common descendant stack for both inputs
        // ie. FindCommonDescendant(A, B) => E
        // Note: if c wasn't connected to E, A and B would not have a common descendant,
        // as no descendant of B would be reachable from C
        //        Root
        //       /   \
        //      A     B
        //     / \    |
        //     C  D   |
        //      \__\ /
        //          E
        // we need to keep two sets/queues, one per initial branch
        // another solution would be to keep an Ancestor hashset associated to each stack model
        // and find a non empty union
        public static StackBaseModel FindCommonDescendant(IStackModel root, StackBaseModel a, StackBaseModel b)
        {
            var stackModels = new HashSet <IStackModel>();

            if (root != a && root != b)
            {
                stackModels.Add(root);
            }
            return(FindCommonDescendant(stackModels, a, b));
        }
        void CreateIfThenElseStacks(StackBaseModel ifStack, string thenName, string elseName, out StackBaseModel thenStack, out StackBaseModel elseStack)
        {
            var ifNode = ifStack.CreateStackedNode <IfConditionNodeModel>("if");

            thenStack = GraphModel.CreateStack(thenName, Vector2.left);
            GraphModel.CreateEdge(thenStack.InputPorts[0], ifNode.ThenPort);

            elseStack = GraphModel.CreateStack(elseName, Vector2.right);
            GraphModel.CreateEdge(elseStack.InputPorts[0], ifNode.ElsePort);
        }
        IfConditionNodeModel CreateIfThenElseStacks(StackBaseModel ifStack, out StackBaseModel thenStack, out StackBaseModel elseStack)
        {
            var ifNode = ifStack.CreateStackedNode <IfConditionNodeModel>("if");

            thenStack = GraphModel.CreateStack("then", Vector2.left);
            GraphModel.CreateEdge(thenStack.InputPorts[0], ifNode.ThenPort);

            elseStack = GraphModel.CreateStack("else", Vector2.right);
            GraphModel.CreateEdge(elseStack.InputPorts[0], ifNode.ElsePort);
            return(ifNode);
        }
        public static StackBaseModel FindConnectedStacksCommonDescendant(INodeModel statement)
        {
            var            firstStack = GetConnectedStack((NodeModel)statement, 0);
            StackBaseModel desc       = statement.OutputsByDisplayOrder.Aggregate(firstStack, (stack, nextPort) =>
            {
                if (nextPort.PortType != PortType.Execution)
                {
                    return(firstStack);
                }
                return(FindCommonDescendant(stack, GetConnectedStack(nextPort)));
            });

            return(desc);
        }
        // This will find a common descendant stack for both inputs
        // ie. FindCommonDescendant(A, B) => E
        // Note: if c wasn't connected to E, A and B would not have a common descendant,
        // as no descendant of B would be reachable from C
        //        Root
        //       /   \
        //      A     B
        //     / \    |
        //     C  D   |
        //      \__\ /
        //          E
        // we need to keep two sets/queues, one per initial branch
        // another solution would be to keep an Ancestor hashset associated to each stack model
        // and find a non empty union
        public static StackBaseModel FindCommonDescendant(StackBaseModel a, StackBaseModel b)
        {
            if (a == b) // FCD(a, a) = a
            {
                return(a);
            }

            if (a == null || b == null) // FCD(x, null) = null
            {
                return(null);
            }

            HashSet <StackBaseModel> aSet = new HashSet <StackBaseModel>();

            aSet.Add(a);
            Queue <StackBaseModel> aQueue = new Queue <StackBaseModel>();

            aQueue.Enqueue(a);

            HashSet <StackBaseModel> bSet = new HashSet <StackBaseModel>();

            bSet.Add(b);
            Queue <StackBaseModel> bQueue = new Queue <StackBaseModel>();

            bQueue.Enqueue(b);

            while (aQueue.Count > 0 || bQueue.Count > 0)
            {
                if (aQueue.Count > 0)
                {
                    a = aQueue.Dequeue();
                }
                if (bQueue.Count > 0)
                {
                    b = bQueue.Dequeue();
                }
                if (Test(ref a, aSet, bSet, aQueue))
                {
                    return(a);
                }
                if (Test(ref b, bSet, aSet, bQueue))
                {
                    return(b);
                }
            }

            return(null);
        }
 public static FunctionCallNodeModel CreateFunctionCallNode(this StackBaseModel stackModel, MethodInfo methodInfo,
                                                            int index = -1, SpawnFlags spawnFlags = SpawnFlags.Default)
 {
     return(CreateStackedNode <FunctionCallNodeModel>(stackModel, methodInfo.Name, index, spawnFlags,
                                                      n => n.MethodInfo = methodInfo));
 }
Exemple #10
0
 public abstract LoopNodeModel CreateLoopNode(StackBaseModel hostStack, int index, SpawnFlags spawnFlags = SpawnFlags.Default);
Exemple #11
0
        public static IGraphElement CreateStack(this ElementBuilder elementBuilder, IStore store, StackBaseModel model)
        {
            var ui = new StackNode();

            ui.Setup(model, store, elementBuilder.GraphView);
            return(ui);
        }
Exemple #12
0
 public InsideStackConstraint(IStackModel expected)
     : base(expected)
 {
     m_ExpectedStack = (StackBaseModel)expected;
 }
 public static UnaryOperatorNodeModel CreateUnaryStatementNode(this StackBaseModel stackModel,
                                                               UnaryOperatorKind kind, int index, SpawnFlags spawnFlags = SpawnFlags.Default)
 {
     return(CreateStackedNode <UnaryOperatorNodeModel>(stackModel, kind.ToString(), index, spawnFlags,
                                                       n => n.kind = kind));
 }
 public static GraphElement CreateStack(this INodeBuilder builder, Store store, StackBaseModel model)
 {
     return(new StackNode(store, model, builder));
 }
        public void DuplicateStackedNodes(INodeModel copiedNode, Dictionary <INodeModel, NodeModel> mapping, Vector2 delta, int stackInsertionIndex, List <StackedNodesStruct> implicitStackedNodes, StackBaseModel pastedStackModel)
        {
            pastedStackModel.ClearNodes();

            if (implicitStackedNodes?.Count > 0)
            {
                foreach (var stackedNodeStruct in implicitStackedNodes)
                {
                    DuplicateNode(stackedNodeStruct.stackedNodeModel, mapping,
                                  pastedStackModel, delta, stackInsertionIndex != -1 ? stackInsertionIndex++ : -1);
                }
            }
        }
Exemple #16
0
 public override LoopNodeModel CreateLoopNode(StackBaseModel hostStack, int index, SpawnFlags spawnFlags = SpawnFlags.Default)
 {
     return(hostStack.CreateStackedNode <WhileNodeModel>(Title, index, spawnFlags));
 }
 public static FunctionRefCallNodeModel CreateFunctionRefCallNode(this StackBaseModel stackModel,
                                                                  FunctionModel methodInfo, int index = -1, SpawnFlags spawnFlags = SpawnFlags.Default)
 {
     return(stackModel.CreateStackedNode <FunctionRefCallNodeModel>(methodInfo.Title, index, spawnFlags, n => n.Function = methodInfo));
 }
 static T CreateStackedNode <T>(this StackBaseModel stackModel, string nodeName, int index,
                                SpawnFlags spawnFlags = SpawnFlags.Default, Action <T> setup = null) where T : NodeModel
 {
     return(stackModel.CreateStackedNode(nodeName, index, spawnFlags, setup));
 }
 static INodeModel CreateStackedNode(this StackBaseModel stackModel, Type type, string nodeName, int index,
                                     SpawnFlags spawnFlags = SpawnFlags.Default, Action <NodeModel> setup = null)
 {
     return(stackModel.CreateStackedNode(type, nodeName, index, spawnFlags, setup));
 }
        public static SetPropertyGroupNodeModel CreateSetPropertyGroupNode(this StackBaseModel stackModel, int index)
        {
            var nodeModel = stackModel.CreateStackedNode <SetPropertyGroupNodeModel>("Set Property", index);

            return(nodeModel);
        }
        public NodeModel DuplicateNode(INodeModel copiedNode, Dictionary <INodeModel, NodeModel> mapping, StackBaseModel pastedNodeParentStack, Vector2 delta, int stackInsertionIndex, List <StackedNodesStruct> implicitStackedNodes = null)
        {
            var pastedNodeModel = (NodeModel)copiedNode.Clone();

            // Set graphmodel BEFORE define node as it is commonly use during Define
            pastedNodeModel.AssetModel = AssetModel;
            pastedNodeModel.Title      = copiedNode.Title;
            pastedNodeModel.AssignNewGuid();
            pastedNodeModel.DefineNode();
            pastedNodeModel.ReinstantiateInputConstants();
            mapping.Add(copiedNode, pastedNodeModel);

            if (pastedNodeParentStack != null)
            {
                pastedNodeParentStack.AddStackedNode(pastedNodeModel, stackInsertionIndex);
            }
            else
            {
                AddNode(pastedNodeModel);
                pastedNodeModel.Position += delta;

                if (pastedNodeModel is StackBaseModel pastedStackModel)
                {
                    DuplicateStackedNodes(copiedNode, mapping, delta, stackInsertionIndex, implicitStackedNodes, pastedStackModel);
                }
            }

            return(pastedNodeModel);
        }
Exemple #22
0
 protected void JoinStacks(StackBaseModel a, StackBaseModel b, string newStackName, out StackBaseModel newJoinStack)
 {
     newJoinStack = GraphModel.CreateStack(newStackName, Vector2.zero);
     GraphModel.CreateEdge(newJoinStack.InputPorts[0], a.OutputPorts[0]);
     GraphModel.CreateEdge(newJoinStack.InputPorts[0], b.OutputPorts[0]);
 }
        public virtual void BuildStack(IStackModel stack, ref BlockSyntax blockNode,
                                       StackExitStrategy exitStrategy = StackExitStrategy.Return)
        {
            if (stack == null || stack.State == ModelState.Disabled)
            {
                return;
            }

            RegisterBuiltStack(stack);

            // JUST in case... until we validate the previous failsafe
            if (m_BuiltStackCounter++ > 10000)
            {
                throw new InvalidOperationException("Infinite loop while building the script, aborting");
            }

            StackExitStrategy origStackExitStrategy = m_StackExitStrategy;

            if (exitStrategy != StackExitStrategy.Inherit)
            {
                m_StackExitStrategy = exitStrategy;
            }

//            Debug.Log($"Build stack {stack}");
            // m_EndStack might get changed by recursive BuildNode() calls
            StackBaseModel origEndStack = EndStack;
            var            statements   = new List <StatementSyntax>();

            foreach (var statement in stack.NodeModels)
            {
                if (statement.State == ModelState.Disabled)
                {
                    continue;
                }
                var syntaxNodes = BuildNode(statement);
                foreach (var syntaxNode in syntaxNodes)
                {
                    switch (syntaxNode)
                    {
                    case StatementSyntax statementNode:
                        statements.Add(statementNode);
                        break;

                    case ExpressionSyntax expressionNode:
                        statements.Add(ExpressionStatement(expressionNode)
                                       .WithAdditionalAnnotations(new SyntaxAnnotation(Annotations.AnnotationKind,
                                                                                       statement.Guid.ToString()))
                                       );
                        break;

                    default:
                        throw new InvalidOperationException($"Expected a statement or expression node, found a {syntaxNode.GetType()} when building {statement}");
                    }
                }
            }

            blockNode = blockNode.AddStatements(statements.ToArray());

            if (stack.DelegatesOutputsToNode(out _))
            {
                var nextStack = EndStack;
                m_StackExitStrategy = origStackExitStrategy;

//                Debug.Log($"Stack {stack} delegates ports. nextStack {nextStack} origEndStack {origEndStack}");

                // if a nested node changed the end stack, but found the same common descendant,
                // let the parent call handle it
                if (EndStack == origEndStack)
                {
                    return;
                }

                EndStack = origEndStack;
                BuildStack(nextStack, ref blockNode, exitStrategy);

                return;
            }

            bool anyConnection = false;

            foreach (var outputPort in stack.OutputPorts)
            {
                foreach (var connectedStack in outputPort.ConnectionPortModels)
                {
                    if (connectedStack.NodeModel is IStackModel nextStack)
                    {
                        anyConnection = true;
                        if (!ReferenceEquals(nextStack, EndStack))
                        {
                            BuildStack(nextStack, ref blockNode, StackExitStrategy.Inherit);
                        }
                    }
                }
            }


            // TODO use function default return value
            StatementSyntax lastStatementSyntax = blockNode.Statements.LastOrDefault();

            if (!anyConnection && !(lastStatementSyntax is ReturnStatementSyntax) && !(lastStatementSyntax is ContinueStatementSyntax))
            {
                //TODO we had that for a reason
//                lastStatementSyntax = StatementFromExitStrategy(m_StackExitStrategy, null);

//                if(lastStatementSyntax != null)
//                    blockNode = blockNode.AddStatements(lastStatementSyntax);
            }

            m_StackExitStrategy = origStackExitStrategy;
        }
Exemple #24
0
 public ConnectedToStackConstraint(IStackModel expected)
     : base(expected)
 {
     m_ExpectedStack = (StackBaseModel)expected;
 }
 public LoopNodeModel CreateLoopNode(StackBaseModel hostStack, int index,
                                     SpawnFlags spawnFlags = SpawnFlags.Default, Action <NodeModel> setup = null, GUID?guid = null)
 {
     return((LoopNodeModel)hostStack.CreateStackedNode(
                MatchingStackedNodeType, Title, index, spawnFlags, setup, guid));
 }
Exemple #26
0
 public IndexInStackConstraint(int expectedIndex, IStackModel expectedStack)
     : base(expectedIndex, expectedStack)
 {
     m_ExpectedIndex = expectedIndex;
     m_ExpectedStack = (StackBaseModel)expectedStack;
 }
        public virtual void BuildStack(IStackModel stack, ref BlockSyntax blockNode,
                                       StackExitStrategy exitStrategy = StackExitStrategy.Return)
        {
            if (stack == null || stack.State == ModelState.Disabled)
            {
                return;
            }

            RegisterBuiltStack(stack);

            // JUST in case... until we validate the previous failsafe
            if (m_BuiltStackCounter++ > 10000)
            {
                throw new InvalidOperationException("Infinite loop while building the script, aborting");
            }

            StackExitStrategy origStackExitStrategy = m_StackExitStrategy;

            if (exitStrategy != StackExitStrategy.Inherit)
            {
                m_StackExitStrategy = exitStrategy;
            }

            //            Debug.Log($"Build stack {stack}");
            // m_EndStack might get changed by recursive BuildNode() calls
            StackBaseModel origEndStack = EndStack;
            var            statements   = new List <StatementSyntax>();

            foreach (var statement in stack.NodeModels)
            {
                if (statement.State == ModelState.Disabled)
                {
                    continue;
                }
                var syntaxNodes = BuildNode(statement);
                foreach (var syntaxNode in syntaxNodes)
                {
                    StatementSyntax resultingStatement;
                    switch (syntaxNode)
                    {
                    case StatementSyntax statementNode:
                        resultingStatement = statementNode;
                        break;

                    case ExpressionSyntax expressionNode:
                        resultingStatement = ExpressionStatement(expressionNode);
                        break;

                    default:
                        throw new InvalidOperationException($"Expected a statement or expression node, found a {syntaxNode.GetType()} when building {statement}");
                    }

                    // TODO: RecordValue codegen counter instead of counting them after the fact
                    if ((Options & UnityEngine.Modifier.VisualScripting.CompilationOptions.Tracing) != 0)
                    {
                        var recordValueCount    = syntaxNode.GetAnnotations(Annotations.RecordValueCountKind).FirstOrDefault();
                        int recordedValuesCount = recordValueCount == null
                            ? syntaxNode.GetAnnotatedNodes(Annotations.RecordValueKind).Count()
                            : int.Parse(recordValueCount.Data);

                        statements.Add(InstrumentForInEditorDebugging.BuildLastCallFrameExpression(recordedValuesCount, statement.Guid, this.GetRecorderName()));
                    }
                    statements.Add(resultingStatement);
                }
            }

            blockNode = blockNode.AddStatements(statements.ToArray());

            if (stack.DelegatesOutputsToNode(out _))
            {
                var nextStack = EndStack;
                m_StackExitStrategy = origStackExitStrategy;

                //                Debug.Log($"Stack {stack} delegates ports. nextStack {nextStack} origEndStack {origEndStack}");

                // if a nested node changed the end stack, but found the same common descendant,
                // let the parent call handle it
                if (EndStack == origEndStack)
                {
                    return;
                }

                EndStack = origEndStack;
                BuildStack(nextStack, ref blockNode, exitStrategy);

                return;
            }

            bool anyConnection = false;

            foreach (var outputPort in stack.OutputPorts)
            {
                foreach (var connectedStack in outputPort.ConnectionPortModels)
                {
                    if (connectedStack.NodeModel is IStackModel nextStack)
                    {
                        anyConnection = true;
                        if (!ReferenceEquals(nextStack, EndStack))
                        {
                            BuildStack(nextStack, ref blockNode, StackExitStrategy.Inherit);
                        }
                    }
                }
            }


            // TODO use function default return value
            StatementSyntax lastStatementSyntax = blockNode.Statements.LastOrDefault();

            if (!anyConnection && !(lastStatementSyntax is ReturnStatementSyntax) && !(lastStatementSyntax is ContinueStatementSyntax))
            {
                //TODO we had that for a reason
                //                lastStatementSyntax = StatementFromExitStrategy(m_StackExitStrategy, null);

                //                if(lastStatementSyntax != null)
                //                    blockNode = blockNode.AddStatements(lastStatementSyntax);
            }

            m_StackExitStrategy = origStackExitStrategy;
        }
Exemple #28
0
        public void DuplicateStackedNodes(INodeModel copiedNode, Dictionary <INodeModel, NodeModel> mapping, Vector2 delta, int stackInsertionIndex, List <StackedNodesStruct> implicitStackedNodes, StackBaseModel pastedStackModel)
        {
            pastedStackModel.ClearNodes();

            if (implicitStackedNodes?.Count > 0)
            {
                foreach (var stackedNodeStruct in implicitStackedNodes)
                {
                    DuplicateNode(stackedNodeStruct.stackedNodeModel, mapping,
                                  pastedStackModel, delta, stackInsertionIndex != -1 ? stackInsertionIndex++ : -1);
                }
            }

            if (copiedNode is FunctionModel copiedFunctionModel && pastedStackModel is FunctionModel pastedFunctionModel)
            {
                pastedFunctionModel.ClearVariableDeclarations();
                foreach (IVariableDeclarationModel functionVariableModel in copiedFunctionModel.FunctionVariableModels)
                {
                    VariableDeclarationModel variableDeclaration = ((VariableDeclarationModel)functionVariableModel).Clone();

                    // Reset name to be the exact same as the original since they are in different scopes
                    variableDeclaration.Name  = functionVariableModel.Name;
                    variableDeclaration.Owner = pastedFunctionModel;
                    pastedFunctionModel.VariableDeclarations.Add(variableDeclaration);
                }

                pastedFunctionModel.ClearParameterDeclarations();
                foreach (IVariableDeclarationModel functionParameterModel in copiedFunctionModel.FunctionParameterModels)
                {
                    VariableDeclarationModel parameterDeclaration = ((VariableDeclarationModel)functionParameterModel).Clone();

                    // Reset name to be the exact same as the original since they are in different scopes
                    parameterDeclaration.Name  = functionParameterModel.Name;
                    parameterDeclaration.Owner = pastedFunctionModel;
                    pastedFunctionModel.FunctionParameters.Add(parameterDeclaration);
                }
            }
        }