# Copyright 2004, @Last Software, Inc., modified by D. Bur
# 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.
#-----------------------------------------------------------------------------
# Name : pushpulltool.rb
# Description : A script to push pull faces along a vector given with 2 clicks
# Menu Item : Context menu->Pushpull tool
# Usage : Select faces, select "Pushpull tool" from the context Menu, then click 2 points on your model
# Date : 11/02/2004
# Type : tool
#-----------------------------------------------------------------------------
require 'sketchup.rb'
class PushPull_Tool
def initialize
$ss = Sketchup.active_model.selection
$ip1 = nil
$ip2 = nil
@xdown = 0
@ydown = 0
end
def activate
$ip1 = Sketchup::InputPoint.new
$ip2 = Sketchup::InputPoint.new
@ip = Sketchup::InputPoint.new
@drawn = false
Sketchup::set_status_text "Length", SB_VCB_LABEL
self.reset(nil)
end
def deactivate(view)
view.invalidate if @drawn
end
def onMouseMove(flags, x, y, view)
if( @state == 0 )
@ip.pick view, x, y
if( @ip != $ip1 )
view.invalidate if( @ip.display? or $ip1.display? )
$ip1.copy! @ip
view.tooltip = $ip1.tooltip
end
else
$ip2.pick view, x, y, $ip1
view.tooltip = $ip2.tooltip if( $ip2.valid? )
view.invalidate
if( $ip2.valid? )
length = $ip1.position.distance($ip2.position)
Sketchup::set_status_text length.to_s, SB_VCB_VALUE
end
if( (x-@xdown).abs > 10 || (y-@ydown).abs > 10 )
@dragging = true
end
end
end
def onLButtonDown(flags, x, y, view)
if( @state == 0 )
$ip1.pick view, x, y
if( $ip1.valid? )
@state = 1
Sketchup::set_status_text "Second point", SB_PROMPT
@xdown = x
@ydown = y
end
else
if( $ip2.valid? )
self.create_geometry($ip1.position, $ip2.position,view)
self.reset(view)
end
end
view.lock_inference
end
# The onLButtonUp method is called when the user releases the left mouse button.
def onLButtonUp(flags, x, y, view)
if( @dragging && $ip2.valid? )
self.create_geometry($ip1.position, $ip2.position,view)
self.reset(view)
end
end
def onKeyDown(key, repeat, flags, view)
if( key == CONSTRAIN_MODIFIER_KEY && repeat == 1 )
@shift_down_time = Time.now
if( view.inference_locked? )
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
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
def onUserText(text, view)
return if not @state == 1
return if not $ip2.valid?
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
pt1 = $ip1.position
vec = $ip2.position - pt1
if( vec.length == 0.0 )
UI.beep
return
end
vec.length = value
pt2 = pt1 + vec
self.create_geometry(pt1, pt2, view)
self.reset(view)
end
def draw(view)
if( $ip1.valid? )
if( $ip1.display? )
$ip1.draw(view)
@drawn = true
end
if( $ip2.valid? )
$ip2.draw(view) if( $ip2.display? )
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
# Reset the tool back to its initial state
def reset(view)
@state = 0
Sketchup::set_status_text("First point", SB_PROMPT)
$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)
model = Sketchup.active_model
model.start_operation "Push-Pull tool"
entities = model.active_entities
ss = model.selection
# Selection error checking
others = 0
i = 0
0.upto(ss.length - 1) do |something|
element = ss[i]
if( element.typename != "Face")
others = others + 1
end
i = i + 1
end #of upto
if( others != 0 )
UI.messagebox( others.to_s + " objects in the selection aren't faces and will be ignored.")
end
dx = $ip2.position.x - $ip1.position.x
dy = $ip2.position.y - $ip1.position.y
dz = $ip2.position.z - $ip1.position.z
# process each face
current_face = 0
0.upto(ss.length - 1) do |pts|
if( ss[current_face].typename == "Face")
pts = ss[current_face].vertices
length_pts = pts.length
# copy the selected face
i = 0
pts2 = []
pts.each do |pt|
pts2[i] = pt.position + [dx,dy ,dz]
i = i +1
end
face_copy = entities.add_face pts2
pts_copy = face_copy.vertices
# create faces between pairs of vertices of each face
i = 0
j = 0
0.upto(pts.length - 2) do |new_face|
new_face = entities.add_face(pts[i], pts_copy[i], pts_copy[i + 1], pts[i + 1])
i = i + 1
end # of upto
# close the shape
new_face = entities.add_face(pts[pts.length - 1], pts_copy[pts.length - 1], pts_copy[0], pts[0])
end # of if == face
current_face = current_face + 1
end #end of upto faces
#That's all folks
model.commit_operation
end
# Draw the geometry
def draw_geometry(pt1, pt2, view)
view.draw_line(pt1, pt2)
end
end # class PushPull_Tool
#-----------------------------------------------------------------------------
# This functions is just a shortcut for selecting the new tool
def ex_pushpull_tool
Sketchup.active_model.select_tool PushPull_Tool.new
end
if( not file_loaded?("pushpull_tool.rb") )
#UI.add_context_menu_handler do |menu|
#menu.add_separator("Pushpull Tool")
#menu.add_item("Pushpull Tool") { ex_pushpull_tool }
#end
UI.add_context_menu_handler do |menu|
menu.add_separator
menu.add_item("Pushpull in any direction") { ex_pushpull_tool }
end
end
#-----------------------------------------------------------------------------
file_loaded("pushpull_tool.rb")