[Example] An extension registrar file that checks for and loads Dynamic Components.
This is a dummy example extension (has no functions) other than to check for and attempt to load the Dynamic Components extension before it loads it’s own extension code.
This might be needed if the extension references any Ruby objects defined by the DC extension.
If the DC extension cannot be found or loaded, this extension will not load itself, output console messages and display a popup notification in the lower-right corner.
The registrar file without the dummy "main.rb"
and icon file:
# encoding: UTF-8
# An sample extension registrar file that requires Dynamic Components. If the
# user has switched off the Dynamic Components extension, then this registrar
# file will reenable it and make it load.
#
# Assumes this registrar file name is: "SomeCompany_ExtensionNeedsDC.rb" and
# that the extension subfolder is named: "SomeCompany_ExtensionNeedsDC" and
# contains a loader file named "main.rb" (or "main.rbe" if encrypted.)
#
# In practice, the programmer will change the top-level namespace module name
# and the extension submodule name as necessary, then enter valid properties
# for the EXTENSION data object.
# DEPENDANCY - Allow the DC extension registrar script to be evaluated first:
load_error = nil
begin
require 'su_dynamiccomponents'
rescue LoadError => load_error
puts load_error.inspect
end
module SomeCompany
module ExtensionNeedsDC
VERSION ||= "1.0.0"
KEY ||= Module.nesting[0].name # A key for saving defaults, options, etc.
@notice = nil
# Instantiate a SketchupExtension data object:
EXTENSION ||= SketchupExtension.new(
KEY.gsub('::','_'), # <--<<< The extension name for the Extension Manager
"#{KEY.gsub('::','_')}/main"
)
# Set the extension data properties:
EXTENSION.instance_eval {
self.version = VERSION
self.creator = "Author at SomeCompany"
self.copyright = "©2025, SomeCompany, LLC"
self.description = "An extension does nifty things for SketchUp modeling."
}
# Checks if the DC extension is already loaded, if not attempts to load it.
# @return [nil] If the DC extension could not be found.
# @return [Boolean] If the DC is loaded, false if it is not loaded.
def self.is_dc_extension_loaded?
# Make sure that the DC extension is loaded:
if defined?($dc_extension)
dc_name = $dc_extension.name
dc_extn = $dc_extension
else
if defined?($dc_strings)
dc_name = $dc_strings["Dynamic Components"]
else
text = LanguageHandler.new("dynamiccomponents.strings")
# If text.strings is empty the file could not be found so, the
# lookup hash is empty and text[] returns the argument unchanged.
dc_name = text["Dynamic Components"]
end
dc_extn = Sketchup.extensions[dc_name]
end
if dc_extn # nil if not found
# If not loaded, then check it to load it:
if dc_extn.loaded?
puts "#{KEY}: The #{dc_name} extension is loaded. All is good."
return true
else
puts "#{KEY}: Attempting to load the #{dc_name} extension ..."
dc_extn.check # loads the extension's files
if dc_extn.loaded? # true | false
puts "#{KEY}: The #{dc_name} extension is now loaded. All is good."
return true
else
return false # message will be output in load_conditionally()
end
end
else
return nil
end
#
end ### is_dc_extension_loaded?()
# Loads the EXTENSION upon the condition that the Dynamic Components
# extension is loaded. If not, display console messages and a popup
# notification to the user in SketchUp's bottom right corner.
def self.load_conditionally
# If this EXTENSION's extension code references any of the DC modules
# or classes, then make sure that the DC extension is loaded before this
# EXTENSION is registered because it will then load and likley produce
# a NameError exception, etc.
success = self.is_dc_extension_loaded?
if success
Sketchup.register_extension(EXTENSION, true)
else
# If EXTENSION was registered in a previous session & the user had it
# switched on in Extension Manager, then it will still load & override a
# false load arg in:
# `Sketchup.register_extension(EXTENSION, false)`, so we skip registration.
#
# Notify the user that the DC extension is required:
if success.nil?
action = 'found'
elsif success == false
action = 'loaded'
end
message = "#{KEY}: The Dynamic Components extension could not be #{action}.\n\n"
puts message
EXTENSION.define_singleton_method(:error) { message }
# Show a popup UI::Notification informing the user:
preamble = %["#{EXTENSION.name}" requires the \r\n] +
%[ Dynamic Components extension, but it could \r\n]
message = preamble + " not be #{action}!\r\n"
@notice = UI::Notification.new(EXTENSION, message)
icon = File.join(__dir__, KEY.gsub('::','_'), 'warning48.png')
#puts icon
#puts "exist: #{File.exist?(icon)}"
@notice.icon_name = icon
@notice.show # for 10 seconds max 2021.1+
end
end ### load_conditionally()
# Later cleanup:
UI.start_timer(120.0, false) {
puts "#{KEY}: Cleaning up ..."
@notice = nil if @notice
remove_instance_variable :@notice
singleton_class.undef_method :is_dc_extension_loaded?
singleton_class.undef_method :load_conditionally
}
# Attempt to load EXTENSION:
self.load_conditionally
end # extension submodule
end # top-level namepsace module
raise(load_error) if load_error