/// <summary> /// This is the method that actually does the work. /// </summary> /// <param name="DA">The DA object can be used to retrieve data from input parameters and /// to store data in output parameters.</param> protected override void SolveInstance(IGH_DataAccess da) { // reset everything, and let's start over.. // things are botched up if this script runs more than once. if (_iteration++ != 0) { return; } string filePath = string.Empty; da.GetData(0, ref filePath); // Find the scripts in the current group. var scripts = FindObjectsOfTypeInCurrentGroup <Component_CSNET_Script>(); if (scripts.Count != 1) { this.Message = "Error"; AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "This component should be added in a group with exactly one C# script."); return; } this.TargetComponent = scripts.First(); this.Message = this.TargetComponent.NickName; try { string inputCode; using (StreamReader streamReader = new StreamReader(filePath)) { inputCode = streamReader.ReadToEnd(); } if (this.TargetComponent != null) { this.TargetComponent.SourceCodeChanged(new GH_ScriptEditor(GH_ScriptLanguage.CS)); var splitLines = new List <string>(); splitLines.Add("#region CustomUsing"); splitLines.Add("#endregion CustomUsing"); splitLines.Add("#region CustomScript"); splitLines.Add("#endregion CustomScript"); splitLines.Add("#region CustomAdditional"); splitLines.Add("#endregion CustomAdditional"); string[] inputs = inputCode.Split(splitLines.ToArray(), StringSplitOptions.None); this.TargetComponent.ScriptSource.UsingCode = inputs[1]; this.TargetComponent.ScriptSource.ScriptCode = inputs[3]; this.TargetComponent.ScriptSource.AdditionalCode = inputs[5]; this.TargetComponent.ExpireSolution(true); } } catch (Exception e) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, e.Message); } }
/// <summary> /// Write script to file using a template /// This is called from the UI thread / solve instance. /// </summary> /// <param name="script"></param> /// <param name="filename"></param> private bool WriteScriptToFile(Component_CSNET_Script script, string filename) { var methodArguments = ExtractScriptParameters(script); var output = new ScriptOutput { InputOutput = methodArguments, UniqueNamespace = "ns" + script.InstanceGuid.ToString().Replace("-", "").Substring(0, 5), // Regex to fix the padding to match 4 tabs. // somehow all code is still botched up. Not sure if I should use some other way to format code. SourceCode = Regex.Replace(script.ScriptSource.ScriptCode, @"^( {4})( *)", @" $2$2", RegexOptions.Multiline | RegexOptions.IgnoreCase), AdditionalCode = Regex.Replace(script.ScriptSource.AdditionalCode, @"^( {2})( *)", @" $2$2", RegexOptions.Multiline | RegexOptions.IgnoreCase), }; var text = output.TransformText(); try { File.WriteAllText(filename, text); return(true); } catch (Exception ex) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, $"Could not write script to file {filename}, error: {ex.Message}"); return(false); } }
protected static void WriteScriptToComponent(Component_CSNET_Script scriptObject, string filename) { var fileContent = ReadFile(filename); var runscript = GetRegion(fileContent, "Runscript"); var rsLines = runscript.Split(new[] { Environment.NewLine }, StringSplitOptions.None); runscript = string.Join(Environment.NewLine, rsLines.Skip(2).Take(rsLines.Length - 3).ToList()); scriptObject.SourceCodeChanged(new GH_ScriptEditor(GH_ScriptLanguage.CS)); var additional = GetRegion(fileContent, "Additional"); scriptObject.ScriptSource.ScriptCode = runscript; scriptObject.ScriptSource.AdditionalCode = additional; }
protected static void WriteScriptToComponent(Component_CSNET_Script scriptObject, string filename) { var usingCodePropertyInfo = scriptObject.ScriptSource.GetType().GetProperty("UsingCode"); var fileContent = ReadFile(filename); var runscript = GetRegion(fileContent, "Runscript"); var rsLines = runscript.Split(new[] { Environment.NewLine }, StringSplitOptions.None); runscript = string.Join(Environment.NewLine, rsLines.Skip(2).Take(rsLines.Length - 3).ToList()); scriptObject.SourceCodeChanged(new GH_ScriptEditor(GH_ScriptLanguage.CS)); var additional = GetRegion(fileContent, "Additional"); scriptObject.ScriptSource.ScriptCode = runscript; scriptObject.ScriptSource.AdditionalCode = additional; if (usingCodePropertyInfo != null) { usingCodePropertyInfo.SetValue(scriptObject.ScriptSource, GetUsing(fileContent), null); } }
/// <summary> /// Extract the parameters of a script /// </summary> /// <param name="script"></param> /// <returns></returns> private string ExtractScriptParameters(Component_CSNET_Script script) { var elements = new List <string>(); var map = BuildMap(); // todo: Add usings to script for RH6 support. foreach (var ghParam in script.Params.Input.OfType <Param_ScriptVariable>()) { var th = ghParam.TypeHint ?? new GH_NullHint(); var key = th.ToString().Replace("Grasshopper.Kernel.Parameters.Hints.", ""); var objectType = map[key][2]; var itemString = ""; var cleanNickname = CleanNickname(ghParam.NickName); switch (ghParam.Access) { case GH_ParamAccess.tree: itemString = $"DataTree<{objectType}> {cleanNickname}"; break; case GH_ParamAccess.list: itemString = $"List<{objectType}> {cleanNickname}"; break; case GH_ParamAccess.item: itemString = $"{objectType} {cleanNickname}"; break; } elements.Add(itemString); } foreach (var pso in script.Params.Output) { if (pso is Param_GenericObject) { elements.Add($"ref object {CleanNickname(pso.NickName)}"); } } var methodArguments = string.Join(", ", elements); return(methodArguments); }
protected override void SolveInstance(IGH_DataAccess da) { // reset everything, and let's start over.. Cleanup(); // things are botched up if this script runs more than once. if (_iteration++ != 0) { return; } if (!da.GetDataTree <GH_Boolean>(0, out var tree)) { return; } if (!da.GetDataTree <GH_String>(1, out var stringTree)) { return; } var folder = stringTree.AllData(true).OfType <GH_String>().Select(x => x.Value).FirstOrDefault(); if (folder == null) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Scripts Folder was not set"); return; } folder = folder.Trim(); if (!TryGetDirectoryVerbose(folder)) { return; } var allBooleans = tree.AllData(true).Select(c => c.ScriptVariable()).Cast <bool>().ToList(); var success = allBooleans.Count == 1 && allBooleans[0]; if (!success) { return; } // Find the scripts in the current group. var scripts = FindObjectsOfTypeInCurrentGroup <Component_CSNET_Script>(); if (scripts.Count != 1) { AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "This component should be added in a group with exactly one C# script."); return; } if (IsBusy) { return; } TargetComponent = scripts[0]; Folder = folder; string directory; string filename; try { directory = Path.GetDirectoryName(FileNameSafe); filename = Path.GetFileName(FileNameSafe); if (directory == null || filename == null) { throw new Exception("No file name found"); } } catch (Exception ex) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, $"Invalid project name or component name, error {ex.Message}"); return; } if (!WriteScriptToFile(TargetComponent, FileNameSafe)) { return; } // Create a new FileSystemWatcher and set its properties. // http://stackoverflow.com/questions/721714/notification-when-a-file-changes AddEvents(directory, filename); WriteDefaultConfig(directory); EnsureProject(Path.Combine(directory, "GrasshopperScripts.csproj")); }