Did a quick look. You are violating several cardinal rules for an extension in a shared environment.
ALL of your extensions need to be within a unique top level namespace module.
No top level classes! Only Ruby and rarely the API should define top level (ie, global classes.)
Any classes that you define should be within the specific extension submodule that uses them.
Ie, separate your extensions from one another … each to their own submodule.
Do not add separators to the main “Extensions” (aka “Plugins”) menu.
Instead create a submenu and add separators on it to your heart’s content.
(The main menus should automatically add a separator at the end of native commands so we do not have to. NOTE that the core is likely not doing this yet for us. We had a discussion on it recently.)
The name of the extension subfolder must be the same name as the extension registrar script:
I am showing "AlanChatham_FPSNav.rb"
for the registrar and "AlanChatham_FPSNav/"
for the folder in the example below.
What we usually recommend is that the registrar and folder name be a “_” joined string of the namespace module identifier and the extension submodule identifier. So as shown below the name could also be "AlanChatham_FPSNavigation"
but not this important as it’s all within your namespace.
What I do question is the wisdom of putting all that help text in the Extension description. Does the Extension Manager even display all that much text ? I would suggest putting the help text in a multiline UI::messagebox
instead.
# AlanChatham_FPSNav.rb
module AlanChatham
module FPSNavigation
EXTENSION = SketchupExtension.new("FPSNav", "AlanChatham_FPSNav/FPSNav.rb")
EXTENSION.instance_eval {
self.version = '0.4'
self.copyright = "2021"
self.creator = "Alan Chatham"
self.description = "First-Person Shooter Style Navigation.".concat(
" When active, move with the arrow keys; alternately, hold 'Shift' and move with WASD, or use the numeric keypad.",
" Movement is restricted to the X-Y Plane.",
" Pressing Shift + Q will move you down in the Z direction, and Shift + E will move you up.",
" Alternatively, 7 and 9 on the numeric keypad do the same",
" Left-click the mouse and hold to look around",
" Double-clicking also toggles mouselook on.",
" Movement speed and mouse sensitivity can be found in the 'Plugins/FPSNav Options' menu."
)
Sketchup.register_extension(self, true)
}
end # extension submodule
end # top level namespace
Ruby Conventions
Minor, but Ruby convention for method names is all lower case with underscores between words.
CamelCase is reserved for Class and Module identifiers. (Ruby does not enforce this rule because of special scenarios where external libraries are wrapped that use the same Ruby method identifier as in for example a C or Visual Basic library.)
Ruby uses 2 space indentation. It looks like you used TAB characters and when pushed to GitHub they used the default 8 space width. In most good code editors you can set the editor to replace TAB with space characters per coding language. (ie, 4 for JavaScript and HTML, 2 for Ruby, 4 for Python, 8 for C, etc. …)
Anyway if replaced with spaces, copying and pasting snippets into the forum will be displayed correctly when needing help with code.
When defining a class, only class methods are defined using the self.
prefix.
In the case of a SketchUp Ruby Tool class, the class methods you have defined should actually be methods of the extension submodule wrapping the Navigator
class.
# FPSNav.rb
module AlanChatham
module FPSNavigation
# Extension options methods setting choices to @@opts
class Navigator
def initialize(opts)
# The @@opts Hash passed into the ::new constructor
@opts = opts
end
# The tool's instance methods ...
end # custom tool class
if not defined?(@loaded)
# define command object(s)
# define menu items and toolbars
@loaded = true
end
end # extension submodule
end # top level namespace
Weirdly you are not using the UI::Command
for you tool for the menu item.
It should be used for both the toolbar button and the menu item.
The command proc should also call the same command method (fpsNavTool
) for debugging and testing purposes. (Ie, you cannot redefine the proc for a UI::Command
or menu item by reloading the file, but a method can be redefined dynamically. So if these procs point to a method, that method can be changed, the file loaded, testing resume… without having to close and restart SketchUp.