Sunday, March 28, 2010

LookAt.rb

Hello this is my first publicly posted script on this blog so i am excited to share it! The script will align a group or component with a target point by first picking two points in the group/component "pivot point" and "align point", then picking a "target point". After picking the 3 points with the built in picking tool the group/component will be rotated so that the "align point" touches the invisible ray from the "pivot point" to the "target point". If your confused just run the damn script ;)

In the future i would like to have it function by picking only the pivot point and then allow the user to "drag" the align point around in 3d space much like the move tool works. Hovering over any point will snap the rotation into action. But for now just be happy with what ya got people! :)

As of now i don't know if i can attach a text file for download here so i had to just post the text. Just copy and paste the red text and save it as "LookAt.rb" in your plugins folder. If you have any troubles let me know. rt8396@gmail.com


# 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'

class PickPoints
def initialize(obj)
@obj = obj
@ip1 = nil
@ip2 = nil
@ip3 = nil
@xdown = 0
@ydown = 0
end
def activate
@ip1 = Sketchup::InputPoint.new
@ip2 = Sketchup::InputPoint.new
@ip3 = Sketchup::InputPoint.new
@ip = Sketchup::InputPoint.new
@drawn = false
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
end
end
def onLButtonDown(flags, x, y, view)
model = Sketchup.active_model
pick = view.inputpoint(x,y)
if pick == nil
UI.messagebox("Must Pick a valid Vertex (green dot SU7)", MB_OK, "Error")
return
end
loc = pick.position()
if (@pt1 == nil) and (@pt2 == nil) and (@pt3 == nil)
# first point not picked yet
if UI.messagebox("Save point as pivot point?:\n"+loc.inspect, MB_OKCANCEL, "Pivot") == 1
@pt1 = loc
Sketchup::set_status_text("Step 2: Pick an align point", SB_PROMPT)
else
self.reset(nil)
end
elsif (@pt1 != nil) and (@pt2 == nil) and (@pt3 == nil)
# first point picked, so prompt for second
if UI.messagebox("Save point as align?:\n"+loc.inspect, MB_OKCANCEL, "Align") == 1
@pt2 = loc
Sketchup::set_status_text("Step 3: Pick a target point", SB_PROMPT)
else
self.reset(nil)
end
elsif (@pt1 != nil) and (@pt2 != nil) and (@pt3 == nil)
# first an second points picked, so prompt for third
if UI.messagebox("Save point as target?:\n"+loc.inspect, MB_OKCANCEL, "Target") == 1
@pt3 = loc
self.rotObj
else
self.reset(nil)
end
end
view.lock_inference
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)
@drawn = true
end
end
end
def onCancel(flag, view)
self.reset(view)
@pt1 = nil
view.lock_inference
end
def enableVCB?
return false
end
def reset(view)
@state = 0
Sketchup::set_status_text("Step 1: Select a pivot point", SB_PROMPT)
@pt1 = nil
@pt2 = nil
@pt3 = nil
if( view )
view.tooltip = nil
view.invalidate if @drawn
end
@drawn = false
@dragging = false
end
def rotObj
hingePt = @pt1
alignPt = @pt2
targetPt = @pt3
obj = @obj
model = Sketchup.active_model
ents = model.active_entities
model.start_operation('lookat')
objVec = hingePt.vector_to(alignPt).normalize!
rayVec = hingePt.vector_to(targetPt).normalize!
axis = objVec.cross(rayVec)
t = Geom::Transformation.rotation(hingePt, axis, objVec.angle_between(rayVec))
obj.transform!(t)
model.commit_operation()
end
end # class PickPoints


module JJ_LookAt
def self.doit
model = Sketchup.active_model
ents = model.active_entities
ss = model.selection
#Sketchup.send_action('showRubyPanel:')
if (ss.length != 1) or (not ss[0].respond_to?('transform!'))
UI.messagebox('Please select the group or component to rotate', MB_OK)
return
end
# Now run the tool so the user can pick `hingePt`, `targetPt`, `alignPt`
model.select_tool(PickPoints.new(ss[0]))
end

end #MODULE

#-- menu --#
filename="lookAt.rb"
if not file_loaded?(filename)
plugins_menu = UI.menu("Plugins")
plugins_menu.add_separator
plugins_menu.add_item('LookAt') {JJ_LookAt.doit}
file_loaded(filename)
end