I apologise in advance for potentially dumb questions as I’m new to Ruby development. In my previous life i did a lot of VB and C# prgramming for various graphic software. Now i’m trying to create couple of extensions for SU2020 but got stuck on VS Code configuration. I managed to configure start of SU from VS Code with required parameters and debugger connects to the SU process ok. But when I try to launch and investigate 01_hello_cube example (from here), i cant make it work. I.e. execution of the code doesnt start, breakpoint are not triggered, new extension doesnt appear in the menu. Actually I don’t understand where is the entry point in this code. It should be in ex_hello_cube.rb, but no breakpoint in this file is triggered, debugger is started but looks to be waiting for something. On this page it is mentioned that after starting debugger you need just to “return to SketchUp and use your extension”. But I dont understand how it can be done if extension registration code was not run yet.
Can this issue be probably related to environment configuration described on on Wiki page for development setup? Recommendation was to “Create a file in your Plugins folder: <…>/Plugins/!external.rb” that specify what additional directories to load. I was not able to make this configuration due to the lack of Plugins folder in SU2020.
Many thanks in advance for any assistance!
There should be a User %AppData% path “Plugins” folder, and can be a %ProgramData% path “Plugins” folder (depending upon what kind of extensions have been installed.) The former should have been created if you installed SketchUp by right-clicking the installer and choosing “Run as administrator”.
Both paths will be hidden from you unless you tell Windows not to hide them …
File Explorer > View > Hidden items (checkbox)
- check the box
… or …
Control Panel > File Explorer Options > View (tab)
- choose Show Hidden files, folders, and drives
When SketchUp starts it processes the several “Plugins” folders and evaluates the
.rb files it finds.
As explained in the documentation for the
SketchupExtension class, these data objects in registrar files are registered with SketchUp’s
ExtensionManager using the
Sketchup::register_extension() module method.
If the user’s load setting for a particular extension is set
true, the extension manager will (at the time of registration,) call the
SketchupExtension instance’s internal
#load method which is a glorified
Sketchup::require(@path) call with a little bit of other housekeeping.
(Note: You can actually read the
"extensions.rb" file yourself. It is located in the
"Tools" subfolder of SketchUp’s %ProgramFiles% folder.)
So, re “entry points”, since SketchUp Ruby is a subprocess of an application, SketchUp extension code objects are really event-driven code. An extension submodule defines it’s entry points as two kinds of things.
Direct user entry:
UI::Command objects assigned to Menu items or Toolbar buttons; context menu procs, or Importers chosen from the native import dialog. The user directly causes a part of the extension code to execute by purposefully choosing a task such as clicking a menu item, clicking a toolbar button, hitting a particular assigned keychord shortcut, or choosing a file of a certain type to import from a browse dialog.
Often a command might active a custom Ruby
Tool that the extension implements.
- For simplicity in development, command procs should normally call a command method so that bugs can be fixed, the code can be reloaded, the method redefined and retested without having to exit and restart SketchUp.
Indirect event entry: The various Observer classes allow extensions to “piggyback” upon application, model, collection or entity events. These are indirectly caused by the user during normal application use such as opening a model file for edit, selecting entity objects, making edits, changing options, manipulating the viewport, loading resources, saving models, closing the application, etc.
So for SketchUp extensions, the code objects are modules (your top level unique Namespace module wrapping extension submodules) that have command methods waiting for users to fire them, or observers watching either the application’s objects or a model’s objects (collections and/or entities.)
This is event driven code.
It is possible when your modules load to have code evaluated to setup things. This setup code is not within methods or procs.
That is exactly what i was looking for! And I missed that part in documentation. Conception of event driven code is well clear, I just could make registration properly, that was a missing entry point.
Now it works like charm! With “wait” parameter on SU starting task it is even possible to hook on extension registration process.
Many many thanks for your detailed explanation!
Have you looked at our VSCode project example?