# Supports Organizer.rb
=begin rdoc

= weld.rb
Copyright 2004-2014 by Rick Wilson - All Rights Reserved

== Disclaimer
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.

== License
This software is distributed under the Smustard End User License Agreement
http://www.smustard.com/eula

== Information
Author:: Rick Wilson
Organization:: Smustard
Name:: Weld
Version:: 3.0.5
SU Version:: 4.0
Date:: 2014-05-16
Description:: weld edges into curve ("polyline")

Usage::
* 1:: Install into the plugins directory or into the Plugins/examples directory and manually load from the ruby console "load 'examples/weld.rb'" 
* 2:: Select edges, then run the script (Plugins>Weld)
* 3:: Edges will be joined into a curve ("polyline")
* 4:: Script will prompt to find faces
	
History::
* 1.0.0:: 2004-08-04
	* first version
* 1.1.0:: 2004-09-10
	* allows working in groups/components
* 1.2.0:: 2005-05-12
	* fixed edge bug that occasionally resulted in strange edge locations and deletions
* 2.0.0:: 2005-07-25
	* fixed bug where unselected edges were welded, now retains existing faces.
* 2.1:: 2005-07-27
	* fixed the fix that caused strange non-welding issues.
* 2.2.0:: 2005-08-01
	* used group/explode to fix most problems; still won't weld to non-arc curves
* 3.0.0:: 2005-08-04
	* Special Anniversary Edition! now welds to existing curves, adds option to find faces
* 3.0.1:: 2010-09-22
	* Updated to include Smustard module and Weld class
* 3.0.2::	2013-05-16
	* Updated to meet Extension Warehouse requirements (no functional changes)
* 3.0.3:: 2013-07-24
	* Fixed bug that prevented closed edge groups (circles, polygons, etc.) from welding
* 3.0.4:: 2014-05-02
	* updated the SmustardToolbar reference from a global to a Smustard module constant
	* updated the submenu reference from a global to a Smustard module constant
* 3.0.5:: 2014-05-16
	* version 3.0.4 works in SU 2014, but a code block didn't work in earlier versions (due to changes in Ruby).  Fixed this to work in all versions.

ToDoList::
	* Parse disconnected sets as multiple operations in one instance
	* 

=end


require 'sketchup.rb'


module Smustard
	
	if ($submenu) # legacy programs creating a global
		Smustard::Submenu = $submenu unless Smustard.constants.include?("Submenu")
	else
		Smustard::Submenu = nil unless Smustard.constants.include?("Submenu")
	end
	

	
	if ($smustard_toolbar)	# legacy programs creating a global
		Smustard::Toolbar = $smustard_toolbar unless Smustard.constants.include?("Toolbar")
			
	else
		Smustard::Toolbar = UI::Toolbar.new("Smustard") unless Smustard.constants.include?("Toolbar")
			
	end

class Weld

	@@firstrun = false

	if Sketchup.read_default("smustard_weld","close_curve")===nil || Sketchup.read_default("smustard_weld","find_faces")===nil
		Sketchup.write_default("smustard_weld","close_curve",false)
		Sketchup.write_default("smustard_weld","find_faces",true)
		@@firstrun = true
	end

	@@settings = {}
	
	@@settings["Close Curve"] = Sketchup.read_default("smustard_weld","close_curve")
	@@settings["Find Faces"] = Sketchup.read_default("smustard_weld","find_faces")
	
	@@cmd_weld = UI::Command.new("Weld"){ Smustard::Weld.new(true) }
	@@cmd_weld.tooltip = "Weld"
	@@cmd_weld.status_bar_text = "Weld edges and curves into polyline"
	@@cmd_weld.large_icon = "weldLarge.png"
	@@cmd_weld.small_icon = "weldSmall.png"
	
	@@cmd_weld_settings = UI::Command.new("Weld Settings"){ Smustard::Weld.new(false) }
	@@cmd_weld_settings.tooltip = "Weld Settings"
	@@cmd_weld_settings.large_icon = "weldSettingsLarge.png"
	@@cmd_weld_settings.small_icon = "weldSettingsSmall.png"
	
	attr_accessor :model
	
	
	
	def initialize(settings = nil)		# nil = ask for settings, do weld	false = ask for settings	true = weld without settings query
		
		settings() if @@firstrun || settings!=true
		
		@model = Sketchup.active_model
		@ents = model.active_entities
		@sel = model.selection
		@sl = @sel.length
		@verts = []
		@edges = []
		@newVerts = []
		@startEdge = @startVert = nil
		
		join_edges() unless settings == false
		
	end



	def join_edges()
		
		
#DELETE NON-EDGES, GET THE VERTICES
		
		@sel.each {|item| @edges << item if item.typename=="Edge"}
		@edges.each {|edge| @verts << (edge.vertices)}
		@verts.flatten!
		return UI.messagebox("Please select at least 2 edges") if @edges.length < 2
		
#FIND AN END VERTEX
		
		vertsShort=[]
		vertsLong=[]
		@verts.each do |v|
			if vertsLong.include?(v)
				vertsShort.push(v)
			else
				vertsLong.push(v)
			end
		end
		if (@startVert=(vertsLong-vertsShort).first)==nil
			@startVert=vertsLong.first
			closed=true
			@startEdge = @startVert.edges.first
		else
			closed=false
			@startEdge = (@edges & @startVert.edges).first
		end
		#sel.clear
		
#SORT VERTICES, LIMITING TO THOSE IN THE SELECTION SET
		
		if @startVert==@startEdge.start
			newVerts=[@startVert]
			counter=0
			while newVerts.length < @verts.length
				@edges.each do |edge|
					if edge.end==newVerts.last
						newVerts.push(edge.start)
					elsif edge.start==newVerts.last
						newVerts.push(edge.end)
					end
				end
				counter+=1
				if counter > @verts.length
					return nil if UI.messagebox("There seems to be a problem. Try again?", MB_YESNO)!=6
					newVerts.reverse!
					reversed=true
				end
			end
		else
			newVerts=[@startVert]
			counter=0
			while newVerts.length < @verts.length
				@edges.each do |edge|
					if edge.end==newVerts.last
						newVerts.push(edge.start)
					elsif edge.start==newVerts.last
						newVerts.push(edge.end)
					end
				end
				counter+=1
				if counter > @verts.length
					return nil if UI.messagebox("There seems to be a problem. Try again?", MB_YESNO)!=6
					newVerts.reverse!
					reversed=true
				end
			end
		end
		newVerts.uniq!
		newVerts.reverse! if reversed
		
#CONVERT VERTICES TO POINT3Ds
		
		newVerts.collect!{|x| x.position}
		if closed
			newVerts.push(newVerts[0])
		#else
		#	newVerts.push(newVerts[0]) if UI.messagebox("Close curve?", MB_YESNO)==6
		#	closed=true
		end
		
#CREATE THE CURVE
		
		@model.start_operation "weld"
		@edges.each {|item| item.explode_curve if item.curve and newVerts.include?(item.start.position)}
		gp1e=(gp1=@ents.add_group).entities
		gp1.make_unique
		curveEdges=gp1e.add_curve(newVerts)
		@gpents=gp1.explode
		#ents[-1].find_faces if closed and ents[-1].typename=="Edge" and UI.messagebox("Find faces for this curve?", MB_YESNO, "Weld Edges Utility")==6
		@model.commit_operation
		@sel.clear
	end
	
	
	
	def settings()
		@@firstrun = false if @@firstrun
		prompts = ["Close Curve: ", "Find Faces: "]
		yesno = ["Yes","No"]
		truefalse = {}; truefalse[true] = "Yes"; truefalse[false] = "No"
		defaults = [truefalse[Sketchup.read_default("smustard_weld","close_curve")],truefalse[Sketchup.read_default("smustard_weld","find_faces")]]
		result = UI.inputbox(prompts,defaults,[yesno.join("|"),yesno.join("|")],"Smustard Weld Settings")
		if result
			options = {}; options["No"] = false; options["Yes"] = true
			Sketchup.write_default("smustard_weld","close_curve",options[result[0]])
			Sketchup.write_default("smustard_weld","find_faces",options[result[1]])
		end
	end
	
	
	
	def Weld.build_ui()
		Smustard::Submenu ? (organizer = Smustard::Submenu) : (organizer = UI.menu("Plugins"))
		organizer.add_item(@@cmd_weld)
		organizer.add_item(@@cmd_weld_settings)
		
		Smustard::Toolbar.add_item(@@cmd_weld)
		Smustard::Toolbar.add_item(@@cmd_weld_settings)
		
	end
	
end #class Weld
	
end #module Smustard



unless file_loaded?(__FILE__)
	Smustard::Weld.build_ui
	file_loaded(__FILE__)
end
