Get and change dynamic attribute

Hi Everyone,

I am using C++ SDK to query the dynamic attributes.
I can get entities of the model, but can’t get entity from it for later using - entity or component instance return null ptr.

SUInitialize();

SUModelRef model = SU_INVALID;
SUModelLoadStatus status;
SUResult res = SUModelCreateFromFileWithStatus(&model, “dynamicObject.skp”, &status);

if (res != SU_ERROR_NONE) {
std::cout << “Failed creating model from a file” << std::endl;
return 1;
}

SUEntitiesRef entities = SU_INVALID;
SUModelGetEntities(model, &entities);

size_t len = 0;
size_t count = 0;
SUComponentInstanceRef instance = SU_INVALID;

SUEntitiesGetInstances(entities, len, &instance, &count);
SUEntityRef entity = SUComponentInstanceToEntity(instance);
SetDoubleAttribute(entity, “dynamic_attributes”, “lenx”, 114.72440944881889);

What I’m doing wrong?

Thank you,
Grigor

Please code correctly in the forum so we don’t get the " replaced with smart-quotes.

It is the C API. (The old C++ API was retired several years ago.)

For your info, the C API cannot be used to modify the model file that is currently open in the SketchUp application. (You can use it to open other SKP files on disk.)

SUEntitiesGetInstances gets an array of instances, not a single instance.
You will need to first call SUEntitiesGetNumInstances so you can set the size of the array.

The C API has dedicated interfaces to query the dynamic dictionary of an instance (or it’s definition.)

See:

I do not see this function in the API. Is it one of your custom functions ?


If so, you need to understand that with only 1 dynamic instance in the model, the dynamic attributes will be held in the definition’s dynamic dictionary. (The instance will have a dynamic dictionary but will usually only contain a bare minimum of hidden informational attributes.)

The attributes in the definition will be the default values. When there are more than 1 instance and an instance differs from the default, the DC extension will create a dynamic attribute in the instance’s dynamic dictionary and also change the same attribute in the definition’s dynamic dictionary so as to update the default to be used by the next instance that the user may create.

Thanks you for answer.
Yes, this is custom function:

void SetDoubleAttribute(SUEntityRef& entity, const char* dictionary, const char* key, double value)
{
    // Prepare value
    SUTypedValueRef typedValue;
    SUSetInvalid(typedValue);
    SUTypedValueCreate(&typedValue);
    SUTypedValueSetFloat(typedValue, value);

    // Set the value
    SUAttributeDictionaryRef dic;
    SUSetInvalid(dic);
    SUEntityGetAttributeDictionary(entity, dictionary, &dic);
    SUAttributeDictionarySetValue(dic, key, typedValue);
    SUTypedValueRelease(&typedValue);
}

Yes, as I thought. Your code is not first checking that the instance is a DC by calling SUComponentInstanceCreateDCInfo() and checking the error result.

Then having determined that the object is a DC, properly first checking the instance’s dictionary for the attribute, and if it doesn’t exist then switching to the definition’s dictionary.

However I do not think that the C API has the internal code to redraw DCs as it is a Ruby extension. So any attribute changes that affect size and scale would not be applied until the model was reopened in the desktop SketchUp application.

In addition, there are quite a few hidden dynamic attributes that go along with each dynamic property (like “LenX”.) The DC extension is a complex and closed source extension, so it would be too extensive to describe completely how it works here.

Thank you for your explanation. I managed to get the attributes from SUDynamicComponentInfoGetDCAttributes.

  SUInitialize();

  SUModelRef model = SU_INVALID;
  SUModelLoadStatus status;
  SUResult res = SUModelCreateFromFileWithStatus(&model, "dynamicObject.skp", &status);

  if (res != SU_ERROR_NONE) {
    std::cout << "Failed creating model from a file" << std::endl;
    return 1;
  }

  SUEntitiesRef entities = SU_INVALID;
  SUModelGetEntities(model, &entities);

  size_t instanceCount = 0;
  size_t instanceLength = 1;
  SUComponentInstanceRef instance = SU_INVALID;
  SUEntitiesGetInstances(entities, instanceLength, &instance, &instanceCount);

  SUDynamicComponentInfoRef dc_info = SU_INVALID;
  SUComponentInstanceCreateDCInfo(instance, &dc_info);

  size_t attributesLength = 3;
  size_t attributesCount = 0;
  SUDynamicComponentAttributeRef attributes[] = SU_INVALID;
  SUResult result = SUDynamicComponentInfoGetDCAttributes(dc_info, attributesLength, attributes, &attributesCount);
  if (result == SU_ERROR_NONE) {
      // TODO something with attributes
  }