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) })); }
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()); }
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); }
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; }
/// <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; }
/// <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(); }
/// <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} }; }
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 } }; }
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; } } } }
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))); }
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} }; }
//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]; }
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; }
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); }
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; }); }
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(); }
/// <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; }
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; }