"Leader Text" in SketchUp

Hi All, I am trying to create a Leader Text tool that has the ability to snap start point and end points when I want to take notes. Here is the Ruby code I wrote but it can only snap the point but no Text yet, I hope to get some help from everyone. Thanks All,

The code is here,

require 'Sketchup.rb'

# Create a class for the tool
class Leadertext
    # Create a method for handling points
    def activate
        # Initialize variables by clicking the mouse
        @ip1 = Sketchup::InputPoint.new
        @ip2 = Sketchup::InputPoint.new
        @mouse_ip = Sketchup::InputPoint.new
        @picked_first_ip = false
        @picked_second_ip = false
    end

    # Create a method for marking elements that need to be redrawn when the tool is deactivated
    def deactivate(view)
        view.invalidate if view
    end

    # Create a method for marking elements that need to be redrawn when the tool is resumed after being paused
    def resume(view)
        view.invalidate if view
    end

    # Create a method for deactivating the tool when the user wants to exit the command, typically by pressing the Esc key
    def onCancel(reason, view)
        Sketchup.active_model.select_tool(nil)
    end

    # Create a method for updating the position of the mouse and displaying tooltip information when the user moves the mouse on the Sketchup interface
    def onMouseMove(flags, x, y, view)
        @mouse_ip.pick(view, x, y)
        view.tooltip = @mouse_ip.tooltip if @mouse_ip.valid?
        view.invalidate
    end

    # Create a method for determining the positions of the selected points when the user clicks the left mouse button to start the text creation method using the tool
    def onLButtonDown(flags, x, y, view)
        # Select the first point
        if not @picked_first_ip
            @ip1.pick(view, x, y)
            @picked_first_ip = true
        # Select the second point
        elsif not @picked_second_ip
            @ip2.pick(view, x, y)
            @picked_second_ip = true
            create_text
            Sketchup.active_model.select_tool(nil)
        end
        view.invalidate
    end

    #
    def draw(view)
        # Draw the position of the mouse
        if @mouse_ip.valid?
            x, y = @mouse_ip.position
            view.draw_points([x, y], 10, 1, "red")
        end

        # Draw a line connecting the two points
        if @picked_first_ip
            view.set_color_from_line(@ip1, @ip2)
            view.draw(GL_LINE_STRIP, [@ip1.position, @ip2.position])
        end
    end

    # Create a method for creating text
    def create_text
        # Create a variable for the starting point of the leader text
        start_point = Geom::Point3d.new(@ip1)

        # Create a vector to orient the leader text
        vector = Geom::Vector3d.new(@ip2)

        # Create a Text object to hold the text of the leader text
        text = Sketchup.active_model.entities.add_text("Hello World", start_point, vector)

        # Set properties for the leader text, such as line weight and color
        text.arrow_type = 2 # 0 for none, 2 for dot, 3 for closed arrow, 4 for open arrow
        text.line_weight = 1 # This method sets line weight in pixels
    end
end

# Create a menu and tool
UI.menu("Plugin").add_item("Leader Text") {
    Sketchup.active_model.select_tool(Leadertext.new)
}
1 Like

(1) Your code must be wrapped within a namespace module and better if also within a submodule of that. Ie, … custom classes must not be defined in the top level ObjectSpace.

  • Also Ruby uses 2 space indents. Your comments are way too long for posting in forum.
    This causes horizontal scrolling in order to your read code in the forum.

(2) For getting text in a tool you have 2 options … using the VCB or an inputbox after the 2nd point has been clicked. (or both)


VCB:

Add @text to activate() callback:

  # Set the tool's variables to intial state.
  def activate
    @text = ""
    # Initialize variables by clicking the mouse
    @ip1 = Sketchup::InputPoint.new
    @ip2 = Sketchup::InputPoint.new
    @mouse_ip = Sketchup::InputPoint.new
    @picked_first_ip = false
    @picked_second_ip = false
  end

… add these callbacks …

  def enableVCB?
    return true
  end

  def onUserText(text, view)
    @text = text
  rescue ArgumentError
    view.tooltip = 'Invalid text!'
  end

After the 2nd point is clicked, check if @text.empty?, if not use the value in @text within your create_text method instead of "Hello World".

After creating the text, reset the tool.

  def reset
    activate()
  end

Remove the Sketchup.active_model.select_tool(nil) from:

  • the onLButtonDown callback.
  • the onCancel callback

Tools do not deactivate themselves. (SketchUp is not AutoCAD.)
SketchUp tools reset to the initial state so that the user can continue doing what the tool does.
This should also be done when hitting the ESC key.

  # This fires for ESC key if onKeyDown returns false or is not defined.
  def onCancel(reason, view)
    view.invalidate
    reset()
  end

Inputbox:

After the 2nd point is clicked, check if @text.empty?

If it is empty, you can display an inputbox to get some text …

  def get_text
    prompts = ["Enter text :    "]
    defaults = [@text]
    input = UI.inputbox(prompts, defaults, "Callout Text")
    if input # false if cancelled by user
      @text = input.first
    else
      reset() # user cancelled
    end
  end
2 Likes

Very sorry for this late reply to you,
Your tutorial is very helpful I thank you for it and from your comments after a few days of practice finally got results that make me very happy :))
I did a lot of research and practice and this is the result, of course this one needs further improvement.

And code is here :))


class LeaderText
    def activate
        @ip = Sketchup::InputPoint.new
        @ip1 = nil
        @ip2 = nil
        @ip3 = nil
        @ip4 = nil
        @ip_point = nil # Điểm bắt đầu ảo cho point
        @ip_text = nil # Đểm bắt đầu ảo cho text
    end

    def deactivate(view)
        puts "Công cụ đã bị vô hiệu"
    end

    def onCancel(reason, view)
        puts "Hủy chọn công cụ"
    end

    def onMouseMove(flags, x, y, view)
        @ip.pick(view, x, y)
        @ip_point = @ip.position
        @ip_text = view.screen_coords(@ip.position)
        #puts "ipmove = #{@ipmove}"
        view.tooltip = @ip.tooltip
        view.invalidate
    end

    def draw(view)
        selection = Sketchup.active_model.selection
        entity = selection.first
        instance_name = entity.name

        if !@ip_point.nil?
            status = view.draw_points(@ip_point, 5, 1, color = "green")

            if !@ip_text.nil?
                option = {
                    :color => "green",
                    :size => 10,
                    :align => TextAlignLeft,
                    :vertical_align => TextVerticalAlignBaseline
                }
                status = view.draw_text(@ip_text, "#{instance_name}", option)
            end
        end

        if !@ip_point.nil? && !@ip1.nil?
            status = view.drawing_color = "green"
            status = view.draw_lines(@ip1, @ip_point)
            #puts "ip1 = #{@ip1}"

            if !@ip_point.nil? && !@ip2.nil?
                status = view.drawing_color = "green"
                status = view.draw_lines(@ip2, @ip_point)
                #puts "ip2 = #{@ip2}"
        
                if !@ip_point.nil? && !@ip3.nil?
                    status = view.drawing_color = "green"
                    status = view.draw_lines(@ip3, @ip_point)
                    #puts "ip3 = #{@ip3}"
        
                    if !@ip_point.nil? && !@ip4.nil?
                        status = view.drawing_color = "green"
                        status = view.draw_lines(@ip4, @ip_point)
                        #puts "ip4 = #{@ip4}"
                    end
                end
            end
        end
        view.invalidate
    end

    def onLButtonDown(flags, x, y, view)
        @ip.pick(view, x, y)
        selection = Sketchup.active_model.selection
        entity = selection.first
        instance_name = entity.name

        if @ip1.nil?
            @ip1 = @ip.position
            puts "ip1 = #{@ip1}"
        elsif @ip2.nil?
            @ip2 = @ip.position
            puts "ip2 = #{@ip2}"
        elsif @ip3.nil?
            @ip3 = @ip.position
            puts "ip3 = #{@ip3}"
        elsif @ip4.nil?
            @ip4 = @ip.position
            puts "ip4 = #{@ip4}"
        end

        if !@ip1.nil? && !@ip2.nil?
            Sketchup.active_model.entities.add_line(@ip1, @ip2)

            if !@ip2.nil? && !@ip3.nil?
                Sketchup.active_model.entities.add_line(@ip2, @ip3)

                if !@ip3.nil? && !@ip4.nil?
                    Sketchup.active_model.entities.add_line(@ip3, @ip4)
                end
            end
        end

        if !@ip4.nil?
            @ip4.x += 5
            text = Sketchup.active_model.entities.add_text("#{instance_name}", @ip4)
            text.show
            text.TextAlignRight
        end
    end
end

toolbar = UI::Toolbar.new ("2D Text")
my_tool = LeaderText.new
cmd1 = UI::Command.new("2D Text") {
    Sketchup.active_model.select_tool(my_tool)
}
cmd1.small_icon = "ToolPencilSmall.png" #Thay bằng biến đường dẫn
cmd1.large_icon = "ToolPencilLarge.png" #Thay bằng biến đường dẫn
cmd1.tooltip = "Đang ngáo lắm"
cmd1.status_bar_text = "Hổng biết ji hết chơn..."
cmd1.menu_text = "Cái này ở chỗ nào ?"
toolbar.add_item(cmd1)
toolbar.show
type or paste code here