I have a problem with a bugsplat if I save a component in a separate skp file using the save_as method.
By now, I have noticed that the bugsplat can be prevented if I hold the mouse pointer not above the plot area (view) of Sketchup, but for example above the tray or the ruby console.
There is at that time a private tool active, but no observers.
Moreover, the save_as method still run correctly, but once the script is finished the bugsplat is there.
Anyone have any idea how to prevent this?
SketchUp version ?
OS platform and version ?
Minimum reproducible code example ?
Official API Issue Tracker is here ā¦
ā¦
Hmmm ⦠if the mouse is moved SketchUp may try to call the toolās onMouseMove
callbacks in the middle of the save operation.
I strongly suggest suspending your tool until the save operation is complete.
SU2018
Windows 10 Home
ruby_tool = Sketchup.active_model.tools.pop_tool()
if frame_definition.save_as("#{folder}/#{project_folder}#{self.code}.skp")
store_succes = true
end
if ruby_tool
# Do NOT prevent for bugsplat
Sketchup.active_model.tools.push_tool(ruby_tool)
# Do prevent, but tool must be reactivated by user
Sketchup.active_model.select_tool(nil)
end
Hi Dan,
How can i suspend a tool?
Simply by calling the suspend method?
:suspend
and :resume
are really about āorbitā and āpanā not your code flowā¦
I tend to wrap exports of any kind in a timer as some things run in a spawned threadā¦
If overwriting an existing file I use File.remove
firstā¦
def wait4export(export_file)
# check File.size() if the export is completed
@export_size = 0
wait_for_export = UI.start_timer(0.1, true) {
Sketchup.active_model.definitions[0].save_as(export_file) unless File.exists?(export_file)
export_size = File.size(export_file) rescue export_size = 1
if export_size != @export_size
@export_size = export_size
p export_size
else
UI.stop_timer(wait_for_export)
p 'export completed'
end
}
end
# to test change the path
test = '/private/tmp/test.skp'
wait4export(test)
EDIT: you will need to point to your component as wellā¦
By doing exactly what you did in the example above.
The suspend()
method is actually a SketchUp engine callback method that should have been named onSuspend()
, but was not. So you need to let SketchUp call those callbacks.
In your case, youād need to let the deactivate
and activate
callback methods to save and restore tool state. These are also called by the SketchUp engine, when you pop tool and push tool. (You do not call them directly.)
If SketchUp does not wait for the save_as()
to complete, then youād need to use a UI.start_timer
block to test when the component SKP fileās modified time is updated. See File::mtime()
class method. Once updated, you can then push your tool object back onto the modelās tool stack.
Please note how to post code in the forums ā¦
Thanks Dan!, pushing back the tool in a start_timer block is preventing a bugsplat. I wrote a special function for it.
def self.Save_As_With_Bugsplat_Prevention(component_definition, export_file)
# Get the active ruby_tool, by removing from tool stack
if !(Sketchup.active_model.tools.active_tool_id.equal? 0)
ruby_tool = Sketchup.active_model.tools.pop_tool()
else
ruby_tool = false
end
# Remove file if already exist
if File.exists?(export_file)
File.delete(export_file)
end
# Save the component to file
store_succes = component_definition.save_as(export_file)
# Push back last ruby_tool to tool stack.
if ruby_tool
# Check on File.size() if export is completed
previous_export_size = 0
wait_for_export = UI.start_timer(0.1, true) {
export_size_progress = File.size(export_file) rescue export_size_progress = 1
if export_size_progress != previous_export_size
previous_export_size = export_size_progress
else
Sketchup.active_model.tools.push_tool(ruby_tool)
UI.stop_timer(wait_for_export)
end
}
end
return store_succes
end
Thanks John, for timer example.
Iāll pick a nit for improvement of your future Ruby code:
You are using the fact that Ruby considers anything except the constants false and nil to be true in logic expressions. Many authors see this aspect of Ruby as muddy semantics since one can never be sure what ātrueā actually is. In your code, instead of setting
ruby_tool = false
Iād set it to nil. And then in the if expression to see if there is a tool to push, use
unless ruby_tool.nil? # or if !ruby_tool.nil?
for the branch that decides whether to pop the tool back.