home *** CD-ROM | disk | FTP | other *** search
/ Freelog 100 / FreelogNo100-NovembreDecembre2010.iso / Graphisme / GoogleSketchUp / GoogleSketchUpWFR.exe / GoogleSketchUp8.msi / SketchUpMeta.cab / linetool.rb.78D17A5F_0E0A_44D2_877D_2C56D45D16B7 < prev    next >
Encoding:
Text File  |  2010-08-26  |  10.8 KB  |  330 lines

  1. # Copyright 2005-2008, Google, Inc.
  2.  
  3. # This software is provided as an example of using the Ruby interface
  4. # to SketchUp.
  5.  
  6. # Permission to use, copy, modify, and distribute this software for 
  7. # any purpose and without fee is hereby granted, provided that the above
  8. # copyright notice appear in all copies.
  9.  
  10. # THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
  11. # IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  12. # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  13. #-----------------------------------------------------------------------------
  14.  
  15. require 'sketchup.rb'
  16.  
  17. #-----------------------------------------------------------------------------
  18.  
  19. # To create a new tool in Ruby, you must define a new class that implements
  20. # the methods for the events that you want to resplond to.  You do not have
  21. # to implement methods for every possible event that a Tool can respond to.
  22.  
  23. # Once you have defined a tool class, you select that tool by creating an
  24. # instance of it and passsing it to Sketchup.active_model.select_tool
  25.  
  26. # This implementation of a tool tries to be pretty complete to show all
  27. # of the kinds of things that you can do in a tool.  This makes it a little
  28. # complicated.  You should also look at the TrackMouseTool defined in
  29. # utilities.rb for an example of a simpler tool.
  30.  
  31. # This example shows the implementation of a simple line tool.  This tool
  32. # is similar to the Pencil tool in SketchUp, but it create construction lines
  33. # rather than edges
  34.  
  35. class LineTool
  36.  
  37. # This is the standard Ruby initialize method that is called when you create
  38. # a new object.
  39. def initialize
  40.     @ip1 = nil
  41.     @ip2 = nil
  42.     @xdown = 0
  43.     @ydown = 0
  44. end
  45.  
  46. # The activate method is called by SketchUp when the tool is first selected.
  47. # it is a good place to put most of your initialization
  48. def activate
  49.     # The Sketchup::InputPoint class is used to get 3D points from screen
  50.     # positions.  It uses the SketchUp inferencing code.
  51.     # In this tool, we will have two points for the endpoints of the line.
  52.     @ip1 = Sketchup::InputPoint.new
  53.     @ip2 = Sketchup::InputPoint.new
  54.     @ip = Sketchup::InputPoint.new
  55.     @drawn = false
  56.  
  57.     # This sets the label for the VCB
  58.     Sketchup::set_status_text $exStrings.GetString("Length"), SB_VCB_LABEL
  59.     
  60.     self.reset(nil)
  61. end
  62.  
  63. # deactivate is called when the tool is deactivated because
  64. # a different tool was selected
  65. def deactivate(view)
  66.     view.invalidate if @drawn
  67. end
  68.  
  69. # The onMouseMove method is called whenever the user moves the mouse.
  70. # because it is called so often, it is important to try to make it efficient.
  71. # In a lot of tools, your main interaction will occur in this method.
  72. def onMouseMove(flags, x, y, view)
  73.     if( @state == 0 )
  74.         # We are getting the first end of the line.  Call the pick method
  75.         # on the InputPoint to get a 3D position from the 2D screen position
  76.         # that is bassed as an argument to this method.
  77.         @ip.pick view, x, y
  78.         if( @ip != @ip1 )
  79.             # if the point has changed from the last one we got, then
  80.             # see if we need to display the point.  We need to display it
  81.             # if it has a display representation or if the previous point
  82.             # was displayed.  The invalidate method on the view is used
  83.             # to tell the view that something has changed so that you need
  84.             # to refresh the view.
  85.             view.invalidate if( @ip.display? or @ip1.display? )
  86.             @ip1.copy! @ip
  87.             
  88.             # set the tooltip that should be displayed to this point
  89.             view.tooltip = @ip1.tooltip
  90.         end
  91.     else
  92.         # Getting the second end of the line
  93.         # If you pass in another InputPoint on the pick method of InputPoint
  94.         # it uses that second point to do additional inferencing such as
  95.         # parallel to an axis.
  96.         @ip2.pick view, x, y, @ip1
  97.         view.tooltip = @ip2.tooltip if( @ip2.valid? )
  98.         view.invalidate
  99.         
  100.         # Update the length displayed in the VCB
  101.         if( @ip2.valid? )
  102.             length = @ip1.position.distance(@ip2.position)
  103.             Sketchup::set_status_text length.to_s, SB_VCB_VALUE
  104.         end
  105.         
  106.         # Check to see if the mouse was moved far enough to create a line.
  107.         # This is used so that you can create a line by either draggin
  108.         # or doing click-move-click
  109.         if( (x-@xdown).abs > 10 || (y-@ydown).abs > 10 )
  110.             @dragging = true
  111.         end
  112.     end
  113. end
  114.  
  115. # The onLButtonDOwn method is called when the user presses the left mouse button.
  116. def onLButtonDown(flags, x, y, view)
  117.     # When the user clicks the first time, we switch to getting the
  118.     # second point.  When they click a second time we create the line
  119.     if( @state == 0 )
  120.         @ip1.pick view, x, y
  121.         if( @ip1.valid? )
  122.             @state = 1
  123.             Sketchup::set_status_text $exStrings.GetString("Select second end"), SB_PROMPT
  124.             @xdown = x
  125.             @ydown = y
  126.         end
  127.     else
  128.         # create the line on the second click
  129.         if( @ip2.valid? )
  130.             self.create_geometry(@ip1.position, @ip2.position,view)
  131.             self.reset(view)
  132.         end
  133.     end
  134.     
  135.     # Clear any inference lock
  136.     view.lock_inference
  137. end
  138.  
  139. # The onLButtonUp method is called when the user releases the left mouse button.
  140. def onLButtonUp(flags, x, y, view)
  141.     # If we are doing a drag, then create the line on the mouse up event
  142.     if( @dragging && @ip2.valid? )
  143.         self.create_geometry(@ip1.position, @ip2.position,view)
  144.         self.reset(view)
  145.     end
  146. end
  147.  
  148. # onKeyDown is called when the user presses a key on the keyboard.
  149. # We are checking it here to see if the user pressed the shift key
  150. # so that we can do inference locking
  151. def onKeyDown(key, repeat, flags, view)
  152.     if( key == CONSTRAIN_MODIFIER_KEY && repeat == 1 )
  153.         @shift_down_time = Time.now
  154.         
  155.         # if we already have an inference lock, then unlock it
  156.         if( view.inference_locked? )
  157.             # calling lock_inference with no arguments actually unlocks
  158.             view.lock_inference
  159.         elsif( @state == 0 && @ip1.valid? )
  160.             view.lock_inference @ip1
  161.         elsif( @state == 1 && @ip2.valid? )
  162.             view.lock_inference @ip2, @ip1
  163.         end
  164.     end
  165. end
  166.  
  167. # onKeyUp is called when the user releases the key
  168. # We use this to unlock the interence
  169. # If the user holds down the shift key for more than 1/2 second, then we
  170. # unlock the inference on the release.  Otherwise, the user presses shift
  171. # once to lock and a second time to unlock.
  172. def onKeyUp(key, repeat, flags, view)
  173.     if( key == CONSTRAIN_MODIFIER_KEY &&
  174.         view.inference_locked? &&
  175.         (Time.now - @shift_down_time) > 0.5 )
  176.         view.lock_inference
  177.     end
  178. end
  179.  
  180. # onUserText is called when the user enters something into the VCB
  181. # In this implementation, we create a line of the entered length if
  182. # the user types a length while selecting the second point
  183. def onUserText(text, view)
  184.     # We only accept input when the state is 1 (i.e. getting the second point)
  185.     # This could be enhanced to also modify the last line created if a length
  186.     # is entered after creating a line.
  187.     return if not @state == 1
  188.     return if not @ip2.valid?
  189.     
  190.     # The user may type in something that we can't parse as a length
  191.     # so we set up some exception handling to trap that
  192.     begin
  193.         value = text.to_l
  194.     rescue
  195.         # Error parsing the text
  196.         UI.beep
  197.         puts "Cannot convert #{text} to a Length"
  198.         value = nil
  199.         Sketchup::set_status_text "", SB_VCB_VALUE
  200.     end
  201.     return if !value
  202.  
  203.     # Compute the direction and the second point
  204.     pt1 = @ip1.position
  205.     vec = @ip2.position - pt1
  206.     if( vec.length == 0.0 )
  207.         UI.beep
  208.         return
  209.     end
  210.     vec.length = value
  211.     pt2 = pt1 + vec
  212.  
  213.     # Create a line
  214.     self.create_geometry(pt1, pt2, view)
  215.     self.reset(view)
  216. end
  217.  
  218. # The draw method is called whenever the view is refreshed.  It lets the
  219. # tool draw any temporary geometry that it needs to.
  220. def draw(view)
  221.     if( @ip1.valid? )
  222.         if( @ip1.display? )
  223.             @ip1.draw(view)
  224.             @drawn = true
  225.         end
  226.         
  227.         if( @ip2.valid? )
  228.             @ip2.draw(view) if( @ip2.display? )
  229.             
  230.             # The set_color_from_line method determines what color
  231.             # to use to draw a line based on its direction.  For example
  232.             # red, green or blue.
  233.             view.set_color_from_line(@ip1, @ip2)
  234.             self.draw_geometry(@ip1.position, @ip2.position, view)
  235.             @drawn = true
  236.         end
  237.     end
  238. end
  239.  
  240. # onCancel is called when the user hits the escape key
  241. def onCancel(flag, view)
  242.     self.reset(view)
  243. end
  244.  
  245.  
  246. # The following methods are not directly called from SketchUp.  They are
  247. # internal methods that are used to support the other methods in this class.
  248.  
  249. # Reset the tool back to its initial state
  250. def reset(view)
  251.     # This variable keeps track of which point we are currently getting
  252.     @state = 0
  253.     
  254.     # Display a prompt on the status bar
  255.     Sketchup::set_status_text($exStrings.GetString("Select first end"), SB_PROMPT)
  256.     
  257.     # clear the InputPoints
  258.     @ip1.clear
  259.     @ip2.clear
  260.     
  261.     if( view )
  262.         view.tooltip = nil
  263.         view.invalidate if @drawn
  264.     end
  265.     
  266.     @drawn = false
  267.     @dragging = false
  268. end
  269.  
  270. # Create new geometry when the user has selected two points.
  271. def create_geometry(p1, p2, view)
  272.     view.model.entities.add_cline(p1,p2)
  273. end
  274.  
  275. # Draw the geometry
  276. def draw_geometry(pt1, pt2, view)
  277.     view.draw_line(pt1, pt2)
  278. end
  279.  
  280. end # class LineTool
  281.  
  282. #-----------------------------------------------------------------------------
  283. # You can use inheritance in Ruby to use the LineTool class as a base class
  284. # for similar kinds of tools.  For example, this is a tool that creates
  285. # cylinders by selecting the two end points.
  286.  
  287. class CylTool < LineTool
  288.  
  289. # The cylinder tool takes a radius when you create it
  290. def initialize(radius = 1)
  291.     @radius = radius
  292.     @numsegs = 16
  293.     super()
  294. end
  295.  
  296. # Now we just have to override the create_geometry method.  You could also
  297. # override the draw_geometry method to make it draw a closer represenation
  298. # to waht it will really create.
  299. def create_geometry(pt1, pt2, view)
  300.     model = view.model
  301.     model.start_operation $exStrings.GetString("Create Cylinder")
  302.     entities = model.entities
  303.     
  304.     # First create a circle
  305.     vec = pt2 - pt1
  306.     length = vec.length
  307.     if( length == 0.0 )
  308.         UI.beep
  309.         puts "Cannot create a zero length cylinder"
  310.         return
  311.     end
  312.     circle = entities.add_circle pt1, vec, @radius, @numsegs
  313.  
  314.     # Now do a pushpull to create the cylinder
  315.     face = entities.add_face circle
  316.     normal = face.normal
  317.     length = -length if( (normal % vec) < 0.0 )
  318.     face.pushpull length
  319.  
  320.     model.commit_operation
  321. end
  322.  
  323. end # class CylTool
  324.  
  325. #-----------------------------------------------------------------------------
  326. # This functions is just a shortcut for selecting the new tool
  327. def linetool
  328.     Sketchup.active_model.select_tool LineTool.new
  329. end
  330.