Setting snapto behavior in component definition has no effect on the UI

Hi all,

I have been feeding on your collective knowledge and experience for some time, and now is the time for me to join in. This time it’s a question, but hopefully in the future I will be able so help others with answers.

I’m developing a number of plugins, and have recently stumbled upon an issue. I’m not sure if this is a bug, or if I’m doing something wrong.

When you create a component, and subsequently change it’s behavior so it will glue to a certain type of surface, this change is not actually effective. Let me demonstrate via the Ruby console:

# I create a simple component
group = Sketchup.active_model.entities.add_group
face = group.entities.add_face([0,0,0],[100,0,0],[100,100,0],[0,100,0])
face.pushpull(-5,false)
component = group.to_component

By default the GlueTo value in the UI is set to None. I can verify this by printing its value, which will be zero:

puts component.definition.behavior.snapto

When I change it in the API, this value is updated:

# change the GlueTo value
component.definition.behavior.snapto = SnapTo_Vertical

# and verify the value
puts component.definition.behavior.snapto

It shows the value two, as expected. Unfortunately the UI still shows None.

GlueTo-None

Now if I change the value in the UI to something (like Horizontal) and then print the value, the expected value is printed.

puts component.definition.behavior.snapto
1

Change it to Vertical and the value two is printed.

So the API value is updated by changes in the UI, but the UI seems to ignore changes made through the API. Am I doing something wrong, is this a bug, or os something els going on.

I have tested this on SketchUp 2018 Pro and 2019 Pro. Both show the same results.

And what is the actual behavior of suchs components (say the one with value 1 and 2) when used in modeling space on different faces? Is it like expected with ‘none’ or do they glue to faces.
What is the value with ‘any’?

When I set behavior via the API, the UI acts like no behavior is set at all. So indeed like the value is set to None in the UI.

When I set the behavior via the UI, the component glues like it is supposed to. Setting it to Vertical glues /snaps the component to a wall for example.

Because of the different names (snapto in the API and GlueTo in the UI) I thought I had the wrong API option, but as you can see in my example, setting the value in the UI does change the value in the API, so they are linked in some way.

I’ve (unfortunately) very limited knowledge of ruby.
In the passed I’ve noticed that setting ‘Glue to’ to vertical or horizontal or any made no difference. The component would just glue to any oriented face. That’s why I was curious about behavior in your examples.

I may be missing something in what you wrote above, I don’t see a check for the new (none-zero) values if you have changed the component’s behavior through UI. As you say there may be a link missing in doing it one way or the other. What are the values when changes are made through the UI?

I know that at least @thomthom made a plugin with which you could change a componentś behavior from ‘none’ to ‘glue to’. So @thomthom (and others!?) should know which code to use or if it somehow was the like yours in a slightly different way. Or if this actually is a bug.
@thomthom, @others?

When I change the value in the API both the value and the behavior in de UI are unaffected.

# Start with UI set to None, now change the GlueTo value
component.definition.behavior.snapto = SnapTo_Horizontal
# UI still set to None
# Start with UI set to None, now change the GlueTo value
component.definition.behavior.snapto = SnapTo_Vertical
# UI still set to None

When I change the value in the UI, I can query the value using the API, and the result reflects the selected value in the UI

# set UI to Horizontal
puts component.definition.behavior.snapto
1
# set UI to Vertical
puts component.definition.behavior.snapto
2

Now that would be awesome!

Thaks for your help so far.

The API names and documentation is confusing on this topic. What you are missing is something hidden in the description of Behavior.is2d=:

The is2d= method is used to set the 2D behavior for a component: whether it can be glued or aligned to a face.
http://ruby.sketchup.com/Sketchup/Behavior.html#is2d=-instance_method

The, minutely, altered version of your example:

# I create a simple component
group = Sketchup.active_model.entities.add_group
face = group.entities.add_face([0,0,0],[100,0,0],[100,100,0],[0,100,0])
face.pushpull(-5,false)
component = group.to_component

# change the GlueTo value
component.definition.behavior.is2d = true
component.definition.behavior.snapto = SnapTo_Vertical

I’m not sure why the is2d is name for this, clearly we are using 3d dimensional geometry here. The reason is lost in history, long before my time.

I can speculate in that this property was originally intended for gluing images to the sides of faces.

I logged an issue for the documentation to be improved for the Behavior class:

3 Likes

Wow, thank you so much! I will implement this in my code.

I don’t know either, but as a mnemonic if nothing more I have always thought it referred to the fact that movement of a glued instance is constrained to the 2d surface of a face. A very weak naming choice!

1 Like

I always thought it referred to the 2D axis that gets displayed…

john

I know that, you mentioned that before.
What I mean is: change the behavior through the UI to vertical/horizontal and any. And then check the value per setting. I know you mentioned zero. But maybe, maybe the value doesn’t change where you can see it (where you changed it through the API) but somewhere else where it has the desired effect. That would mean that there is a link missing.

It was actually quite simple. Like thomthom said in post #8, I missed the is2d property. When that property is set to true, it all works as expected.

When you do just this, the GlueTo value is not properly set:

component.definition.behavior.snapto = SnapTo_Vertical

But when you first set is2d to true, the GlueTo value is set as it should, and it is reflected in the UI as well.

component.definition.behavior.is2d = true
component.definition.behavior.snapto = SnapTo_Vertical
1 Like

From an API design point of view, if the snapping behavior can’t be set without gluing fist being enabled, wouldn’t it be possible for the API to at least warn when you are trying to do so? Raising an exception may not be a good idea as existing code could break from it.

Also, if any method in the API should be renamed/get an alias, it is is2d which really should be called something like gluable.

3 Likes

Sorry, I just missed Thomthom’s post above and answered your post above some 2h ago while things got resolved already.

One thing I need to correct about what I said in my second post:

This is only true (=not restricted to certain face orientations) for copies of a ‘Glue to’ component instance whareas a component picked in the component browser obeys the rules it is set to.