How can I lock the mouse pointer in a plane?

Hello Guys,
In my model, I have a face and plane of this face (plane1 = face1.plane). Now I wish my mouse just can select some points inside this plane. Would you please help me with it?
Thank you in advance.

Within your tool, you would use InputPoint#degrees_of_freedom to test that the points the tool is getting is from a face.

You can also use Geom::Point3d#on_plane? to test the inputpoint.

1 Like

I guess the
Geom::Point3d #project_to_plane instance_method
you are looking for…

Something like this you can start from…

class TestTool
  def initialize
    @ip = Sketchup::InputPoint.new
  end

  def onMouseMove(flags, x, y, view)
    # assuming the plane is already defined ( @plane)

    @ip.pick(view, x, y)
    projected_point = @ip.position.project_to_plane( @plane )
    @ip = Sketchup::InputPoint.new(projected_point)
    
    
    #
  end
end
1 Like
module MM
  module MA
    class MB
      def activate
        @ip = Sketchup::InputPoint.new
        @ip_help = Sketchup::InputPoint.new
        @pt = []            # Point
        @mp = @ip.position.to_a # Mouse Pointer
        @st = 0 
        @pick_point = []
      end
      def onMouseMove(flags, x, y, view)
        if @ip_help.valid?
          @ip.pick(view, x, y, @ip_help)
        else
          @ip.pick(view, x, y)
        end
        @mp = @ip.position.to_a
        if @st == 0
          Sketchup.status_text= "Pick a Face"
        elsif @st == 1
          projected_point = @ip.position.project_to_plane( @plane )
          @ip = Sketchup::InputPoint.new(projected_point)
          @mp = @ip.position.to_a
          Sketchup.status_text= "Select First Refrence Point"
        elsif @st == 2
          projected_point = @ip.position.project_to_plane( @plane )
          @ip = Sketchup::InputPoint.new(projected_point)
          @mp = @ip.position.to_a
          Sketchup.status_text= "Select Second Refrence Point"
        end
        view.invalidate
      end
      def draw (view)
        @ip.draw(view)
        if @st == 2 && @ip.valid?
          view.line_width = 5
          view.drawing_color= "red"
          view.draw_polyline @pick_point, @mp
        end
      end
      def onLButtonDown(flags, x, y, view)
        if @ip_help.valid?
          @ip.pick(view, x, y, @ip_help)
        else
          @ip.pick(view, x, y)
        end
        @ip_help.copy!(@ip)
        if @st == 0 && @ip.valid?
          ph = view.pick_helper
          ph.do_pick(x, y)
          pick_face = ph.picked_face
          if pick_face
            @st = 1
            @plane = pick_face.plane
          end
        elsif @st == 1 && @ip.valid?
          @st = 2
          @pick_point = @ip.position.to_a
        else
          @st = 0
        end
      end
    end
    unless file_loaded?(__FILE__)
      UI.menu("Plugins").add_item("MB") {
        Sketchup.active_model.select_tool(MB.new)
      }
      file_loaded(__FILE__)
    end
  end
end

I have 2 problems with these codes.
1- After I select a face, the first point can be anywhere in the model (not just in the plane) but the second point is just in the plane.
2- After selecting the plane, the mouse pointer doesn’t show points in the plane.
I hope you can help me with it.
Thank you in advance,

This quick one is a little different, but may help.
The reference face (“@lock_face”) here is selected/deselected by shift key (while hover mouse over the face) and the collected points are all in the selected face plane…

ltof

class TestTool
  def initialize
    @ip = Sketchup::InputPoint.new
    @ip_help = Sketchup::InputPoint.new
    @collected_points = []
  end
  
  def onCancel(reason, view)
    puts "MyTool was canceled for reason ##{reason} in view: #{view}"
    @collected_points = []
    view.invalidate
  end
  
  def onMouseMove(flags, x, y, view)
    @ip.pick(view, x, y) unless @ip_help.valid?
    @ip.pick(view, x, y, @ip_help) if @ip_help.valid?
    @ip_face = @ip.face
    if @lock_face
      @projected_point = @ip.position.project_to_plane( @lock_face.plane )
    else
      @projected_point = nil
    end
    view.invalidate
  end
  
  def onLButtonDown(flags, x, y, view)
    @ip_help.copy!(@ip)
    @collected_points<<@projected_point if @projected_point
    view.invalidate
  end
  
  def onKeyDown(key, repeat, flags, view)
    if( key == CONSTRAIN_MODIFIER_KEY ) # "shift key"
      if @lock_face == @ip_face
        @lock_face = nil
      else
        @lock_face = @ip_face
      end
      @collected_points = []
      view.invalidate
    end 
  end
  
  def draw(view)
    @ip.draw(view) if @ip.valid?
    @ip_help.draw(view) if @ip_help.valid?
    view.tooltip = @ip.tooltip
    
    view.line_width = 2
    view.draw_points( @ip.position, 20, 3, "blue" ) if @ip.valid?
    view.draw_points( @projected_point, 20, 4, "orange" ) if @projected_point
    view.draw_lines( @collected_points.last, @projected_point ) if @projected_point && @collected_points.last
    
    view.line_width = 3
    view.drawing_color ="orange" 
    view.draw(GL_LINE_STRIP, @collected_points) if @collected_points.size > 1
    
    view.line_width = 4
    view.drawing_color ="magenta" 
    view.draw(GL_LINE_LOOP, @lock_face.outer_loop.vertices.map(&:position)) if @lock_face
  end
  
  def getExtents
    bb = Geom::BoundingBox.new
    return Sketchup.active_model.bounds unless @collected_points.size > 0
    bb.add(@collected_points) if @collected_points.size > 0
    bb
  end
end
Sketchup.active_model.select_tool( TestTool.new )
4 Likes

You are great. Thank you so much.

1 Like