Associating data structures with save
-
I am working on developing a plugin for Sketchup. In the plugin I am working with Arrays of Faces. I would like to be able to associate these arrays with a particular save.
Things I have tried:
-
- Just using a global Ruby Array of these faces.
- This doesn't work because the Array is shared between windows of sketchup. Furthermore the Array is destroyed when sketchup closes.
-
- I also tried using an empty group entity and using the attribute dictionary to save these Arrays.
- This doesn't seem to work because the attribute dictionary doesn't seem to work with Arrays or the Face objects.
-
- The only idea I have left (but haven't tried to implement) is for each of the Faces in the scene use its attribute dictionary to store its array id and position.
- However this seems extremely cumbersome to me because what I would really like is to have three different arrays that contain arrays of faces.
Any pointers or ideas would be greatly appreciated, I am fairly new to the Sketchup API as well as Ruby.
Thank you.
-
-
Can you describe some more the overall concept of what you are doing?
-
@devinlange said:
. I would like to be able to associate these arrays with a particular save.
Please expand on this. I don't understand what you mean to accomplish.
-
@slbaumgartner said:
@devinlange said:
. I would like to be able to associate these arrays with a particular save.
Please expand on this. I don't understand what you mean to accomplish.
Basically I would like the user to be able to create a list of faces. More specifically I want them to functionally be a list of pointers to faces in the scene. When the user saves, closes sketchup, and reopens this save I want them to be able to access and manipulate these lists of faces they generated in the past.
-
@tt_su said:
Can you describe some more the overall concept of what you are doing?
Right now I'm working on the first step of a project involving Sketchup. At the end of this step I would like Sketchup to output lists of faces. (I intend to use these lists for path-planning like in games). Right now I am trying to make an interface so the user can create these lists of faces.
So far the way I've been doing this is let the user create face geometry like they normally would. Then when they select my path creator tool as they click on subsequent faces they get added to a Ruby array.
What I need is for the user to be able to create these paths, save, then be able to access them when they reopen. This is my most immediate issue, however I foresee other problems that I don't know how to solve, which may affect your answer. I would like to be able to modify the paths after they are created (insert, delete, append). At the very least if the user modifies the faces I don't want anything to fail.
Thank you for your interest, let me know if you have any ideas even if it requires me to restructure everything I've done so far
-
Your Array of references to Faces can not be saved per-se because Ruby objects are not persistent. Whereas the geometry is redrawn when you load a file, the Entities are not given the same Ruby object id's, which is what the Array contains.
Instead, you will need to "tag" them by adding an attribute corresponding to the path, e.g. a path name (see the API refs for AttributeDictionaries and AttributeDictionary). Provided the contents don't reference volatile things, the AttributeDictionaries of an Entity are saved in the file. Then on reload, your plugin can search for Faces with your key in their AD's. If you need to reassemble in the original order, you could use the path name as the key and the Array index as the value on each Face.
-
FYI: When you attach an attribute dictionary to the model, prepend it with your toplevel namespace and plugin name (then specific dictionary name,) separated by underscore character.
Ex:
"Lange_PathMaker_Options"
and/or
"Lange_PathMaker_Paths"
You can use more than one dictionary, but if you use a common name, there would likely be clashes between other plugin's dictionaries.
Also: It is not evident to many users of the API that both the
Sketchup::AttributeDictionaries
collection class, and theSketchup::AttributeDictionary
are both subclasses ofSketchup::Entity
.
Therefore, a dictionary can have a child collection of dictionaries attached to it.
So
Model | AttributeDictionaries collection - shared by all plugins | AttributeDictionary for Lange's PathMaker - sibling of other plugin dictionary(s) | AttributeDictionaries collection | nested AttributeDictionary(s) - perhaps one for each path?
-
@slbaumgartner said:
Your Array of references to Faces can not be saved per-se because Ruby objects are not persistent.
Yes.. the persistent collection of faces (and edges,) that are saved in the model, are
Sketchup::Entities
collections. The model has one, which is the toplevel collection of entities.Sketchup::Group
andSketchup::ComponentDefinition
also have entities collections.In addition, since SketchUp 2014, instances of these later two classes can have unique persistent IDs assigned to them. See:
So consider grouping your path faces if possible.
-
@dan rathbun said:
@slbaumgartner said:
Your Array of references to Faces can not be saved per-se because Ruby objects are not persistent.
Yes.. the persistent collection of faces (and edges,) that are saved in the model, are
Sketchup::Entities
collections. The model has one, which is the toplevel collection of entities.Sketchup::Group
andSketchup::ComponentDefinition
also have entities collections.In addition, since SketchUp 2014, instances of these later two classes can have unique persistent IDs assigned to them. See:
So consider grouping your path faces if possible.
I see very interesting, thank you for all the information. One question about the groups; do they have to be mutually exclusive? That is it would be nice if one face could be used for two separate paths.
-
@devinlange said:
I see very interesting, thank you for all the information. One question about the groups; do they have to be mutually exclusive? That is it would be nice if one face could be used for two separate paths.
An Entity can be in only one Entities collection at a time, so a Face can be in only one Group at a time.
-
@devinlange said:
At the very least if the user modifies the faces I don't want anything to fail.
This will be difficult. As faces get modified, or new edges intersect with them, they get split up into multiple faces, and sometimes get new object ids.
Myself, I'd never rely on "setting" a path of primitives, and expecting the path of them to survive.
Instead I'd create a virtual path. Could be a series of Guidelines (Construction lines) in a special group. Or actually maybe a Curve (which is SketchUp's name for a series of edges connected end to end,) within a group context, and on a "path" layer that can be turned off. The path and it's group can also be locked.
You could associate the vertices of the path with one of the vertices of a face.
Later on when you need to "follow the path" you iterate the Curve's collection of vertices, and use a PickHelper object to find the face under the current vertex. Push the face reference into an array, and repeat.
Just thinking out loud.
Advertisement