How To Make Custom Dynamic Component Attribute

I created a simple tire figure to learn how to offer dynamic attributes. The component works fine but I cannot figure out how to associate the attribute with the entity variable. I get a “Unable to get property value of undefined reference” when I enter any number into the dialog box. Any suggestions or references would be appreciated.tireErrortireErrorCode

Component attributes can not handle @ in names, only letters and numbers…
By doing this via Ruby you might pass the warning presented by the Dynamic Components

UhOh. That presents a problem since the ‘@’ sign defines ‘innerDiameter’ as a member of the Tire class. Membership gives ‘@innerDiameter’ visibility throughout Tire. If I just remove the ‘@’ then the class does not work.:slightly_frowning_face:

Sure but variable references and dictionary attributes are not directly linked.
(In fact all dictionary attributes are stored as string text.)

So YOU need to make the link.

  1. Remove all '@' from the dictionary names, and leave the '@' prefixes on the Ruby instance variable names.

  2. Change the "_innerDiameter_label" to just "Inner Diameter"
    (the user should not need to know what the actual variable / attribute reference names are.)

  3. Use a class constant to reference the dynamic attributes dictionary name, rather than creating a bunch of identical literal string objects:

DYNDICT = 'dynamic_attributes'
  1. Then in your setAttributes() method:
theDef.set_attribute( DYNDICT, 'innerDiameter', @innerDiameter )

1 Like

Thanks for the excellent response. It gets me closer but I am still missing something since the error persists.

I suspect the problem is related to the ‘_formula’ attribute. If theDef.set_attribute(DYNATS,‘innerDiameter’,@innerDiameter) is what links the program variable to the dictionary attribute then I don’t know what “_innerDiameter_formula” does.![tireErrorCode2|443x499](upload://rYLxuV1sO9sm

I also don’t think I got the label right.

no, you don’t! there is still an ‘@’, so Dynamic components will not accept a reference to that attribute (=@innerDiameter)
In general : Dynamic components are developed long time ago with very little progress and even less information as of how they are built/work.
The string in the _innerDiameter_formula is converted in the Dynamic Component, but it is not documented how exactly.
What is your ultimate goal with this? If you wish to make a dialog -box for user-input, then I would program some more in ruby. If you want to make a Dynamic Component, make a Dynamic Component…

Thanks for the excellent response.

My goal is to create dynamic components for which the user can change numerous variables and those variables are saved with the Sketchup file. I think I successfully made Tire into a dynamic component because when I right click on it the pull down menu includes “Component Attributes”. It even includes the inner diameter attribute which I desire. The thing that won’t work is for the tire’s inner diameter to actually change when I type a number into the dialog box.

Inner diameter is just the simplest example. The next variable might be “tread type”. Each defined tread type would have a complex set of drawing instructions. When I save the Sketchup session I want the component to save it’s tread type in case the user wants to change it next session.

I understand from other forum threads that these attributes are a marginal element of the Sketchup/Ruby software development experience. But I think it is worth a shot.

I do appreciate your help.

You misunderstand. This does not really set up any kind of automated “link”. The link is only a brute force read or write by YOUR program code. (So it only happens when you make it happen.)

You should likely study example DCs more closely.

Please see the link above on how to quote code in the forums, rather than pasting in hard to read images of your editor.

Great. Thanks for the references. I am studying further.

In the mean time, since dynamic components have been reported to be “marginal”, is there a better way to save a variable like the tire’s ‘tread type’ with each tire instance so that it’s state is preserved when the Sketchup session is relaunched?

The same way that the DC extension does this, is the same way many extensions do it. And that is to save the setting in a custom attribute dictionary attached to the instance.

Dictionaries are accessible to any code, so just like the shared top level Ruby namespace, you should qualify your extension’s dictionaries with your author/company name and extension name as a prefix.
So for example say that your toplevel “company” namespace module was “JGinc” and your extension’s name was “VehicleWizard”, then your modules would be qualified as:


Then, I always suggest qualifying your extension dictionaries with the same but replacing the :: scope operator with an underscore so that your dictionary would be named "JGinc_VehicleWizard".
If your extension needs different kinds of dictionaries for different kinds of “objects” you have the choice of either adding a suffux, like: "JGinc_VehicleWizard_Properties", "JGinc_VehicleWizard_Options", etc., or you can nest dictionaries within dictionaries (because dictionaries are a subclass of Sketchup::Entity, and all subclasses of this class can have a collection of dictionaries.)
So your “objects” can be given a custom “toplevel” dictionary named "JGinc_VehicleWizard", which could have sub-dictionaries named “Properties”, “Options”, etc.

Your choice. However, don’t expect that toplevel dictionaries with common names like “Properties” would not be used by more than one extension, that doesn’t know about the other, causing data clashes / corruption.

1 Like

Thanks for the excellent response.

Progress report on my tire:

  1. I found that the capital D in “inner Diameter” broke the dynamic component in the same way that the “@” symbol was doing, thus the persistent “Unable to get property value…” error. All lower case letters in keys was the key. Spaces are acceptable.
  2. I moved my attribute definitions ahead of my geometry so I can create the tire using attribute values directly. No more need to translate back and forth.

I am still working on getting the model to change based on Attribute Dialog Box input. I can change the ‘inner diameter’ attribute but my createTheTire() method does not get called. Forum traffic says to create a ‘redraw()’ method but I don’t know how to get the dialog box to call that. The console reports that a redraw took place but no change to the tire.

1 Like

Sorry, was offline (without power) for a week due to hurricane Irma.

When referring to something somewhere else, please insert a link to it.
To get a link to another forum thread or post, use the “chain” link button (found under each post, or at the end of every topic thread.)

You cannot make the DC dialog call YOUR methods,… only the DC dialog methods.

Assuming you have a reference my_tire_dc_instance to your DC component instance:

$dc_observers.get_latest_class.redraw_with_undo( my_tire_dc_instance )

Thanks so much for the reply. I know how disruptive a regional power failure can be.

Thanks to you help I think I am getting close but there is still something I don’t get. Where in my program should I place this …redraw_with_undo…statement?

If I place it right after creating the tire then I get a load error: "Error: #<NoMethodError: undefined method `get_latest_class’ for nil:NilClass>"

If I place it in the Console window with the tire selected then I get “Error: #<NameError: undefined local variable or method `my_tire_dc_instance’’ for main:Object>

If you are following Dan’s latest suggestion of rolling your own system - unrelated to DC then you should have no redraw_with_undo.

You might want to look at something like the SketchUp Shapes extension: GitHub - SketchUp/sketchup-shapes: Shapes adds new tools for drawing more shapes and primitives in SketchUp.
It creates a set of geometric shapes which can be edited parametrically.

That being said, that extension example is old and not the best example. But it’s a better guide than DC for what you are trying to do.

1 Like

Thanks for the reply. I am still trying to make DC work before I move on to my own custom attribute dictionary that Dan suggested. I am pretty sure I can do the latter, either using UI.inputbox for user data or some richer dialog box in javascript or something.

I will look at the sketchup-shapes reference.

I don’t know what you meant by this:
“That being said, that extension example is old and not the best example. But it’s a better guide than DC for what you are trying to do.”

The Shapes extension is an example extension of how to write a parametric extension that leverages the simple UI.inpubox() method.

The Shapes extension is one of several example extensions on the SketchUp Team’s Extension Warehouse store page. There is also a similar Window Maker parametric extension.

Because the Dynamic Components extension is not open source, so hacking code to manipulate DCs requires intimate knowledge of DCs and how all their attributes interact, very good knowledge of the SketchUp API and almost expert level at Ruby introspection and reflection. (Ie, there is no technical manual because DCs are supposed to be created in SketchUp Pro only with the DC extension itself.)

If you need to do geometry regeneration from parameters then DC really isn’t the platform you want to use. I can only perform some instance transformations.

Thanks again all for the excellent responses. This is exactly the information I needed. I had wanted to allow users to use the dynamic component attribute dialog box to edit my custom shapes like ‘tire’. But now I see that is not the way to go. Instead I can use the techniques such as exampled in the “Shapes” extension. It saves the custom entities in between Sketchup sessions and allows users to edit them.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.