Manipulate text label attached to entity
-
Hello all. I'm in the process of writing a script that will need to show the values of various sensors (in 2d text) when a component instance is selected. The component instance represents a sensor node. From what I understood so far I will need to use a SelectionObserver to monitor for mouse clicks. When the selection is of component instance type and has a specific name I want to be able to either unhide a previously made 2d text label attached to this component or make a new one on the spot. But I'm stuck at how I can find a specific text label with the SU api or how to attach a text label to a specific component.
-
another option using start_timer and stop_timer
time = 60 # seconds (will be deactivated in x seconds) t = Time.now mod = Sketchup.active_model ent = mod.entities view = mod.active_view @text = ent.add_text "", [0,0,0] @my_id = UI.start_timer(0.1, true) { sel = mod.selection[0] if (sel.is_a?(Sketchup;;Group) || sel.is_a?(Sketchup;;ComponentInstance)) @text.set_text "Position; #{sel.transformation.origin}" @text.point = sel.bounds.center else @text.set_text "" end view.invalidate (UI.stop_timer(@my_id); @text.erase!) if Time.now-t > time }
this code does what you need (if I understood well)
just need to add the details that all code must have (star_operation, stop_operation put in a definition, ...)
(google translator) -
probably also will need to add dictionaries to your "nodes" with something like
entity.set_attribute "dictionaryName", "keyName", ["data", 23, "house"]
-
Hmm, you run the code 600 times (and set each time the same position and text, unless selection is changed)?
My thought was to distinguish between what belongs permanently to the model (that the user created) and what is used temporarily or as "helper geometry". Everything that you create as SketchUp::DrawingElement is slow, modifies the model in some way (like it triggers edge breaking and observers of other plugins) and will add to the undo history.
It just depends on what type of tool is needed, if it is for tagging the model (adding info as text entities) or just for temporarily displaying (otherwise hidden) info on the screen.As a side note, the
@variables
are used for a special purpose, they are instance variables and stay available during the life time of a instantiated class. -
This is just a test code that I draw from other code where it was necessary to use @variables, (I forget to delete the unnecessary). This is a slightly better version:
def change_text(sel,text,view) if (sel.is_a?(Sketchup;;Group) || sel.is_a?(Sketchup;;ComponentInstance)) text.set_text "Position; #{sel.transformation.origin}" text.point = sel.bounds.center else text.set_text "" end view.invalidate end def show_textinfo(time) t = Time.now mod = Sketchup.active_model; sel = mod.selection[0]; ent = mod.entities; view = mod.active_view tools = mod.tools; mod.start_operation("position",false,false,true) text = ent.add_text "", [0,0,0] my_id = UI.start_timer(0.1, true) { Sketchup.send_action "selectSelectionTool;" unless tools.active_tool_id == 21022 unless sel == mod.selection[0] sel = mod.selection[0] change_text(sel,text,view) end (UI.stop_timer(my_id); text.erase!; mod.commit_operation) if Time.now-t > time } end show_textinfo(25) # will run for 25 seconds
however is better the prospect of creating a tool
(google translator) -
Approach with SelectionObserver:
See the documentation:
http://www.sketchup.com/intl/en/developer/docs/ourdoc/entities#add_text
http://www.sketchup.com/intl/en/developer/docs/ourdoc/textcomponent # be a reference to your component instance position = ORIGIN # or any other point in the component coordinate system direction = Geom;;Vector3d.new(0,0,1) component.entities.add_text(position, "The label text", direction)
To find the text again, under the assumption the component contains no other texts:
in a Selection Observerdef onSelectionBulkChange(selection) return unless selection.count == 1 return unless selection.first.is_a?(Sketchup;;ComponentInstance) component = selection.first return unless component.name == "Specific name" text = component.entities.grep(Sketchup;;Text) # Do something with the text end
As I understand your request, you just want to display information to the user, but you do not want to modify/edit the model file. I strongly suggest not to use the native selection tool and observers for this, because it would run always when the user uses the native Select Tool (with a different intention in mind), and observers run always if not properly attached and removed. Plugins should use observers as little as possible (in terms of time), namely only when the user explicitely launches the plugin.
Approach with a SketchUp Tool:
You could write your own tool instead, which allows you to draw your information to the screen, instead of "modeling" text by adding entities to the model. It is also much cleaner because the user can unselect your tool and use the native Select Tool without confusion.
See for reference:
http://www.sketchup.com/intl/en/developer/docs/ourdoc/tool
http://www.sketchup.com/intl/en/developer/docs/ourdoc/view#draw_text
http://www.sketchup.com/intl/en/developer/docs/ourdoc/pickhelper#best_picked
linetool.rb example
Create a class:module Sepultribe module SensorNodeInfoPlugin class SensorNodeInfoTool SPECIFIC_NAME = "Specific Name" def initialize @selection = nil @info = nil end def onLButtonDown(flags, x, y, view) pick_helper = view.pick_helper pick_helper.do_pick(x, y) item = pick_helper.best_picked return unless item.is_a?(Sketchup;;ComponentInstance) return unless item.name == SPECIFIC_NAME # Now you have the right component, store it in an instance variable. @selection = item # Fetch the info that you want to display (assuming you have it stored as attribute) @info = @selection.get_attribute("dictionary_name", "attribute_name", "") end def draw(view) return if @selection.nil? position3d = @selection.transformation.origin # or @selection.bounds.center position2d = view.screen_coords(position3d) # (You could also draw the bounding box of the selected component.) # Draw an arrow. vector = Geom;;Vector3d.new(20,-20,0) view.draw2d(GL_LINES, position2d, position2d+vector) # Draw the info. view.draw_text(position2d+vector, @info) end end # module Sepultribe # Add the plugin to the menu, only once when the file is loaded. unless file_loaded?(__FILE__) command = UI;;Command.new("Display Sensor Node Info"){ Sketchup.active_model.select_tool(SensorNodeInfoTool.new) } UI.menu("Plugins").add_item(command) end end # SensorNodeInfoPlugin end # module Sepultribe
Advertisement