/// <summary> /// Save a function. This includes writing to a file and compiling the /// function and saving it to the FSchemeEnvironment /// </summary> /// <param name="definition">The definition to saveo</param> /// <param name="bool">Whether to write the function to file</param> /// <returns>Whether the operation was successful</returns> public string SaveFunctionOnly(FunctionDefinition definition) { if (definition == null) return ""; // Get the internal nodes for the function dynWorkspace functionWorkspace = definition.Workspace; string directory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); string pluginsPath = Path.Combine(directory, "definitions"); try { if (!Directory.Exists(pluginsPath)) Directory.CreateDirectory(pluginsPath); string path = Path.Combine(pluginsPath, FormatFileName(functionWorkspace.Name) + ".dyf"); SaveWorkspace(path, functionWorkspace, definition.FunctionId); return path; } catch (Exception e) { Bench.Log("Error saving:" + e.GetType()); Bench.Log(e); return ""; } }
protected override dynFunction CreateFunction(IEnumerable<string> inputs, IEnumerable<string> outputs, FunctionDefinition functionDefinition) { if (functionDefinition.Workspace.Nodes.Any(x => x is dynRevitTransactionNode) || functionDefinition.Dependencies.Any(d => d.Workspace.Nodes.Any(x => x is dynRevitTransactionNode))) { return new dynFunctionWithRevit(inputs, outputs, functionDefinition); } return base.CreateFunction(inputs, outputs, functionDefinition); }
/// <summary> /// Save a function. This includes writing to a file and compiling the /// function and saving it to the FSchemeEnvironment /// </summary> /// <param name="definition">The definition to saveo</param> /// <param name="bool">Whether to write the function to file</param> /// <returns>Whether the operation was successful</returns> public void SaveFunction(FunctionDefinition definition, bool writeDefinition = true) { if (definition == null) return; // Get the internal nodes for the function dynWorkspace functionWorkspace = definition.Workspace; // If asked to, write the definition to file if (writeDefinition) { string directory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); string pluginsPath = Path.Combine(directory, "definitions"); try { if (!Directory.Exists(pluginsPath)) Directory.CreateDirectory(pluginsPath); string path = Path.Combine(pluginsPath, FormatFileName(functionWorkspace.Name) + ".dyf"); SaveWorkspace(path, functionWorkspace, definition.FunctionId); } catch (Exception e) { Bench.Log("Error saving:" + e.GetType()); Bench.Log(e); } } try { #region Find outputs // Find output elements for the node IEnumerable<dynNode> outputs = functionWorkspace.Nodes.Where(x => x is dynOutput); var topMost = new List<Tuple<int, dynNode>>(); IEnumerable<string> outputNames; // if we found output nodes, add select their inputs // these will serve as the function output if (outputs.Any()) { topMost.AddRange( outputs.Where(x => x.HasInput(0)).Select(x => x.Inputs[0])); outputNames = outputs.Select(x => (x as dynOutput).Symbol); } else { // if there are no explicitly defined output nodes // get the top most nodes and set THEM as tht output IEnumerable<dynNode> topMostNodes = functionWorkspace.GetTopMostNodes(); var outNames = new List<string>(); foreach (dynNode topNode in topMostNodes) { foreach (int output in Enumerable.Range(0, topNode.OutPortData.Count)) { if (!topNode.HasOutput(output)) { topMost.Add(Tuple.Create(output, topNode)); outNames.Add(topNode.OutPortData[output].NickName); } } } outputNames = outNames; } #endregion // color the node to define its connectivity foreach (var ele in topMost) { ele.Item2.NodeUI.ValidateConnections(); } //Find function entry point, and then compile the function and add it to our environment IEnumerable<dynNode> variables = functionWorkspace.Nodes.Where(x => x is dynSymbol); IEnumerable<string> inputNames = variables.Select(x => (x as dynSymbol).Symbol); INode top; var buildDict = new Dictionary<dynNode, Dictionary<int, INode>>(); if (topMost.Count > 1) { InputNode node = new ExternalFunctionNode( FScheme.Value.NewList, Enumerable.Range(0, topMost.Count).Select(x => x.ToString())); int i = 0; foreach (var topNode in topMost) { string inputName = i.ToString(); node.ConnectInput(inputName, topNode.Item2.Build(buildDict, topNode.Item1)); i++; } top = node; } else top = topMost[0].Item2.BuildExpression(buildDict); // if the node has any outputs, we create a BeginNode in order to evaluate all of them // sequentially (begin evaluates a list of expressions) if (outputs.Any()) { var beginNode = new BeginNode(); List<dynNode> hangingNodes = functionWorkspace.GetTopMostNodes().ToList(); foreach (var tNode in hangingNodes.Select((x, index) => new {Index = index, Node = x})) { beginNode.AddInput(tNode.Index.ToString()); beginNode.ConnectInput(tNode.Index.ToString(), tNode.Node.Build(buildDict, 0)); } beginNode.AddInput(hangingNodes.Count.ToString()); beginNode.ConnectInput(hangingNodes.Count.ToString(), top); top = beginNode; } // make the anonymous function FScheme.Expression expression = Utils.MakeAnon(variables.Select(x => x.NodeUI.GUID.ToString()), top.Compile()); // make it accessible in the FScheme environment FSchemeEnvironment.DefineSymbol(definition.FunctionId.ToString(), expression); //Update existing function nodes which point to this function to match its changes foreach (dynNode el in AllNodes) { if (el is dynFunction) { var node = (dynFunction) el; if (node.Definition != definition) continue; node.SetInputs(inputNames); node.SetOutputs(outputNames); el.NodeUI.RegisterAllPorts(); } } //Call OnSave for all saved elements foreach (dynNode el in functionWorkspace.Nodes) el.onSave(); } catch (Exception ex) { Bench.Log(ex.GetType() + ": " + ex.Message); } }
public void nodeWorkspaceWasLoaded( FunctionDefinition def, Dictionary<Guid, HashSet<FunctionDefinition>> children, Dictionary<Guid, HashSet<Guid>> parents) { //If there were some workspaces that depended on this node... if (children.ContainsKey(def.FunctionId)) { //For each workspace... foreach (FunctionDefinition child in children[def.FunctionId]) { //Nodes the workspace depends on HashSet<Guid> allParents = parents[child.FunctionId]; //Remove this workspace, since it's now loaded. allParents.Remove(def.FunctionId); //If everything the node depends on has been loaded... if (!allParents.Any()) { SaveFunction(child, false); nodeWorkspaceWasLoaded(child, children, parents); } } } }
protected virtual dynFunction CreateFunction(IEnumerable<string> inputs, IEnumerable<string> outputs, FunctionDefinition functionDefinition) { return new dynFunction(inputs, outputs, functionDefinition); }
/// <summary> /// Change the currently visible workspace to a custom node's workspace /// </summary> /// <param name="symbol">The function definition for the custom node workspace to be viewed</param> internal void ViewCustomNodeWorkspace(FunctionDefinition symbol) { if (symbol == null || CurrentSpace.Name.Equals(symbol.Workspace.Name)) return; dynWorkspace newWs = symbol.Workspace; //Make sure we aren't dragging Bench.WorkBench.isDragInProgress = false; Bench.WorkBench.ignoreClick = true; //Step 1: Make function workspace invisible foreach (dynNode ele in Nodes) { ele.NodeUI.Visibility = Visibility.Collapsed; } foreach (dynConnector con in CurrentSpace.Connectors) { con.Visible = false; } foreach (dynNote note in CurrentSpace.Notes) { note.Visibility = Visibility.Hidden; } //var ws = new dynWorkspace(this.elements, this.connectors, this.CurrentX, this.CurrentY); if (!ViewingHomespace) { //Step 3: Save function SaveFunction(CustomNodeLoader.GetDefinitionFromWorkspace(newWs)); } CurrentSpace = newWs; foreach (dynNode ele in Nodes) { ele.NodeUI.Visibility = Visibility.Visible; } foreach (dynConnector con in CurrentSpace.Connectors) { con.Visible = true; } foreach (dynNote note in CurrentSpace.Notes) { note.Visibility = Visibility.Visible; } //this.saveFuncItem.IsEnabled = true; Bench.homeButton.IsEnabled = true; //this.varItem.IsEnabled = true; Bench.workspaceLabel.Content = symbol.Workspace.Name; Bench.editNameButton.Visibility = Visibility.Visible; Bench.editNameButton.IsHitTestVisible = true; Bench.setFunctionBackground(); PackageManagerClient.ShowPackageControlInformation(); CurrentSpace.OnDisplayed(); }
internal FunctionDefinition NewFunction(Guid id, string name, string category, bool display, double workspaceOffsetX = dynBench.CANVAS_OFFSET_X, double workspaceOffsetY = dynBench.CANVAS_OFFSET_Y ) { //Add an entry to the funcdict var workSpace = new FuncWorkspace( name, category, workspaceOffsetX, workspaceOffsetY); List<dynNode> newElements = workSpace.Nodes; List<dynConnector> newConnectors = workSpace.Connectors; var functionDefinition = new FunctionDefinition(id) { Workspace = workSpace }; this.CustomNodeLoader.AddFunctionDefinition(functionDefinition.FunctionId, functionDefinition); // add the element to search SearchViewModel.Add(workSpace); if (display) { if (!ViewingHomespace) { var def = dynSettings.Controller.CustomNodeLoader.GetDefinitionFromWorkspace(CurrentSpace); if (def != null) SaveFunction( def ); } DynamoController.hideWorkspace(CurrentSpace); CurrentSpace = workSpace; Bench.homeButton.IsEnabled = true; Bench.workspaceLabel.Content = CurrentSpace.Name; Bench.editNameButton.Visibility = Visibility.Visible; Bench.editNameButton.IsHitTestVisible = true; Bench.setFunctionBackground(); dynSettings.ReturnFocusToSearch(); } return functionDefinition; }