I want to slightly change the behaviour of the text tool so it defaults to showing tags and other info (as opposed to the length of an edge).
I got quite far recreating it from scratch, but I think the native tool has some clever logic where it uses the camera position to determine the placement of the text.
Has anyone successfully implemented something similar before?
(1) All primitive geometry (edges and faces) should be untagged (using Layer0.)
(2) The native text (callout) tool uses “text always face camera”. When you use API methods to create text callouts, what specific problems do you have. (Please show screen snips or post code.)
Thanks for the very fast reply. I’ve uploaded a screenshot that hopefully shows the issue.
The native tool (blue mark up) cleverly infers an insertion point from the camera position that makes sense.
My tool (green mark up) places it the text really far away.
Full code is below. Thanks! Ross
module RTSAPTools
module LabelThermalBridges
class Tool
def initialize
@start_point = nil
@instance_path = nil
@label_text = “”
@label_mode = :unset
end
def activate
return unless @label_mode == :unset
show_label_mode_dialog
end
def show_label_mode_dialog
html = <<-HTML
<html>
<body style="font-family:sans-serif;padding:10px;">
<h3>Label Mode</h3>
<form>
<input type="radio" name="mode" value="short" checked> Short (e.g. E05)<br>
<input type="radio" name="mode" value="full"> Full label<br><br>
<button onclick="submitForm(); return false;">OK</button>
<button onclick="cancelForm(); return false;">Cancel</button>
</form>
<script>
function submitForm() {
let selected = document.querySelector('input[name="mode"]:checked').value;
sketchup.submit_choice(selected);
}
function cancelForm() {
sketchup.cancel();
}
</script>
</body>
</html>
HTML
@dialog = UI::HtmlDialog.new(
dialog_title: "Label Thermal Bridges",
preferences_key: "label_thermal_bridges",
scrollable: true,
resizable: false,
width: 320,
height: 200,
style: UI::HtmlDialog::STYLE_DIALOG
)
@dialog.set_html(html)
@dialog.add_action_callback("submit_choice") do |_, mode|
@label_mode = mode.to_sym
@dialog.close
end
@dialog.add_action_callback("cancel") do |_|
@dialog.close
Sketchup.active_model.select_tool(nil)
end
@dialog.show
end
def onMouseMove(flags, x, y, view)
@mouse_ip = view.inputpoint(x, y)
@x = x
@y = y
view.invalidate
end
def onLButtonDown(flags, x, y, view)
return unless @mouse_ip
return if @label_mode == :unset
if @start_point.nil?
@start_point = @mouse_ip.position
@instance_path = @mouse_ip.instance_path
edge = @instance_path.to_a.grep(Sketchup::Edge).first
if edge && edge.layer
name = edge.layer.display_name
@label_text = (@label_mode == :short ? name[0, 3] : name)
end
else
end_point = @mouse_ip.position
vector = @start_point.vector_to(end_point)
entities = Sketchup.active_model.active_entities
if @instance_path&.valid?
entities.add_text(@label_text, [@instance_path, @start_point.transform(@instance_path.transformation.inverse)], vector)
end
@start_point = nil
@instance_path = nil
end
end
def draw(view)
return unless @mouse_ip
@mouse_ip.draw(view) if @mouse_ip.valid? && @mouse_ip.display?
if @start_point
view.draw_text(Geom::Point3d.new(@x, @y, 0), @label_text, size: 22)
view.drawing_color = 'black'
view.draw_line(@start_point, @mouse_ip.position)
end
end
def getExtents
bbox = Sketchup.active_model.bounds
bbox.add(@mouse_ip.position) if @mouse_ip&.valid?
bbox
end
def reset(view)
@mouse_ip.clear
@label_text = ""
end
end
# Entry point
def self.run
Sketchup.active_model.select_tool(Tool.new)
end
end
end