• Login
sketchucation logo sketchucation
  • Login
⚠️ Libfredo 15.4b | Minor release with bugfixes and improvements Update

Manipulate text label attached to entity

Scheduled Pinned Locked Moved Developers' Forum
6 Posts 3 Posters 612 Views 3 Watching
Loading More Posts
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S Offline
    sepultribe
    last edited by 2 Aug 2014, 14:54

    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.

    1 Reply Last reply Reply Quote 0
    • D Offline
      dacastror
      last edited by 3 Aug 2014, 02:53

      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)

      1 Reply Last reply Reply Quote 0
      • D Offline
        dacastror
        last edited by 3 Aug 2014, 02:59

        probably also will need to add dictionaries to your "nodes" with something like

        entity.set_attribute "dictionaryName", "keyName", ["data", 23, "house"]

        1 Reply Last reply Reply Quote 0
        • A Offline
          Aerilius
          last edited by 4 Aug 2014, 08:22

          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.

          1 Reply Last reply Reply Quote 0
          • D Offline
            dacastror
            last edited by 4 Aug 2014, 16:58

            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)

            1 Reply Last reply Reply Quote 0
            • A Offline
              Aerilius
              last edited by 4 Aug 2014, 17:48

              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/text

              
              component # 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 Observer

              
              def 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
              
              
              1 Reply Last reply Reply Quote 0
              • 1 / 1
              1 / 1
              • First post
                1/6
                Last post
              Buy SketchPlus
              Buy SUbD
              Buy WrapR
              Buy eBook
              Buy Modelur
              Buy Vertex Tools
              Buy SketchCuisine
              Buy FormFonts

              Advertisement