Is anyone aware of a way to redraw a group of components or the entire model in one shot? I am finding that individually selecting and right clicking to redraw is tedious and it’s easy to miss a component in large models…
Sketchup.active_model.selection.grep(Sketchup::ComponentInstance).each do |s|
$dc_observers.get_latest_class.redraw_with_undo(s)
end
Open the Ruby Console (Window) and paste
This worked great. Added it with toolbar editor as an icon. Select the entire model and execute. Works like “regenall” in Autocad. Thanks!!
Hello Mike. Would it be possible tor run this script every time I click on DC using onClick tool? Thank you.
I think (but am not sure) that the DCInteractTool
will do a redraw for the single instance clicked, when it is appropriate to do so.
(If it does not, when it should, please open a bug report in the Technical Issues > SketchUp category.)
As to making it work upon ALL DC instances in the model, the answer is NO.
-
This tool is part of Trimble’s proprietary (and closed source) Dynamic Components extension, and changing it is a “no-no”.
-
Regardless, it also is not a good idea to modify a tool that acts upon a single object, to affect multiple objects.
There is a single instance redraw command in the right-click context menu (if you right-click on a instance that is a DC.)
Code to add a right-click command to redraw all instances of the right-clicked instance’s definition :
UI.add_context_menu_handler do |context_menu|
ss = Sketchup.active_model.selection
if defined?($dc_observers) && ss.single_object? &&
(ss[0].attribute_dictionary('dynamic_attributes') ||
ss[0].definition.attribute_dictionary('dynamic_attributes'))
context_menu.add_item("Redraw all these DCs") {
dco = $dc_observers.get_latest_class
ss[0].definition.instances.each {|i| dco.redraw_with_undo(i) }
}
end
end
(And no we cannot put the command on the DC edit submenu.
The API does not give access to previously defined menu objects.)
Thank you very much for info. I will try to get my head around it. Thanks again
Yep that was easy (because you’ve wrote all the code ) Just pasted into .rb file and now menu option is there.
So there is no script that listens to interact tool being clicked on DC? I am just in the beginig of getting involved with ruby.
Was a mistake in the first code post. Fixed it (above).
Ie, I had to check both the instance and the definition for a DC attribute dictionary.
There is a ToolsObserver
but it did not work all that well for native tools in the past.
However, this is a RubyTool and in a very recent release the Ruby tool names are now able to read by the observer. (In the past we’d only get "Rubytool"
or something similarly worthless.)
I do not think the engine calls ToolsObserver#onToolStateChanged
for Ruby tools.
Also, with the 2016 release, observers were overhauled cache up their callback queues and then do them all at once at the end of the tool’s action.
All in all, it’d be easier to write your own “Redraw” click tool to do this.
Thank. But the code only works with one component. If you select 2 or more components, there is no right-click redraw menu.
Here is a revised edition that will work on multiple selection …
# Redraw all selected (and siblings)
UI.add_context_menu_handler do |context_menu|
ss = Sketchup.active_model.selection
if defined?($dc_observers) && !ss.empty?
insts = ss.grep(Sketchup::ComponentInstance)
if !insts.empty?
dynatts = 'dynamic_attributes'
insts.select! {|i| i.definition.attribute_dictionary(dynatts) }
if !insts.empty?
cdefs = insts.map(&:definition).uniq
dco = $dc_observers.get_latest_class
context_menu.add_item("Redraw ALL sibling DCs") {
cdefs.each {|cdef|
puts "\nRedrawing Instances of: \"#{cdef.name}\"..."
cdef.instances.each {|i|
puts "Redrawing ... #{i.inspect}"
dco.redraw_with_undo(i)
}
}
}
context_menu.add_item("Redraw ONLY selected DCs") {
puts
insts.each {|i|
puts "Redrawing Instance of: \"#{i.definition.name}\"... #{i.inspect}"
dco.redraw_with_undo(i)
}
}
end # if DC instances were selected
end # if component instances were selected
end # if DC loaded and something is selected
end # context menu handler block
Thanks Dan! This helped me a lot!
Thanks 4 providing this
Hey @DanRathbun, is there a way to get this redraw to see DC’s inside a selected group or groups? For example I have the framing of a deck in a couple of different groups and I want to trigger a redraw on all of them. I do this to update some aspects of the DCs I use that seem to get stuck, like the material/colour in a concatenated description, or length of a piece lumber. A redraw fixes this, however going into each group to select and redraw is time consuming and I run the risk of missing something. What I want to do is select the whole model or part that I have been working on and redraw all of the DCs in the selected group(s) at once. I would also like to reset the nominal len XYZ in the same manner. Learning Ruby is on my list but time just hasn’t been available to get to it, any help you can offer is greatly appreciated. Thanks
Try this … (untested) …
ADD (2021-04-10): This file has been posted to this topic:
Force Redraw - #4 by DanRathbun
# Redraw all selected (and siblings)
UI.add_context_menu_handler do |context_menu|
ss = Sketchup.active_model.selection
if defined?($dc_observers) && !ss.empty?
insts = ss.grep(Sketchup::ComponentInstance)
grps = ss.grep(Sketchup::Group)
if !grps.empty?
grps.each {|grp|
insts.push(*grp.entities.grep(Sketchup::ComponentInstance))
}
end
if !insts.empty?
dynatts = 'dynamic_attributes'
insts.select! {|i| i.definition.attribute_dictionary(dynatts) }
if !insts.empty?
cdefs = insts.map(&:definition).uniq
dco = $dc_observers.get_latest_class
context_menu.add_item("Redraw ALL sibling DCs") {
cdefs.each {|cdef|
puts "\nRedrawing Instances of: \"#{cdef.name}\"..."
cdef.instances.each {|i|
puts "Redrawing ... #{i.inspect}"
dco.redraw_with_undo(i)
}
}
}
context_menu.add_item("Redraw ONLY selected DCs") {
puts
insts.each {|i|
puts "Redrawing Instance of: \"#{i.definition.name}\"... #{i.inspect}"
dco.redraw_with_undo(i)
}
}
end # if DC instances were selected
end # if component instances were selected
end # if DC loaded and something is selected
end # context menu handler block
It is the same as above, but after …
insts = ss.grep(Sketchup::ComponentInstance)
… I added these few lines …
grps = ss.grep(Sketchup::Group)
if !grps.empty?
grps.each {|grp|
insts.push(*grp.entities.grep(Sketchup::ComponentInstance))
}
end
It should separately “grep” groups from the selection set and then iterate them adding any nested component instances to the “redraw” collection.
This would be “a bit” off-topic for this thread. I do have a code snippet that is so old (it was from NOV 2020) … I cannot remember if it works or not. I’ll add the bit to “grep” groups and PM it to you so you can try it.
ADD: FYI, Ryan also had started the topic on resetting DC nominal length attributes …
- Len X is incorrect on redraw
… which is where the snippets in question came from.
Is there forum or web page where I can learn how to add this code to an icon as you did?
Is there forum or web page where I can learn how to add this code to an icon as you did?
hey Edwin, you can use Aerilius’s Toolbar Editor to execute ruby snippets, assign them to icons and make custom tool bars. Or you can start learning how to code ruby and build your own custom extension…