Exemplo n.º 1
0
        protected override void BuildAstForPartialMultiOutput(
            NodeModel model, AssociativeNode rhs, List<AssociativeNode> resultAst)
        {
            base.BuildAstForPartialMultiOutput(model, rhs, resultAst);

            var emptyList = AstFactory.BuildExprList(new List<AssociativeNode>());
            var previewIdInit = AstFactory.BuildAssignment(model.AstIdentifierForPreview, emptyList);

            resultAst.Add(previewIdInit);
            resultAst.AddRange(
                Definition.ReturnKeys.Select(
                    (rtnKey, idx) =>
                        AstFactory.BuildAssignment(
                            AstFactory.BuildIdentifier(
                                model.AstIdentifierForPreview.Name,
                                AstFactory.BuildStringNode(rtnKey)),
                            model.GetAstIdentifierForOutputIndex(idx))));
        }
Exemplo n.º 2
0
        /// <summary>
        ///     Returns the names of all the variables defined in this code block.
        /// </summary>
        /// <returns>List containing all the names</returns>
        public List<string> GetDefinedVariableNames()
        {
            var defVarNames = new List<string>();

            // For unbound identifier, ideally if there is an input connect 
            // to it, it is defined variable. But here we have to be more
            // aggresive. For copy/paste, the connectors haven't been 
            // created yet, so if a variable is defined in other CBN, even
            // that variable is defined in this CBN, it is not included in
            // the return value. 
            defVarNames.AddRange(inputIdentifiers);

            // Then get all variabled on the LHS of the statements
            foreach (Statement stmnt in codeStatements)
            {
                defVarNames.AddRange(Statement.GetDefinedVariableNames(stmnt, true));
            }

            return defVarNames;
        }
Exemplo n.º 3
0
        void DeleteModelImpl(DeleteModelCommand command)
        {
            var modelsToDelete = new List<ModelBase>();
            if (command.ModelGuid == Guid.Empty)
            {
                // When nothing is specified then it means all selected models.
                modelsToDelete.AddRange(DynamoSelection.Instance.Selection.OfType<ModelBase>());
            }
            else
            {
                modelsToDelete.AddRange(command.ModelGuids.Select(guid => CurrentWorkspace.GetModelInternal(guid)));
            }

            DeleteModelInternal(modelsToDelete);
        }
Exemplo n.º 4
0
        /// <summary>
        ///     Paste ISelectable objects from the clipboard to the workspace.
        /// </summary>
        public void Paste()
        {
            //clear the selection so we can put the
            //paste contents in
            DynamoSelection.Instance.ClearSelection();

            //make a lookup table to store the guids of the
            //old models and the guids of their pasted versions
            var modelLookup = new Dictionary<Guid, ModelBase>();

            //make a list of all newly created models so that their
            //creations can be recorded in the undo recorder.
            var createdModels = new List<ModelBase>();

            var nodes = ClipBoard.OfType<NodeModel>();
            var connectors = ClipBoard.OfType<ConnectorModel>();
            var notes = ClipBoard.OfType<NoteModel>();
            var annotations = ClipBoard.OfType<AnnotationModel>();

            var minX = Double.MaxValue;
            var minY = Double.MaxValue;

            // Create the new NoteModel's
            var newNoteModels = new List<NoteModel>();
            foreach (var note in notes)
            {
                var noteModel = new NoteModel(note.X, note.Y, note.Text, Guid.NewGuid());
                //Store the old note as Key and newnote as value.
                modelLookup.Add(note.GUID,noteModel);
                newNoteModels.Add(noteModel);

                minX = Math.Min(note.X, minX);
                minY = Math.Min(note.Y, minY);
            }

            var xmlDoc = new XmlDocument();

            // Create the new NodeModel's
            var newNodeModels = new List<NodeModel>();
            foreach (var node in nodes)
            {
                NodeModel newNode;

                if (CurrentWorkspace is HomeWorkspaceModel && (node is Symbol || node is Output))
                {
                    var symbol = (node is Symbol
                        ? (node as Symbol).InputSymbol
                        : (node as Output).Symbol);
                    var code = (string.IsNullOrEmpty(symbol) ? "x" : symbol) + ";";
                    newNode = new CodeBlockNodeModel(code, node.X, node.Y, LibraryServices, CurrentWorkspace.ElementResolver);
                }
                else
                {
                    var dynEl = node.Serialize(xmlDoc, SaveContext.Copy);
                    newNode = NodeFactory.CreateNodeFromXml(dynEl, SaveContext.Copy, CurrentWorkspace.ElementResolver);
                }

                var lacing = node.ArgumentLacing.ToString();
                newNode.UpdateValue(new UpdateValueParams("ArgumentLacing", lacing));
                if (!string.IsNullOrEmpty(node.NickName))
                    newNode.NickName = node.NickName;

                modelLookup.Add(node.GUID, newNode);

                newNodeModels.Add( newNode );

                minX = Math.Min(node.X, minX);
                minY = Math.Min(node.Y, minY);
            }

            // Move all of the notes and nodes such that they are aligned with
            // the top left of the workspace
            var workspaceX = -CurrentWorkspace.X / CurrentWorkspace.Zoom;
            var workspaceY = -CurrentWorkspace.Y / CurrentWorkspace.Zoom;

            // Provide a small offset when pasting so duplicate pastes aren't directly on top of each other
            CurrentWorkspace.IncrementPasteOffset();

            var shiftX = workspaceX - minX + CurrentWorkspace.CurrentPasteOffset;
            var shiftY = workspaceY - minY + CurrentWorkspace.CurrentPasteOffset;

            foreach (var model in newNodeModels.Concat<ModelBase>(newNoteModels))
            {
                model.X = model.X + shiftX;
                model.Y = model.Y + shiftY;
            }

            // Add the new NodeModel's to the Workspace
            foreach (var newNode in newNodeModels)
            {
                CurrentWorkspace.AddAndRegisterNode(newNode, false);
                createdModels.Add(newNode);
                AddToSelection(newNode);
            }

            // TODO: is this required?
            OnRequestLayoutUpdate(this, EventArgs.Empty);

            // Add the new NoteModel's to the Workspace
            foreach (var newNote in newNoteModels)
            {
                CurrentWorkspace.AddNote(newNote, false);
                createdModels.Add(newNote);
                AddToSelection(newNote);
            }

            ModelBase start;
            ModelBase end;
            var newConnectors =
                from c in connectors

                // If the guid is in nodeLookup, then we connect to the new pasted node. Otherwise we
                // re-connect to the original.
                let startNode =
                    modelLookup.TryGetValue(c.Start.Owner.GUID, out start)
                        ? start as NodeModel
                        : CurrentWorkspace.Nodes.FirstOrDefault(x => x.GUID == c.Start.Owner.GUID)
                let endNode =
                    modelLookup.TryGetValue(c.End.Owner.GUID, out end)
                        ? end as NodeModel
                        : CurrentWorkspace.Nodes.FirstOrDefault(x => x.GUID == c.End.Owner.GUID)
             
                // Don't make a connector if either end is null.
                where startNode != null && endNode != null
                select
                    ConnectorModel.Make(startNode, endNode, c.Start.Index, c.End.Index);

            createdModels.AddRange(newConnectors);

            //Grouping depends on the selected node models. 
            //so adding the group after nodes / notes are added to workspace.
            //select only those nodes that are part of a group.             
            var newAnnotations = new List<AnnotationModel>();
            foreach (var annotation in annotations)
            {
                var annotationNodeModel = new List<NodeModel>();
                var annotationNoteModel = new List<NoteModel>();
                //checked condition here that supports pasting of multiple groups
                foreach (var models in annotation.SelectedModels)
                {
                    ModelBase mbase;
                    modelLookup.TryGetValue(models.GUID, out mbase);
                    if (mbase is NodeModel)
                    {
                        annotationNodeModel.Add(mbase as NodeModel);
                    }
                    if (mbase is NoteModel)
                    {
                        annotationNoteModel.Add(mbase as NoteModel);
                    }
                }

                var annotationModel = new AnnotationModel(annotationNodeModel, annotationNoteModel)
                {
                    GUID = Guid.NewGuid(),
                    AnnotationText = annotation.AnnotationText,
                    Background = annotation.Background,
                    FontSize = annotation.FontSize
                };
              
                newAnnotations.Add(annotationModel);
            }

            // Add the new Annotation's to the Workspace
            foreach (var newAnnotation in newAnnotations)
            {
                CurrentWorkspace.AddAnnotation(newAnnotation);
                createdModels.Add(newAnnotation);
                AddToSelection(newAnnotation);
            }

            // Record models that are created as part of the command.
            CurrentWorkspace.RecordCreatedModels(createdModels);
        }
Exemplo n.º 5
0
        internal override IEnumerable<AssociativeNode> BuildAst(List<AssociativeNode> inputAstNodes)
        {
            //Do not build if the node is in error.
            if (this.State == ElementState.Error)
            {
                return null;
            }

            var resultNodes = new List<AssociativeNode>();

            // Define unbound variables if necessary
            if (inputIdentifiers != null && 
                inputAstNodes != null && 
                inputIdentifiers.Count == inputAstNodes.Count)
            {
                var initStatments = inputIdentifiers.Zip(inputAstNodes,
                    (ident, rhs) =>
                    {
                        var identNode = AstFactory.BuildIdentifier(ident);
                        MapIdentifiers(identNode);
                        return AstFactory.BuildAssignment(identNode, rhs);
                    });
                resultNodes.AddRange(initStatments);
            }

            foreach (var stmnt in codeStatements)
            {
                var astNode = ProtoCore.Utils.NodeUtils.Clone(stmnt.AstNode);
                MapIdentifiers(astNode);
                resultNodes.Add(astNode as ProtoCore.AST.AssociativeAST.AssociativeNode);
            }

            return resultNodes;
        }
Exemplo n.º 6
0
        public FScheme.Expression Compile()
        {
            IEnumerable<string> inputNames = null;
            IEnumerable<string> outputNames = null;

            // Get the internal nodes for the function
            WorkspaceModel functionWorkspace = this.WorkspaceModel;

            #region Find outputs

            // Find output elements for the node
            List<Output> outputs = functionWorkspace.Nodes.OfType<Output>().ToList();

            var topMost = new List<Tuple<int, NodeModel>>();

            // if we found output nodes, add select their inputs
            // these will serve as the function output
            if (outputs.Any())
            {
                topMost.AddRange(
                    outputs.Where(x => x.HasInput(0)).Select(x => x.Inputs[0]));

                outputNames = outputs.Select(x => x.Symbol);
            }
            else
            {
                // if there are no explicitly defined output nodes
                // get the top most nodes and set THEM as the output
                IEnumerable<NodeModel> topMostNodes = functionWorkspace.GetTopMostNodes();

                NodeModel infinite = null;

                var outNames = new List<string>();

                foreach (NodeModel topNode in topMostNodes)
                {
                    if (topNode is Function && (topNode as Function).Definition == this)
                    {
                        infinite = topNode;
                        continue;
                    }

                    foreach (int output in Enumerable.Range(0, topNode.OutPortData.Count))
                    {
                        if (!topNode.HasOutput(output))
                        {
                            topMost.Add(Tuple.Create(output, topNode));
                            outNames.Add(topNode.OutPortData[output].NickName);
                        }
                    }
                }

                if (infinite != null && outNames.Count == 0)
                {
                    topMost.Add(Tuple.Create(0, infinite));
                    outNames.Add("∞");
                }

                outputNames = outNames;
            }

            #endregion

            // color the node to define its connectivity
            foreach (var ele in topMost)
            {
                ele.Item2.ValidateConnections();
            }

            //Find function entry point, and then compile
            var variables = functionWorkspace.Nodes.OfType<Symbol>().ToList();
            inputNames = variables.Select(x => x.InputSymbol);

            //Update existing function nodes which point to this function to match its changes
            dynSettings.Controller.DynamoModel.AllNodes
                .OfType<Function>()
                .Where(el => el.Definition != null && el.Definition.FunctionId == this.FunctionId)
                .ToList()
                .ForEach(node =>
                {
                    node.SetInputs(inputNames);
                    node.SetOutputs(outputNames);
                    node.RegisterAllPorts();
                });

            //Call OnSave for all saved elements
            functionWorkspace.Nodes.ToList().ForEach(x => x.onSave());

            INode top;
            var buildDict = new Dictionary<NodeModel, Dictionary<int, INode>>();

            if (topMost.Count > 1)
            {
                InputNode node = new ExternalFunctionNode(FScheme.Value.NewList);

                int i = 0;
                foreach (var topNode in topMost)
                {
                    string inputName = i.ToString(CultureInfo.InvariantCulture);
                    node.AddInput(inputName);
                    node.ConnectInput(inputName, new BeginNode());
                    try
                    {
                        var exp = topNode.Item2.Build(buildDict, topNode.Item1);
                        node.ConnectInput(inputName, exp);
                    }
                    catch
                    {

                    }

                    i++;
                }

                top = node;
            }
            else if (topMost.Count == 1)
            {
                top = topMost[0].Item2.Build(buildDict, topMost[0].Item1);
            }
            else
            {
                // if the custom node is empty, it will initially be an empty begin
                top = new BeginNode();
            }

            // if the node has any outputs, we create a BeginNode in order to evaluate all of them
            // sequentially (begin evaluates a list of expressions)
            if (outputs.Any())
            {
                var beginNode = new BeginNode();
                List<NodeModel> hangingNodes = functionWorkspace.GetHangingNodes().ToList();

                foreach (var tNode in hangingNodes.Select((x, index) => new { Index = index, Node = x }))
                {
                    beginNode.AddInput(tNode.Index.ToString(CultureInfo.InvariantCulture));
                    beginNode.ConnectInput(
                        tNode.Index.ToString(CultureInfo.InvariantCulture),
                        tNode.Node.Build(buildDict, 0));
                }

                beginNode.AddInput(hangingNodes.Count.ToString(CultureInfo.InvariantCulture));
                beginNode.ConnectInput(hangingNodes.Count.ToString(CultureInfo.InvariantCulture), top);

                top = beginNode;
            }

            // make the anonymous function
            FScheme.Expression expression = Utils.MakeAnon(
                variables.Select(x => x.GUID.ToString()),
                top.Compile());

            return expression;
        }
        public List<Type> LoadAllTypesFromDynamoAssemblies()
        {
            var nodeTypes = new List<Type>();
            var loadedAssemblyNames = new HashSet<string>();
            var allLoadedAssembliesByPath = new Dictionary<string, Assembly>();
            var allLoadedAssemblies = new Dictionary<string, Assembly>();

            // cache the loaded assembly information
            foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
            {
                if (assembly.IsDynamic)
                    continue;

                try
                {
                    allLoadedAssembliesByPath[assembly.Location] = assembly;
                    allLoadedAssemblies[assembly.FullName] = assembly;
                }
                catch { }
            }

            // find all the dlls registered in all search paths
            // and concatenate with all dlls in the current directory
            var allDynamoAssemblyPaths =
                DynamoPathManager.Instance.Nodes.SelectMany((path) =>
                    {
                        return (Directory.GetFiles(path, "*.dll", SearchOption.TopDirectoryOnly));
                    }).ToList();

            // add the core assembly to get things like code block nodes and watches.
            allDynamoAssemblyPaths.Add(Path.Combine(DynamoPathManager.Instance.MainExecPath, "DynamoCore.dll"));

            var resolver = new ResolveEventHandler(delegate(object sender, ResolveEventArgs args)
            {
                Assembly result;
                allLoadedAssemblies.TryGetValue(args.Name, out result);
                return result;
            });

            foreach (var assemblyPath in allDynamoAssemblyPaths)
            {
                var fn = Path.GetFileName(assemblyPath);

                if (fn == null)
                    continue;

                // if the assembly has already been loaded, then
                // skip it, otherwise cache it.
                if (loadedAssemblyNames.Contains(fn))
                    continue;

                loadedAssemblyNames.Add(fn);

                if (allLoadedAssembliesByPath.ContainsKey(assemblyPath))
                {
                    List<Type> types = LoadNodesFromAssembly(allLoadedAssembliesByPath[assemblyPath]);
                    nodeTypes.AddRange(types);
                }
                else
                {
                    try
                    {
                        var assembly = Assembly.LoadFrom(assemblyPath);
                        allLoadedAssemblies[assembly.GetName().Name] = assembly;
                        List<Type> types = LoadNodesFromAssembly(assembly);
                        nodeTypes.AddRange(types);
                    }
                    catch (Exception e)
                    {
                        DynamoViewModel.Model.Logger.Log(e);
                    }
                }
            }

            return nodeTypes;
        }
Exemplo n.º 8
0
        private void OnPreviewControlLoaded(object sender, RoutedEventArgs e)
        {
            phaseInStoryboard = this.Resources["phaseInStoryboard"] as Storyboard;
            phaseOutStoryboard = this.Resources["phaseOutStoryboard"] as Storyboard;
            expandStoryboard = this.Resources["expandStoryboard"] as Storyboard;
            condenseStoryboard = this.Resources["condenseStoryboard"] as Storyboard;
            resizingStoryboard = this.Resources["resizingStoryboard"] as Storyboard;

            var children = new List<Timeline>();
            children.AddRange(phaseInStoryboard.Children);
            children.AddRange(expandStoryboard.Children);
            children.AddRange(condenseStoryboard.Children);
            children.AddRange(resizingStoryboard.Children);

            this.sizeAnimators = new Dictionary<string, DoubleAnimation>();

            foreach (var child in children)
            {
                if (string.IsNullOrEmpty(child.Name))
                    continue;

                switch (child.Name)
                {
                    case Element.PhaseInWidthAnimator:
                    case Element.PhaseInHeightAnimator:
                    case Element.ExpandWidthAnimator:
                    case Element.ExpandHeightAnimator:
                    case Element.CondenseWidthAnimator:
                    case Element.CondenseHeightAnimator:
                    case Element.GridWidthAnimator:
                    case Element.GridHeightAnimator:
                        sizeAnimators.Add(child.Name, child as DoubleAnimation);
                        break;
                }
            }

            if (this.sizeAnimators.Count != 8)
            {
                var message = "One or more DoubleAnimation timeline not found";
                throw new InvalidOperationException(message);
            }

            // If there was a request queued before this control is loaded, 
            // then process the request as we now have the right width.
            BeginNextTransition();
        }
Exemplo n.º 9
0
 private static void ParseSolid(GeometryObject obj, List<XYZ> pts)
 {
     var solid = obj as Solid;
     foreach (Edge gEdge in solid.Edges)
     {
         Curve c = gEdge.AsCurve();
         if (c is Line)
         {
             pts.Add(c.Evaluate(0, true));
             pts.Add(c.Evaluate(1,true));
         }
         else
         {
             IList<XYZ> xyzArray = gEdge.Tessellate();
             pts.AddRange(xyzArray);
         }
     }
 }
Exemplo n.º 10
0
        /// <summary>
        /// Gathers the Ids of the upstream drawable nodes.
        /// </summary>
        /// <param name="inputs">A dictionary describing the inputs on the node.</param>
        /// <returns>A collection of strings.</returns>
        private List<string> GetUpstreamDrawableIds(Dictionary<int, Tuple<int, NodeModel>> inputs)
        {
            var drawables = new List<string>();

            foreach (KeyValuePair<int, Tuple<int, NodeModel>> pair in inputs)
            {
                if (pair.Value == null)
                    continue;

                NodeModel node = pair.Value.Item2;

                if(node.OldValue != null)
                    drawables.Add(node.GUID.ToString());

                if (node.IsUpstreamVisible)
                    drawables.AddRange(GetUpstreamDrawableIds(node.Inputs));

            }

            return drawables;
        }
Exemplo n.º 11
0
        internal override IEnumerable<AssociativeNode> BuildAst(List<AssociativeNode> inputAstNodes)
        {
            var resultAst = new List<AssociativeNode>();

            string function = Definition.Name;
            AssociativeNode rhs;

            // All inputs are provided, then we should pack all inputs that
            // belong to variable input parameter into a single array. 
            if (!HasUnconnectedInput())
            {
                var paramCount = Definition.Parameters.Count();
                var packId = "__var_arg_pack_" + GUID;
                resultAst.Add(
                    AstFactory.BuildAssignment(
                        AstFactory.BuildIdentifier(packId),
                        AstFactory.BuildExprList(inputAstNodes.Skip(paramCount - 1).ToList())));

                inputAstNodes =
                    inputAstNodes.Take(paramCount - 1)
                                 .Concat(new[] { AstFactory.BuildIdentifier(packId) })
                                 .ToList();
            }

            switch (Definition.Type)
            {
                case FunctionType.Constructor:
                case FunctionType.StaticMethod:
                    if (HasUnconnectedInput())
                    {
                        var functionNode = new IdentifierListNode
                        {
                            LeftNode = new IdentifierNode(Definition.ClassName),
                            RightNode = new IdentifierNode(Definition.Name)
                        };
                        rhs = CreateFunctionObject(functionNode, inputAstNodes);
                    }
                    else
                    {
                        rhs = AstFactory.BuildFunctionCall(Definition.ClassName,
                                                           Definition.Name,
                                                           inputAstNodes);
                    }
                    break;

                case FunctionType.StaticProperty:

                    var staticProp = new IdentifierListNode
                    {
                        LeftNode = new IdentifierNode(Definition.ClassName),
                        RightNode = new IdentifierNode(Definition.Name)
                    };
                    rhs = staticProp;
                    break;

                case FunctionType.InstanceProperty:

                    // Only handle getter here. Setter could be handled in CBN.
                    rhs = new NullNode();
                    if (inputAstNodes != null && inputAstNodes.Count >= 1)
                    {
                        var thisNode = inputAstNodes[0];
                        if (thisNode != null && !(thisNode is NullNode))
                        {
                            var insProp = new IdentifierListNode
                            {
                                LeftNode = inputAstNodes[0],
                                RightNode = new IdentifierNode(Definition.Name)
                            };
                            rhs = insProp;
                        }
                    }

                    break;

                case FunctionType.InstanceMethod:

                    rhs = new NullNode();
                    if (inputAstNodes != null && inputAstNodes.Count >= 1)
                    {
                        var thisNode = inputAstNodes[0];
                        inputAstNodes.RemoveAt(0); // remove this pointer

                        if (thisNode != null && !(thisNode is NullNode))
                        {
                            var memberFunc = new IdentifierListNode
                            {
                                LeftNode = thisNode,
                                RightNode = AstFactory.BuildFunctionCall(function, inputAstNodes)
                            };
                            rhs = memberFunc;
                        }
                    }

                    break;

                default:
                    if (HasUnconnectedInput())
                    {
                        var functionNode = new IdentifierNode(function);
                        rhs = CreateFunctionObject(functionNode, inputAstNodes);
                    }
                    else
                    {
                        rhs = AstFactory.BuildFunctionCall(function, inputAstNodes);
                    }
                    break;
            }

            resultAst.Add(AstFactory.BuildAssignment(AstIdentifierForPreview, rhs));

            if (OutPortData.Count == 1)
            {
                var outputIdentiferNode = GetAstIdentifierForOutputIndex(0);
                string outputIdentifier = outputIdentiferNode.ToString();
                string thisIdentifier = AstIdentifierForPreview.ToString();
                if (!string.Equals(outputIdentifier, thisIdentifier))
                {
                    resultAst.Add(
                        AstFactory.BuildAssignment(outputIdentiferNode, AstIdentifierForPreview));
                }
            }
            else
            {
                var undefinedOutputs = Definition.ReturnKeys == null || !Definition.ReturnKeys.Any();

                resultAst.AddRange(
                    Enumerable.Range(0, OutPortData.Count)
                              .Select(
                                  outputIdx =>
                                      undefinedOutputs
                                          ? AstIdentifierForPreview
                                          : new IdentifierNode(AstIdentifierForPreview)
                                          {
                                              ArrayDimensions =
                                                  new ArrayNode
                                                  {
                                                      Expr =
                                                          new StringNode
                                                          {
                                                              value =
                                                                  Definition.ReturnKeys.ElementAt(
                                                                      outputIdx)
                                                          }
                                                  }
                                          }));
            }

            return resultAst;
        }
Exemplo n.º 12
0
        internal override IEnumerable<AssociativeNode> BuildAst(List<AssociativeNode> inputAstNodes)
        {
            string function = Definition.Name;
            AssociativeNode rhs;

            switch (Definition.Type)
            {
                case FunctionType.Constructor:
                case FunctionType.StaticMethod:
                    if (IsPartiallyApplied)
                    {
                        var functionNode = new IdentifierListNode
                        {
                            LeftNode = new IdentifierNode(Definition.ClassName),
                            RightNode = new IdentifierNode(Definition.Name)
                        };
                        rhs = CreateFunctionObject(functionNode, inputAstNodes);
                    }
                    else
                    {
                        AppendReplicationGuides(inputAstNodes);
                        rhs = AstFactory.BuildFunctionCall(
                            Definition.ClassName,
                            Definition.Name,
                            inputAstNodes);
                    }
                    break;

                case FunctionType.StaticProperty:

                    var staticProp = new IdentifierListNode
                    {
                        LeftNode = new IdentifierNode(Definition.ClassName),
                        RightNode = new IdentifierNode(Definition.Name)
                    };
                    rhs = staticProp;
                    break;

                case FunctionType.InstanceProperty:

                    // Only handle getter here. Setter could be handled in CBN.
                    if (IsPartiallyApplied)
                    {
                        var functionNode = new IdentifierListNode
                        {
                            LeftNode = new IdentifierNode(Definition.ClassName),
                            RightNode = new IdentifierNode(Definition.Name)
                        };
                        rhs = CreateFunctionObject(functionNode, inputAstNodes);
                    }
                    else
                    {
                        rhs = new NullNode();
                        if (inputAstNodes != null && inputAstNodes.Count >= 1)
                        {
                            var thisNode = inputAstNodes[0];
                            if (thisNode != null && !(thisNode is NullNode))
                            {
                                var insProp = new IdentifierListNode
                                {
                                    LeftNode = inputAstNodes[0],
                                    RightNode = new IdentifierNode(Definition.Name)
                                };
                                rhs = insProp;
                            }
                        }
                    }

                    break;

                case FunctionType.InstanceMethod:
                    if (IsPartiallyApplied)
                    {
                        var functionNode = new IdentifierListNode
                        {
                            LeftNode = new IdentifierNode(Definition.ClassName),
                            RightNode = new IdentifierNode(Definition.Name)
                        };
                        rhs = CreateFunctionObject(functionNode, inputAstNodes);
                    }
                    else
                    {
                        rhs = new NullNode();
                        AppendReplicationGuides(inputAstNodes);

                        if (inputAstNodes != null && inputAstNodes.Count >= 1)
                        {
                            var thisNode = inputAstNodes[0];
                            inputAstNodes.RemoveAt(0); // remove this pointer

                            if (thisNode != null && !(thisNode is NullNode))
                            {
                                var memberFunc = new IdentifierListNode
                                {
                                    LeftNode = thisNode,
                                    RightNode = AstFactory.BuildFunctionCall(function, inputAstNodes)
                                };
                                rhs = memberFunc;
                            }
                        }
                    }

                    break;

                default:
                    if (IsPartiallyApplied)
                    {
                        var functionNode = new IdentifierNode(function);
                        rhs = CreateFunctionObject(functionNode, inputAstNodes);
                    }
                    else
                    {
                        AppendReplicationGuides(inputAstNodes);
                        rhs = AstFactory.BuildFunctionCall(function, inputAstNodes);
                    }
                    break;
            }

            var resultAst = new List<AssociativeNode>
            {
                AstFactory.BuildAssignment(AstIdentifierForPreview, rhs)
            };

            if (OutPortData.Count == 1)
            {
                var outputIdentiferNode = GetAstIdentifierForOutputIndex(0);
                string outputIdentifier = outputIdentiferNode.ToString();
                string thisIdentifier = AstIdentifierForPreview.ToString();
                if (!string.Equals(outputIdentifier, thisIdentifier))
                {
                    resultAst.Add(AstFactory.BuildAssignment(outputIdentiferNode, AstIdentifierForPreview));
                }
            }
            else
            {
                var undefinedOutputs = Definition.ReturnKeys == null || !Definition.ReturnKeys.Any();

                resultAst.AddRange(
                    Enumerable.Range(0, OutPortData.Count)
                        .Select(
                            outputIdx =>
                                undefinedOutputs
                                    ? AstIdentifierForPreview
                                    : new IdentifierNode(AstIdentifierForPreview)
                                    {
                                        ArrayDimensions =
                                            new ArrayNode
                                            {
                                                Expr =
                                                    new StringNode
                                                    {
                                                        value = Definition.ReturnKeys.ElementAt(outputIdx)
                                                    }
                                            }
                                    }));
            }
            return resultAst;
        }
Exemplo n.º 13
0
        private static List<Color> GetColorsFromMirrorData(RuntimeMirror colorsMirror)
        {
            var colors = new List<Color>();

            if (colorsMirror == null || colorsMirror.GetData() == null) return colors;

            var data = colorsMirror.GetData();
            if (data != null)
            {
                if (data.IsCollection)
                {
                    colors.AddRange(data.GetElements().Select(e => e.Data).OfType<Color>());
                }
                else
                {
                    var color = data.Data as Color;
                    if (color != null)
                        colors.Add(color);
                }
            }

            return colors;
        }
Exemplo n.º 14
0
        Mesh3D MergeMeshes(List<Mesh3D> meshes)
        {
            if (meshes.Count == 0)
                return null;

            Mesh3D fullMesh = new Mesh3D();

            List<Point3D> positions = new List<Point3D>();
            List<int> triangleIndices = new List<int>();

            int offset = 0;
            foreach (Mesh3D m in meshes)
            {
                positions.AddRange(m.Vertices);

                foreach (int[] face in m.Faces)
                {
                    triangleIndices.Add(face[0] + offset);
                    triangleIndices.Add(face[1] + offset);
                    triangleIndices.Add(face[2] + offset);
                }

                offset = positions.Count;
            }

            return new Mesh3D(positions, triangleIndices);
        }
Exemplo n.º 15
0
        /// <summary>
        /// Sends workspace and its' dependencies to Flood.
        /// </summary>
        internal void Send(IEnumerable<IWorkspaceModel> workspaces)
        {
            if (String.IsNullOrWhiteSpace(serverUrl) || String.IsNullOrWhiteSpace(authenticationProvider.Username))
                throw new Exception(Resource.ServerErrorMessage);

            if (authenticationProvider == null)
                throw new Exception(Resource.AuthenticationErrorMessage);

            string fullServerAdress = serverUrl + ":" + port;

            if (reachClient == null)
                reachClient = new WorkspaceStorageClient(authenticationProvider, fullServerAdress);

            HomeWorkspace = workspaces.OfType<HomeWorkspaceModel>().First();
            var functionNodes = HomeWorkspace.Nodes.OfType<Function>();

            List<CustomNodeDefinition> dependencies = new List<CustomNodeDefinition>();
            foreach (var node in functionNodes)
            {
                dependencies.AddRange(node.Definition.Dependencies);
            }

            CustomNodeWorkspaces = new List<CustomNodeWorkspaceModel>();
            foreach (var dependency in dependencies)
            {
                CustomNodeWorkspaceModel customNodeWs;
                var isWorkspaceCreated = customNodeManager.TryGetFunctionWorkspace(dependency.FunctionId, false, out customNodeWs);
                if (isWorkspaceCreated && !CustomNodeWorkspaces.Contains(customNodeWs))
                    CustomNodeWorkspaces.Add(customNodeWs);
            }

            var result = reachClient.Send(HomeWorkspace, CustomNodeWorkspaces);
        }
Exemplo n.º 16
0
        /// <summary>
        /// Get a property value from a member
        /// </summary>
        /// <param name="args">The incoming arguments</param>
        /// <param name="api_base_type">The base type</param>
        /// <param name="pi">The property info object for which you will return the value.</param>
        /// <param name="return_type">The expected return type.</param>
        /// <returns></returns>
        public static Value GetAPIPropertyValue( FSharpList<Value> args,
                                                 Type api_base_type, PropertyInfo pi, Type return_type)
        {
            //var arg0 = (Autodesk.Revit.DB.HermiteFace)DynamoTypeConverter.ConvertInput(args[0], typeof(Autodesk.Revit.DB.HermiteFace));
            //var result = arg0.Points;

            var results = new List<object>();

            //there should only be one argument
            foreach (var arg in args)
            {
                if (arg.IsList)
                {
                    FSharpList<Value> lst = FSharpList<Value>.Empty;

                    //the values here are the items whose properties
                    //you want to query. nothing fancy, just get the
                    //property for each of the items.
                    results.AddRange(((Value.List) arg).Item.
                        Select(v => DynamoTypeConverter.ConvertInput(v, api_base_type)).
                        Select(invocationTarget => pi.GetValue(invocationTarget, null)));
                }
                else
                {
                    var invocationTarget = DynamoTypeConverter.ConvertInput(args[0], api_base_type);
                    results.Add(pi.GetValue(invocationTarget,null));
                }
            }

            return ConvertAllResults(results);
        }
Exemplo n.º 17
0
        /// <summary>
        /// Invoke an API method, using the node's lacing strategy to build lists of arguments
        /// </summary>
        /// <param name="node">The node.</param>
        /// <param name="args">The incoming Values on the node.</param>
        /// <param name="api_base_type">The API's base type whose method we will invoke.</param>
        /// <param name="pi">An array of parameter info for the method.</param>
        /// <param name="mi">The method info for the method.</param>
        /// <param name="return_type">The expected return type from the method.</param>
        /// <returns></returns>
        public static Value InvokeAPIMethod(dynRevitTransactionNode node, FSharpList<Value> args, Type api_base_type, ParameterInfo[] pi, MethodBase mi, Type return_type)
        {
            //if any argument are a list, honor the lacing strategy
            //compile a list of parameter lists to be used in our method invocation
            List<List<object>> parameters = null;

            switch (node.ArgumentLacing)
            {
                case LacingStrategy.Single:
                    parameters = GetSingleArguments(args, pi);
                    break;
                case LacingStrategy.Shortest:
                    parameters = GetShortestArguments(args, pi);
                    break;
                case LacingStrategy.Longest:
                    parameters = GetLongestArguments(args, pi);
                    break;
                default:
                    parameters = GetSingleArguments(args, pi);
                    break;
            }

            var invocationTargetList = new List<object>();

            if (api_base_type == typeof(Autodesk.Revit.Creation.Document) ||
                api_base_type == typeof(Autodesk.Revit.Creation.FamilyItemFactory) ||
                api_base_type == typeof(Autodesk.Revit.Creation.ItemFactoryBase))
            {
                if (dynRevitSettings.Doc.Document.IsFamilyDocument)
                {
                    invocationTargetList.Add(dynRevitSettings.Doc.Document.FamilyCreate);
                }
                else
                {
                    invocationTargetList.Add(dynRevitSettings.Doc.Document.Create);
                }
            }
            else if (api_base_type == typeof(Autodesk.Revit.Creation.Application))
            {
                invocationTargetList.Add(dynRevitSettings.Revit.Application.Create);
            }
            else
            {
                if (!mi.IsStatic && !mi.IsConstructor)
                {
                    if (args[0].IsList)
                    {
                        invocationTargetList.AddRange(((Value.List)args[0]).Item.Select(x => DynamoTypeConverter.ConvertInput(x, api_base_type)));
                    }
                    else
                    {
                        //the first input will always hold the instance
                        //whose methods you want to invoke
                        invocationTargetList.Add(DynamoTypeConverter.ConvertInput(args[0], api_base_type));
                    }
                }
            }

            //object result = null;
            List<object> results = null;

            //if the method info is for a constructor, then
            //call the constructor for each set of parameters
            //if it's an instance method, then invoke the method for
            //each instance passed in.
            results = mi.IsConstructor ?
                parameters.Select(x => ((ConstructorInfo) mi).Invoke(x.ToArray())).ToList() :
                invocationTargetList.SelectMany(x => parameters.Select(y => mi.Invoke(x, y.ToArray())).ToList()).ToList();

            dynRevitUtils.StoreElements(node, results);

            return ConvertAllResults(results);
        }
Exemplo n.º 18
0
        public CustomNodeDefinition(
            Guid functionId,
            string displayName="",
            IList<NodeModel> nodeModels=null)
        {
            if (functionId == Guid.Empty)
                throw new ArgumentException(@"FunctionId invalid.", "functionId");

            nodeModels = nodeModels ?? new List<NodeModel>();

            #region Find outputs

            // Find output elements for the node

            var outputs = nodeModels.OfType<Output>().ToList();

            var topMost = new List<Tuple<int, NodeModel>>();

            List<string> outNames;

            // if we found output nodes, add select their inputs
            // these will serve as the function output
            if (outputs.Any())
            {
                topMost.AddRange(
                    outputs.Where(x => x.HasInput(0)).Select(x => Tuple.Create(0, x as NodeModel)));
                outNames = outputs.Select(x => x.Symbol).ToList();
            }
            else
            {
                outNames = new List<string>();

                // if there are no explicitly defined output nodes
                // get the top most nodes and set THEM as the output
                IEnumerable<NodeModel> topMostNodes = nodeModels.Where(node => node.IsTopMostNode);

                var rtnPorts =
                    //Grab multiple returns from each node
                    topMostNodes.SelectMany(
                        topNode =>
                            //If the node is a recursive instance...
                            topNode is Function && (topNode as Function).Definition.FunctionId == functionId
                                // infinity output
                                ? new[] {new {portIndex = 0, node = topNode, name = "∞"}}
                                // otherwise, grab all ports with connected outputs and package necessary info
                                : topNode.OutPortData
                                    .Select(
                                        (port, i) =>
                                            new {portIndex = i, node = topNode, name = port.NickName})
                                    .Where(x => !topNode.HasOutput(x.portIndex)));

                foreach (var rtnAndIndex in rtnPorts.Select((rtn, i) => new {rtn, idx = i}))
                {
                    topMost.Add(Tuple.Create(rtnAndIndex.rtn.portIndex, rtnAndIndex.rtn.node));
                    outNames.Add(rtnAndIndex.rtn.name ?? rtnAndIndex.idx.ToString());
                }
            }

            var nameDict = new Dictionary<string, int>();
            foreach (var name in outNames)
            {
                if (nameDict.ContainsKey(name))
                    nameDict[name]++;
                else
                    nameDict[name] = 0;
            }

            nameDict = nameDict.Where(x => x.Value != 0).ToDictionary(x => x.Key, x => x.Value);

            outNames.Reverse();

            var returnKeys = new List<string>();
            foreach (var name in outNames)
            {
                int amt;
                if (nameDict.TryGetValue(name, out amt))
                {
                    nameDict[name] = amt - 1;
                    returnKeys.Add(name == "" ? amt + ">" : name + amt);
                }
                else
                    returnKeys.Add(name);
            }

            returnKeys.Reverse();

            #endregion

            #region Find inputs

            //Find function entry point, and then compile
            var inputNodes = nodeModels.OfType<Symbol>().ToList();
            var parameters = inputNodes.Select(x => new TypedParameter(
                                                   x.GetAstIdentifierForOutputIndex(0).Value, 
                                                   x.Parameter.Type, 
                                                   x.Parameter.DefaultValue));
            var displayParameters = inputNodes.Select(x => x.Parameter.Name);

            #endregion

            FunctionBody = nodeModels.Where(node => !(node is Symbol));
            DisplayName = displayName;
            FunctionId = functionId;
            Parameters = parameters;
            ReturnKeys = returnKeys;
            DisplayParameters = displayParameters;
            OutputNodes = topMost.Select(x => x.Item2.GetAstIdentifierForOutputIndex(x.Item1));
            DirectDependencies = nodeModels
                .OfType<Function>()
                .Select(node => node.Definition)
                .Where(def => def.FunctionId != functionId)
                .Distinct();
        }
Exemplo n.º 19
0
        private static FScheme.Expression CompileFunction( FunctionDefinition definition )
        {
            if (definition == null)
                return null;

            // Get the internal nodes for the function
            dynWorkspace functionWorkspace = definition.Workspace;

            #region Find outputs

            // Find output elements for the node
            IEnumerable<dynNode> outputs = functionWorkspace.Nodes.Where(x => x is dynOutput);

            var topMost = new List<Tuple<int, dynNode>>();

            IEnumerable<string> outputNames;

            // if we found output nodes, add select their inputs
            // these will serve as the function output
            if (outputs.Any())
            {
                topMost.AddRange(
                    outputs.Where(x => x.HasInput(0)).Select(x => x.Inputs[0]));

                outputNames = outputs.Select(x => (x as dynOutput).Symbol);
            }
            else
            {
                // if there are no explicitly defined output nodes
                // get the top most nodes and set THEM as tht output
                IEnumerable<dynNode> topMostNodes = functionWorkspace.GetTopMostNodes();

                var outNames = new List<string>();

                foreach (dynNode topNode in topMostNodes)
                {
                    foreach (int output in Enumerable.Range(0, topNode.OutPortData.Count))
                    {
                        if (!topNode.HasOutput(output))
                        {
                            topMost.Add(Tuple.Create(output, topNode));
                            outNames.Add(topNode.OutPortData[output].NickName);
                        }
                    }
                }

                outputNames = outNames;
            }

            #endregion

            // color the node to define its connectivity
            foreach (var ele in topMost)
            {
                ele.Item2.NodeUI.ValidateConnections();
            }

            //Find function entry point, and then compile the function and add it to our environment
            IEnumerable<dynNode> variables = functionWorkspace.Nodes.Where(x => x is dynSymbol);
            IEnumerable<string> inputNames = variables.Select(x => (x as dynSymbol).Symbol);

            INode top;
            var buildDict = new Dictionary<dynNode, Dictionary<int, INode>>();

            if (topMost.Count > 1)
            {
                InputNode node = new ExternalFunctionNode(
                    FScheme.Value.NewList,
                    Enumerable.Range(0, topMost.Count).Select(x => x.ToString()));

                int i = 0;
                foreach (var topNode in topMost)
                {
                    string inputName = i.ToString();
                    node.ConnectInput(inputName, topNode.Item2.Build(buildDict, topNode.Item1));
                    i++;
                }

                top = node;
            }
            else
                top = topMost[0].Item2.BuildExpression(buildDict);

            // if the node has any outputs, we create a BeginNode in order to evaluate all of them
            // sequentially (begin evaluates a list of expressions)
            if (outputs.Any())
            {
                var beginNode = new BeginNode();
                List<dynNode> hangingNodes = functionWorkspace.GetTopMostNodes().ToList();
                foreach (var tNode in hangingNodes.Select((x, index) => new { Index = index, Node = x }))
                {
                    beginNode.AddInput(tNode.Index.ToString());
                    beginNode.ConnectInput(tNode.Index.ToString(), tNode.Node.Build(buildDict, 0));
                }
                beginNode.AddInput(hangingNodes.Count.ToString());
                beginNode.ConnectInput(hangingNodes.Count.ToString(), top);

                top = beginNode;
            }

            // make the anonymous function
            FScheme.Expression expression = Utils.MakeAnon(variables.Select(x => x.NodeUI.GUID.ToString()),
                                                            top.Compile());

            return expression;
        }
Exemplo n.º 20
0
        /// <summary>
        /// Sends workspace and its' dependencies to Flood.
        /// </summary>
        /// <returns>String which is response from server.</returns>
        internal string Send(IEnumerable<IWorkspaceModel> workspaces, WorkspaceProperties workspaceProperties = null)
        {
            if (String.IsNullOrWhiteSpace(serverUrl))
            {
                Error = UploadErrorType.ServerNotFound;
                return Resources.FailedMessage;
            }

            if (String.IsNullOrWhiteSpace(authenticationProvider.Username))
            {
                Error = UploadErrorType.AuthenticationFailed;
                return Resources.FailedMessage;
            }

            if (authenticationProvider == null)
            {
                Error = UploadErrorType.AuthProviderNotFound;
                return Resources.FailedMessage;
            }

            if (reachClient == null)
                reachClient = new WorkspaceStorageClient(authenticationProvider, serverUrl);

            HomeWorkspace = workspaces.OfType<HomeWorkspaceModel>().First();
            var functionNodes = HomeWorkspace.Nodes.OfType<Function>();

            List<CustomNodeDefinition> dependencies = new List<CustomNodeDefinition>();
            foreach (var node in functionNodes)
            {
                dependencies.AddRange(node.Definition.Dependencies);
            }

            CustomNodeWorkspaces = new List<ICustomNodeWorkspaceModel>();
            foreach (var dependency in dependencies)
            {
                ICustomNodeWorkspaceModel customNodeWs;
                var isWorkspaceCreated = customNodeManager.TryGetFunctionWorkspace(dependency.FunctionId, false, out customNodeWs);
                if (isWorkspaceCreated && !CustomNodeWorkspaces.Contains(customNodeWs))
                    CustomNodeWorkspaces.Add(customNodeWs);
            }

            string result;
            try
            {
                result = reachClient.Send(
                    HomeWorkspace,
                    CustomNodeWorkspaces.OfType<CustomNodeWorkspaceModel>(), 
                    workspaceProperties);
                InvalidNodeNames = null;
            }
            catch (InvalidNodesException ex)
            {
                InvalidNodeNames = ex.InvalidNodeNames;
                result = Resources.FailedMessage;
            }
            catch
            {
                result = Resources.FailedMessage;
            }

            return result;
        }
Exemplo n.º 21
0
        /// <summary>
        /// Utility method to get the Revit geometry associated with nodes.
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        private static List<GeometryObject> RevitGeometryFromNodes(FScheme.Value value)
        {
            var geoms = new List<GeometryObject>();

            if (value == null)
            {
                return geoms;
            }

            if (value.IsList)
            {
                foreach (var val_inner in ((FScheme.Value.List)value).Item)
                {
                    geoms.AddRange(RevitGeometryFromNodes(val_inner));
                }
                return geoms;
            }

            var container = value as Value.Container;
            if (container == null)
                return geoms;

            var geom = ((FScheme.Value.Container)value).Item as GeometryObject;
            if (geom != null && !(geom is Face))
                geoms.Add(geom);

            var ps = ((FScheme.Value.Container) value).Item as ParticleSystem;
            if (ps != null)
            {
                geoms.AddRange(ps.Springs.Select(spring => Line.CreateBound(spring.getOneEnd().getPosition(), spring.getTheOtherEnd().getPosition())).Cast<GeometryObject>());
            }

            var cl = ((FScheme.Value.Container) value).Item as Autodesk.Revit.DB.CurveLoop;
            if (cl != null)
            {
                geoms.AddRange(cl);
            }

            //draw xyzs as Point objects
            var pt = ((FScheme.Value.Container)value).Item as XYZ;
            if (pt != null)
            {
                Type pointType = typeof(Point);
                MethodInfo[] pointTypeMethods = pointType.GetMethods(BindingFlags.Static | BindingFlags.Public);
                var method = pointTypeMethods.FirstOrDefault(x => x.Name == "CreatePoint");

                if (method != null)
                {
                    var args = new object[3];
                    args[0] = pt.X;
                    args[1] = pt.Y;
                    args[2] = pt.Z;
                    geoms.Add((Point)method.Invoke(null, args));
                }
            }

            return geoms;
        }
Exemplo n.º 22
0
        /// <summary>
        /// This method adds relevant models to the undo recorder.
        /// </summary>
        /// <param name="isGroupLayout">True if all the selected models are groups.</param>
        private void RecordUndoGraphLayout(bool isGroupLayout)
        {
            List<ModelBase> undoItems = new List<ModelBase>();

            if (!isGroupLayout)
            {
                // Add all selected items to the undo recorder
                undoItems.AddRange(Nodes);
                undoItems.AddRange(Notes);
                if (DynamoSelection.Instance.Selection.Count > 0)
                {
                    undoItems = undoItems.Where(x => x.IsSelected).ToList();
                }
            }
            else
            {
                // Add all models inside selected groups
                foreach (var group in Annotations)
                {
                    if (group.IsSelected)
                    {
                        group.Deselect();
                        undoItems.AddRange(group.SelectedModels);
                    }
                }
            }

            WorkspaceModel.RecordModelsForModification(undoItems, UndoRecorder);
        }
Exemplo n.º 23
0
        /// <summary>
        /// Return all nodes that are in the scope of this node. 
        /// nodes are not in the scope.
        /// </summary>
        /// <param name="checkEscape">
        /// Specifies if need to exclude nodes that one of their downstream
        /// nodes are not in the scope
        /// </param>
        /// <param name="isInclusive">
        /// If one of its upstream node is ScopedNodeModel, if need to include 
        /// all upstream nodes of that node.
        /// </param>
        /// <returns></returns>
        public IEnumerable<NodeModel> GetInScopeNodes(bool checkEscape = true, bool isInclusive = true)
        {
            var inScopedNodes = new List<NodeModel>();

            foreach (int index in Enumerable.Range(0, InPortData.Count))
            {
                if (!IsScopedInport(index))
                {
                    continue;
                }

                var inScopedNodesForInport = GetInScopeNodesForInport(index, checkEscape, isInclusive);
                inScopedNodes.AddRange(inScopedNodesForInport);
            }

            return inScopedNodes;
        }
Exemplo n.º 24
0
        /// <summary>
        /// This method extracts all models from the workspace and puts them
        /// into the combined graph object, LayoutSubgraphs.First()
        /// <param name="isGroupLayout">True if all the selected models are groups.</param>
        /// </summary>
        private void GenerateCombinedGraph(bool isGroupLayout)
        {
            LayoutSubgraphs = new List<GraphLayout.Graph>();
            LayoutSubgraphs.Add(new GraphLayout.Graph());

            GraphLayout.Graph combinedGraph = LayoutSubgraphs.First();
            SubgraphClusters = new List<List<GraphLayout.Node>>();

            if (!isGroupLayout)
            {
                foreach (AnnotationModel group in Annotations)
                {
                    // Treat a group as a graph layout node/vertex
                    combinedGraph.AddNode(group.GUID, group.Width, group.Height, group.X, group.Y,
                        group.IsSelected || DynamoSelection.Instance.Selection.Count == 0);
                }
            }

            foreach (NodeModel node in Nodes)
            {
                if (!isGroupLayout)
                {
                    AnnotationModel group = Annotations.Where(
                        g => g.SelectedModels.Contains(node)).ToList().FirstOrDefault();

                    // Do not process nodes within groups
                    if (group == null)
                    {
                        combinedGraph.AddNode(node.GUID, node.Width, node.Height, node.X, node.Y,
                            node.IsSelected || DynamoSelection.Instance.Selection.Count == 0);
                    }
                }
                else
                {
                    // Process all nodes inside the selection
                    combinedGraph.AddNode(node.GUID, node.Width, node.Height, node.X, node.Y,
                        node.IsSelected || DynamoSelection.Instance.Selection.Count == 0);
                }
            }

            foreach (ConnectorModel edge in Connectors)
            {
                if (!isGroupLayout)
                {
                    AnnotationModel startGroup = null, endGroup = null;
                    startGroup = Annotations.Where(
                        g => g.SelectedModels.Contains(edge.Start.Owner)).ToList().FirstOrDefault();
                    endGroup = Annotations.Where(
                        g => g.SelectedModels.Contains(edge.End.Owner)).ToList().FirstOrDefault();

                    // Treat a group as a node, but do not process edges within a group
                    if (startGroup == null || endGroup == null || startGroup != endGroup)
                    {
                        combinedGraph.AddEdge(
                            startGroup == null ? edge.Start.Owner.GUID : startGroup.GUID,
                            endGroup == null ? edge.End.Owner.GUID : endGroup.GUID,
                            edge.Start.Center.X, edge.Start.Center.Y, edge.End.Center.X, edge.End.Center.Y);
                    }
                }
                else
                {
                    // Edges within a group are also processed
                    combinedGraph.AddEdge(edge.Start.Owner.GUID, edge.End.Owner.GUID,
                        edge.Start.Center.X, edge.Start.Center.Y, edge.End.Center.X, edge.End.Center.Y);
                }
            }

            foreach (NoteModel note in Notes)
            {
                // Link a note to the nearest node
                GraphLayout.Node nd = combinedGraph.Nodes.OrderBy(node =>
                    Math.Pow(node.X + node.Width / 2 - note.X - note.Width / 2, 2) +
                    Math.Pow(node.Y + node.Height / 2 - note.Y - note.Height / 2, 2)).FirstOrDefault();

                if (nd != null)
                {
                    nd.LinkNote(note, note.Width, note.Height);
                }
            }

            if (!isGroupLayout)
            {
                // Add all nodes to one big cluster
                List<GraphLayout.Node> bigcluster = new List<GraphLayout.Node>();
                bigcluster.AddRange(combinedGraph.Nodes);
                SubgraphClusters.Add(bigcluster);
            }
            else
            {
                // Each group becomes one cluster
                foreach (AnnotationModel group in DynamoSelection.Instance.Selection.OfType<AnnotationModel>())
                {
                    List<GraphLayout.Node> cluster = new List<GraphLayout.Node>();
                    cluster.AddRange(group.SelectedModels.Select(x => combinedGraph.FindNode(x.GUID)));
                    SubgraphClusters.Add(cluster);
                }
            }

        }
Exemplo n.º 25
0
        public DynamoView(DynamoViewModel dynamoViewModel)
        {
            // The user's choice to enable hardware acceleration is now saved in
            // the Dynamo preferences. It is set to true by default. 
            // When the view is constructed, we enable or disable hardware acceleration based on that preference. 
            //This preference is not exposed in the UI and can be used to debug hardware issues only
            // by modifying the preferences xml.
            RenderOptions.ProcessRenderMode = dynamoViewModel.Model.PreferenceSettings.UseHardwareAcceleration ? 
                RenderMode.Default : RenderMode.SoftwareOnly;
            
            this.dynamoViewModel = dynamoViewModel;
            this.dynamoViewModel.UIDispatcher = Dispatcher;            
            nodeViewCustomizationLibrary = new NodeViewCustomizationLibrary(this.dynamoViewModel.Model.Logger);

            DataContext = dynamoViewModel;
            Title = dynamoViewModel.BrandingResourceProvider.GetString(ResourceNames.MainWindow.Title);

            tabSlidingWindowStart = tabSlidingWindowEnd = 0;

            _timer = new Stopwatch();
            _timer.Start();

            InitializeComponent();

            ToggleIsUsageReportingApprovedCommand.ToolTip = string.Format(
                Wpf.Properties.Resources.DynamoViewSettingMenuEnableDataReportingTooltip,
                dynamoViewModel.BrandingResourceProvider.ProductName);

            Loaded += DynamoView_Loaded;
            Unloaded += DynamoView_Unloaded;

            SizeChanged += DynamoView_SizeChanged;
            LocationChanged += DynamoView_LocationChanged;

            // Check that preference bounds are actually within one
            // of the available monitors.
            if (CheckVirtualScreenSize())
            {
                Left = dynamoViewModel.Model.PreferenceSettings.WindowX;
                Top = dynamoViewModel.Model.PreferenceSettings.WindowY;
                Width = dynamoViewModel.Model.PreferenceSettings.WindowW;
                Height = dynamoViewModel.Model.PreferenceSettings.WindowH;
            }
            else
            {
                Left = 0;
                Top = 0;
                Width = 1024;
                Height = 768;
            }

            _workspaceResizeTimer.Tick += _resizeTimer_Tick;

            if (dynamoViewModel.Model.AuthenticationManager.HasAuthProvider)
            {
                loginService = new LoginService(this, new System.Windows.Forms.WindowsFormsSynchronizationContext());
                dynamoViewModel.Model.AuthenticationManager.AuthProvider.RequestLogin += loginService.ShowLogin;
            }

            var viewExtensions = new List<IViewExtension>();
            foreach (var dir in dynamoViewModel.Model.PathManager.ViewExtensionsDirectories)
            {
                viewExtensions.AddRange(viewExtensionManager.ExtensionLoader.LoadDirectory(dir));
            }

            viewExtensionManager.MessageLogged += Log;

            var startupParams = new ViewStartupParams(dynamoViewModel);

            foreach (var ext in viewExtensions)
            {
                try
                {
                    var logSource = ext as ILogSource;
                    if (logSource != null)
                        logSource.MessageLogged += Log;

                    ext.Startup(startupParams);
                    viewExtensionManager.Add(ext);
                }
                catch (Exception exc)
                {
                    Log(ext.Name + ": " + exc.Message);
                }
            }

            this.dynamoViewModel.RequestPaste += OnRequestPaste;
            this.dynamoViewModel.RequestReturnFocusToView += OnRequestReturnFocusToView;
            FocusableGrid.InputBindings.Clear();
        }
Exemplo n.º 26
0
        /// <summary>
        /// Compiles this custom node definition, updating all UI instances to match
        /// inputs and outputs and registering new definition with the EngineController.
        /// </summary>
        public void Compile(DynamoModel dynamoModel, EngineController controller)
        {
            // If we are loading dyf file, dont compile it until all nodes are loaded
            // otherwise some intermediate function defintions will be created.
            // TODO: This is a hack, in reality we should be preventing this from being called at the Workspace.RequestSync() level --SJE
            if (IsBeingLoaded || IsProxy)
                return;

            #region Outputs and Inputs and UI updating

            #region Find outputs

            // Find output elements for the node
            List<Output> outputs = WorkspaceModel.Nodes.OfType<Output>().ToList();
 
            var topMost = new List<Tuple<int, NodeModel>>();

            List<string> outNames;

            // if we found output nodes, add select their inputs
            // these will serve as the function output
            if (outputs.Any())
            {
                topMost.AddRange(
                    outputs.Where(x => x.HasInput(0)).Select(x => Tuple.Create(0, x as NodeModel)));
                outNames = outputs.Select(x => x.Symbol).ToList();
            }
            else
            {
                outNames = new List<string>();

                // if there are no explicitly defined output nodes
                // get the top most nodes and set THEM as the output
                IEnumerable<NodeModel> topMostNodes = WorkspaceModel.GetTopMostNodes();

                var rtnPorts =
                    //Grab multiple returns from each node
                    topMostNodes.SelectMany(
                        topNode =>
                            //If the node is a recursive instance...
                            topNode is Function && (topNode as Function).Definition == this
                                // infinity output
                                ? new[] { new { portIndex = 0, node = topNode, name = "∞" } }
                                // otherwise, grab all ports with connected outputs and package necessary info
                                : topNode.OutPortData
                                    .Select(
                                        (port, i) =>
                                            new { portIndex = i, node = topNode, name = port.NickName })
                                    .Where(x => !topNode.HasOutput(x.portIndex)));

                foreach (var rtnAndIndex in rtnPorts.Select((rtn, i) => new { rtn, idx = i }))
                {
                    topMost.Add(Tuple.Create(rtnAndIndex.rtn.portIndex, rtnAndIndex.rtn.node));
                    outNames.Add(rtnAndIndex.rtn.name ?? rtnAndIndex.idx.ToString());
                }
            }

            var nameDict = new Dictionary<string, int>();
            foreach (var name in outNames)
            {
                if (nameDict.ContainsKey(name))
                    nameDict[name]++;
                else
                    nameDict[name] = 0;
            }

            nameDict = nameDict.Where(x => x.Value != 0).ToDictionary(x => x.Key, x => x.Value);

            outNames.Reverse();

            var keys = new List<string>();
            foreach (var name in outNames)
            {
                int amt;
                if (nameDict.TryGetValue(name, out amt))
                {
                    nameDict[name] = amt - 1;
                    keys.Add(name == "" ? amt + ">" : name + amt);
                }
                else
                    keys.Add(name);
            }

            keys.Reverse();

            ReturnKeys = keys;

            #endregion

            //Find function entry point, and then compile
            var inputNodes = WorkspaceModel.Nodes.OfType<Symbol>().ToList();
            var parameters = inputNodes.Select(x => x.GetAstIdentifierForOutputIndex(0).Value);
            Parameters = inputNodes.Select(x => x.InputSymbol);

            //Update existing function nodes which point to this function to match its changes
            var customNodeInstances = dynamoModel.AllNodes
                        .OfType<Function>()
                        .Where(el => el.Definition != null && el.Definition == this);
            
            foreach (var node in customNodeInstances)
                node.ResyncWithDefinition();

            //Call OnSave for all saved elements
            foreach (var node in WorkspaceModel.Nodes)
                node.OnSave();

            #endregion

            var outputNodes = topMost.Select((x) =>
            {
                var n = x.Item2.GetAstIdentifierForOutputIndex(x.Item1);
                return n as AssociativeNode;
            });

            controller.GenerateGraphSyncDataForCustomNode(
                this,
                WorkspaceModel.Nodes.Where(x => !(x is Symbol)),
                outputNodes,
                parameters);

            // Not update graph until Run 
            // if (success)
            //    controller.UpdateGraph();
        }
Exemplo n.º 27
0
        internal override IEnumerable<AssociativeNode> BuildAst(List<AssociativeNode> inputAstNodes, AstBuilder.CompilationContext context)
        {
            //Do not build if the node is in error.
            if (State == ElementState.Error)
            {
                return Enumerable.Empty<AssociativeNode>();
            }

            var resultNodes = new List<AssociativeNode>();

            // Define unbound variables if necessary
            if (inputIdentifiers != null &&
                inputAstNodes != null &&
                inputIdentifiers.Count == inputAstNodes.Count)
            {
                var initStatments = inputIdentifiers.Zip(inputAstNodes,
                    (ident, rhs) =>
                    {
                        var identNode = AstFactory.BuildIdentifier(ident);
                        if (context != AstBuilder.CompilationContext.NodeToCode)
                            MapIdentifiers(identNode);
                        return AstFactory.BuildAssignment(identNode, rhs);
                    });
                resultNodes.AddRange(initStatments);
            }

            foreach (var astNode in codeStatements.Select(stmnt => NodeUtils.Clone(stmnt.AstNode)))
            {
                if (context != AstBuilder.CompilationContext.NodeToCode)
                    MapIdentifiers(astNode);
                resultNodes.Add(astNode as AssociativeNode);
            }

            return resultNodes;
        }
Exemplo n.º 28
0
        //public override void Evaluate(FSharpList<FScheme.Value> args, Dictionary<PortData, FScheme.Value> outPuts)
        //{
        //    if (OutPortData.Count > 1)
        //    {
        //        var query = (Evaluate(args) as FScheme.Value.List).Item.Zip(
        //            OutPortData,
        //            (value, data) => new { value, data });

        //        foreach (var result in query)
        //            outPuts[result.data] = result.value;
        //    }
        //    else
        //        base.Evaluate(args, outPuts);
        //}

        //public override FScheme.Value Evaluate(FSharpList<FScheme.Value> args)
        //{
        //    //return ((FScheme.Value.Function)Controller.FSchemeEnvironment.LookupSymbol(Symbol))
        //    //    .Item.Invoke(args);

        //    throw new NotImplementedException("FSchemeEnvironment has been removed.");
        //}

        internal override IEnumerable<AssociativeNode> BuildAst(List<AssociativeNode> inputAstNodes)
        {
            var resultAst = new List<AssociativeNode>();

            if (OutPortData.Count == 1)
            {
                if (IsPartiallyApplied)
                {
                    var count = Definition.Parameters.Count();
                    AssociativeNode functionCall = AstFactory.BuildFunctionObject(
                        Definition.FunctionName,
                        count,
                        Enumerable.Range(0, count).Where(HasInput),
                        inputAstNodes);
                    resultAst.Add(AstFactory.BuildAssignment(AstIdentifierForPreview, functionCall));
                    resultAst.Add(
                        AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), AstIdentifierForPreview));
                }
                else
                {
                    AssociativeNode functionCall = AstFactory.BuildFunctionCall(
                        Definition.FunctionName,
                        inputAstNodes);

                    resultAst.Add(AstFactory.BuildAssignment(AstIdentifierForPreview, functionCall));

                    // assign the entire result to the only output port

                    var outId = GetAstIdentifierForOutputIndex(0);

                    if (AstIdentifierForPreview.Value != outId.Value)
                        resultAst.Add(AstFactory.BuildAssignment(outId, AstIdentifierForPreview));
                }
            }
            else
            {
                AssociativeNode functionCall = AstFactory.BuildFunctionCall(
                    Definition.FunctionName,
                    inputAstNodes);
                resultAst.Add(AstFactory.BuildAssignment(AstIdentifierForPreview, functionCall));

                /* previewId = customNodeFunc(arg0, arg1 ...);
                 * outId0 = previewId[key0];
                 * outId1 = previewId[key1];
                 * ...
                 */

                // indexers for each output
                IEnumerable<AssociativeNode> indexers = Definition.ReturnKeys != null
                    ? Definition.ReturnKeys.Select(AstFactory.BuildStringNode) as IEnumerable<AssociativeNode>
                    : Enumerable.Range(0, OutPortData.Count).Select(AstFactory.BuildIntNode);

                // for each output, pull the output from the result
                // based on the associated return key and assign to
                // corresponding output identifier
                resultAst.AddRange(
                    indexers.Select(
                        (rtnKey, index) =>
                            AstFactory.BuildAssignment(
                                GetAstIdentifierForOutputIndex(index),
                                AstFactory.BuildIdentifier(AstIdentifierForPreview.Name, rtnKey))));
            }

            return resultAst;
        }
Exemplo n.º 29
0
        /// <summary>
        ///     Collapse a set of nodes in a given workspace.
        /// </summary>
        /// <param name="selectedNodes"> The function definition for the user-defined node </param>
        /// <param name="currentWorkspace"> The workspace where</param>
        /// <param name="isTestMode"></param>
        /// <param name="args"></param>
        public CustomNodeWorkspaceModel Collapse(
            IEnumerable<NodeModel> selectedNodes, WorkspaceModel currentWorkspace,
            bool isTestMode, FunctionNamePromptEventArgs args)
        {
            var selectedNodeSet = new HashSet<NodeModel>(selectedNodes);
            // Note that undoable actions are only recorded for the "currentWorkspace", 
            // the nodes which get moved into "newNodeWorkspace" are not recorded for undo,
            // even in the new workspace. Their creations will simply be treated as part of
            // the opening of that new workspace (i.e. when a user opens a file, she will 
            // not expect the nodes that show up to be undoable).
            // 
            // After local nodes are moved into "newNodeWorkspace" as the result of 
            // conversion, if user performs an undo, new set of nodes will be created in 
            // "currentWorkspace" (not moving those nodes in the "newNodeWorkspace" back 
            // into "currentWorkspace"). In another word, undo recording is on a per-
            // workspace basis, it does not work across different workspaces.
            // 
            UndoRedoRecorder undoRecorder = currentWorkspace.UndoRecorder;

            CustomNodeWorkspaceModel newWorkspace;

            using (undoRecorder.BeginActionGroup())
            {
                #region Determine Inputs and Outputs

                //Step 1: determine which nodes will be inputs to the new node
                var inputs =
                    new HashSet<Tuple<NodeModel, int, Tuple<int, NodeModel>>>(
                        selectedNodeSet.SelectMany(
                            node =>
                                Enumerable.Range(0, node.InPortData.Count)
                                .Where(node.HasConnectedInput)
                                .Select(data => Tuple.Create(node, data, node.InputNodes[data]))
                                .Where(input => !selectedNodeSet.Contains(input.Item3.Item2))));

                var outputs =
                    new HashSet<Tuple<NodeModel, int, Tuple<int, NodeModel>>>(
                        selectedNodeSet.SelectMany(
                            node =>
                                Enumerable.Range(0, node.OutPortData.Count)
                                .Where(node.HasOutput)
                                .SelectMany(
                                    data =>
                                        node.OutputNodes[data].Where(
                                            output => !selectedNodeSet.Contains(output.Item2))
                                        .Select(output => Tuple.Create(node, data, output)))));

                #endregion

                #region Detect 1-node holes (higher-order function extraction)

                Log(Properties.Resources.CouldNotRepairOneNodeHoles, WarningLevel.Mild);
                // http://adsk-oss.myjetbrains.com/youtrack/issue/MAGN-5603

                //var curriedNodeArgs =
                //    new HashSet<NodeModel>(
                //        inputs.Select(x => x.Item3.Item2)
                //            .Intersect(outputs.Select(x => x.Item3.Item2))).Select(
                //                outerNode =>
                //                {
                //                    //var node = new Apply1();
                //                    var node = newNodeWorkspace.AddNode<Apply1>();
                //                    node.SetNickNameFromAttribute();

                //                    node.DisableReporting();

                //                    node.X = outerNode.X;
                //                    node.Y = outerNode.Y;

                //                    //Fetch all input ports
                //                    // in order
                //                    // that have inputs
                //                    // and whose input comes from an inner node
                //                    List<int> inPortsConnected =
                //                        Enumerable.Range(0, outerNode.InPortData.Count)
                //                            .Where(
                //                                x =>
                //                                    outerNode.HasInput(x)
                //                                        && selectedNodeSet.Contains(
                //                                            outerNode.Inputs[x].Item2))
                //                            .ToList();

                //                    var nodeInputs =
                //                        outputs.Where(output => output.Item3.Item2 == outerNode)
                //                            .Select(
                //                                output =>
                //                                    new
                //                                    {
                //                                        InnerNodeInputSender = output.Item1,
                //                                        OuterNodeInPortData = output.Item3.Item1
                //                                    })
                //                            .ToList();

                //                    nodeInputs.ForEach(_ => node.AddInput());

                //                    node.RegisterAllPorts();

                //                    return
                //                        new
                //                        {
                //                            OuterNode = outerNode,
                //                            InnerNode = node,
                //                            Outputs =
                //                                inputs.Where(
                //                                    input => input.Item3.Item2 == outerNode)
                //                                    .Select(input => input.Item3.Item1),
                //                            Inputs = nodeInputs,
                //                            OuterNodePortDataList = inPortsConnected
                //                        };
                //                }).ToList();

                #endregion

                #region UI Positioning Calculations

                double avgX = selectedNodeSet.Average(node => node.X);
                double avgY = selectedNodeSet.Average(node => node.Y);

                double leftMost = selectedNodeSet.Min(node => node.X);
                double topMost = selectedNodeSet.Min(node => node.Y);
                double rightMost = selectedNodeSet.Max(node => node.X + node.Width);

                double leftShift = leftMost - 250;

                #endregion

                #region Handle full selected connectors

                // Step 2: Determine all the connectors whose start/end owners are 
                // both in the selection set, and then move them from the current 
                // workspace into the new workspace.

                var fullySelectedConns = new HashSet<ConnectorModel>(
                    currentWorkspace.Connectors.Where(
                        conn =>
                        {
                            bool startSelected = selectedNodeSet.Contains(conn.Start.Owner);
                            bool endSelected = selectedNodeSet.Contains(conn.End.Owner);
                            return startSelected && endSelected;
                        }));

                foreach (var connector in fullySelectedConns)
                {
                    undoRecorder.RecordDeletionForUndo(connector);
                    connector.Delete();
                }

                #endregion

                #region Handle partially selected connectors

                // Step 3: Partially selected connectors (either one of its start 
                // and end owners is in the selection) are to be destroyed.

                var partiallySelectedConns =
                    currentWorkspace.Connectors.Where(
                        conn =>
                            selectedNodeSet.Contains(conn.Start.Owner)
                                || selectedNodeSet.Contains(conn.End.Owner)).ToList();

                foreach (var connector in partiallySelectedConns)
                {
                    undoRecorder.RecordDeletionForUndo(connector);
                    connector.Delete();
                }

                #endregion

                #region Transfer nodes and connectors to new workspace

                var newNodes = new List<NodeModel>();
                var newAnnotations = new List<AnnotationModel>();
            
                // Step 4: move all nodes to new workspace remove from old
                // PB: This could be more efficiently handled by a copy paste, but we
                // are preservering the node 
                foreach (var node in selectedNodeSet)
                {                   
                    undoRecorder.RecordDeletionForUndo(node);
                    currentWorkspace.RemoveNode(node);

                    // Assign a new guid to this node, otherwise when node is
                    // compiled to AST, literally it is still in global scope
                    // instead of in function scope.
                    node.GUID = Guid.NewGuid();
                    node.RenderPackages.Clear();

                    // shift nodes
                    node.X = node.X - leftShift;
                    node.Y = node.Y - topMost;
                 
                    newNodes.Add(node);
                }

                //Copy the group from newNodes
                foreach (var group in DynamoSelection.Instance.Selection.OfType<AnnotationModel>())
                {
                    undoRecorder.RecordDeletionForUndo(group);
                    currentWorkspace.RemoveGroup(group);

                    group.GUID = Guid.NewGuid();
                    group.SelectedModels = group.DeletedModelBases;
                    newAnnotations.Add(group);
                }


                foreach (var conn in fullySelectedConns)
                {
                    ConnectorModel.Make(conn.Start.Owner, conn.End.Owner, conn.Start.Index, conn.End.Index);
                }

                #endregion

                #region Process inputs

                var inConnectors = new List<Tuple<NodeModel, int>>();
                var uniqueInputSenders = new Dictionary<Tuple<NodeModel, int>, Symbol>();

                //Step 3: insert variables (reference step 1)
                foreach (var input in Enumerable.Range(0, inputs.Count).Zip(inputs, Tuple.Create))
                {
                    int inputIndex = input.Item1;

                    NodeModel inputReceiverNode = input.Item2.Item1;
                    int inputReceiverData = input.Item2.Item2;

                    NodeModel inputNode = input.Item2.Item3.Item2;
                    int inputData = input.Item2.Item3.Item1;

                    Symbol node;

                    var key = Tuple.Create(inputNode, inputData);
                    if (uniqueInputSenders.ContainsKey(key))
                    {
                        node = uniqueInputSenders[key];
                    }
                    else
                    {
                        inConnectors.Add(Tuple.Create(inputNode, inputData));

                        node = new Symbol
                        {
                            InputSymbol = inputReceiverNode.InPortData[inputReceiverData].NickName,
                            X = 0
                        };

                        // Try to figure out the type of input of custom node 
                        // from the type of input of selected node. There are
                        // two kinds of nodes whose input type are available:
                        // function node and custom node. 
                        List<Library.TypedParameter> parameters = null;

                        if (inputReceiverNode is Function) 
                        {
                            var func = inputReceiverNode as Function; 
                            parameters =  func.Controller.Definition.Parameters.ToList(); 
                        }
                        else if (inputReceiverNode is DSFunctionBase)
                        {
                            var dsFunc = inputReceiverNode as DSFunctionBase;
                            var funcDesc = dsFunc.Controller.Definition;
                            parameters = funcDesc.Parameters.ToList();

                            if (funcDesc.Type == DSEngine.FunctionType.InstanceMethod ||
                                funcDesc.Type == DSEngine.FunctionType.InstanceProperty)
                            {
                                var dummyType = new ProtoCore.Type() { Name = funcDesc.ClassName };
                                var instanceParam = new TypedParameter(funcDesc.ClassName, dummyType);
                                parameters.Insert(0, instanceParam);
                            }
                        }

                        // so the input of custom node has format 
                        //    input_var_name : type
                        if (parameters != null && parameters.Count() > inputReceiverData)
                        {
                            var typeName = parameters[inputReceiverData].DisplayTypeName;
                            if (!string.IsNullOrEmpty(typeName))
                            {
                                node.InputSymbol += " : " + typeName;
                            }
                        }

                        node.SetNickNameFromAttribute();
                        node.Y = inputIndex*(50 + node.Height);

                        uniqueInputSenders[key] = node;

                        newNodes.Add(node);
                    }

                    //var curriedNode = curriedNodeArgs.FirstOrDefault(x => x.OuterNode == inputNode);

                    //if (curriedNode == null)
                    //{
                    ConnectorModel.Make(node, inputReceiverNode, 0, inputReceiverData);
                    //}
                    //else
                    //{
                    //    //Connect it to the applier
                    //    newNodeWorkspace.AddConnection(node, curriedNode.InnerNode, 0, 0);

                    //    //Connect applier to the inner input receive
                    //    newNodeWorkspace.AddConnection(
                    //        curriedNode.InnerNode,
                    //        inputReceiverNode,
                    //        0,
                    //        inputReceiverData);
                    //}
                }

                #endregion

                #region Process outputs

                //List of all inner nodes to connect an output. Unique.
                var outportList = new List<Tuple<NodeModel, int>>();

                var outConnectors = new List<Tuple<NodeModel, int, int>>();

                int i = 0;
                if (outputs.Any())
                {
                    foreach (var output in outputs)
                    {
                        if (outportList.All(x => !(x.Item1 == output.Item1 && x.Item2 == output.Item2)))
                        {
                            NodeModel outputSenderNode = output.Item1;
                            int outputSenderData = output.Item2;

                            //NodeModel outputReceiverNode = output.Item3.Item2;

                            //if (curriedNodeArgs.Any(x => x.OuterNode == outputReceiverNode))
                            //    continue;

                            outportList.Add(Tuple.Create(outputSenderNode, outputSenderData));

                            //Create Symbol Node
                            var node = new Output
                            {
                                Symbol = outputSenderNode.OutPortData[outputSenderData].NickName,
                                X = rightMost + 75 - leftShift
                            };

                            node.Y = i*(50 + node.Height);

                            node.SetNickNameFromAttribute();

                            newNodes.Add(node);
                            ConnectorModel.Make(outputSenderNode, node, outputSenderData, 0);

                            i++;
                        }
                    }

                    //Connect outputs to new node
                    outConnectors.AddRange(
                        from output in outputs
                        let outputSenderNode = output.Item1
                        let outputSenderData = output.Item2
                        let outputReceiverData = output.Item3.Item1
                        let outputReceiverNode = output.Item3.Item2
                        select
                            Tuple.Create(
                                outputReceiverNode,
                                outportList.FindIndex(
                                    x => x.Item1 == outputSenderNode && x.Item2 == outputSenderData),
                                outputReceiverData));
                }
                else
                {
                    foreach (var hanging in
                        selectedNodeSet.SelectMany(
                            node =>
                                Enumerable.Range(0, node.OutPortData.Count)
                                .Where(port => !node.HasOutput(port))
                                .Select(port => new { node, port })).Distinct())
                    {
                        //Create Symbol Node
                        var node = new Output
                        {
                            Symbol = hanging.node.OutPortData[hanging.port].NickName,
                            X = rightMost + 75 - leftShift
                        };
                        node.Y = i*(50 + node.Height);
                        node.SetNickNameFromAttribute();

                        newNodes.Add(node);
                        ConnectorModel.Make(hanging.node, node, hanging.port, 0);

                        i++;
                    }
                }

                #endregion

                var newId = Guid.NewGuid();
                newWorkspace = new CustomNodeWorkspaceModel(
                    nodeFactory,
                    newNodes,
                    Enumerable.Empty<NoteModel>(),
                    newAnnotations,
                    Enumerable.Empty<PresetModel>(),
                    new WorkspaceInfo()
                    {
                        X = 0,
                        Y = 0,
                        Name = args.Name,
                        Category = args.Category,
                        Description = args.Description,
                        ID = newId.ToString(),
                        FileName = string.Empty
                    },
                    currentWorkspace.ElementResolver);
                
                newWorkspace.HasUnsavedChanges = true;

                RegisterCustomNodeWorkspace(newWorkspace);

                var collapsedNode = CreateCustomNodeInstance(newId, isTestMode: isTestMode);
                collapsedNode.X = avgX;
                collapsedNode.Y = avgY;
                currentWorkspace.AddNode(collapsedNode, centered: false);
                undoRecorder.RecordCreationForUndo(collapsedNode);

                foreach (var connector in
                    inConnectors.Select((x, idx) => new { node = x.Item1, from = x.Item2, to = idx })
                        .Select(
                            nodeTuple =>
                                ConnectorModel.Make(
                                    nodeTuple.node,
                                    collapsedNode,
                                    nodeTuple.@from,
                                    nodeTuple.to))
                        .Where(connector => connector != null))
                {
                    undoRecorder.RecordCreationForUndo(connector);
                }

                foreach (var connector in
                    outConnectors.Select(
                        nodeTuple =>
                            ConnectorModel.Make(
                                collapsedNode,
                                nodeTuple.Item1,
                                nodeTuple.Item2,
                                nodeTuple.Item3)).Where(connector => connector != null))
                {
                    undoRecorder.RecordCreationForUndo(connector);
                }
            }
            return newWorkspace;
        }
Exemplo n.º 30
0
        /// <summary>
        /// Gathers the Ids of the upstream drawable nodes.
        /// </summary>
        /// <param name="inputs">A dictionary describing the inputs on the node.</param>
        /// <returns>A collection of strings.</returns>
        private IEnumerable<IRenderPackage> GetUpstreamPackages(Dictionary<int, Tuple<int, NodeModel>> inputs, 
            int recursionLevelCount)
        {
#if DEBUG
            const int MAX_RECURSION = 200;
            Validity.Assert(recursionLevelCount < MAX_RECURSION, "Stack Overflow protection trap");
#endif

            var packages = new List<IRenderPackage>();

            foreach (KeyValuePair<int, Tuple<int, NodeModel>> pair in inputs)
            {
                if (pair.Value == null)
                    continue;

                NodeModel node = pair.Value.Item2;

                //We no longer depend on OldValue, as long as the given node has
                //registered it's render description with Visualization manager
                //we will be able to visualize the given node. -Sharad
                if (node != null)
                {
                    lock (node.RenderPackagesMutex)
                    {
                        packages.AddRange(node.RenderPackages);
                    }
                }

                if (node.IsUpstreamVisible)
                    packages.AddRange(GetUpstreamPackages(node.Inputs, recursionLevelCount + 1));
            }

            return packages;
        }