home *** CD-ROM | disk | FTP | other *** search
- # Copyright 2005-2008, Google, Inc.
-
- # This software is provided as an example of using the Ruby interface
- # to SketchUp.
-
- # Permission to use, copy, modify, and distribute this software for
- # any purpose and without fee is hereby granted, provided that the above
- # copyright notice appear in all copies.
-
- # THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
- # IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- #-----------------------------------------------------------------------------
-
- require 'sketchup.rb'
-
- #-----------------------------------------------------------------------------
-
- # To create a new tool in Ruby, you must define a new class that implements
- # the methods for the events that you want to resplond to. You do not have
- # to implement methods for every possible event that a Tool can respond to.
-
- # Once you have defined a tool class, you select that tool by creating an
- # instance of it and passsing it to Sketchup.active_model.select_tool
-
- # This implementation of a tool tries to be pretty complete to show all
- # of the kinds of things that you can do in a tool. This makes it a little
- # complicated. You should also look at the TrackMouseTool defined in
- # utilities.rb for an example of a simpler tool.
-
- # This example shows the implementation of a simple line tool. This tool
- # is similar to the Pencil tool in SketchUp, but it create construction lines
- # rather than edges
-
- class LineTool
-
- # This is the standard Ruby initialize method that is called when you create
- # a new object.
- def initialize
- @ip1 = nil
- @ip2 = nil
- @xdown = 0
- @ydown = 0
- end
-
- # The activate method is called by SketchUp when the tool is first selected.
- # it is a good place to put most of your initialization
- def activate
- # The Sketchup::InputPoint class is used to get 3D points from screen
- # positions. It uses the SketchUp inferencing code.
- # In this tool, we will have two points for the endpoints of the line.
- @ip1 = Sketchup::InputPoint.new
- @ip2 = Sketchup::InputPoint.new
- @ip = Sketchup::InputPoint.new
- @drawn = false
-
- # This sets the label for the VCB
- Sketchup::set_status_text $exStrings.GetString("Length"), SB_VCB_LABEL
-
- self.reset(nil)
- end
-
- # deactivate is called when the tool is deactivated because
- # a different tool was selected
- def deactivate(view)
- view.invalidate if @drawn
- end
-
- # The onMouseMove method is called whenever the user moves the mouse.
- # because it is called so often, it is important to try to make it efficient.
- # In a lot of tools, your main interaction will occur in this method.
- def onMouseMove(flags, x, y, view)
- if( @state == 0 )
- # We are getting the first end of the line. Call the pick method
- # on the InputPoint to get a 3D position from the 2D screen position
- # that is bassed as an argument to this method.
- @ip.pick view, x, y
- if( @ip != @ip1 )
- # if the point has changed from the last one we got, then
- # see if we need to display the point. We need to display it
- # if it has a display representation or if the previous point
- # was displayed. The invalidate method on the view is used
- # to tell the view that something has changed so that you need
- # to refresh the view.
- view.invalidate if( @ip.display? or @ip1.display? )
- @ip1.copy! @ip
-
- # set the tooltip that should be displayed to this point
- view.tooltip = @ip1.tooltip
- end
- else
- # Getting the second end of the line
- # If you pass in another InputPoint on the pick method of InputPoint
- # it uses that second point to do additional inferencing such as
- # parallel to an axis.
- @ip2.pick view, x, y, @ip1
- view.tooltip = @ip2.tooltip if( @ip2.valid? )
- view.invalidate
-
- # Update the length displayed in the VCB
- if( @ip2.valid? )
- length = @ip1.position.distance(@ip2.position)
- Sketchup::set_status_text length.to_s, SB_VCB_VALUE
- end
-
- # Check to see if the mouse was moved far enough to create a line.
- # This is used so that you can create a line by either draggin
- # or doing click-move-click
- if( (x-@xdown).abs > 10 || (y-@ydown).abs > 10 )
- @dragging = true
- end
- end
- end
-
- # The onLButtonDOwn method is called when the user presses the left mouse button.
- def onLButtonDown(flags, x, y, view)
- # When the user clicks the first time, we switch to getting the
- # second point. When they click a second time we create the line
- if( @state == 0 )
- @ip1.pick view, x, y
- if( @ip1.valid? )
- @state = 1
- Sketchup::set_status_text $exStrings.GetString("Select second end"), SB_PROMPT
- @xdown = x
- @ydown = y
- end
- else
- # create the line on the second click
- if( @ip2.valid? )
- self.create_geometry(@ip1.position, @ip2.position,view)
- self.reset(view)
- end
- end
-
- # Clear any inference lock
- view.lock_inference
- end
-
- # The onLButtonUp method is called when the user releases the left mouse button.
- def onLButtonUp(flags, x, y, view)
- # If we are doing a drag, then create the line on the mouse up event
- if( @dragging && @ip2.valid? )
- self.create_geometry(@ip1.position, @ip2.position,view)
- self.reset(view)
- end
- end
-
- # onKeyDown is called when the user presses a key on the keyboard.
- # We are checking it here to see if the user pressed the shift key
- # so that we can do inference locking
- def onKeyDown(key, repeat, flags, view)
- if( key == CONSTRAIN_MODIFIER_KEY && repeat == 1 )
- @shift_down_time = Time.now
-
- # if we already have an inference lock, then unlock it
- if( view.inference_locked? )
- # calling lock_inference with no arguments actually unlocks
- view.lock_inference
- elsif( @state == 0 && @ip1.valid? )
- view.lock_inference @ip1
- elsif( @state == 1 && @ip2.valid? )
- view.lock_inference @ip2, @ip1
- end
- end
- end
-
- # onKeyUp is called when the user releases the key
- # We use this to unlock the interence
- # If the user holds down the shift key for more than 1/2 second, then we
- # unlock the inference on the release. Otherwise, the user presses shift
- # once to lock and a second time to unlock.
- def onKeyUp(key, repeat, flags, view)
- if( key == CONSTRAIN_MODIFIER_KEY &&
- view.inference_locked? &&
- (Time.now - @shift_down_time) > 0.5 )
- view.lock_inference
- end
- end
-
- # onUserText is called when the user enters something into the VCB
- # In this implementation, we create a line of the entered length if
- # the user types a length while selecting the second point
- def onUserText(text, view)
- # We only accept input when the state is 1 (i.e. getting the second point)
- # This could be enhanced to also modify the last line created if a length
- # is entered after creating a line.
- return if not @state == 1
- return if not @ip2.valid?
-
- # The user may type in something that we can't parse as a length
- # so we set up some exception handling to trap that
- begin
- value = text.to_l
- rescue
- # Error parsing the text
- UI.beep
- puts "Cannot convert #{text} to a Length"
- value = nil
- Sketchup::set_status_text "", SB_VCB_VALUE
- end
- return if !value
-
- # Compute the direction and the second point
- pt1 = @ip1.position
- vec = @ip2.position - pt1
- if( vec.length == 0.0 )
- UI.beep
- return
- end
- vec.length = value
- pt2 = pt1 + vec
-
- # Create a line
- self.create_geometry(pt1, pt2, view)
- self.reset(view)
- end
-
- # The draw method is called whenever the view is refreshed. It lets the
- # tool draw any temporary geometry that it needs to.
- def draw(view)
- if( @ip1.valid? )
- if( @ip1.display? )
- @ip1.draw(view)
- @drawn = true
- end
-
- if( @ip2.valid? )
- @ip2.draw(view) if( @ip2.display? )
-
- # The set_color_from_line method determines what color
- # to use to draw a line based on its direction. For example
- # red, green or blue.
- view.set_color_from_line(@ip1, @ip2)
- self.draw_geometry(@ip1.position, @ip2.position, view)
- @drawn = true
- end
- end
- end
-
- # onCancel is called when the user hits the escape key
- def onCancel(flag, view)
- self.reset(view)
- end
-
-
- # The following methods are not directly called from SketchUp. They are
- # internal methods that are used to support the other methods in this class.
-
- # Reset the tool back to its initial state
- def reset(view)
- # This variable keeps track of which point we are currently getting
- @state = 0
-
- # Display a prompt on the status bar
- Sketchup::set_status_text($exStrings.GetString("Select first end"), SB_PROMPT)
-
- # clear the InputPoints
- @ip1.clear
- @ip2.clear
-
- if( view )
- view.tooltip = nil
- view.invalidate if @drawn
- end
-
- @drawn = false
- @dragging = false
- end
-
- # Create new geometry when the user has selected two points.
- def create_geometry(p1, p2, view)
- view.model.entities.add_cline(p1,p2)
- end
-
- # Draw the geometry
- def draw_geometry(pt1, pt2, view)
- view.draw_line(pt1, pt2)
- end
-
- end # class LineTool
-
- #-----------------------------------------------------------------------------
- # You can use inheritance in Ruby to use the LineTool class as a base class
- # for similar kinds of tools. For example, this is a tool that creates
- # cylinders by selecting the two end points.
-
- class CylTool < LineTool
-
- # The cylinder tool takes a radius when you create it
- def initialize(radius = 1)
- @radius = radius
- @numsegs = 16
- super()
- end
-
- # Now we just have to override the create_geometry method. You could also
- # override the draw_geometry method to make it draw a closer represenation
- # to waht it will really create.
- def create_geometry(pt1, pt2, view)
- model = view.model
- model.start_operation $exStrings.GetString("Create Cylinder")
- entities = model.entities
-
- # First create a circle
- vec = pt2 - pt1
- length = vec.length
- if( length == 0.0 )
- UI.beep
- puts "Cannot create a zero length cylinder"
- return
- end
- circle = entities.add_circle pt1, vec, @radius, @numsegs
-
- # Now do a pushpull to create the cylinder
- face = entities.add_face circle
- normal = face.normal
- length = -length if( (normal % vec) < 0.0 )
- face.pushpull length
-
- model.commit_operation
- end
-
- end # class CylTool
-
- #-----------------------------------------------------------------------------
- # This functions is just a shortcut for selecting the new tool
- def linetool
- Sketchup.active_model.select_tool LineTool.new
- end
-