Custom Select Tool That Displays Tag Name

Just experimenting…

I have implemented this using onSelectionBulkChange but it requires me to actually click on the entity to get the tooltip to display the tag name.

So looking at the script class ToolTests, the following will display for me a tooltip with the tag name (I know that there is an extension that does this).

def onMouseMove(flags, x, y, view)
	ph = view.pick_helper(x, y)
	entity = ph.best_picked
	layer = entity.layer
 	view.tooltip = layer.name
end

I’ve been trying to build on the above (so far unsuccessfully) so that I can also select in the same way as the native select tool.

Can someone give me some pointers to what I should be looking at…?

Thanks

1 Like

You need to be careful because moving over the axes will produce a NoMethodError (undefined method 'layer" …)

module Testing
  class LayerSniffer

    CURSOR ||= 633 # SelectionTool cursor

    def self.use
      Sketchup.focus rescue nil
      Sketchup.active_model.select_tool(self.new)
    end

    # TOOL CALLBACKS:

    def activate
      view = Sketchup.active_model.active_view
      view.tooltip = ''
      view.invalidate
    end

    def deactivate(view)
      view.tooltip = ''
      view.invalidate
    end

    def onMouseMove(flags, x, y, view)
      ph = view.pick_helper(x, y)
      entity = ph.best_picked
      return unless entity && entity.respond_to?(:layer)
      view.tooltip = entity.layer.name
      view.invalidate
    end

    def onSetCursor
      UI.set_cursor(CURSOR)
    end

  end # tool class
end

From the console, a menu item or a toolbar button …

Testing::LayerSniffer.use

Another suggestion might be to also display the information on the status bar
as the tooltip text can be quite small.

Add to end of onMouseMove callback …

if entity.respond_to?(:name)
  Sketchup.status_text= "#{entity.name} layer: #{entity.layer.name}"
elsif entity.respond_to?(:typename)
  Sketchup.status_text= "#{entity.typename} layer: #{entity.layer.name}"
else
  Sketchup.status_text= "#{entity.class} layer: #{entity.layer.name}"
end

And at the end of the deactivate callback …

  Sketchup.status_text= ""
1 Like

Thanks Dan, especially this…

2 Likes

I’m able to select and can select using PickHelper - PICK_CROSSING and PICK_INSIDE but I’m trying to work out how to replicate the visual representation of the selection rectangle…

select

I’ve been looking at linetools and also the rotated rectangle tool.

Am I looking in the right direction or is there something (simpler?) that I’m missing?

Oh, I missed that you were doing a select tool. I thought it was a inspection kinda tool.

Do you mean the solid left to right and dotted right to left boxes in screen space ?

yes, the solid and dotted screen space boxes

You have to use the View#draw method (or it’s siblings.)

Before drawing (in the #draw method of your tool,) set the line color and stipple with View#drawing_color= and View#line_stipple= setters.

If you want black then it’s the default. Solid is the default stipple.

Thinking a bit (out loud) …

So then the PickHelper does not actually draw the pick box.

Your onMouseMove callback is going to feed the temporary 2nd point (@pt2) for drawing the pick box as the user moves the mouse.

So your draw method needs to know what state your tool is in. (0 for initial state, 1 for when the @pt1 is picked and the pick box needs to be drawn.)
After the 2nd pick and the selection has been done the tool likely should reset to the initial state.

The #window_pick method is called after the user picks the 2nd point in your onLButtonUp callback.
(Ie, this callback should be the state changer for your tool instance.)

EDIT: When I talk of points above, I’m meaning 2D x, y coordinates in screen space.
It will be a test of @pt2.x - @pt1.x to determine what window pick mode and stipple to use.
If positive use solid stipple (PICK_INSIDE), if negative dashed stipple (PICK_CROSSING).

Again, thinking out loud …

I need to modify this previous statement. You can actually call the #window_pick method as often as you like to discern if there has been a valid pick. (Ie, you can call it each time the mouse moves if you need to.)

If you do a window pick with the native tool you’ll see that nothing is added to the selection until after the left mouse button is released. (For whatever this is worth.)

That’s very helpful Dan.

You’ve distilled clearly what I’ve been vaguely mulling over.

1 Like

:smiley:

Got a rudimentary working script drawing a selection box - just need to work through the window pick mode and ctrl & shift modifiers…

2 Likes

Here’s a short code example of mimicking the box select.

https://github.com/SketchUp/api-issue-tracker/issues/640#issuecomment-858441049

It’s intended to show a bug so it is quite simplified, but attempts to change the line stipple similar to native Select. There is also a comment explaining how lines are drawn. For this example I simply drew the full rectangle as a closed loop, but SU is a bit smarter and draws lines individually from the direction of the starting point to the current mouse position, so the stipple isn’t shifted when the mouse moves (SketchUp is full of those small details :heart: ).

2 Likes

Thanks Christina.

That’s more or less what I’ve done but your code is more concise and not clunky like mine!

So that bug that Christina refers to where PICK_INSIDE selects a component if one of its sub components is fully inside the window, is annoying!

And the other issue that has cropped up is that there is no API ability to open a group for editing.

But I found the Windows hack method…

def open_group
	sel = Sketchup.active_model.selection
	if sel.length > 1
		return
	else
		if sel.empty?
			return
		else		
		first_sel = sel[0]
			if first_sel.respond_to?(:definition)
				require "win32ole"
				shell = WIN32OLE.new('WScript.Shell')
				shell.SendKeys('{ENTER}')
			end
		end	
	end
end

The above works as a standalone module but if I include it in def onLButtonDoubleClick it doesn’t work.

This is no longer true. A setter method was added for the 2020.0 release. See …

You should have a platform guard on the require "win32ole" call.

In order to work you must make sure that the SketchUp application window has the focus.
If the console or a web dialog has the focus then sending ENTER will not work.

1 Like

The native selection tool must be the active tool (in order for the ENTER hack to work.)

ok :slightly_frowning_face:

I looked briefly at:

Sketchup::Model#active_path=
Sketchup::InstancePath

And couldn’t get anywhere - I’ll have another look.

Thanks

I think the setter also takes a plain Array.

So if the current selection had a single object at the model level, and it responds to :definition then to open it for edit …

 model.active_path= [selection.first]

If it is not at the top level, then model.active_path will return an array and not nil, so …

if model.active_path.nil?
  # At top level
  model.active_path= [selection.first]
else
  model.active_path= model.active_path << selection.first
end

Just thinking out loud, while it is a great learning experience to re-implement a SketchUp tool, it often isn’t necessary. Maybe you could display the info you are interested in in a HtmlDialog, and have it work independently of whatever tool is active.