Okay, here’s my first stab at the problem - it appears to work fine for the Addition component and simply throws an error if there are more than 2 inputs
(Hopefully the name should discourage anyone from reckless use on critical files)
experimental_grasshopper_surgery.gh (7.4 KB)
test_subject.gh (6.6 KB)
Before:
After:
I don’t have access to a Rhino 6, so I haven’t tested this with the Multiplication and Subtraction components yet, but it should be a matter of obtaining their GUIDs and putting them into the mapping dictionary.
Also it’s my first time using GH_IO, so there are some bits that might not be done correctly like changing the name of a GH_Chunk by messing with its read-only field m_name
…
import os
import clr
clr.AddReferenceByName("GH_IO")
import GH_IO
from GH_IO.Serialization import *
from GH_IO.Types import *
from System import Guid
from System.Reflection import BindingFlags
from System.IO import BinaryReader, BinaryWriter, MemoryStream, SeekOrigin
import rhinoscriptsyntax as rs
new2old_mapping = {
Guid("a0d62394-a118-422d-abb3-6af115c75b25"): Guid("d18db32b-7099-4eea-85c4-8ba675ee8ec3"), # addition
"???": Guid("2c56ab33-c7cc-4129-886c-d5856b714010"), # subtraction
"???": Guid("b8963bb1-aa57-476e-a20e-ed6cf635a49c") # multiplication
}
param_name_map = {"InputParam": "param_input",
"OutputParam": "param_output"}
# read only attributes:
chunk_name_field = clr.GetClrType(GH_Chunk).GetField("m_name", BindingFlags.NonPublic | BindingFlags.Instance) # type: FieldInfo
# print "\n".join(map(str, clr.GetClrType(GH_Chunk).GetMembers(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance)))
def main(file_name):
archive = GH_Archive()
archive.ReadFromFile(file_name)
root = archive.GetRootNode # type: GH_Chunk
defn = root.FindChunk("Definition")
objs = defn.FindChunk("DefinitionObjects")
for obj in objs.Chunks:
obj_guid = obj.GetGuid("GUID") # type: GH_Item
if obj_guid in new2old_mapping:
print "Found new ZUI component \"{}\"".format(obj.FindItem("Name"))
container = obj.FindChunk("Container")
if not container.FindChunk("ParameterData"):
continue
if container.FindChunk("ParameterData").GetInt32("InputCount") != 2:
msg = "ZUI component \"{}\" has more than 2 inputs,\ncannot convert to older component".format(obj.FindItem("Name"))
print msg
rs.MessageBox(title="Surgery Error",
message=msg,
buttons=0) # OK button only
continue
# alternatively Abort => break, don't write archive, Ignore => continue
# replace the guids
repl_guid = new2old_mapping[obj_guid]
print "Replacing GUID {} with {}".format(obj_guid, repl_guid)
obj.RemoveItem("GUID")
# obj.Items.Add(GH_Item("GUID", new2old_mapping[obj_guid])) # doesn't work
obj.SetGuid("GUID", repl_guid)
for param_chunk in container.FindChunk("ParameterData").Chunks:
chunkname = param_chunk.Name
new_chunk = container.CreateChunk(chunk_name=param_name_map[chunkname],
chunk_index=param_chunk.Index)
ms = MemoryStream()
writer = BinaryWriter(ms)
reader = BinaryReader(ms)
param_chunk.Write(writer)
ms.Seek(0, SeekOrigin.Begin)
new_chunk.Read(reader) # this overwrites the chunk.Name value, so it has to be written again
# setting a "read only" field (!!)
chunk_name_field.SetValue(new_chunk, param_name_map[chunkname])
print "removing ZUI params: ", container.RemoveChunk(container.FindChunk("ParameterData"))
archive.WriteToFile(file_name.replace(".gh", "_edited.gh"), True, True)
if button:
main(file_name)