Polygon Tool
-
When it comes to creating "tools" within SketchUp I am severely handicapped. I kind of understand what is going on but it is more of black box to me than anything. With the code below I am trying to have the user input in a polygon that will be the perimeter of the slab foundation. I've got it mostly working but cannot figure out how to make it snap to the x and y axis or start and end points of lines. My code thus far is below:
######################################### # # Foundation POSITIONING LOGIC (Polygon) # ######################################### module FoundationPositionToolPolygon # -------- FOUNDATION POSITIONING TOOL ------------------------------------------------ # Positions the foundation assembly. This tool allows the user # to place the foundation assembly using the mouse to select a polygon class PositionToolPolygon # Show the Ruby Console at startup so we can # see any programming errors we may make. # SKETCHUP_CONSOLE.show # these are the states that a tool can be in STATE_EDIT = 0 if not defined? STATE_EDIT STATE_PICK = 1 if not defined? STATE_PICK STATE_PICK_2 = 2 if not defined? STATE_PICK_2 STATE_PICK_3 = 3 if not defined? STATE_PICK_3 STATE_PICK_FINAL = 4 if not defined? STATE_PICK_FINAL STATE_MOVING = 6 if not defined? STATE_MOVING STATE_SELECT = 7 if not defined? STATE_SELECT def initialize() @tool_name = "FOUNDATION LOCATOR" @type = "foundation" @pointcount = 0 end def reset @pts = [] @state = STATE_PICK @pointcount = 0 # This sets the label for the VCB Sketchup;;set_status_text "MEDEEK FOUNDATION", SB_VCB_LABEL Sketchup;;set_status_text "[#{@tool_name}] Click first corner of Polygon" @status_text = "[#{@tool_name}] Click first corner of Polygon" @drawn = false end def activate @ip1 = Sketchup;;InputPoint.new @ip = Sketchup;;InputPoint.new self.reset end def deactivate(view) view.invalidate if @drawn @ip1 = nil end def onMouseMove(flags, x, y, view) self.set_current_point(x, y, view) Sketchup;;set_status_text @status_text,SB_PROMPT end def onLButtonDown(flags, x, y, view) self.set_current_point(x, y, view) self.update_state end def set_current_point(x, y, view) if (!@ip.pick(view, x, y, @ip1)) return false end need_draw = true # Set the tooltip that will be displayed view.tooltip = @ip.tooltip # Compute points case @state when STATE_PICK @pts[0] = @ip.position # need_draw = @ip.display? || @drawn when STATE_PICK_2 @pts[1] = @ip.position when STATE_PICK_3 @pts[2] = @ip.position when STATE_PICK_FINAL @pts[@pointcount] = @ip.position end view.invalidate if need_draw end def update_state case @state when STATE_PICK @ip1.copy! @ip @pointcount = @pointcount + 1 Sketchup;;set_status_text "[#{@tool_name}] Click second corner of Polygon" @state = STATE_PICK_2 puts "#{@state} #{@pointcount}" @status_text = "[#{@tool_name}] Click second corner of Polygon" when STATE_PICK_2 @ip1.clear @pointcount = @pointcount + 1 Sketchup;;set_status_text "[#{@tool_name}] Click third corner of Polygon" @state = STATE_PICK_3 puts "#{@state} #{@pointcount}" @status_text = "[#{@tool_name}] Click third corner of Polygon" when STATE_PICK_3 @ip1.clear @pointcount = @pointcount + 1 Sketchup;;set_status_text "[#{@tool_name}] Click fourth corner of Polygon" @state = STATE_PICK_FINAL puts "#{@state} #{@pointcount}" @status_text = "[#{@tool_name}] Click fourth corner of Polygon" when STATE_PICK_FINAL @ip1.clear ptcurrent = @ip.position @distorigin = @pts[0].distance ptcurrent if (@distorigin > 0.0001) @pointcount = @pointcount + 1 @nextpointcount = @pointcount + 1 @state = STATE_PICK_FINAL puts "#{@state} #{@pointcount}" Sketchup;;set_status_text "[#{@tool_name}] Click corner #{@nextpointcount} of Polygon" @status_text = "[#{@tool_name}] Click corner #{@nextpointcount} of Polygon" else # Final point picked self.calculate_obj Sketchup.active_model.select_tool(nil) end end end def calculate_obj ########### # # Check units of template again lengthconstant = Sketchup.active_model.options["UnitsOptions"]["LengthUnit"] if (lengthconstant == 0) || (lengthconstant == 1) @Unitstemplate2 = "imperial" else @Unitstemplate2 = "metric" end if @Unitstemplate2 == "metric" # Sketchup;;set_status_text "Foundation Width; #{@BuildingSpan_m.round(4)} m - Foundation Length; #{@BuildingLength_m.round(4)} m" else # Sketchup;;set_status_text "Foundation Width; #{@BuildingSpan_ft.round(4)} ft. - Foundation Length; #{@BuildingLength_ft.round(4)} ft." end MedeekMethods.main_menu_polygon @pts, @pointcount end def onCancel(flag, view) view.invalidate if @drawn reset end def onUserText(text, view) # 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 value = nil Sketchup;;set_status_text "", SB_VCB_VALUE end return if !value case @state when STATE_PICK_NEXT # update the width vec = @pts[1] - @pts[0] if( vec.length > 0.0 ) vec.length = value @pts[1] = @pts[0].offset(vec) view.invalidate self.update_state end when STATE_PICK_LAST # update the height vec = @pts[3] - @pts[0] if( vec.length > 0.0 ) vec.length = value @pts[2] = @pts[1].offset(vec) @pts[3] = @pts[0].offset(vec) self.update_state end end end def getExtents bb = Geom;;BoundingBox.new case @state when STATE_PICK # We are getting the first point if( @ip.valid? && @ip.display? ) bb.add @ip.position end when STATE_PICK_2 bb.add @pts[0] bb.add @pts[1] when STATE_PICK_3 bb.add @pts[2] when STATE_PICK_FINAL bb.add @pts end return bb end def onKeyDown(key, rpt, flags, view) if( key == CONSTRAIN_MODIFIER_KEY && rpt == 1 ) @shift_down_time = Time.now # if we already have an inference lock, then unlock it if( view.inference_locked? ) view.lock_inference elsif( @state == 0 ) view.lock_inference @ip elsif( @state == 1 ) view.lock_inference @ip, @ip1 elsif( @state == 2 ) view.lock_inference @ip, @ip1 elsif( @state == 3 ) view.lock_inference @ip, @ip1 elsif( @state == 4 ) view.lock_inference @ip, @ip1 end end end def onKeyUp(key, rpt, flags, view) if( key == CONSTRAIN_MODIFIER_KEY && view.inference_locked? && (Time.now - @shift_down_time) > 0.5 ) view.lock_inference end end # draw a polygon for the outline of the foundation def draw(view) @drawn = false # Show the current input point if( @ip.valid? && @ip.display? ) @ip.draw(view) @drawn = true end case @state when STATE_PICK # do nothing when STATE_PICK_2 # just draw a line from the start to the end point view.set_color_from_line(@ip1, @ip) view.drawing_color = [0, 0, 200] inference_locked = view.inference_locked? view.line_width = 2 if inference_locked view.line_width = 2 view.draw(GL_LINE_STRIP, @pts[0], @pts[1]) @drawn = true else # view.set_color_from_line(@ip1, @ip) view.drawing_color = [0, 0, 200] inference_locked = view.inference_locked? view.line_width = 2 if inference_locked view.line_width = 2 view.draw(GL_LINE_STRIP, @pts) @drawn = true end end end # class PositionToolPolygon ####################################### end # module FoundationPositionToolPolygon
-
Pls edit and remove code, then re-post properly indented code in a [ code ] ... [ /code ] block.
(Ie, no one will even attempt to read it.)
-
Hopefully that is a bit better.
-
What would be useful is if I could somehow constrain the line angle (or snap to) to 15 degree increments. Has anyone ever tried to do something like this?
-
Fredo's DrawAlong tool in Fredo Tools snaps to increments.
-
You would basically save the user's current angle snap settings, set 15 degrees and angle snap ON, do your thing, then restore the user's settings.
At the least you should honor the user's settings (perhaps as a starting point.)
Access via
Sketchup::Model#options()
, ie:model = Sketchup.active_model manager = model.options manager.each {|key| puts "#{key.name}" } #=> PageOptions #=> UnitsOptions #=> SlideshowOptions #=> NamedOptions #=> PrintOptions opts = manager["UnitsOptions"] #=> #<Sketchup;;OptionsProvider;0x00000009215148> opts.each {|key,name| puts "#{key} = #{name}" } #=> LengthPrecision = 3 #=> LengthFormat = 0 #=> LengthUnit = 0 #=> LengthSnapEnabled = true #=> LengthSnapLength = 0.0001 #=> AnglePrecision = 1 #=> AngleSnapEnabled = true #=> SnapAngle = 15.0 #=> SuppressUnitsDisplay = false #=> ForceInchDisplay = false
so:
def save_angle_options(model=Sketchup;;active_model) opts = model.options["UnitsOptions"] opts["AngleSnapEnabled"], opts["SnapAngle"] end def restore_angle_options(snapping,angle,model=Sketchup;;active_model) opts = model.options["UnitsOptions"] opts["AngleSnapEnabled"]= snapping opts["SnapAngle"]= angle end # In code elsewhere; snapping, angle = save_angle_options() # do your thing restore_angle_options(snapping,angle)
-
Even when I'm drawing a line with the built in tools the angle snapping in SketchUp doesn't seem to work, what am I missing here?
-
Angle snapping works for rotational tools or tool states.
Length snapping would work for linear tool states.
Advertisement