Initial load of extension and menus


#1
  1. Where would I ever need to call: SketchupExtension.check? Unless I wanted to load some other extension? And normally user checking an extension requires a Sketchup reboot anyhow.

  2. Why do many extensions test to see if menus are already loaded? In the current implementation I don’t see how that can happen unless developer reloads from console.

Maybe these are holdovers from previous versions?


#2

You can establish if an Extension is loaded:

Extension.loaded?

If it’s not you can ‘check’ its tick-box - a poor wording IMHO.

Extension.check

It will load in that session [and thereafter], without needing a SketchUp restart.
If it is ‘active’ [loaded] and you want to ‘disable’ it so that it is not auto-loaded after a SketchUp restart, then use:

Extension.uncheck

The equivalent of removing the tick from the box.

You only need these if your Plugin seeks to enable/disable Extensions - the SketchUcation Extensions Manager is one such tool [in the SCF PluginStore toolset…]


Chances are that your Plugin/Extension won't ever make duplicate menu or toolbar entries. Simply because it is likely to only load once as SketchUp starts. However, when testing your tool's new or edited code, then the `file_loaded[?]` method is useful - it allows you to reload your code multiple times from the Ruby Console, without restarting SketchUp, and only get one set of menu/toolbar entries. Also if you RE-install an already loaded script [e.g. from an RBZ] and it is then auto-loaded, clearly there is a possibility that it could make its menu/toolbars again, unless it checks for the `file_loaded?` to avoid that. It's good practice to add the `file_loaded?` trap, but it is not essential. It is set up by `require('sketchup.rb')` so include that BEFORE using any `file_loaded` code...

I’d recommend you do it.


#3

Thanks for the info.

I’m not checking for already loaded menus, I do get them doubled if I load my load.rb from the console. However If I uncheck my extension in preferences window (“disabled but not unloaded”) then check it again I don’t get a reload. (?)

In the rare case you describe you could get a double load of menus. But that would be fixed on next Sketchup reboot.

The examples of menu loaders I see don’t use file_loaded? they set a variable after menu add and test it before menu add, but since the variable is tested before it’s set I just get “undefined local variable.”(?) So I don’t understand how that can work.


#4

They are maybe not using local variables (local variables will anyways be lost as soon as Ruby execution leaves the method scope; and local variables outside of a method cannot be persistent at all).

Module variables (or class instance variables) are initialized with nil when ever one calls a non-existing variable. A safe way to test for a variable/constant that has not been defined is defined?(MyUninitializedConstant).

What speaks against using file_loaded? as all most the other developers do?


#5

If you ‘uncheck’ a loaded Extension and then ‘check’ that Extension again, then it doesn’t reload, it’s already loaded.
You will need to force the ‘load’ - as explained below…
Let’s say you extension is named ‘SuperWidget.rb’, it has a subfolder named ‘SuperWidget’.
In there is a file named ‘SuperWidget_code.rb’ which is what the Extension [say it’s named ‘SuperWidget’] which is set up in ‘SuperWidget.rb’ loads.
When ‘SuperWidget.rb’ is loaded [as Sketchup starts] it makes the Extension ‘SuperWidget’, and checks for its ‘state’.
If it’s ‘checked’ in loads ‘SuperWidget_code.rb’ - making menus etc.
If you ‘uncheck’ it later on [manually OR in code] then it cannot ‘unload’ its contents/menus etc - it’s not [readily] possible in the way Ruby works.
So the ‘SuperWidget’ Extension remains loaded, although is now ‘unchecked’.
If you now ‘check’ it [manually or in code] then nothing happens as SketchUp has already loaded the Extension’s code and it knows it.

If you have ‘unchecked’ its Extension, then when SketchUp restarts it does not load ‘SuperWidget.rb’ - no menus are made etc.
If however, if it was initially ‘unchecked’ but you then ‘checked’ it [manually or in code] then SketchUp sees that the Extension is not yet loaded, and so it then loads it.


To force a “reload” of your code whilst testing do not try to:
load 'SuperWidget.rb'

It will not do anything if its code is primarily involved in its Extension set up: rather use:

load 'SuperWidget/SuperWidget_code.rb'

Loading this WILL reload that file’s code.
Unless you have correctly used file_loaded in that file’s menu creation code you will get duplicate menu entries created when you load it again.
You cannot add to a preexisting menus once SketchUp has started.
However, new menu can/will be created when code is [re]loaded unless a file_loaded trap is used.
You will not get/see additional buttons in existing toolbars, irrespective of the file_loaded set up.
You may get duplicated toolbars, if you have changed the ‘name’ of the toolbar in the loading code.


#6

Be aware that many old examples use the very poor practise of creating global variables just to track whether their menuitems have been “loaded”.

Any variable used only by a specific plugin, should be a module or instance variable, within the plugin module’s namespace.

Ex:

module Author
  module SomePlugin
    @@menu_loaded ||= false

    # lots of plugin code

    unless @@menuloaded
       # load the plugin's menuitems here
       @@menu_loaded = true
    end

  end # this plugin's namespace
end # this author's namespace

#7

I do, and wrote an extensive topic at SCF on this.

  1. using file_loaded?() creates the dependency upon the "sketchup.rb" file, which causes the need to insert a require("sketchup.rb") statement in your file, somewhere before making any calls to methods that are defined within it. (If you follow good practise, that is.)
  2. All the functionality defined within "sketchup.rb" is long overdue to be properly baked into the API, within the appropriate modules and classes. (For instance, file_loaded?() is better added as an extension to the Kernel module,… but only if it is deemed indispensable. But I personally think this kind of functionality, would be better as a mixin module.)
  3. file_loaded?() is misnamed, because it does not really check whether any file has been loaded. So therefore misleading. All it does is check if the string argument exists within a global array (also defined within "sketchup.rb", which again highlights [1] above.)
    The argument does not need to be some long exact pathstring. I used to use a nesting scope name such as "MyAuthorModule::ThisPlugin:ThisfileName" because of number 4…
  4. file_loaded?() uses the $loaded_files array (defined within "sketchup.rb",) which is global. Any script can change it. There exists the possibility of different coders using the same arguments. Any script could wipe out the entire contents of the global array.
    This is why I suggest that a plugin author create their own file_loaded?() method and @@loaded_files array within their own author namespace. (They can be called something more appropriate, like @@loaded_plugins.)

By now you should know that I feel that "sketchup.rb" should be retired.

I’ve felt that way since the first year I began using SketchUp back in the original v7 release.

If you do a search at SCF on “sketchup.rb must die”… you’ll find my old rants on this subject.