I have hundreds of 3dm files in which I need to modify some text values. All text have been generated from a common template file, therefore their ids are the same in all the files.
I assumed it would be possible to edit all files without directly open them via Rhino.FileIO.File3dm, in such a kind of way:
var id = new Guid("xxxxxxxx"); // constant id of TextObject to be modified
foreach (var filePath in allPaths)
{
var rhinoFile = File3dm.Read(filePath);
var obj = rhinoFile.Objects.FindId(id);
if (obj.Geometry is TextEntity text)
{
text.PlainText = newTextValue;
}
rhinoFile.Write(filePath);
}
But for some reason, the changes are not taken into account once the file gets written. Am I missing something?
However, changes made on the object Attributes seem to be properly saved: for example, I successfully can change the color of the text object like following:
var rhinoFile = File3dm.Read(filePath);
var obj = rhinoFile.Objects.FindId(id);
obj.Attributes.ColorSource = Rhino.DocObjects.ObjectColorSource.ColorFromObject;
obj.Attributes.ObjectColor = Color.Blue;
rhinoFile.Write(filePath);
I know that for Rhino.DocObjects.RhinoObject, it is necessary to run the CommitChanges() method in order to take modifications into account, but I don’t see something similar for Rhino.FileIO.File3dmObject.
Thanks for your hint. Unfortunately, unlike the ‘normal’ ObjectTable (Rhino.DocObjects.Tables.ObjectTable), the Rhino.FileIO.File3dmObjectTable does not provide any Replace method.
My guess right now, is that File3dm is just not capable enough and is maybe not the right tool to use for those kind of tasks (modify existing objects geometry).
Maybe @dale or @menno are the erudite ones that could confirm this assertion.
The Object Table allows you to Add() and Delete() objects, It would make you loose the common id
but that would be a means to replace the old object for a new one.
I’ll need to extract the relevant stuff of the source text (string, plane etc…), pass these into this method for instance AddText(String, Plane, Double, String, Boolean, Boolean, TextJustification, ObjectAttributes) and finally delete the source object.
But as you mentioned, the id will be replaced in each file and it won’t be handy for further editing.
For that you could add usertext to the object. This makes you no longer rely on the id. You would be able to retrieve the object by searching for that usertext.
As for the addition of textentity, what if you pass it through the Add() method. Maybe Rhino allows that.
your idea of using UserText was pretty nice, I was completely hung up on the ids conservations…
I didn’t manage to get the Add() to work as it only accepts File3dmObject. I also didn’t try to death and my overall comprehension of Rhinocommon is still limited, so maybe it is still possible…
I achieved to create the text with AddText(String, Plane, Double, String, Boolean, Boolean, TextJustification, ObjectAttributes) and also managed to modify the id of the new created object to match the source object after it was deleted.
But in the end…I finally renounced to use File3dm, as I also need to output a PDF for each file and it doesn’t seem to be possible currently: PDF Printing with Rhino.FileIO
I’m now reading each files with RhinoDoc.ReadFile(..., ...), doing my modifications and finally exporting the PDF and saving the modified file to another directory.
thanks for sharing your work, that’s a shame that it wasn’t possible to modify existing objects inside 3dm files. I hope that a better solution will come up eventually - I think that it would be really useful.