=begin
btm_Sculpt6_Grab.rb

Copyright 2009, btmsketchup@hotmail.com

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.

Created by •BTM on 23/07/09.

Name:			Grab (sculpt tools)
Version:		1.0
Description:	Grabs parts of a mesh, to move and deform.
Usage:			Set the settings of the tool with the Sculpt Tools Dialog, and use it by grabing the mesh, with the left mouse button held down, and draging.
=end
require 'sketchup.rb'
#===================================================================================
class GrabSculpt
#===================================================================================
	def activate

	@model = Sketchup.active_model
	if Sketchup.version_number < 7000000
		@model.start_operation "Grab & Drag"
	else
		@model.start_operation "Grab & Drag", true
	end
	@entities = @model.active_entities
	@selection = @model.selection

	@points = []
	@apns = []
	@drawlocked = []
	@sculptlocks = []

	@max_thing = $btm_sculpt_radius
	@percent = $btm_sculpt_strength
	@area = $btm_sculpt_area
	@gravity = $btm_sculpt_gravity
	@kind = $btm_sculpt_trans
	@platform = $btm_sculpt_platform
	@locked = $btm_sculpt_lock

	cursor_path = Sketchup.find_support_file("point_cursor.png", "Plugins/btm_Sculpt_Tools/")
	@cursor = UI.create_cursor(cursor_path, 9, 1)
#     -     -     -     -     -     -     -     -     -     -     -     -     -    -
	@ip1 = Sketchup::InputPoint.new
    @ip2 = Sketchup::InputPoint.new
	@apns = []
	@drawlocked = []
#     -     -     -     -     -     -     -     -     -     -     -     -     -    -
	if @locked == "Use + Show" or @locked == "Use"
		@entities.each do |e|
			if e.is_a? Sketchup::Edge
			@apns << e.start
			@apns << e.end
			end
		att = e.get_attribute "sculpt", "lockgroup"
			if att != nil
			@sculptlocks << att
			end
		end
		@apns.uniq!
#     -     -     -     -     -     -     -     -     -     -     -     -     -    -
		@apns.each do |p|
			@sculptlocks.each do |l|
				if p.position.on_plane? l
				@drawlocked << p
				attrs = p.get_attribute  "sculpt", "lock"
				attrs = [] if not p.get_attribute  "sculpt", "lock"
				attrs << l
				p.set_attribute "sculpt", "lock", attrs
				end
			end
		end
	@drawlocked.uniq!
	end
#     -     -     -     -     -     -     -     -     -     -     -     -     -    -
	
	@viewpoints = []
	@show = 0
	end
#==================================================================================
	def onSetCursor
	UI.set_cursor(@cursor)
	end
#===================================================================================
	def onMouseMove(flags,x,y,view)
	@ip1.pick view, x, y
	@mouse_point = @ip1.position
		if @show == 1
			@points.each do |v|	
			pos = v.position
			vector = @firstpoint.vector_to @mouse_point
			vdist = @firstpoint.distance @mouse_point
			if vector != [0,0,0]
			length = v.get_attribute "btm", "sculpt"
			vlength = length*vdist
			vector.length = vlength
			pos2 = pos.offset vector
			@viewpoints << pos2
			end
			end
		end
		if @ip1 != @ip2
		view.invalidate# if( @ip1.display? or @ip2.display? )
		@ip2.copy! @ip1
		end

	end
#===================================================================================
#THIS SECTION OF CODE UNTILL end#def WAS WRITTEN BY TIG.
def circleArray(center,normal,radius,numseg)
    # Get the x and y axes
    axes = Geom::Vector3d.new(normal).axes
    center = Geom::Point3d.new(center)
    xaxis = axes[0]
    yaxis = axes[1]
    xaxis.length = radius
    yaxis.length = radius
    # compute the points
    da = (Math::PI * 2) / numseg
    pts = []
    for i in 0...numseg do
        angle = i * da
        cosa = Math.cos(angle)
        sina = Math.sin(angle)
        vec = Geom::Vector3d.linear_combination(cosa,xaxis,sina,yaxis)
        pts.push(center + vec)
    end
    # close the circle
    pts.push(pts[0].clone)
    pts
end#def
#===================================================================================

	def draw(view)
		if $btm_sculpt_visual == "Inference" or $btm_sculpt_visual == "Inference + Radius"
		@ip1.draw view
		end
			
		if @locked== "Use + Show" and @drawlocked != []
		dps = []
			@drawlocked.each do |d|
			dps << d.position
			end
		view.draw_points dps, 6, 1, "red"
		end
#     -     -     -     -     -     -     -     -     -     -     -     -     -    -
		if @show == 1
			if @viewpoints != []
			view.draw_points @viewpoints, 5, 2, "orange"
			end
		view.drawing_color = "blue"
		view.draw_line @firstpoint,@mouse_point
		@viewpoints = []
		end
#     -     -     -     -     -     -     -     -     -     -     -     -     -    -
		if @show == 0
			points = []
			viewvec = [0,0,1]
			rad = @max_thing + @area
			@entities.each do |f|
				if f.is_a? Sketchup::Face and @ip1.position.on_plane? f.plane
				viewvec = f.normal
				end
			end
			if $btm_sculpt_visual == "Radius" or $btm_sculpt_visual == "Inference + Radius"
				if @max_thing > 0.to_l
				view.drawing_color="blue"
				view.draw GL_LINE_LOOP, circleArray(@ip1.position, viewvec, rad, 30)
				end
				if @area > 0.to_l
				view.drawing_color="red"
				view.draw GL_LINE_LOOP, circleArray(@ip1.position, viewvec, @area, 30)
				end
			end
		end
#     -     -     -     -     -     -     -     -     -     -     -     -     -    -
	end
#===================================================================================
	def onLButtonDown(flags,x,y,view)
	@model.start_operation "Grab & Drag"
#     -     -     -     -     -     -     -     -     -     -     -     -     -    -
		@entities.each do |e|
			if e.is_a? Sketchup::Edge
			@points << e.start
			@points << e.end
			end
		end
#     -     -     -     -     -     -     -     -     -     -     -     -     -    -
	@points.uniq!
#     -     -     -     -     -     -     -     -     -     -     -     -     -    -
		@points.each do |p|
		@pos = p.position
		dist = @pos.distance @mouse_point
		@firstpoint = @mouse_point
		radius = @max_thing + @area
		half_dist = @max_thing /2
		in_dist = dist - @area
		dist_from_half = half_dist - in_dist
#     -     -     -     -     -     -     -     -     -     -     -     -     -    -
			if @area < dist and dist <= radius
				if @kind == "s curve"
				@length = ((radius / ( 1 + E**-(5/ half_dist*dist_from_half)**1))/ radius)/100*@percent
				p.set_attribute "btm", "sculpt", @length.to_f
				
				elsif @kind == "pinch"
				@length = ((((radius - dist)**2)/ radius**2)/100)*@percent
				p.set_attribute "btm", "sculpt", @length.to_f
				
				elsif @kind == "bump"
				@length = ((((radius**2) - (dist**2))/ radius**2)/100)*@percent
				p.set_attribute "btm", "sculpt", @length.to_f
				
				else
				@length = ((radius - dist)/ radius)/100*@percent
				p.set_attribute "btm", "sculpt", @length.to_f
				end
			elsif dist <= @area
			@length = (radius/ radius)/100*@percent
			p.set_attribute "btm", "sculpt", @length.to_f
			
			elsif dist > radius
			@points = @points - [p]
			end
#     -     -     -     -     -     -     -     -     -     -     -     -     -    -
		end
	@show = 1
#     -     -     -     -     -     -     -     -     -     -     -     -     -    -
	end
#===================================================================================
	def onLButtonUp(flags,x,y,view)
	@show = 0
		@points.each do |p|
		pos = p.position
		@vector = @firstpoint.vector_to @mouse_point
		vdist = @firstpoint.distance @mouse_point
		length = p.get_attribute "btm", "sculpt"
		p.delete_attribute "btm"
		vlength = length*vdist
		@vector.length = vlength
		@entities.transform_entities(@vector,p)
			if @gravity != 0
			pos2 = p.position
			change = pos.distance pos2
			drop = -(change / 100)*@gravity
			vector2 = Geom::Vector3d.new [ 0, 0, drop]
			@entities.transform_entities(vector2,p)
			end
			if @locked == "Use + Show" or @locked == "Use"
			ats = p.get_attribute "sculpt", "lock"
				if ats != nil
					ats.each do |a|
					pos3 = p.position
					lockpoint = pos3.project_to_plane a
					vector3 = pos3.vector_to lockpoint
					@entities.transform_entities(vector3,p)
					end
				end
			end
		end
	end
#===================================================================================
	def deactivate(view)
		@drawlocked.each do |p|
		p.delete_attribute "sculpt", "lock"
		end
	end
#===================================================================================
end

		mgp = UI::Command.new("Grab") { Sketchup.active_model.select_tool GrabSculpt.new }
		$btm_sculpt_menu.add_item mgp
		mgp.large_icon = "./grab_cursor.png"
		mgp.small_icon = "./grab_cursor_s.png"
		mgp.tooltip = "Grab & Drag"
		toolbar = $btm_sculpt_toolbar.add_item mgp
		case toolbar.get_last_state
		when 1
			toolbar.restore
		when -1   
			toolbar.show
		end