Hi community,
I’ve been trying for a few days to recreate the UX of the “Components” window.
Here’s the experience I want to create:
Users click on a model in my HTML extension which sends the URL of this model to Sketchup API.
Ruby downloads the model (a .glb file).
When the users move their mouse in the interface, an entity of the model follows the mouse.
When the user clicks, an entity is created at the location of the mouse.
I’ve been able to perform steps 1 and 2 (even importing the model). But I’m struggling with steps 3 and 4.
I have the intuition that I need to create a custom tool for that.
Do you have some ideas to achieve that?
P.S.: Here’s my current code
def self.show_dialog
# Define dialog properties
dialog = UI::HtmlDialog.new(
dialog_title: "Form3d",
# preferences_key: "form3d.extension",
width: 525,
height: 750 + 30, # 30px for the title bar
resizable: false,
scrollable: false,
style: UI::HtmlDialog::STYLE_DIALOG
)
# Point to the HTML file (output from Svelte)
html_file = File.join(__dir__, 'ui', 'build', 'index.html')
dialog.set_file(html_file)
dialog.add_action_callback("import_model") do |action_context, link|
import_model(link)
end
dialog.show
end
def self.import_model(link)
begin
# Create a temporary file with a .glb extension
temp_file = Tempfile.new(['model', '.glb'])
temp_path = temp_file.path
# Download the remote .glb file
URI.open(link, 'rb') do |remote_file|
File.open(temp_path, 'wb') do |local_file|
local_file.write(remote_file.read)
end
end
# Import the model into SketchUp
model = Sketchup.active_model
status = model.import(temp_path)
# Cleanup: Close and remove temp file
temp_file.close
temp_file.unlink
# Show success or failure message
if status
UI.messagebox("Model imported successfully from Form3D.")
else
UI.messagebox("Failed to import the model.")
end
rescue => e
UI.messagebox("Error: #{e.message}")
end
end
This is not really a tool interface; it is a command. Meaning, the code is basically sequential and does not act like a tool.
It does not use any tool callbacks, does not leverage the VCB (ie, Measurements toolbar) for offset input instead implementing an inputbox.
It does not have any tool states and does not stay in the tool and reset after each use like a tool interface should. (i.e., a tool would go back to the select edge or cline state as the initial tool state. A tool would reset when the ESC key is clicked.)
It does not set a cursor so it looks weird if the user uses custom system cursor scheme. Instead of the SketchUp select cursor, the system arrow cursor is shown. (I use extra large bright orange system cursor scheme that I drew many years ago. So I know immediately when a Ruby tool does not set the cursor.) This is avoided now that the code does not set the command interface as the active tool.
A tool generally uses interactive mouse movements and clicks or drags, often at multiple states (stages) of the task.
I’m not sure how you are trying to execute your code, but if you are pasting it into the Ruby Console, you need to then click in the model view to place the newly imported Component Instance. The place instance action of following the cursor is automatically invoked by model.import and the focus has to be in the view window for you to see it.
As noted, this is really a command, not a Tool because it is a once-and-done thing. But you still need a better way to launch it than pasting code into the Ruby Console. For that you should wrap it as a UI::Command and create a menu item and/or toolbar to fire the command.
Edit: PS I tried model#import with importing a skp file via the Ruby Console, and it worked as I described. So if you are doing that and your code is still failing, it is due to something else.
Instead use DefinitionList#import which should return a reference to the new component definition within the model’s definitions collection.
Then, using this definition reference, make a call to Model#place_component, which creates a new instance and attaches it to the mouse cursor.
(Take note that SketchUp automatically creates an undo operation with the Model#place_component method.)
Also, the SketchUp API has non-blocking HTTP classes. See:
Hi everyone,
There seems to be an issue happening only on macOS.
There’s an extra click that’s required to display the component.
From my understanding, this is related to this characteristic of Sketchup#active_model:
On the PC, this is the only model that one can have access to via the API, but Macintosh versions of SketchUp can have multiple models open at once, in which case the method will return the model that the user currently has focused.