Could anyone help me with my highlight detect tool, please.
The issue lies with the nested components, which are being drawn in the wrong position. I believe it has something to do with the transformations. Notice that my code contains two ‘draw’ methods where I attempted to fix this. Comment and uncomment them to test as needed.
Steps for testing:
- Place the script in the ‘Plugins’ folder of SketchUp.
- Go to the Extensions menu and click on ‘Highlight Tool with Hidden Detection 2’.
- Hover the mouse over the component in the model I sent as an example. (Notice that there are nested components; try to target them).
module MyHighlightTool
module HighlightTool
class Highlighter
def activate
@hovered_entity = nil
@bounds_color_visible = Sketchup::Color.new(0, 255, 0, 128) # Semi-transparent green
@bounds_color_hidden = Sketchup::Color.new(255, 0, 0, 128) # Semi-transparent red
end
def deactivate(view)
clear_highlight(view)
end
def onMouseMove(flags, x, y, view)
model = Sketchup.active_model
active_entities = model.active_entities
entities = active_entities.grep(Sketchup::ComponentInstance).concat(active_entities.grep(Sketchup::Group))
unless @hovered_entity.nil?
definition_entities = @hovered_entity.definition.entities
entities = definition_entities.grep(Sketchup::ComponentInstance).concat(definition_entities.grep(Sketchup::Group))
end
process_entities(entities, x, y, view)
end
def process_entities(entities, x, y, view)
return if entities.nil?
# Converts mouse position to a 3D radius
ray = view.pickray(x, y)
# Checks all entities (visible and hidden)
closest_entity, closest_distance = nil, Float::INFINITY
entities.each do |entity|
next unless entity.is_a?(Sketchup::ComponentInstance) || entity.is_a?(Sketchup::Group)
# Ignore excluded entities or entities without valid bounds
next unless entity.valid? && entity.bounds
# Checks if the radius reaches the entity's bounds
hit_point = bounds_ray_intersection(entity.bounds, ray)
if hit_point
distance = hit_point.distance(ray[0]) # Calculates the distance between the origin of the ray and the hit
if distance < closest_distance
closest_entity = entity
closest_distance = distance
end
end
end
# Updates the entity under the mouse
if closest_entity != @hovered_entity
@hovered_entity = closest_entity
view.invalidate
end
end
def onLButtonDown(flags, x, y, view)
puts "onLButtonDown: flags = #{flags}"
puts " x = #{x}"
puts " y = #{y}"
puts " view = #{view}"
print
end
def print
unless @hovered_entity.nil?
puts @hovered_entity
puts @hovered_entity.is_a?(Sketchup::ComponentInstance)
if @hovered_entity.name.nil? || @hovered_entity.name.empty?
puts @hovered_entity.definition.name
return
end
puts @hovered_entity.name
end
end
def draw(view)
return unless @hovered_entity
bounds = @hovered_entity.bounds
color = @hovered_entity.visible? ? @bounds_color_visible : @bounds_color_hidden
# Draw filled faces
draw_filled_faces(view, bounds, color)
end
# def draw(view)
# return unless @hovered_entity
# # We obtain the global transformation of the entity
# global_transformation = @hovered_entity.transformation
# bounds = @hovered_entity.bounds
# color = @hovered_entity.visible? ? @bounds_color_visible : @bounds_color_hidden
# # Transforms the bounding box coordinates to global space
# transformed_bounds = transform_bounds(bounds, global_transformation)
# # Draws filled faces in global space
# draw_filled_faces(view, transformed_bounds, color)
# end
def transform_bounds(bounds, transformation)
transformed_corners = (0..7).map do |i|
bounds.corner(i).transform(transformation)
end
transformed_bounds = Geom::BoundingBox.new
transformed_corners.each { |corner| transformed_bounds.add(corner) }
transformed_bounds
end
private
# Checks the intersection between the radius and the planes of the BoundingBox faces
def bounds_ray_intersection(bounds, ray)
planes = bounding_box_planes(bounds)
planes.each do |plane|
hit_point = Geom.intersect_line_plane(ray, plane)
# Checks if the intersection point is inside the BoundingBox
return hit_point if hit_point && bounds.contains?(hit_point)
end
nil
end
# Generates BoundingBox plans
def bounding_box_planes(bounds)
[
[bounds.corner(0), bounds.corner(1), bounds.corner(2)], # Face inferior
[bounds.corner(4), bounds.corner(5), bounds.corner(6)], # Face superior
[bounds.corner(0), bounds.corner(4), bounds.corner(5)], # Face lateral 1
[bounds.corner(1), bounds.corner(5), bounds.corner(6)], # Face lateral 2
[bounds.corner(2), bounds.corner(6), bounds.corner(7)], # Face lateral 3
[bounds.corner(3), bounds.corner(7), bounds.corner(4)] # Face lateral 4
]
end
# Draw filled faces
def draw_filled_faces(view, bounds, color)
view.drawing_color = color
# Defines the faces of the BoundingBox
faces = [
[bounds.corner(0), bounds.corner(2), bounds.corner(3), bounds.corner(1)], # Lower face
[bounds.corner(4), bounds.corner(5), bounds.corner(7), bounds.corner(6)], # Top face
[bounds.corner(0), bounds.corner(3), bounds.corner(7), bounds.corner(4)], # Side face 1 left
[bounds.corner(1), bounds.corner(5), bounds.corner(6), bounds.corner(2)], # Side face 1 right
[bounds.corner(0), bounds.corner(4), bounds.corner(5), bounds.corner(1)], # Side face 3 front
[bounds.corner(3), bounds.corner(2), bounds.corner(6), bounds.corner(7)] # Side face 3 bck
]
# Draws each face as a polygon
faces.each do |face|
view.draw(GL_POLYGON, face)
end
end
# Clears the highlight
def clear_highlight(view)
@hovered_entity = nil
view.invalidate
end
end
unless file_loaded?(__FILE__)
UI.menu("Plugins").add_item("Highlight Tool with Hidden Detection 2") {
Sketchup.active_model.select_tool(Highlighter.new)
}
file_loaded(__FILE__)
end
end
end
Thank you in advance to everyone who can help…
highlight_tool.skp (14.8 KB)
highlight_tool_hidden_detection.rb (4.4 KB)