Exemplo n.º 1
0
        protected AssociativeNode CreateOutputAST(
            AssociativeNode codeInputNode, List<AssociativeNode> inputAstNodes,
            List<Tuple<string, AssociativeNode>> additionalBindings)
        {
            var names =
                additionalBindings.Select(
                    x => AstFactory.BuildStringNode(x.Item1) as AssociativeNode).ToList();
            names.Add(AstFactory.BuildStringNode("IN"));

            var vals = additionalBindings.Select(x => x.Item2).ToList();
            vals.Add(AstFactory.BuildExprList(inputAstNodes));

            Func<string, IList, IList, object> backendMethod =
                IronPythonEvaluator.EvaluateIronPythonScript;

            return AstFactory.BuildAssignment(
                GetAstIdentifierForOutputIndex(0),
                AstFactory.BuildFunctionCall(
                    backendMethod,
                    new List<AssociativeNode>
                    {
                        codeInputNode,
                        AstFactory.BuildExprList(names),
                        AstFactory.BuildExprList(vals)
                    }));
        }
Exemplo n.º 2
0
        void mi_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            if (AllElements.Count == 0)
                return;

            //select the elements
            dynRevitSettings.Doc.Selection.Elements.Clear();

            var existingElements = new List<Element>();

            foreach (var id in AllElements)
            {
                Element el;
                if (dynUtils.TryGetElement(id, typeof (Element), out el))
                {
                    existingElements.Add(el);
                }
            }

            existingElements.ForEach(x => dynRevitSettings.Doc.Selection.Elements.Add(x));

            //show the elements
            dynRevitSettings.Doc.ShowElements(existingElements.Select(x => x.Id).ToList());
        }
Exemplo n.º 3
0
        private IEnumerable<PackageDependency> GetAllDependencies()
        {
            var pmExtension = dynamoViewModel.Model.GetPackageManagerExtension();
            var pkgLoader = pmExtension.PackageLoader;

            // all workspaces
            var workspaces = new List<CustomNodeWorkspaceModel>();
            foreach (var def in AllDependentFuncDefs())
            {
                CustomNodeWorkspaceModel ws;
                if (dynamoViewModel.Model.CustomNodeManager.TryGetFunctionWorkspace(
                    def.FunctionId,
                    DynamoModel.IsTestMode,
                    out ws))
                {
                    workspaces.Add(ws);
                }
            }

            // get all of dependencies from custom nodes and additional files
            var allFilePackages =
                workspaces
                    .Select(x => x.FileName)
                    .Union(AdditionalFiles)
                    .Where(pkgLoader.IsUnderPackageControl)
                    .Select(pkgLoader.GetOwnerPackage)
                    .Where(x => x != null)
                    .Where(x => (x.Name != Name))
                    .Distinct()
                    .Select(x => new PackageDependency(x.Name, x.VersionName));

            workspaces = new List<CustomNodeWorkspaceModel>();
            foreach (var def in AllFuncDefs())
            {
                CustomNodeWorkspaceModel ws;
                if (dynamoViewModel.Model.CustomNodeManager.TryGetFunctionWorkspace(
                    def.FunctionId,
                    DynamoModel.IsTestMode,
                    out ws))
                {
                    workspaces.Add(ws);
                }
            }

            // get all of the dependencies from types
            var allTypePackages = workspaces
                .SelectMany(x => x.Nodes)
                .Select(x => x.GetType())
                .Where(pkgLoader.IsUnderPackageControl)
                .Select(pkgLoader.GetOwnerPackage)
                .Where(x => x != null)
                .Where(x => (x.Name != Name))
                .Distinct()
                .Select(x => new PackageDependency(x.Name, x.VersionName));

            var dsFunctionPackages = workspaces
                .SelectMany(x => x.Nodes)
                .OfType<DSFunctionBase>()
                .Select(x => x.Controller.Definition.Assembly)
                .Where(pkgLoader.IsUnderPackageControl)
                .Select(pkgLoader.GetOwnerPackage)
                .Where(x => x != null)
                .Where(x => (x.Name != Name))
                .Distinct()
                .Select(x => new PackageDependency(x.Name, x.VersionName));

            return allFilePackages.Union(allTypePackages).Union(dsFunctionPackages);

        }
Exemplo n.º 4
0
        private IEnumerable<string> GetAllFiles()
        {
            // get all function defs
            var allFuncs = AllFuncDefs().ToList();

            // all workspaces
            var workspaces = new List<CustomNodeWorkspaceModel>();
            foreach (var def in allFuncs)
            {
                CustomNodeWorkspaceModel ws;
                if (dynamoViewModel.Model.CustomNodeManager.TryGetFunctionWorkspace(
                    def.FunctionId,
                    DynamoModel.IsTestMode,
                    out ws))
                {
                    workspaces.Add(ws);
                }
            }
            
            // make sure workspaces are saved
            var unsavedWorkspaceNames =
                workspaces.Where(ws => ws.HasUnsavedChanges || ws.FileName == null).Select(ws => ws.Name).ToList();
            if (unsavedWorkspaceNames.Any())
            {
                throw new Exception(Wpf.Properties.Resources.MessageUnsavedChanges0 +
                                    String.Join(", ", unsavedWorkspaceNames) +
                                    Wpf.Properties.Resources.MessageUnsavedChanges1);
            }

            var pmExtension = dynamoViewModel.Model.GetPackageManagerExtension();
            // omit files currently already under package control
            var files =
                workspaces.Select(f => f.FileName)
                    .Where(
                        p =>
                            (pmExtension.PackageLoader.IsUnderPackageControl(p)
                                && (pmExtension.PackageLoader.GetOwnerPackage(p).Name == Name)
                                || !pmExtension.PackageLoader.IsUnderPackageControl(p)));

            // union with additional files
            files = files.Union(AdditionalFiles);
            files = files.Union(Assemblies.Select(x => x.Assembly.Location));

            return files;
        }
Exemplo n.º 5
0
        /// <summary>
        ///     Get a dynFunction from a guid, also stores type internally info for future instantiation.
        ///     And add the compiled node to the enviro
        ///     As a side effect, any of its dependent nodes are also initialized.
        /// </summary>
        /// <param name="environment">The environment from which to get the </param>
        /// <param name="guid">Open a definition from a path, without instantiating the nodes or dependents</param>
        public bool GetNodeInstance(DynamoController controller, Guid guid, out dynFunction result)
        {
            if ( !this.Contains(guid) ) {
                result = null;
                return false;
            }

            FunctionDefinition def = null;
            if (!this.IsInitialized(guid))
            {
                if (!GetDefinitionFromPath(guid, controller, out def))
                {
                    result = null;
                    return false;
                }
            } else {
                def = this.loadedNodes[guid];
            }

            dynWorkspace ws = def.Workspace;

            //TODO: Update to base off of Definition

                IEnumerable<string> inputs =
                    ws.Nodes.Where(e => e is dynSymbol)
                        .Select(s => (s as dynSymbol).Symbol);

                IEnumerable<string> outputs =
                    ws.Nodes.Where(e => e is dynOutput)
                        .Select(o => (o as dynOutput).Symbol);

                if (!outputs.Any())
                {
                    var topMost = new List<Tuple<int, dynNode>>();

                    IEnumerable<dynNode> topMostNodes = ws.GetTopMostNodes();

                    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));
                        }
                    }

                    outputs = topMost.Select(x => x.Item2.OutPortData[x.Item1].NickName);
                }

            result = new dynFunction(inputs, outputs, def);
            result.NodeUI.NickName = ws.Name;

            return true;
        }
Exemplo n.º 6
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.º 7
0
        /// <summary>
        ///     Collapse a set of nodes in a given workspace.
        /// </summary>
        /// <param name="dynamoModel">The current DynamoModel</param>
        /// <param name="selectedNodes"> The function definition for the user-defined node </param>
        /// <param name="currentWorkspace"> The workspace where</param>
        /// <param name="args"></param>
        public static void Collapse(DynamoModel dynamoModel, IEnumerable<NodeModel> selectedNodes, WorkspaceModel currentWorkspace, FunctionNamePromptEventArgs args = null)
        {
            var selectedNodeSet = new HashSet<NodeModel>(selectedNodes);

            if (args == null || !args.Success)
            {
                args = new FunctionNamePromptEventArgs();
                dynamoModel.OnRequestsFunctionNamePrompt(null, args);

                
                if (!args.Success)
                {
                    return;
                }
            }

            // 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;
            using (undoRecorder.BeginActionGroup())
            {

                var newNodeWorkspace = new CustomNodeWorkspaceModel(
                    dynamoModel,
                    args.Name,
                    args.Category,
                    args.Description,
                    0,
                    0) { WatchChanges = false, HasUnsavedChanges = true };

                var newNodeDefinition = new CustomNodeDefinition(Guid.NewGuid())
                {
                    WorkspaceModel = newNodeWorkspace
                };

                currentWorkspace.DisableReporting();

                #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.Inputs[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.Outputs[data].Where(
                                            output => !selectedNodeSet.Contains(output.Item2))
                                        .Select(output => Tuple.Create(node, data, output)))));

                #endregion

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

                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);

                #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 ele in fullySelectedConns)
                {
                    undoRecorder.RecordDeletionForUndo(ele);
                    currentWorkspace.Connectors.Remove(ele);
                }

                #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 (ConnectorModel connector in partiallySelectedConns)
                {
                    undoRecorder.RecordDeletionForUndo(connector);
                    connector.NotifyConnectedPortsOfDeletion();
                    currentWorkspace.Connectors.Remove(connector);
                }

                #endregion

                #region Transfer nodes and connectors to new workspace

                // 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 ele in selectedNodeSet)
                {
                    undoRecorder.RecordDeletionForUndo(ele);
                    ele.SaveResult = false;
                    currentWorkspace.Nodes.Remove(ele);
                    ele.Workspace = newNodeWorkspace;
                }

                //  add to new
                newNodeWorkspace.Nodes.AddRange(selectedNodeSet);
                newNodeWorkspace.Connectors.AddRange(fullySelectedConns);

                foreach (var node in newNodeWorkspace.Nodes)
                    node.DisableReporting();

                double leftShift = leftMost - 250;
                foreach (NodeModel node in newNodeWorkspace.Nodes)
                {
                    node.X = node.X - leftShift;
                    node.Y = node.Y - topMost;
                }

                #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 = newNodeWorkspace.AddNode<Symbol>();
                        node.InputSymbol = inputReceiverNode.InPortData[inputReceiverData].NickName;

                        node.SetNickNameFromAttribute();

                        node.DisableReporting();

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

                        uniqueInputSenders[key] = node;
                    }

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

                    if (curriedNode == null)
                    {
                        newNodeWorkspace.AddConnection(
                            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 = newNodeWorkspace.AddNode<Output>();
                            node.Symbol = outputSenderNode.OutPortData[outputSenderData].NickName;

                            node.SetNickNameFromAttribute();
                            node.DisableReporting();

                            node.X = rightMost + 75 - leftShift;
                            node.Y = i*(50 + node.Height);

                            newNodeWorkspace.AddConnection(
                                outputSenderNode,
                                node,
                                outputSenderData,
                                0);

                            i++;
                        }
                    }

                    //Connect outputs to new node
                    foreach (var output in outputs)
                    {
                        //Node to be connected to in CurrentWorkspace
                        NodeModel outputSenderNode = output.Item1;

                        //Port to be connected to on outPutNode_outer
                        int outputSenderData = output.Item2;

                        int outputReceiverData = output.Item3.Item1;
                        NodeModel outputReceiverNode = output.Item3.Item2;

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

                        if (curriedNode == null)
                        {
                            // we create the connectors in the current space later
                            outConnectors.Add(
                                Tuple.Create(
                                    outputReceiverNode,
                                    outportList.FindIndex(
                                        x =>
                                            x.Item1 == outputSenderNode
                                                && x.Item2 == outputSenderData),
                                    outputReceiverData));
                        }
                        else
                        {
                            int targetPort =
                                curriedNode.Inputs.First(
                                    x => x.InnerNodeInputSender == outputSenderNode)
                                    .OuterNodeInPortData;

                            int targetPortIndex =
                                curriedNode.OuterNodePortDataList.IndexOf(targetPort);

                            //Connect it (new dynConnector)
                            newNodeWorkspace.AddConnection(
                                outputSenderNode,
                                curriedNode.InnerNode,
                                outputSenderData,
                                targetPortIndex + 1);

                        }
                    }
                }
                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 = newNodeWorkspace.AddNode<Output>();
                        node.Symbol = hanging.node.OutPortData[hanging.port].NickName;

                        node.SetNickNameFromAttribute();

                        //store the element in the elements list
                        node.DisableReporting();

                        node.X = rightMost + 75 - leftShift;
                        node.Y = i*(50 + node.Height);

                        newNodeWorkspace.AddConnection(hanging.node, node, hanging.port, 0);

                        i++;
                    }
                }

                #endregion

                // save and load the definition from file
                newNodeDefinition.SyncWithWorkspace(dynamoModel, true, true);
                dynamoModel.Workspaces.Add(newNodeWorkspace);

                string name = newNodeDefinition.FunctionId.ToString();
                var collapsedNode = currentWorkspace.AddNode(avgX, avgY, name);
                undoRecorder.RecordCreationForUndo(collapsedNode);

                // place the node as intended, not centered
                collapsedNode.X = avgX;
                collapsedNode.Y = avgY;

                collapsedNode.DisableReporting();

                foreach (
                    var nodeTuple in
                        inConnectors.Select(
                            (x, idx) => new { node = x.Item1, from = x.Item2, to = idx }))
                {
                    var conn = currentWorkspace.AddConnection(
                        nodeTuple.node,
                        collapsedNode,
                        nodeTuple.from,
                        nodeTuple.to);

                    if (conn != null)
                    {
                        undoRecorder.RecordCreationForUndo(conn);
                    }
                }

                foreach (var nodeTuple in outConnectors)
                {

                    var conn = currentWorkspace.AddConnection(
                        collapsedNode,
                        nodeTuple.Item1,
                        nodeTuple.Item2,
                        nodeTuple.Item3);

                    if (conn != null)
                    {
                        undoRecorder.RecordCreationForUndo(conn);
                    }
                }

                collapsedNode.EnableReporting();
                currentWorkspace.EnableReporting();

                foreach (var node in newNodeWorkspace.Nodes)
                    node.EnableReporting();

                newNodeWorkspace.WatchChanges = true;
            }
        }
        public static Dictionary<string, object> ExportZonesToGBXML(string FilePath, List<ElementId> ZoneIds, Boolean Run = false)
        {
            Boolean IsSuccess = false;

            string FileName = Path.GetFileNameWithoutExtension(FilePath);
            string Folder = Path.GetDirectoryName(FilePath);

            //make RUN? inputs set to True mandatory
            if (Run == false)
            {
                throw new Exception("Set 'Connect' to True!");
            }

            //local varaibles
            Document RvtDoc = DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument.Document;

            //enable the analytical model in the document if it isn't already
            try
            {
                PrepareEnergyModel.ActivateEnergyModel(RvtDoc);
            }
            catch (Exception)
            {
                throw new Exception("Something went wrong when trying to enable the energy model.");
            }

            //convert the ElementId wrapper instances to actual Revit ElementId objects
            List<Autodesk.Revit.DB.ElementId> outZoneIds = ZoneIds.Select(e => new Autodesk.Revit.DB.ElementId(e.InternalId)).ToList();

            // Create gbXML
            MassGBXMLExportOptions gbXmlExportOptions = new MassGBXMLExportOptions(outZoneIds);

            RvtDoc.Export(Folder, FileName, gbXmlExportOptions);


            // if the file exists return success message if not return failed message
            string path = Path.Combine(Folder, FileName + ".xml");

            if (System.IO.File.Exists(path))
            {
                // Modify the xml Program Info element, aithorize the
                XmlDocument doc = new XmlDocument();
                doc.Load(path);

                // EE: There must be a shorter way !
                XmlNode node = doc.DocumentElement;
                foreach (XmlNode node1 in node.ChildNodes)
                {
                    foreach (XmlNode node2 in node1.ChildNodes)
                    {
                        if (node2.Name == "ProgramInfo")
                        {
                            foreach (XmlNode childnode in node2.ChildNodes)
                            {
                                if (childnode.Name == "ProductName")
                                {
                                    string productname = "Dynamo _ " + childnode.InnerText;
                                    childnode.InnerText = productname;
                                }
                            }
                        }
                    }
                }

                doc.Save(path);

                IsSuccess = true;
            }
            string message = "Failed to create gbXML file!";

            if (IsSuccess)
            {
                message = "Success! The gbXML file was created";
            }
            else
            {
                path = string.Empty;
            }


            return new Dictionary<string, object>
            {
                { "report", message},
                { "gbXMLPath", path} 
            };


        }
Exemplo n.º 9
0
        private Dictionary<int, INode> buildPartialSingleOut(IEnumerable<string> portNames, List<Tuple<string, INode>> connections, List<string> partials)
        {
            InputNode node = Compile(portNames);

            foreach (var partial in partials)
            {
                node.ConnectInput(partial, new SymbolNode(partial));
            }

            var outerNode = new AnonymousFunctionNode(partials, node);
            if (connections.Any())
            {
                outerNode = new AnonymousFunctionNode(connections.Select(x => x.Item1), outerNode);
                foreach (var connection in connections)
                {
                    node.ConnectInput(connection.Item1, new SymbolNode(connection.Item1));
                    outerNode.ConnectInput(connection.Item1, connection.Item2);
                }
            }

            return new Dictionary<int, INode> { { 0, outerNode } };
        }
Exemplo n.º 10
0
 public static void GetObjectList(List<List<FScheme.Value>> input, out object[,] output, out int numRows,
                            out int numCols)
 {
     numRows = input.Count;
     numCols = input.Select(x => x.Count).Max();
     output = new object[numRows, numCols];
     for (int i = 0; i < numRows; i++)
     {
         for (int j = 0; j < numCols; j++)
         {
             if (j >= input[i].Count )
             {
                 output[i, j] = "";
             }
             else if (input[i][j] is FScheme.Value.String)
             {
                 output[i, j] = ((FScheme.Value.String)input[i][j]).Item;
             }
             else if (input[i][j] is FScheme.Value.Number)
             {
                 output[i, j] = ((FScheme.Value.Number)input[i][j]).Item;
             }
         }
     }
 }
Exemplo n.º 11
0
        public override Value Evaluate(FSharpList<Value> args)
        {
            var curve = (Curve) ((Value.Container) args[0]).Item;
            var plane = (Autodesk.Revit.DB.Plane) ((Value.Container) args[1]).Item;

            var curvePts = curve.Tessellate();
            var xSects = new List<XYZ>();

            for (int i = 0; i < curvePts.Count - 1; ++i)
            {
                var a = curvePts[i];
                var b = curvePts[i + 1];
                var xsect = linePlaneIntersection(plane, a, b);
                if (xsect != null)
                {
                    xSects.Add(xsect);
                }
            }

            return Value.NewList(Utils.SequenceToFSharpList(xSects.Select(Value.NewContainer)));
        }
Exemplo n.º 12
0
        public static Dictionary<string, object> ExportZonesToGBXML(string FilePath, List<ElementId> ZoneIds, List<AbstractFamilyInstance> MassShadingInstances, Boolean Run = false)
        {
            // Local variables
            Boolean IsSuccess = false;
            string FileName = string.Empty;
            string Folder = string.Empty;

            // Check if path and directory valid
            if (System.String.IsNullOrEmpty(FilePath) || FilePath == "No file selected.")
            {
                throw new Exception("No File selected !");
            }

            FileName = Path.GetFileNameWithoutExtension(FilePath);
            Folder = Path.GetDirectoryName(FilePath);

            // Check if Directory Exists
            if (!Directory.Exists(Folder))
            {
                throw new Exception("Folder doesn't exist. Input valid Directory Path!");
            }

            //make RUN? inputs set to True mandatory
            if (Run == false)
            {
                throw new Exception("Set 'Connect' to True!");
            }

            //local varaibles
            Document RvtDoc = DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument.Document;

            //enable the analytical model in the document if it isn't already
            try
            {
                PrepareEnergyModel.ActivateEnergyModel(RvtDoc);
            }
            catch (Exception)
            {
                throw new Exception("Something went wrong when trying to enable the energy model.");
            }

            //convert the ElementId wrapper instances to actual Revit ElementId objects
            List<Autodesk.Revit.DB.ElementId> outZoneIds = ZoneIds.Select(e => new Autodesk.Revit.DB.ElementId(e.InternalId)).ToList();

            // get shading Ids
            List<Autodesk.Revit.DB.ElementId> ShadingIds = new List<Autodesk.Revit.DB.ElementId>();
            for (int i = 0; i < MassShadingInstances.Count(); i++)
            {

                // make sure input mass is valid as a shading
                if (MassInstanceUtils.GetMassLevelDataIds(RvtDoc, MassShadingInstances[i].InternalElement.Id).Count() > 0)
                {
                    throw new Exception("Item " + i.ToString() + " in MassShadingInstances has mass floors assigned. Remove the mass floors and try again.");
                }

                ShadingIds.Add(MassShadingInstances[i].InternalElement.Id);
            }

            if (ShadingIds.Count != 0)
            {
                // Create gbXML with shadings
                MassGBXMLExportOptions gbXmlExportOptions = new MassGBXMLExportOptions(outZoneIds.ToList(), ShadingIds); // two constructors
                RvtDoc.Export(Folder, FileName, gbXmlExportOptions);

            }
            else
            {
                // Create gbXML
                MassGBXMLExportOptions gbXmlExportOptions = new MassGBXMLExportOptions(outZoneIds.ToList()); // two constructors
                RvtDoc.Export(Folder, FileName, gbXmlExportOptions);
            }

            // if the file exists return success message if not return failed message
            string path = Path.Combine(Folder, FileName + ".xml");

            if (System.IO.File.Exists(path))
            {
                // Modify the xml Program Info element, aithorize the
                XmlDocument doc = new XmlDocument();
                doc.Load(path);

                // EE: There must be a shorter way !
                XmlNode node = doc.DocumentElement;
                foreach (XmlNode node1 in node.ChildNodes)
                {
                    foreach (XmlNode node2 in node1.ChildNodes)
                    {
                        if (node2.Name == "ProgramInfo")
                        {
                            foreach (XmlNode childnode in node2.ChildNodes)
                            {
                                if (childnode.Name == "ProductName")
                                {
                                    string productname = "Dynamo _ " + childnode.InnerText;
                                    childnode.InnerText = productname;
                                }
                            }
                        }
                    }
                }

                doc.Save(path);

                IsSuccess = true;
            }
            string message = "Failed to create gbXML file!";

            if (IsSuccess)
            {
                message = "Success! The gbXML file was created";
            }
            else
            {
                path = string.Empty;
            }

            return new Dictionary<string, object>
            {
                { "report", message},
                { "gbXMLPath", path}
            };
        }
Exemplo n.º 13
0
        //TODO: do all of this as the Ui is modified, simply return this?
        /// <summary>
        /// Builds an INode out of this Element. Override this or Compile() if you want complete control over this Element's
        /// execution.
        /// </summary>
        /// <returns>The INode representation of this Element.</returns>
        protected internal virtual INode Build(Dictionary<dynNodeModel, Dictionary<int, INode>> preBuilt, int outPort)
        {
            //Debug.WriteLine("Building node...");

            Dictionary<int, INode> result;
            if (preBuilt.TryGetValue(this, out result))
                return result[outPort];

            //Fetch the names of input ports.
            var portNames = InPortData.Zip(Enumerable.Range(0, InPortData.Count), (x, i) => x.NickName + i).ToList();

            //Compile the procedure for this node.
            InputNode node = Compile(portNames);

            //Is this a partial application?
            var partial = false;

            var connections = new List<Tuple<string, INode>>();
            var partialSymList = new List<string>();

            //For each index in InPortData
            //for (int i = 0; i < InPortData.Count; i++)
            foreach (var data in Enumerable.Range(0, InPortData.Count).Zip(portNames, (data, name) => new { Index = data, Name = name }))
            {
                //Fetch the corresponding port
                //var port = InPorts[i];

                Tuple<int, dynNodeModel> input;

                //If this port has connectors...
                //if (port.Connectors.Any())
                if (TryGetInput(data.Index, out input))
                {
                    //Debug.WriteLine(string.Format("Connecting input {0}", data.Name));

                    //Compile input and connect it
                    connections.Add(Tuple.Create(data.Name, input.Item2.Build(preBuilt, input.Item1)));
                }
                else //othwise, remember that this is a partial application
                {
                    partial = true;
                    node.ConnectInput(data.Name, new SymbolNode(data.Name));
                    partialSymList.Add(data.Name);
                }
            }

            var nodes = new Dictionary<int, INode>();

            if (OutPortData.Count > 1)
            {
                if (partial)
                {
                    foreach (var connection in connections)
                    {
                        node.ConnectInput(connection.Item1, new SymbolNode(connection.Item1));
                    }
                }
                else
                {
                    foreach (var connection in connections)
                    {
                        node.ConnectInput(connection.Item1, connection.Item2);
                    }
                }

                InputNode prev = node;
                int prevIndex = 0;

                foreach (var data in OutPortData.Select((d, i) => new { Index = i, Data = d }))
                {
                    if (HasOutput(data.Index))
                    {
                        if (data.Index > 0)
                        {
                            var diff = data.Index - prevIndex;
                            InputNode restNode;
                            if (diff > 1)
                            {
                                restNode = new ExternalFunctionNode(FScheme.Drop, new[] { "amt", "list" });
                                restNode.ConnectInput("amt", new NumberNode(diff));
                                restNode.ConnectInput("list", prev);
                            }
                            else
                            {
                                restNode = new ExternalFunctionNode(FScheme.Cdr, new[] { "list" });
                                restNode.ConnectInput("list", prev);
                            }
                            prev = restNode;
                            prevIndex = data.Index;
                        }

                        var firstNode = new ExternalFunctionNode(FScheme.Car, new[] { "list" }) as InputNode;
                        firstNode.ConnectInput("list", prev);

                        if (partial)
                        {
                            var outerNode = new AnonymousFunctionNode(partialSymList, firstNode);
                            if (connections.Any())
                            {
                                outerNode = new AnonymousFunctionNode(
                                    connections.Select(x => x.Item1),
                                    outerNode);
                                foreach (var connection in connections)
                                {
                                    outerNode.ConnectInput(connection.Item1, connection.Item2);
                                }
                            }
                            firstNode = outerNode;
                        }

                        nodes[data.Index] = firstNode;
                    }
                    else
                        nodes[data.Index] = new NumberNode(0);
                }
            }
            else
            {
                if (partial)
                {
                    var outerNode = new AnonymousFunctionNode(partialSymList, node);
                    if (connections.Any())
                    {
                        outerNode = new AnonymousFunctionNode(
                            connections.Select(x => x.Item1),
                            outerNode);
                        foreach (var connection in connections)
                        {
                            node.ConnectInput(connection.Item1, new SymbolNode(connection.Item1));
                            outerNode.ConnectInput(connection.Item1, connection.Item2);
                        }
                    }
                    node = outerNode;
                }
                else
                {
                    foreach (var connection in connections)
                    {
                        node.ConnectInput(connection.Item1, connection.Item2);
                    }
                }
                nodes[outPort] = node;
            }

            //If this is a partial application, then remember not to re-eval.
            if (partial)
            {
                OldValue = Value.NewFunction(null); // cache an old value for display to the user
                RequiresRecalc = false;
            }

            preBuilt[this] = nodes;

            //And we're done
            return nodes[outPort];
        }
Exemplo n.º 14
0
        public override Value Evaluate(FSharpList<Value> args)
        {
            var result = new List<List<FamilyInstance>>();

            //"Get an interface to the divided surfaces on this element."
            //TODO: do we want to select a face instead and try to get
            //the divided surface that way?
            DividedSurfaceData dsd = SelectedElement.GetDividedSurfaceData();

            if(dsd == null)
                throw new Exception("The selected form has no divided surface data.");

            foreach (Reference r in dsd.GetReferencesWithDividedSurfaces())
            {
                Autodesk.Revit.DB.DividedSurface ds = dsd.GetDividedSurfaceForReference(r);

                var gn = new GridNode();

                int u = 0;
                while (u < ds.NumberOfUGridlines)
                {
                    var lst = new List<FamilyInstance>();

                    gn.UIndex = u;

                    int v = 0;
                    while (v < ds.NumberOfVGridlines)
                    {
                        gn.VIndex = v;

                        //"Reports whether a grid node is a "seed node," a node that is associated with one or more tiles."
                        if (ds.IsSeedNode(gn))
                        {
                            FamilyInstance fi
                                = ds.GetTileFamilyInstance(gn, 0);

                            //put the family instance into the tree
                            lst.Add(fi);
                        }
                        v = v + 1;
                    }

                    //don't add list if it's empty
                    if (lst.Any())
                        result.Add(lst);

                    u = u + 1;
                }
            }

            _data = Value.NewList(
                Utils.SequenceToFSharpList(
                    result.Select(
                        row => Value.NewList(
                            Utils.SequenceToFSharpList(
                                row.Select(Value.NewContainer))))));

            return _data;
        }
Exemplo n.º 15
0
        public override Value Evaluate(FSharpList<Value> args)
        {
            View3D view = null;
            var eye = (XYZ)((Value.Container)args[0]).Item;
            var target = (XYZ)((Value.Container)args[1]).Item;
            var name = ((Value.String)args[2]).Item;
            var extents = ((Value.Container)args[3]).Item;
            var isolate = Convert.ToBoolean(((Value.Number)args[4]).Item);

            var globalUp = XYZ.BasisZ;
            var direction = target.Subtract(eye);
            var up = direction.CrossProduct(globalUp).CrossProduct(direction);
            var orient = new ViewOrientation3D(eye, up, direction);

            if (this.Elements.Any())
            {
                if (dynUtils.TryGetElement(this.Elements[0], out view))
                {
                    if (!view.ViewDirection.IsAlmostEqualTo(direction) || !view.Origin.IsAlmostEqualTo(eye))
                    {
                        view.Unlock();
                        view.SetOrientation(orient);
                        view.SaveOrientationAndLock();
                    }

                    if (!view.Name.Equals(name))
                        view.Name = ViewBase.CreateUniqueViewName(name);
                }
                else
                {
                    //create a new view
                    view = ViewBase.Create3DView(orient, name, isPerspective);
                    Elements[0] = view.Id;
                }
            }
            else
            {
                view = Create3DView(orient, name, isPerspective);
                Elements.Add(view.Id);
            }

            var fec = dynRevitUtils.SetupFilters(dynRevitSettings.Doc.Document);

            if (isolate)
            {
                view.CropBoxActive = true;

                var element = extents as Element;
                if (element != null)
                {
                    var e = element;

                    var all = fec.ToElements();
                    var toHide =
                        fec.ToElements().Where(x => !x.IsHidden(view) && x.CanBeHidden(view) && x.Id != e.Id).Select(x => x.Id).ToList();

                    if (toHide.Count > 0)
                        view.HideElements(toHide);

                    dynRevitSettings.Doc.Document.Regenerate();

                    Debug.WriteLine(string.Format("Eye:{0},Origin{1}, BBox_Origin{2}, Element{3}",
                        eye.ToString(), view.Origin.ToString(), view.CropBox.Transform.Origin.ToString(), (element.Location as LocationPoint).Point.ToString()));

                    //http://wikihelp.autodesk.com/Revit/fra/2013/Help/0000-API_Deve0/0039-Basic_In39/0067-Views67/0069-The_View69
                    if (isPerspective)
                    {
                        var farClip = view.get_Parameter("Far Clip Active");
                        farClip.Set(0);
                    }
                    else
                    {
                        //http://adndevblog.typepad.com/aec/2012/05/set-crop-box-of-3d-view-that-exactly-fits-an-element.html
                        var pts = new List<XYZ>();

                        ParseElementGeometry(element, pts);

                        var bounding = view.CropBox;
                        var transInverse = bounding.Transform.Inverse;
                        var transPts = pts.Select(transInverse.OfPoint).ToList();

                        //ingore the Z coordindates and find
                        //the max X ,Y and Min X, Y in 3d view.
                        double dMaxX = 0, dMaxY = 0, dMinX = 0, dMinY = 0;

                        //geom.XYZ ptMaxX, ptMaxY, ptMinX,ptMInY;
                        //coorresponding point.
                        bool bFirstPt = true;
                        foreach (var pt1 in transPts)
                        {
                            if (true == bFirstPt)
                            {
                                dMaxX = pt1.X;
                                dMaxY = pt1.Y;
                                dMinX = pt1.X;
                                dMinY = pt1.Y;
                                bFirstPt = false;
                            }
                            else
                            {
                                if (dMaxX < pt1.X)
                                    dMaxX = pt1.X;
                                if (dMaxY < pt1.Y)
                                    dMaxY = pt1.Y;
                                if (dMinX > pt1.X)
                                    dMinX = pt1.X;
                                if (dMinY > pt1.Y)
                                    dMinY = pt1.Y;
                            }
                        }

                        bounding.Max = new XYZ(dMaxX, dMaxY, bounding.Max.Z);
                        bounding.Min = new XYZ(dMinX, dMinY, bounding.Min.Z);
                        view.CropBox = bounding;
                    }
                }
                else
                {
                    var xyz = extents as BoundingBoxXYZ;
                    if (xyz != null)
                    {
                        view.CropBox = xyz;
                    }
                }

                view.CropBoxVisible = false;
            }
            else
            {
                view.UnhideElements(fec.ToElementIds());
                view.CropBoxActive = false;
            }

            return Value.NewContainer(view);
        }
Exemplo n.º 16
0
        private Dictionary<int, INode> buildPartialMultiOut(IEnumerable<string> portNames, List<Tuple<string, INode>> connections, List<string> partials)
        {
            return OutPortData.Select((d, i) => new { Index = i, Data = d }).ToDictionary(
                data => data.Index,
                data =>
                {
                    var node = Compile(portNames);

                    foreach (var partial in partials)
                        node.ConnectInput(partial, new SymbolNode(partial));

                    var accessor = new ExternalFunctionNode(FScheme.Get, new[] { "idx", "list" });
                    accessor.ConnectInput("list", node);
                    accessor.ConnectInput("idx", new NumberNode(data.Index));

                    var outerNode = new AnonymousFunctionNode(partials, accessor);
                    if (connections.Any())
                    {
                        outerNode = new AnonymousFunctionNode(connections.Select(x => x.Item1), outerNode);
                        foreach (var connection in connections)
                        {
                            node.ConnectInput(connection.Item1, new SymbolNode(connection.Item1));
                            outerNode.ConnectInput(connection.Item1, connection.Item2);
                        }
                    }

                    return outerNode as INode;
                });
        }
Exemplo n.º 17
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.º 18
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.º 19
0
        internal dynNode CreateDragNode(string name)
        {
            dynNode result;
            if (FunctionDict.ContainsKey(name))
            {
                dynWorkspace ws = FunctionDict[name];

                var inputs =
                    ws.Nodes.Where(e => e is dynSymbol)
                        .Select(s => (s as dynSymbol).Symbol);

                var outputs =
                    ws.Nodes.Where(e => e is dynOutput)
                        .Select(o => (o as dynOutput).Symbol);

                if (!outputs.Any())
                {
                    var topMost = new List<Tuple<int, dynNode>>();

                    var topMostNodes = ws.GetTopMostNodes();

                    foreach (var topNode in topMostNodes)
                    {
                        foreach (var output in Enumerable.Range(0, topNode.OutPortData.Count))
                        {
                            if (!topNode.HasOutput(output))
                                topMost.Add(Tuple.Create(output, topNode));
                        }
                    }

                    outputs = topMost.Select(x => x.Item2.OutPortData[x.Item1].NickName);
                }

                result = new dynFunction(inputs, outputs, name);
            }
            else
            {
                TypeLoadData tld = builtinTypesByNickname[name];

                var obj = Activator.CreateInstanceFrom(tld.Assembly.Location, tld.Type.FullName);
                var newEl = (dynNode)obj.Unwrap();
                newEl.NodeUI.DisableInteraction();
                result = newEl;
            }

            if (result is dynDouble)
                (result as dynDouble).Value = this.storedSearchNum;
            else if (result is dynStringInput)
                (result as dynStringInput).Value = this.storedSearchStr;
            else if (result is dynBool)
                (result as dynBool).Value = this.storedSearchBool;

            return result;
        }