algorithmic modeling for Rhino
Now, the RegisterXXXXParams methods:Public Class GH_ExampleComponent_VarOutputInherits GH_ComponentPublic Sub New()MyBase.New("Extract Paths", "ExPath", "Extract all the paths from a tree", "Sets", "Tree")End SubEnd Class
Protected Overrides Sub RegisterInputParams(ByVal pManager As GH_Component.GH_InputParamManager)pManager.Register_GenericParam("Tree", "T", "Data tree to examine", GH_ParamAccess.tree)End SubProtected Overrides Sub RegisterOutputParams(ByVal pManager As GH_Component.GH_OutputParamManager)'We'll add one output parameter, just to not have a jagged output.pManager.Register_PathParam("Path 1", "1", "1st path in tree")End Sub
Protected Overrides Sub SolveInstance(ByVal DA As IGH_DataAccess)'We have only one input parameter and it is set to Tree,'so SolveInstance will only be called once for every solution.'We don't actually need the data inside the input, we're only interested in the paths.'So we don't actually need to call DA.GetDataTree, we can just go in and extract the'paths directly:Dim paths As IList(Of GH_Path) = Params.Input(0).VolatileData.Paths'Abort if there is no tree.If (paths.Count = 0) Then Return'Post a warning if the number of output parameters does not'equal the number of paths in the tree.If (paths.Count < Params.Output.Count) ThenAddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "There are more outputs than paths in the tree.")ElseIf (paths.Count > Params.Output.Count) ThenAddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "There are fewer outputs than paths in the tree.")End If'Iterate over all paths and assign to output parameters.For i As Int32 = 0 To Math.Min(Params.Output.Count, paths.Count) - 1DA.SetData(i, paths(i))NextEnd Sub
Protected Overrides Sub Menu_AppendCustomComponentItems(ByVal iMenu As System.Windows.Forms.ToolStripDropDown)'Add a single item to the component menu.Menu_AppendGenericMenuItem(iMenu, "Synch outputs", AddressOf Menu_SynchOutputClicked)End SubPrivate Sub Menu_SynchOutputClicked(ByVal sender As Object, ByVal e As EventArgs)'Here we have to synch the number of output parameters with the number'of paths in the volatile data tree in the input parameter.'This requires a few steps:'1. Determine whether something needs to happen at all.'2. Record an undo event.'3. Remove excess outputs or add missing outputs.Dim paths As IList(Of GH_Path) = Params.Input(0).VolatileData.PathsIf (paths.Count = Params.Output.Count) Then Return 'yay, nothing needs to be done.'Something needs to be done, record an undo state.RecordUndoEvent("Synch output")'We either have too few or too many outputs, determine which is the case.If (paths.Count > Params.Output.Count) Then'Add the missing outputsFor i As Int32 = Params.Output.Count + 1 To paths.CountDim param As New Grasshopper.Kernel.Parameters.Param_GenericObject()param.Name = "Path " & i.ToString()param.NickName = i.ToString()If (i.ToString.EndsWith("1")) Thenparam.Description = i.ToString() & "st path in tree"ElseIf (i.ToString.EndsWith("2")) Thenparam.Description = i.ToString() & "nd path in tree"ElseIf (i.ToString.EndsWith("3")) Thenparam.Description = i.ToString() & "rd path in tree"Elseparam.Description = i.ToString() & "th path in tree"End IfParams.RegisterOutputParam(param)NextElse'Remove excessive outputsDoIf (Params.Output.Count <= paths.Count) Then Exit DoDim param As IGH_Param = Params.Output(Params.Output.Count - 1)Params.UnregisterOutputParameter(param)LoopEnd IfParams.OnParametersChanged()ExpireSolution(True)End Sub
Public Overrides Function Write(ByVal writer As GH_IO.Serialization.GH_IWriter) As Boolean'We must make sure that the number of output parameters is correctly stored.'We'll use a special function on the GH_ComponentParamServer to accompish this'without too much sweat.Params.WriteParameterTypeData(writer)Return MyBase.Write(writer)End FunctionPublic Overrides Function Read(ByVal reader As GH_IO.Serialization.GH_IReader) As Boolean'Very important, we must make sure all parameters exist before we'start with the main deserialization.Params.Clear()Params.ReadParameterTypeData(reader)Return MyBase.Read(reader)End Function
Tags:
David,
I am writing a component to read wav files and I want to make a new output for each audio channel. I have everything working, but if I switch the wav file from two channels to one, I get an exception. If I click ok on the exception box, the component corrects itself and everything is fine.
I have implemented a version of the code above in c#, where I have the following in SolveInstance:
//...load audio and calculate number of channels...then
if (this.NumberOfChannels + 1 != Params.Output.Count)//there is an extra output for samplerate
{
if (this.NumberOfChannels + 1 > Params.Output.Count)
{
for (int i = Params.Output.Count; i < this.NumberOfChannels + 1; i++)
{
Grasshopper.Kernel.Parameters.Param_GenericObject param = new Grasshopper.Kernel.Parameters.Param_GenericObject();
param.Name = "Channel" + i.ToString();
param.NickName = i.ToString();
param.Description = "Channel" + param.NickName.ToString();
Params.RegisterOutputParam(param);
}
}
else if (Params.Output.Count > this.NumberOfChannels + 1)
{
for (int i = 0; i < Params.Output.Count - this.NumberOfChannels + 1; i++)
{
List<IGH_Param> param = new List<IGH_Param>(Params.Output);//I think the exception is happening here
Params.UnregisterOutputParameter(param[param.Count - 1]);
}
}
Params.OnParametersChanged();
ExpireSolution(true);
}
try
{
for (int i = 1; i < NumberOfChannels + 1; i++)
{
List<Int32> audio_data = new List<Int32>(Data[i - 1]);
DA.SetDataList(i, audio_data);
}
}catch { return; }
DA.SetData(0, SampleRate);
Thanks for any help you can provide.
What's the exception type and message?
--
David Rutten
david@mcneel.com
Seattle, WA
Sorry, here it is:
and the assembly is here if necessary. http://www.grasshopper3d.com/forum/topics/buzz-v-0-3-acoustic-and-a...
I imagine the problem is the reason you use the "synch output" menu item in the example, I was just hoping to get it to work automatically.
Thanks!
Ah yes, I see now that you are changing the number of outputs from within SolveInstance. That is not allowed. Grasshopper assumes the topology of a network doesn't change during a solution.
What happens if someone supplies two WAV files each with different channel counts?
I myself am very hesitant to automatically remove parameters from a file. There could always be a hiccup that would cause me to delete a number of carefully hooked up parameters and will just make people angry.
My advice is to test inside SolveInstance whether the current number of outputs matches the number of channels in the current WAV file. If it doesn't, write a runtime error message to inform the user something is out of synch.
Then add an item to the component menu which allows people to specifically synch channels and outputs. The event handler for this menu item runs outside of a solution, so it's safe to modify your component layout then.
Furthermore, you should make sure your component implements the IGH_VariableParameterComponent interface, because you will run into (de)serialization problems otherwise.
I'd also recommend adding an undo record just before you change the number of outputs so people can always revert if they don't like the new layout.
Alternatively, instead of outputting multiple channels in separate parameters and getting all this complicated overhead, you could also output a list of channel data on a single parameter.
--
David Rutten
david@mcneel.com
Seattle, WA
Hi David,
I'm piggybacking on this comment because my question is similar. I have a component that implements the IGH_VariableParameterComponent interface, and have code handling variable parameters.
Is it possible to call VariableParameterMaintenance() when an input parameter changes, or within SolveInstance, as to react to parameters? For example: a user using a Grasshopper slider in order to change the number of inputs or outputs.
That's actually not my use case, but I am trying have the component dynamically create/delete parameters based on a loaded file. It's important that it's automatic to me, as the user may not know how many outputs are necessary for a given process. Ideally, the component would 'tell' the user by adding those parameters by itself. (It's a continuation of this component.)
I tried calling an empty VariableParameterMaintenance() within ValuesChanged():
(this as IGH_VariableParameterComponent).VariableParameterMaintenance();
, hoping that it would execute only on but Grasshopper didn't seem to like it and immediately crashed.
Do you have any ideas/suggestions? Thank you!
You cannot change the topology of a grasshopper component during a solution. That will invalidate data that has been computed when the solution started.
You can call VariableParameterMaintenance, provided it doesn't change any of the solution-related properties of your parameters (such as the access type or the optionality of parameters).
I'm not a big fan of automatically changing parameter count, mostly because you don't want to remove any parameters that people have wired up. Adding parameters is ok I guess.
My preferred solution is to display a warning or message when the parameter count is out of whack and then provide an easy way for people to fix it. For example by double clicking on the component, or clicking on a custom button you display or via a menu-item.
These clicks will occur outside of a solution and they will thus not cause any problems.
It would be better to start a new discussion for this as Ning only allows a few levels of nesting and we'll run out pretty quick.
--
David Rutten
david@mcneel.com
What I wonder to know is that How do you know Which year David born?
What? I'm confused...
25 years + 00000111 days = 32 years + 7 days
2^0 + 2^1 + 2^3 =11 -- There is no need to know when david was born. 11 days before he say this is his birthday. Am I right?
The years were given as powers-of-two, the days as binary numbers.
--
David Rutten
david@mcneel.com
Poprad, Slovakia
Welcome to
Grasshopper
Added by Parametric House 0 Comments 0 Likes
Added by Parametric House 0 Comments 0 Likes
Added by Parametric House 0 Comments 0 Likes
Added by Parametric House 0 Comments 0 Likes
© 2024 Created by Scott Davidson. Powered by