GH C# script serialization

Hi,
I usually use the serialization in Grasshopper C# Components through overriding the Write and Read methods and this works fine.
Is there a way to use serialization, using Read and Write (or equivalent) inside a C# script directly on Grasshoppes canvas?

Thanks in advance.

No, you can’t use the Read and Write methods of C# scripting comp.

Yes, you can do your own (de)serialization in your own file, in that case consider use the Data Input and Data Ouput components. If you want to include it in the gh file, you must use gh objects, custom or native. Maybe you can use a panel to set your data or a text (or your data type) parameter.

Another alternative can be to use the GH_IO library to change the current document, but it sounds very problematic.

Hi Dani,
Thank for your reply. Lets consider I will follow the 2° option “include it in the gh file, you must use gh objects, custom or native.”. In this case the serialization is performed in a standard way, e.g. “BinaryFormatter”? Do you have any examples?

Thanks

In that case you don’t (de)serialize, you just need set and get the persistant value with your data of gh object like a panel or parameter. Gh will do the rest.

Dear Dani,
Thanks for reply. To be honest is not very clear for me.
I found this discussion in the forum, maybe is the same you mean:

Alternatively can you provide a detailed explanation?

Thanks

Try this:

Dear Dani,
Thanks for reply and link, was very usefull. Maybe was not very clear but what I really need, to exlain it better, is to store a value inside the C# Script like this:

private void RunScript()
{
Method() -> Value;
if storedValue == Value -> No action
if storedValue != Value -> Action, storedValue = Value;
}

string storedValue = “”;

Now, I tried to apply what I think you explained to me, but not work as expected:
a.) Is difficult to retrieve data;
b.) Data is not saved when i re-open the Gh file.

private void RunScript(double x, ref object out_IsEmpty, ref object out_x, ref object out_check, ref object out_value_init, ref object out_value_fin)
{
if(param0.PersistentData.IsEmpty == true)
{

  param0.Access = GH_ParamAccess.item;
  param0.TypeHint = new Grasshopper.Kernel.Parameters.Hints.GH_DoubleHint_CS();
  param0.NickName = "Number";
  param0.Description = "Number Input";
}

object obj = Grasshopper.Utility.InvokeGetterSafe(param0, "PersistentData");
IGH_Structure persistent = obj as IGH_Structure;

List<double> list = new List<double>();
out_x = list;
string comp_str = persistent.DataDescription(false, false).ToString();

param0.SetPersistentData(x);
object obj1 = Grasshopper.Utility.InvokeGetterSafe(param0, "PersistentData");
IGH_Structure persistent1 = obj as IGH_Structure;
string comp_str1 = persistent1.DataDescription(false, false).ToString();

string x_str = x.ToString();
out_x = x_str;
out_value_init = comp_str;

if(param0.PersistentData.IsEmpty == true)
{
  param0.SetPersistentData(x);
}
else if(comp_str == comp_str1)
{
  out_check = "inside_loop";
  param0.ClearData();
  double x1 = x + 1;
  param0.SetPersistentData(x1);
  Component.ExpireSolution(true);
}

out_IsEmpty = param0.PersistentData.IsEmpty;
//param0.PersistentData.DataItem(
out_value_fin = persistent.DataDescription(false, false);
//out_value = persistent.AllData(true);

}

//

Grasshopper.Kernel.Parameters.Param_ScriptVariable param0 = new Grasshopper.Kernel.Parameters.Param_ScriptVariable();

You can’t serialize data inside a scripting component. What you can do is to store a runtime variable inside the < Custom additional code >. But each time the component starts its instance, this value will return to its default or original value.

If you just need a boolean, why not to use a toogle button and keep it simple?

Maybe I was not clear. I not mean to get/set the value in a scripting component parameter, but in an isolated parameter in the canvas (all the components in the Params tab, Geometry and Primitive panels are parameters, same as input and output componet, but isolated). You can do that from code and use it as a database. But again, if you just need to store a simple boolean or integer, don’t get complicated, especially if you’re not familiar with these hacks, and use a simple solution, ie, a source parameter. In case you really need to change this source value, then yes, try what I suggest you before but in an isolated parameter, not in a scripting component parameter.

Hi Dani,
Thanks for your great support!! Principaly I wanted to avoid any component creation since I planned to do some very simple tests within a particular application. However I think i will try using a component that is more familiar for me to solve the problem.

Thanks again.

A little late ^^, but I needed something similar and using the volatile data didn’t do the trick.
This however solved it for me and I figured I share it:

private void RunScript(double x, bool internalize, ref object A)
  {
    if (internalize)
    {
      ((Grasshopper.Kernel.Parameters.Param_ScriptVariable) Component.Params.Input[0]).PersistentData.Clear();
      ((Grasshopper.Kernel.Parameters.Param_ScriptVariable) Component.Params.Input[0]).PersistentData.Append(new GH_Number(x));
      Component.Params.Input[0].RemoveAllSources();
    }
    A = ((Grasshopper.Kernel.Parameters.Param_ScriptVariable) Component.Params.Input[0]).PersistentData.AllData(true);
  }

I was looking to programmatically internalize inputs in script components and ran into the error: Unable to cast object of type 'Grasshopper.Kernel.Parameters.Param_ScriptVariable' to type 'Grasshopper.Kernel.GH_PersistentParam1[Grasshopper.Kernel.Types.GH_Number]'.`

So if you attach a number to input x and then set internalize to true, the same thing happens as if you used the context menu (internalize data) on the input of the scripted component.

1 Like