Custom tool creating instances of text labels
-
I'm in the process of making a Tool that will display some text labels on the Component entities that it gets clicked on. The text label contents will be drawn from a soap webservice but that is another subject. What I'm having trouble with is getting the tool to operate on each entity separately. Right now it will only work on 1 entity at a time.
module SensorNodeInfoPlugin class SensorNodeInfoTool def initialize @selection = nil @info = nil @new_text = nil @label_exists = false end def onLButtonDown(flags, x, y, view) if @label_exists==false pick_helper = view.pick_helper pick_helper.do_pick(x, y) @selection = pick_helper.best_picked @info = @selection.name arrow_x = @selection.bounds.corner(7)[0] arrow_y = @selection.bounds.corner(7)[1] arrow_z = @selection.bounds.corner(7)[2] text_x = 20 text_y = 20 text_z = 20 @new_text = Sketchup.active_model.entities.add_text "", [arrow_x, arrow_y, arrow_z], [text_x, text_y, text_z] @new_text.text = "Loading #{@info}'s info..." @new_text.leader_type = 2 @new_text.line_weight = 4 @new_text.arrow_type = 4 @label_exists=true else Sketchup.active_model.active_entities.erase_entities @new_text @label_exists=false end end def draw(view) 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
If I understand correctly there is only one instance of the Tool at all times? I need multiple instances or is there some other way?
-
Find an example Tool - like the Line-Tool script - there are dozens [e.g. My 2dTools scripts] - which take multiple point clicking - for a line instead of adding geometry from the clicked points you just add you label at its clicked point....
You have a activate() method to set up the tool once, and that then runs a rest() method which starts the processing.
You can have any Tool running until the user selects another tool etc...
After the mouse-button-click code is done adding the label you then run the reset() method to set up for the next label... -
@tig said:
Find an example Tool - like the Line-Tool script - there are dozens [e.g. My 2dTools scripts] - which take multiple point clicking - for a line instead of adding geometry from the clicked points you just add you label at its clicked point....
You have a activate() method to set up the tool once, and that then runs a rest() method which starts the processing.
You can have any Tool running until the user selects another tool etc...
After the mouse-button-click code is done adding the label you then run the reset() method to set up for the next label...Yes but I will need to be able to both create and delete text labels on each component that is clicked(show on 1st LClick, hide on 2nd LClick, and in between update the contents of the text label at specified second intervals). Will that work with the above philosophy or will it need that I create a class to hold references to which text label is attached to which component and detect which one is clicked and delete it? I'm really confused.
-
Here's how I would do it...
Let's first assume that a component-instance has no label.
The user clicks on it.
It is confirmed as a component-instance.
It is also checked for a special attribute,tid=instance.get_attribute("SensorNodeInfo", "tid", nil)
, in this case it returnsnil
as it has no label.unless tid ### add_label_code else ### delete_label_code end
The 'add_label_code' will make the Text object, and give it a 'tid', a matching 'tid' will also be given to the picked instance...
` tid=Time.now.to_f+rand
instance.set_attribute("SensorNodeInfo", "tid", tid)some code to add the Text object - referenced as 'label'
label.set_attribute("SensorNodeInfo", "tid", tid)`
Now the instance and its label are pair with a matching [unique] tid attribute.The 'delete_label_code' erases any related 'label', by matching its 'tid'.
The 'label' Text object will have been previously given a unique 'tid' returned in the 'instance' match that was NOTnil
, so you need to iterate the instances context to get possible candidates,
labels_to_go=instance.parent.entities.grep(Sketcup::Text).select{|e| e.get_attribute("SensorNodeInfo", "tid", nil)==tid }
then
instance.parent.entities.erase_entities(labels_to_go) if labels_to_go[0]
-
@tig said:
Here's how I would do it...
Let's first assume that a component-instance has no label.
The user clicks on it.
It is confirmed as a component-instance.
It is also checked for a special attribute,tid=instance.get_attribute("SensorNodeInfo", "tid", nil)
, in this case it returnsnil
as it has no label.unless tid > ### add_label_code > else > ### delete_label_code > end
The 'add_label_code' will make the Text object, and give it a 'tid', a matching 'tid' will also be given to the picked instance...
` tid=Time.now.to_f+rand
instance.set_attribute("SensorNodeInfo", "tid", tid)some code to add the Text object - referenced as 'label'
label.set_attribute("SensorNodeInfo", "tid", tid)`
Now the instance and its label are pair with a matching [unique] tid attribute.The 'delete_label_code' erases any related 'label', by matching its 'tid'.
The 'label' Text object will have been previously given a unique 'tid' returned in the 'instance' match that was NOTnil
, so you need to iterate the instances context to get possible candidates,
labels_to_go=instance.parent.entities.grep(Sketcup::Text).select{|e| e.get_attribute("SensorNodeInfo", "tid", nil)==tid }
then
instance.parent.entities.erase_entities(labels_to_go) if labels_to_go[0]
Thanks that's very helpful.
Advertisement