Changing dynamic component parameters from importer doesn't always work

Hi,
I’m attempting to write an importer for SketchUp, but I cannot change some parameters on some dynamic components, while I can change these on other dynamic components.

I’ve asked this question before in the following thread Changing parameters of dynamic components problems but @tt_su asked me to start a new thread for each of the issues I described there.

The issue is the following:

A small sample project (for windows) illustrating this problem can be downloaded here:
ExampleImporter.zip (19.5 KB)
In order to build this project, a directory containing the SDK should be added in a binaries directory in the same directory where the ExampleImporter directory resides.

All of the relevant code is located in the common directory of the project. The importing process starts from the Convert function in exampleImporter.cpp.

A release build of this project can be downloaded here:
exampleImporter.zip (13.5 KB)
This dll file should be placed in the Importers directory which is located in the installation directory of SketchUp.

In order to test the exporter any .txt file should be opened. This will trigger the importer, which will in turn download both components mentioned above and will try to change the lenz parameter of both. If successful the imported components will scale when redrawn from the dynamic components menu. You will notice that only the big frame will scale, but not the small cover.

Any help is greatly appreciated!

What part of the code is where it doesn’t behave as expected?

Also, have you checked the return values of the function calls to the SketchUp C API?

I often create a helper macro to assist in this for debugging:

#define SU(api_function_call) {\
SUResult su_api_result = api_function_call;\
assert(SU_ERROR_NONE == su_api_result);\
}\

Then I use that to wrap function calls so I get asserts in debug builds when a function returns with an error:

std::string GetString(const SUStringRef& string) {
  size_t length = 0;
  SU(SUStringGetUTF8Length(string, &length));
  std::vector<char> buffer(length + 1);
  size_t out_length = 0;
  SU(SUStringGetUTF8(string, length + 1, buffer.data(), &out_length));
  assert(out_length == length);
  return std::string(begin(buffer), end(buffer));
}
1 Like

Side note, as I’m looking at the code getting familiar:

This:

    SUTypedValueRef typedValue;
    SUSetInvalid(typedValue);

can be simplified to:

    SUTypedValueRef typedValue = SU_INVALID;
2 Likes

Thank you for your reply!

The misbehaving code is called in the Convert function of the CExampleImporter class. This class can be found in Common/exampleImporter. I’ve created a function that executes exactly the same code for both situations, which is situated in the same class: LoadDefinitionInstantiateAndSetParameter. This function downloads a model from an URL, loads it as a definition, instatiates the definition and sets the height parameter on this definition.

When running the code, you can see that everything works fine, except for setting the parameter on the small cover. I think that the problem lies in the SetDoubleAttribute function of the HelperFunctions class (Common/HelperFunctions).

I’ve tried adding the helper macro to all function calls in the SetDoubleAttribute function. The importer still completes successfully, so I can conclude that all of these function calls succeed.

I also noticed that I forgot to add the common/utils.h file from the root directory. This file contains the SU_CALL macro which has the same functionality as the macro you’ve sent me. I’ve created a new zip containing the common/utils.h file and with the helper macro you provided to the SetDoubleAttribute function.
SketchupPlugin.zip (17.6 KB)

I think that SU_CALL throws an error. Which isn’t something I’d recommend in production as you’d crash the application. Instead it’s better to handle the error gracefully. The macro I used simply triggers an assert in debug build. (Also not ideal for production as it doesn’t handle any errors in any way - but useful for examples like this.)

Inspecting the model after running the importer I can confirm that the attribute “lenz” is being set:

image

image

You can verify that visually with the Attribute Helper:
https://extensions.sketchup.com/en/content/attribute-helper

But I do see that it appear differently in the Dynamic Component dialog:

image

At this point I’m not sure what is going on. Setting DC attributes via code is poking into internal logic and I’m not familiar with exactly how DC works.

But I’m guessing it relates to some of the other attributes that is set on the definition.

1 Like

Actually, it appear that these extensions have fixed set of options for LenZ, and only one of them list 114.7" as a valid value:

This will be very helpful for debugging these issues, thanks for the tip!

Doesn’t the auto option automatically map other values to the expected values?

I’m still in the prototyping phase. When I’m moving up to production, I’ll handle errors and exceptions more gracefully.

I’m afraid that I don’t know much about the exact details of Dynamic Components.
But DC is made with the intent of the components being edited by the user. When setting attribute data directly from a third party extension there might be a number of things that are not updated in the same manner as the UI would.

I see you are writing an importer for aluvision components, with which I happen to have some experience.

Why not, instead of changing the lenz attribute, actually change the scale of the component in z direction? That is the workflow a user would follow when doing it manually.

1 Like

Hi,

I will give this a shot, thanks for your feedback!

That won’t work from an importer - as it’s being done on a temporary model and Dynamic Components won’t have any knowledge of its existence.

Since this appear to rely so heavily on DC it might be better to have a Ruby extension importer.

You can either make a Ruby C extension to build your importer in C/C++ - but use the Ruby Importer interface instead of the SDK interface.

Alternatively you can use Fiddle to interact with dynamic libraries directly if you want to avoid Ruby C extensions. (Ruby C extensions will need a separate version per Ruby version you target, which differ from SU version to version.)

But if you go this route you can probably do some post-import cleanups in Ruby land which can trigger DC to do its thing.

However, I want to take a step back as ask what you are using Dynamic Components for? I’ve seem people try to do some really complication interactions with it when it turned out they didn’t really need to use DCs at all. I just want to make sure there isn’t a simpler and more stable solution at hand.

I was hoping dc would do a redraw upon file load.

I think it only will do this upon interacting directly with each instance.

I’ll give the Ruby Importer a try.

I’m building a tool that imports a configuration of Aluvision models and applies settings to them in order to integrate SketchUp with a custom external tool. I don’t see a way around using the DCs for solving this problem.

Aluvision happens to have a sketchup extension. Perhaps this could be integrated in that extension?

I cannot use the Aluvision extension to aid me, because this only spawns a dynamic component with default parameters. Then the end user can change some parameters of this dynamic component. I’ve not found a way to spawn a DC with non default values using this extension, which is required for my extension.

Or are you asking that my custom importer will be integrated into the existing sketchup extension? If so, I will have to find the developer of that extension.

Well, it does seem plausible that if you are creating a tool that is very Aluvision-specific, that it gets integrated in their extension.

1 Like