I am working on automating a large amount of SketchUp files that require running a few commands from installed extensions.
Is there a way to find out the commands that are available in an extension and run them?
An example of one of the steps would be the last step of exporting the file into GLB using the SketchUp glTF Exporter by Evan Prananta. The command that I am looking to run is under Extensions > SKP glTF Exporter > Export Binary glTF 2.0
I am assuming this is a registered command somewhere withing the SketchUp environment, just need help finding out how to access it.
SketchUp has no direct way of invoking a specific command using the API. It might be possible to directly call whatever the command would call, but this requires knowledge of the internal workings of the extension. Even for an open source extension it’s fragile as method names can change, and for a proprietary extension the developer may not want you to poke around in there. You could however try reaching out to the author and see what they say. Maybe they are okay with exposing a set of simple commands publicly.
Assign a keychord shortcut via the Shortcuts panel of the Preferences dialog.
Via the Ruby WIN32OLE library class, use the SendKeys method of the Windows Scripting Host’s Shell object to send the keychord to the SketchUp application. (The main window needs to have the focus in order for the keychords to be accepted.)
Example, say that you have assigned the keychord CTRL+F8 to the above menu item command:
module ShawnFrueh # <---<< top level namespace module
module SomeNiftyTasks # <---<< extension submodule
extend self
def export_gltf_binary
require 'win32ole' unless defined?(WIN32OLE)
shell = WIN32OLE.new('WScript.Shell')
Sketchup.focus
shell.SendKeys("{^F8}")
end
def do_task
# ... preliminary stuff here ...
export_gltf_binary()
end
end
end
The above is MS Windows platform only.
You can use utilities such as “cliclick” on Mac OS platform to send keychords to an application.
The Obvious: Since users subjectively assign shortcut keychords as they will, this paradigm is not well suited for public use in a distributed extension.
The array of shortcut strings form Sketchup.get_shortcuts can be examined and find out what shortcut is assigned to the specific plugin…
(But still, this is not well suited.)
FYI: This has changed with the release of SketchUp 2022.0.
The API added the UI::Command#proc instance method to get the Proc object attached to a command.
If the extension created a UI::Command object then it’s proc can be called.
commands = ObjectSpace.each_object(UI::Command).map(&:itself)
glb_export = commands.find { |cmd| cmd.menu_text == 'Export Binary glTF 2.0' }
if glb_export && glb_export.respond_to?(:proc) # nil if not found
glb_export.proc.call
end
But if the extension author only used Sketchup::Menu#add_item then this will not work as the menu interface does not automatically create command objects (as of the 23.0 release.)
@DanRathbun this was helpful to understand, thanks! I wonder if there’s a way to see in which module/class the proc derives from. Alternatively I used the path within the small_icon to provide a more robust filter. The icon is likely to be located in same plugin directory.
commands = ObjectSpace.each_object(UI::Command).map(&:itself)
commands.each do |cmd|
if (cmd.small_icon.include?("SomePluginDirectoryName") && cmd.menu_text == 'Export')
cmd.proc.call
break
end
end
Unfortunately for the plugin mentioned above, it looks like the dev used Sketchup::Menu#add_item. It worked for my case as I’m working with a different plugin/scenario.
Only method objects have an #owner method to tell this.
The closest you’ll get is the Proc#source_location method which will return the path to the ruby file as the first member of the array returned. From that you can get the directory name …