SUGroupRef confusion in the C API

Looking through the C API, I am a little confused about creating Groups. As I understand it, conceptually, Groups and ComponentInstances are basically the same - they are both essentially “instances” of a ComponentDefinition.

Now, when creating a new ComponentInstance and adding to an EntitiesRef object, all is very simple:
SUComponentInstanceRef instance = SU_INVALID; SUComponentDefinitionCreateInstance(definition, &instance); SUComponentInstanceSetTransform(instance, &transform); SUEntitiesAddInstance(entities, instance, NULL);

Essentially, you get a pre-existing ComponentDefinitionRef, apply a transformation and you get your instance added to the model.

With a GroupRef, however, there is no equivalent to “SUComponentDefinitionCreateInstance” - ie there is no SUComponentDefinitionCreateGroup. One is instead forced to do this:
SUGroupRef group = SU_INVALID; SUEntitiesAddGroup(entities, group); SUEntitiesRef = SU_INVALID; SUGroupGetEntities(SUGroupRef group, &entities); // Build your entities object here.

In other words, you have to rebuild geometry every time. This is despite the fact that the Group object has the function SUGroupGetDefinition( SUGroupRef group, SUComponentDefinitionRef* component), which allows access to the group’s ComponentDefinitionRef object.

Is there a way for me to avoid having to rebuild the geometry in a group every time? Or in other words, to be able to use a ComponentDefinition object and a Transformation struct to create a group, like with ComponentInstance?

Perhaps I have overlooked something - is it possible that a Group is a kind of ComponentInstance (in C++ terms, the ComponentInstance is a parent class of Group)? I would appreciate the clarity!

This is similar to the Ruby API. In the Ruby API you do entities.add_group to create groups. You don’t create the definition first like with component instances. The APIs have in part tried to hide some implementation details here - but the definitions references for groups break that illusion.

I’m not entirely sure what you are looking to do? Groups are for all intents and purposes unique objects. Currently the implementation detail is that when groups are copied new instances of the group is added - but SketchUp quickly make them unique the moment it thinks the user is about to modify it.

If you have geometry you want to re-use then it sounds like a ComponentInstance is what you want to be using.

OK, I understand the logic. Thanks for reiterating this. I suppose the fact that I can see that a group can have “copies” in Sketchup’s Entity Info window threw me.

I am making a plugin which potentially will make many copies of a Group (which is user defined), and creating a unique ComponentDefinition for every identical group seems like a waste of processing power, and also bloats the size of the output file unnecessarily.

I was hoping that I could treat Groups much the same way as ComponentInstances. If that is not possible, I will just have to make new Groups and Definitions every time. :frowning:

While we are on the rough subject, could you explain the use of SUGroupToComponentInstance function? It is described as an “upcast” operation, what is the relationship between Groups and ComponentInstance objects? Are Groups a special kind of ComponentInstance?

Yes, whose definition is marked as being that for groups. (Images are in the same mold. They have definitions marked as being that for images instances.)

Both types of “special” definitions do NOT appear to the user, in the component browser’s “In Model” definition list.

This is the main reason why coders would choose to use a group rather than a component. Ie, they do not want the definition to appear in the “In Model” list.

This “hacky use” of groups could be avoided if coders hide the definition from the user via the definition’s hidden property, and it works as described in the API docs. (I just myself noticed that the API docs say that this property has a different use, for definitions, than that of any other Drawingelement subclass.)

So why not use ComponentInstances? What is the reason to have groups if you don’t want them to be unique?

The functions available for ComponentInstances is available to Groups as well. In order to use them in the C API you must cast the group to an instance. In the same manner if you want to use the Entity or DrawingElement functions - you need to cast the entity. The casting is due to C’s lack of classes and inheritance. As oppose to the Ruby API.

This makes me happier, thank you.

I am building an extension whereby a user-created library model (with various groups, instances and faces) is “applied” to another model, which involves a lot of copying of geometry. If they want to use Groups, I’ll copy across Groups - I just hoped there would be a lightweight way in which I could implement this. I want to do something along the lines of the Profile Builder 2 plugin, in which you can make assemblies of groups/components.

Happy to hear about the casting of Groups to ComponentInstances. Though it still doesn’t help me to keep GroupDefinition numbers down.

Are you doing this in context of a separate application? Or are you combining Ruby API and C API?
With the Ruby API you can in fact place extra copies of groups.

If you detail a bit more your scenario there might be some specific suggestion we can provide.

I appreciate your suggestions. I think I have got my head around the situation now.

For your interest, I am combining Ruby API and C API - the aim being for the C-side of things to take care of the heavy processing. I am aware that you can do more through the Ruby API than the C API. In the first instance, I will make most of my application in C++, with a lightweight Ruby interface.

The specific problem I am having came up while developing a C++ wrapper for the C API, with the aim of covering as many of the equivalent Ruby API methods as possible. I was just a bit sad to see that I couldn’t “Copy” a Group in the C API like in the Ruby API.

Happy Christmas!

Yea, we might have something to share in regard to C++ wrapper soon.

And I should really get around to extract my C++ wrapper on top of Ruby and the Ruby API. It makes it so much easier to work with Ruby C Extensions when you have some C++ type safety that the compiler can use to catch logical flaws in your code.

For SUbD I have a similar approach as you, core logic is in C++, while the rest of UI logic is in Ruby. Fast C++ computing, fast Ruby UI development. However, I still use the Ruby API to extract data from the model - as well as build geometry. I’m eager to switch to C API for model access.

I have added a feature request to add a new function to add groups from component definitions here:

1 Like