Hello.
I have this piece of code.
model.start_operation("Material change", true)
component_definition.set_attribute("dynamic_attributes", "material","red")
component_definition.material = "red"
model.commit_operation("Material change")
model.active_view.invalidate
model.active_view.refresh
After running the code, I don’t see any changes to the material.
But if I press Ctrl+S, the changes become visible.
You must have more code than the one you write.
model and component_definition are not declared as variables.
def selector(my_guid)
model = Sketchup.active_model
view = model.active_view
component_definition = model.definitions.find { |e| e.guid == my_guid }
if component_definition
model.start_operation("Material change", true)
component_definition.set_attribute("dynamic_attributes", "material","red")
component_definition.material = "red"
model.commit_operation
model.active_view.invalidate
model.active_view.refresh
end
end
What is your main purpose? Do you want to change the color of one selected component?
Can this code help you?
Sketchup.active_model.selection.each do |e|
e.material = "red" if e.respond_to?(:material)
e.back_material = "red" if e.respond_to?(:back_material)
end
1 Like
Thank you, but your code didn’t help. (
I think my problem is that the View is not refreshing.
Although I am trying to do this manually in my code.
dezmo
May 3, 2023, 6:16pm
7
perhaps…
...
component_definition.material = "red"
component_definition.set_attribute("dynamic_attributes", "material","red")
component_definition.instances.each{|inst|
$dc_observers.get_latest_class.redraw_with_undo(inst)
}
...
1 Like
The script runs without errors.
However, I can only see the changes after pressing the Ctrl+S keys or after the document is autosaved.
def selector(my_guid)
model = Sketchup.active_model
view = model.active_view
component_definition = model.definitions.find { |e| e.guid == my_guid }
if component_definition
#model.start_operation("Material change", true)
component_definition.set_attribute("dynamic_attributes", "material","red")
component_definition.material = "red"
component_definition.instances.each{|inst|
puts "redrawing model"
$dc_observers.get_latest_class.redraw_with_undo(inst)
}
#model.commit_operation("Material change")
#model.redraw_with_undo("Material change")
#view.redraw_with_undo("Material change")
#$dc_observers.get_latest_class.redraw_with_undo(component_definition)
#model.active_view.invalidate
#model.active_view.refresh
#model.selection.add(component_definition)
#model.active_view.zoom(component_definition)
puts "Material changed: #{component_definition.name} "
else
puts "Error: #{component_definition.class} "
end
end
component_definition.material = "red"
Do not set material property upon a component definition object.
It has weird behavior that is undocumented. For more see …
opened 03:43AM - 03 Jan 18 UTC
enhancement
Ruby API
SketchUp
logged
### SketchUp API: Ruby
### Bug Report
**1. SketchUp/LayOut Version:** 2016…
**2. OS Platform:** Win 7 SP1
**Describe briefly what you are doing and what is happening.**
**`Sketchup::ComponentDefinition`** inherits `#material` and `#material=` from **`Sketchup::Drawingelement`** ...
```ruby
Sketchup::ComponentDefinition.instance_method(:material=).owner
#=> Sketchup::Drawingelement
```
**Describe what the expected result is.**
We would expect (or hope) that the definition material was applied as a "initial paint" to any instances of the definition **immediately** when placed in the model.
**a. The definition material only shows whilst the definition is attached to the cursor.**
**b. The instances show as not having material assigned after insertion.**
**c. But the instances do not get painted with the definition's material until the model is saved.**
**d. The saving resets the definition material to `nil`**.
**e. Subsequent definition material assignment (for example to a different material) is applied to ALL instances upon the next file save, and not just the instances placed since new definition material assignment. Ie, the repaint also happens to instances manually painted by the user with other materials.**
```ruby
# Complete reprodusible code snippet. (Important!)
mod = Sketchup.active_model
#<Sketchup::Model:0x0000000bac5868>
ss = mod.selection
#<Sketchup::Selection:0x0000000bac4698>
ci = ss[0]
#<Sketchup::ComponentInstance:0x0000000b805b00>
cd = ci.definition
#<Sketchup::ComponentDefinition:0x0000000b805bc8>
cd.material = "Red"
#=> Red
```
### Ref public forum discussion:
https://forums.sketchup.com/t/apply-a-material-with-oncomponentinstanceadded/58645/5
https://forums.sketchup.com/t/apply-a-material-with-oncomponentinstanceadded/58645/6
https://forums.sketchup.com/t/apply-a-material-with-oncomponentinstanceadded/58645/21
### Feature Request
1. Formalize the use of the definition material property as an "initial paint" for **subsequently placed instances** but do not override instances already placed with or without material applied.
2. Apply the paint immediately upon instance insertion.
3. Allow a SHIFT + LMB modifier to insert with default material **`nil`** assigned instead of "initial" definition material.
4. Add a checkbox to **Model Info** > **Components** to reverse SHIFT key modifier to initial paint of instances (which then a bare LMB inserts unpainted instances as it always did.)
5. Do not reset definition material on model save.
6. Allow a GUI means of picking a definition's material for those in the "In Model" collection. (RMB + "Choose Material ...")
7. Show component painted with initial materials in browser thumbnail images.
8. Document **`material`** and **`#material=`** for the **`Sketchup::ComponentDefinition`** class, (just as was done for the **`Sketchup::Face`** class,) and explain the special behavior of a definition's material.
~
2 Likes
This implies then that you should set the material upon instance objects.
SketchUp comes with sample Dynamic Components that can change color.
With a DC, the default color is set in the definition’s dynamic dictionary, but if instances differ from the default, then the material attribute will be added to the instance’s dynamic dictionary.
DanRathbun:
This implies then that you should set the material upon instance objects.
SketchUp comes with sample Dynamic Components that can change color.
With a DC, the default color is set in the definition’s dynamic dictionary, but if instances differ from the default, then the material attribute will be added to the instance’s dynamic dictionary.
Can you give me an example of code? I’ve been trying to figure out my problem for several days, but I can’t seem to get it right. ((
dezmo
May 5, 2023, 12:30pm
12
#comment out:
#component_definition.material = "red"
#component_definition.set_attribute("dynamic_attributes", "material","red")
####
component_definition.instances.each{|inst|
#perhaps you need to add a condition if you do not want to paint all instances..
inst.set_attribute("dynamic_attributes", "material","red")
inst.material = "red"
}
1 Like
dezmo:
component_definition.instances.each{|inst|
#perhaps you need to add a condition if you do not want to paint all instances..
inst.set_attribute("dynamic_attributes", "material","red")
inst.material = "red"
}
Hooray, it works! Thank you very much!
1 Like
Of course, it works because the snippet is directly setting the instance’s material
property.
This is not really hooking into the DC functionality where the dynamic “material” attribute is controlling the instance’s material property.
Again, use an Attribute Inspector extension to interrogate one of the DC samples that comes with SketchUp.
P.S. - Please remove the solution for the topic as the discussion is continuing.
(It will get rid of the nag screen that the topic has been solved, which it really hasn’t.)
Also, there are numerous discussions on Ruby coding DCs in the forum’s Dynamic Components subcategory.
3 Likes