# lss_matrix_tools.rb ver. 1.0.  11-Jan-12
# Main ccript, which contains LSS Matrix tools and commands.

#~ '(C) 2010, Links System Software
#~ 'Feedback information
#~ 'E-mail1: designer@ls-software.ru
#~ 'E-mail2: kirill2007_77@mail.ru (search this e-mail to add skype contact)
#~ 'icq: 328-958-369

# 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 'lss_matrix/lssmatrix_utils.rb'

class Lss_Matrix_Cmds
	def initialize
		@su_tools=Sketchup.active_model.tools
		@lss_matrix_tools_observer=nil
		@lss_matrix_tools_observer_state="disabled"
		
		lss_matrix_cmd=UI::Command.new($lssmatrixStrings.GetString("LSS Matrix Dialog")){
			lss_matrix_tool=Lss_Matrix_Tool.new("lss_matrix_mini.html") #web-dialog name
			Sketchup.active_model.select_tool(lss_matrix_tool)
		}
		lss_matrix_cmd.small_icon = "./tb_icons/web_dial_16.png"
		lss_matrix_cmd.large_icon = "./tb_icons/web_dial_24.png"
		lss_matrix_cmd.tooltip = $lssmatrixStrings.GetString("Click to launch LSS Matrix dialog window.")
		$lssmatrixToolbar.add_item(lss_matrix_cmd)
		$lssmatrixMenu.add_item(lss_matrix_cmd)

		props_cmd=UI::Command.new($lssmatrixStrings.GetString("Edit Copy Instance Properties...")){
			selection=Sketchup.active_model.selection
			if selection.count>1 or selection.count<0
				UI.messagebox($lssmatrixStrings.GetString("It is necessary to select one copy instance."))
				return
			end
			matrix_inst=selection[0]
			if matrix_inst.typename=="Group" or matrix_inst.typename=="ComponentInstance"
			lss_matrix_attr_dict=nil
			lss_matrix_attr_dicts=Array.new
				if matrix_inst.attribute_dictionaries.to_a.length>0
					matrix_inst.attribute_dictionaries.each{|attr_dict|
						if attr_dict.name.split("_")[0]=="lssmatrixdict"
							lss_matrix_attr_dict=attr_dict
							lss_matrix_attr_dicts<<lss_matrix_attr_dict
						end
					}
				end
			else
				UI.messagebox($lssmatrixStrings.GetString("The selected object is not a copy instance of LSS Matrix group."))
			end
			if lss_matrix_attr_dicts.length>1
				prompts=[$lssmatrixStrings.GetString("Instance Type and Time")]
				defaults=["1) #{lss_matrix_attr_dicts[0]["inst_type"]}, #{Time.at(lss_matrix_attr_dicts[0].name.split("_")[1].to_f).utc.to_s}"]
				list_str=""
				lss_matrix_attr_dicts.each_index{|ind|
					list_str+="#{ind+1}) #{lss_matrix_attr_dicts[ind]["inst_type"]}, #{Time.at(lss_matrix_attr_dicts[ind].name.split("_")[1].to_f).utc.to_s}|"
				}
				list=[list_str]
				input_res = UI.inputbox(prompts, defaults, list, $lssmatrixStrings.GetString("Choose Instance to Edit Its Properties"))
				if input_res
					res_ind=input_res[0].split(")")[0].to_i-1
					lss_matrix_attr_dict=lss_matrix_attr_dicts[res_ind]
				else
					return
				end
			end
			if lss_matrix_attr_dict
				case lss_matrix_attr_dict["inst_type"]
					when "zero_inst"
					self.zero_inst_props(matrix_inst, lss_matrix_attr_dict)
					when "copy_inst"
					self.copy_inst_props(matrix_inst, lss_matrix_attr_dict)
					when "result_copy"
					UI.messagebox($lssmatrixStrings.GetString("The selected object is a result copy instance of LSS Matrix copies array."))
					when "links_grp"
					UI.messagebox($lssmatrixStrings.GetString("The selected object is a group, which represents links between copy instances centers."))
					when "surf_grp"
					UI.messagebox($lssmatrixStrings.GetString("The selected object is a surface."))
				end
			else
				UI.messagebox($lssmatrixStrings.GetString("The selected object is not a copy instance of LSS Matrix group."))
			end
		}
		props_cmd.small_icon = "./tb_icons/props_16.png"
		props_cmd.large_icon = "./tb_icons/props_24.png"
		props_cmd.tooltip = $lssmatrixStrings.GetString("Select copy instance, then click to edit its properties.")
		$lssmatrixToolbar.add_item(props_cmd)
		$lssmatrixMenu.add_item(props_cmd)

		refresh_cmd=UI::Command.new($lssmatrixStrings.GetString("Refresh Copies Array...")){
			@entities=Sketchup.active_model.active_entities
			selection=Sketchup.active_model.selection
			if selection.count<0
				UI.messagebox($lssmatrixStrings.GetString("It is necessary to select any instance of LSS Matrix group."))
				return
			end
			processed_grps_names=Array.new
			set_of_obj=Array.new
			selection.each{|obj|
				set_of_obj<<obj
			}
			lss_matrix_attr_dicts=Array.new
			set_of_obj.each{|copy_inst|
				if copy_inst.typename=="Group" or copy_inst.typename=="ComponentInstance"
					if copy_inst.attribute_dictionaries.to_a.length>0
						copy_inst.attribute_dictionaries.each{|attr_dict|
							if attr_dict.name.split("_")[0]=="lssmatrixdict"
								lss_matrix_attr_dicts+=[attr_dict.name]
							end
						}
					end
				end
			}
			selection.clear
			if lss_matrix_attr_dicts.length>0
				lss_matrix_attr_dicts.each{|lss_matrix_attr_dict_name|
					process_grp=true
					processed_grps_names.each{|dict_name|
						process_grp=false if lss_matrix_attr_dict_name==dict_name
					}
					if process_grp
						#~ if lss_matrix_attr_dict_name
							processed_grps_names<<lss_matrix_attr_dict_name
							lss_matrix_group=LSS_Matrix_Group.new(lss_matrix_attr_dict_name)
							lss_matrix_group.process_lss_matrix_grp
						#~ end
					end
				}
			end
		}
		refresh_cmd.small_icon = "./tb_icons/refresh_16.png"
		refresh_cmd.large_icon = "./tb_icons/refresh_24.png"
		refresh_cmd.tooltip = $lssmatrixStrings.GetString("Select instance, then click to rebuild copies array.")
		$lssmatrixToolbar.add_item(refresh_cmd)
		$lssmatrixMenu.add_item(refresh_cmd)
		
		@observe_cmd=UI::Command.new($lssmatrixStrings.GetString("Observe Changes...")){
			self.set_observer_state
		}
		@observe_cmd.small_icon = "./tb_icons/observe_16.png"
		@observe_cmd.large_icon = "./tb_icons/observe_24.png"
		@observe_cmd.tooltip = $lssmatrixStrings.GetString("Click to toggle 'LSS Matrix' observer state.")
		@observe_cmd.set_validation_proc {
			if @lss_matrix_tools_observer_state=="disabled"
				MF_UNCHECKED
			else
				MF_CHECKED
			end
		}
		$lssmatrixToolbar.add_item(@observe_cmd)
		$lssmatrixMenu.add_item(@observe_cmd)

		settings_cmd=UI::Command.new($lssmatrixStrings.GetString("Settings")){
			self.settings_dial
		}
		settings_cmd.small_icon = "./tb_icons/settings_16.png"
		settings_cmd.large_icon = "./tb_icons/settings_24.png"
		settings_cmd.tooltip = $lssmatrixStrings.GetString("Click to view/edit LSS Matrix settings.")
		$lssmatrixToolbar.add_item(settings_cmd)
		$lssmatrixMenu.add_item(settings_cmd)

		matrix_visit_cmd=UI::Command.new($lssmatrixStrings.GetString("Visit Program Website...")){
			UI.openURL("http://sites.google.com/site/lssoft2011/home/lss_matrix")
		}
		matrix_visit_cmd.small_icon = "./tb_icons/matrix_www_16.png"
		matrix_visit_cmd.large_icon = "./tb_icons/matrix_www_24.png"
		matrix_visit_cmd.tooltip = $lssmatrixStrings.GetString("Click to visit LSS Matrix website")
		$lssmatrixToolbar.add_item(matrix_visit_cmd)
		$lssmatrixMenu.add_item(matrix_visit_cmd)  

		lssmatrix_about_cmd=UI::Command.new($lssmatrixStrings.GetString("About...")){
			about_str=""
			about_str+="LSS Matrix ver. 1.0 (beta)\n\n"
			about_str+="E-mail1: designer@ls-software.ru\n"
			about_str+="E-mail2: kirill2007_77@mail.ru\n"
			about_str+="icq: 328-958-369\n"
			about_str+="\n\n(C) Links System Software 2012"
			UI.messagebox(about_str,MB_MULTILINE,"LSS Matrix")
		}
		$lssmatrixMenu.add_separator
		$lssmatrixMenu.add_item(lssmatrix_about_cmd)

	end
	
	def settings_dial
		y_str=$lssmatrixStrings.GetString("Yes")
		no_str=$lssmatrixStrings.GetString("No")
		full_str=$lssmatrixStrings.GetString("full")
		mini_str=$lssmatrixStrings.GetString("mini")
		# Patch to solve encoding issue start
		Sketchup.active_model.set_attribute("LSS Matrix", "y_str", y_str)
		Sketchup.active_model.set_attribute("LSS Matrix", "no_str", no_str)
		y_str=Sketchup.active_model.get_attribute("LSS Matrix", "y_str")
		no_str=Sketchup.active_model.get_attribute("LSS Matrix", "no_str")
		
		Sketchup.active_model.set_attribute("LSS Matrix", "y_str", full_str)
		Sketchup.active_model.set_attribute("LSS Matrix", "no_str", mini_str)
		full_str=Sketchup.active_model.get_attribute("LSS Matrix", "full_str")
		mini_str=Sketchup.active_model.get_attribute("LSS Matrix", "mini_str")
		# Patch to solve encoding issue end
		copies_number = Sketchup.read_default("LSS_Matrix", "copies_number", "10")
		interpolate = Sketchup.read_default("LSS_Matrix", "interpolate", "false")
		connect_centers = Sketchup.read_default("LSS_Matrix", "connect_centers", "false")
		supress_copying = Sketchup.read_default("LSS_Matrix", "supress_copying", "false")
		dialog_size = Sketchup.read_default("LSS_Matrix", "dialog_size", "full") # Alternate value = "mini"
		prompts=Array.new
		defaults=Array.new
		list=Array.new
		prompts+=[$lssmatrixStrings.GetString("Copies number: ")]
		prompts+=[$lssmatrixStrings.GetString("Interpolate: ")]
		prompts+=[$lssmatrixStrings.GetString("Connect centers: ")]
		prompts+=[$lssmatrixStrings.GetString("Supress copying: ")]
		prompts+=[$lssmatrixStrings.GetString("Dialog size: ")]
		
		defaults+=[copies_number]
		if interpolate=="false"
			defaults+=[no_str]
		else
			defaults+=[y_str]
		end
		if connect_centers=="false"
			defaults+=[no_str]
		else
			defaults+=[y_str]
		end
		if supress_copying=="false"
			defaults+=[no_str]
		else
			defaults+=[y_str]
		end
		if dialog_size=="full"
			defaults+=[full_str]
		else
			defaults+=[mini_str]
		end
		
		list+=[""]
		list+=["#{y_str}|#{no_str}"]
		list+=["#{y_str}|#{no_str}"]
		list+=["#{y_str}|#{no_str}"]
		list+=["#{full_str}|#{mini_str}"]
		
		input_res = UI.inputbox(prompts, defaults, list, $lssmatrixStrings.GetString("LSS Matrix Settings"))
		if input_res
			copies_number=input_res[0]
			if input_res[1]==no_str
				interpolate="false"
			else
				interpolate="true"
			end
			if input_res[2]==no_str
				connect_centers="false"
			else
				connect_centers="true"
			end
			if input_res[3]==no_str
				supress_copying="false"
			else
				supress_copying="true"
			end
			if input_res[4]==full_str
				dialog_size="full"
			else
				dialog_size="mini"
			end
		end
		
		Sketchup.write_default("LSS_Matrix", "copies_number", copies_number)
		Sketchup.write_default("LSS_Matrix", "interpolate", interpolate)
		Sketchup.write_default("LSS_Matrix", "connect_centers", connect_centers)
		Sketchup.write_default("LSS_Matrix", "supress_copying", supress_copying)
		Sketchup.write_default("LSS_Matrix", "dialog_size", dialog_size) # Alternate value = "mini"
	end
	
	def set_observer_state
		if @lss_matrix_tools_observer_state=="disabled"
			@lss_matrix_tools_observer=LSS_Matrix_Tools_Observer.new
			@su_tools.add_observer(@lss_matrix_tools_observer)
			@lss_matrix_tools_observer_state="enabled"
		else
			@su_tools.remove_observer(@lss_matrix_tools_observer) if @lss_matrix_tools_observer
			@lss_matrix_tools_observer_state="disabled"
		end
	end
	
	def zero_inst_props(zero_inst, lss_matrix_attr_dict)
		y_str=$lssmatrixStrings.GetString("Yes")
		no_str=$lssmatrixStrings.GetString("No")
		# Patch to solve encoding issue start
		Sketchup.active_model.set_attribute("LSS Matrix", "y_str", y_str)
		Sketchup.active_model.set_attribute("LSS Matrix", "no_str", no_str)
		y_str=Sketchup.active_model.get_attribute("LSS Matrix", "y_str")
		no_str=Sketchup.active_model.get_attribute("LSS Matrix", "no_str")
		# Patch to solve encoding issue end
		surf_opt_str=lss_matrix_attr_dict["surf_opt_str"]
		if surf_opt_str.nil? or surf_opt_str==""
			UI.messagebox($lssmatrixStrings.GetString("It is possble to edit only surface properties of the initial instance. The selected instance has no surface options."))
			return
		end
		surf_opt_arr1=surf_opt_str.split(";")
		prompts=Array.new
		defaults=Array.new
		list=Array.new
		surf_opt_arr=Array.new
		surf_opt_arr1.each{|opt|
			prompts<<opt.split(",")[0]
			if opt.split(",")[1]=="true"
				defaults+=[y_str]
			else
				defaults+=[no_str]
			end
			list<<"#{y_str}|#{no_str}"
			surf_opt_arr+=[opt.split(",")]
		}
		input_res = UI.inputbox(prompts, defaults, list, $lssmatrixStrings.GetString("Zero Instance Properties"))
		if input_res
			input_res.each_index{|ind|
				flag=input_res[ind]
				if flag==y_str
					surf_opt_arr[ind][1]="true"
				else
					surf_opt_arr[ind][1]="false"
				end
			}
			surf_opt_str=""
			surf_opt_arr.each{|opt|
				surf_opt_str+=opt[0].to_s  + "," + opt[1].to_s + ";"
			}
			zero_inst.set_attribute(lss_matrix_attr_dict.name, "surf_opt_str", surf_opt_str)
			if @lss_matrix_tools_observer_state=="disabled"
				res2=UI.messagebox($lssmatrixStrings.GetString("Is it necessary to refresh surfaces?"), MB_OKCANCEL)
				@entities=Sketchup.active_model.active_entities
				if res2==1
					lss_matrix_group=LSS_Matrix_Group.new(lss_matrix_attr_dict.name)
					lss_matrix_group.process_lss_matrix_grp
				end
			else
				lss_matrix_group=LSS_Matrix_Group.new(lss_matrix_attr_dict.name)
				lss_matrix_group.process_lss_matrix_grp
			end
		end
		
	end
	
	def copy_inst_props(copy_inst, lss_matrix_attr_dict)
		y_str=$lssmatrixStrings.GetString("Yes")
		no_str=$lssmatrixStrings.GetString("No")
		# Patch to solve encoding issue start
		Sketchup.active_model.set_attribute("LSS Matrix", "y_str", y_str)
		Sketchup.active_model.set_attribute("LSS Matrix", "no_str", no_str)
		y_str=Sketchup.active_model.get_attribute("LSS Matrix", "y_str")
		no_str=Sketchup.active_model.get_attribute("LSS Matrix", "no_str")
		# Patch to solve encoding issue end
		prompts=Array.new
		prompts+=[$lssmatrixStrings.GetString("Number of Copies")]
		prompts+=[$lssmatrixStrings.GetString("Interpolate")]
		prompts+=[$lssmatrixStrings.GetString("Connect Centers")]
		prompts+=[$lssmatrixStrings.GetString("Supress Copying")]
		defaults=Array.new
		defaults+=[lss_matrix_attr_dict["copies_number"]]
		if lss_matrix_attr_dict["interpolate"]=="true"
			defaults+=[y_str]
		else
			defaults+=[no_str]
		end
		if lss_matrix_attr_dict["connect_centers"]=="true"
			defaults+=[y_str]
		else
			defaults+=[no_str]
		end
		if lss_matrix_attr_dict["supress_copying"]=="true"
			defaults+=[y_str]
		else
			defaults+=[no_str]
		end
		list=Array.new
		list+=[""]
		list+=["#{y_str}|#{no_str}"] 
		list+=["#{y_str}|#{no_str}"] 
		list+=["#{y_str}|#{no_str}"] 
		input_res = UI.inputbox(prompts, defaults, list, $lssmatrixStrings.GetString("Copy Instance Properties"))
		if input_res
			copies_number=input_res[0]
			if input_res[1]==y_str
				interpolate="true"
			else
				interpolate="false"
			end
			if input_res[2]==y_str
				connect_centers="true"
			else
				connect_centers="false"
			end
			if input_res[3]==y_str
				supress_copying="true"
			else
				supress_copying="false"
			end
			copy_inst.set_attribute(lss_matrix_attr_dict.name, "copies_number", copies_number.to_s)
			copy_inst.set_attribute(lss_matrix_attr_dict.name, "interpolate", interpolate)
			copy_inst.set_attribute(lss_matrix_attr_dict.name, "connect_centers", connect_centers)
			copy_inst.set_attribute(lss_matrix_attr_dict.name, "supress_copying", supress_copying)
			
			if @lss_matrix_tools_observer_state=="disabled"
				res2=UI.messagebox($lssmatrixStrings.GetString("Is it necessary to refresh copies array?"), MB_OKCANCEL)
				@entities=Sketchup.active_model.active_entities
				if res2==1
					lss_matrix_group=LSS_Matrix_Group.new(lss_matrix_attr_dict.name)
					lss_matrix_group.process_lss_matrix_grp
				end
			else
				lss_matrix_group=LSS_Matrix_Group.new(lss_matrix_attr_dict.name)
				lss_matrix_group.process_lss_matrix_grp
			end
		end
	end
end #class Lss_Matrix_Cmds

class LSS_Matrix_Group
	def initialize(dict_name)
		@attr_dict_name=dict_name
		@entities=Sketchup.active_model.active_entities
	end

	def process_lss_matrix_grp
		copy_inst_cnt=0
		@entities.each{|ent|
			attr_dicts=ent.attribute_dictionaries
			if attr_dicts
				attr_dicts.each{|attr_dict|
					if attr_dict.name==@attr_dict_name
						if attr_dict["inst_type"]=="zero_inst"
							@zero_inst=ent
							copy_inst_cnt=attr_dict["copy_inst_cnt"].to_i
							#~ @copies_arr=Array.new(copy_inst_cnt) # removed 29_03_12
						end
					end
				}
			end
		}
		if @zero_inst and copy_inst_cnt>0
			@copies_arr=Array.new(copy_inst_cnt) # 29/03/12
			@entities.each{|ent|
				attr_dicts=ent.attribute_dictionaries
				if attr_dicts
					attr_dicts.each{|attr_dict|
						if attr_dict.name==@attr_dict_name
							if attr_dict["inst_type"]=="copy_inst"
								copy_ind=attr_dict["copy_ind"].to_i
								copies_number=attr_dict["copies_number"].to_i
								interpolate=false
								connect_centers=false
								supress_copying=false
								if attr_dict["interpolate"]=="true"
									interpolate=true
								end
								if attr_dict["connect_centers"]=="true"
									connect_centers=true
								end
								if attr_dict["supress_copying"]=="true"
									supress_copying=true
								end
								ext_copy_inst=Lss_Matrix_Copy_Inst.new(ent, copies_number, interpolate, connect_centers, supress_copying)
								@copies_arr[copy_ind]=ext_copy_inst
							end
						end
					}
				end
			}
		end
		if @zero_inst and @copies_arr
			surf_opt_str=@zero_inst.get_attribute(@attr_dict_name, "surf_opt_str")
			if surf_opt_str
				surf_opt_arr1=surf_opt_str.split(";")
				surf_opt_arr=Array.new
				surf_opt_arr1.each{|opt|
					surf_opt_arr+=[opt.split(",")]
				}
			end
			self.clear_from_prev
			lss_matrix_tool=Lss_Matrix_Tool.new(nil) #nil supresses web dialog creation
			lss_matrix_tool.zero_inst=@zero_inst
			lss_matrix_tool.copies_arr=@copies_arr
			lss_matrix_tool.attr_dict=@attr_dict_name
			lss_matrix_tool.surf_opt_arr=surf_opt_arr if surf_opt_arr
			lss_matrix_tool.generate_preview_bnds
			lss_matrix_tool.draw(Sketchup.active_model.active_view)
			lss_matrix_tool.apply_settings
		end
	end

	def clear_from_prev
		ents2erase=Array.new
		@entities.each{|ent|
			attr_dicts=ent.attribute_dictionaries
			if attr_dicts
				attr_dicts.each{|attr_dict|
					if attr_dict.name==@attr_dict_name
						if attr_dict["inst_type"]=="result_copy" or attr_dict["inst_type"]=="links_grp" or attr_dict["inst_type"]=="surf_grp"
							ents2erase<<ent
						end
					end
				}
			end
		}
		@entities.erase_entities(ents2erase)
	end
end #class LSS_Matrix_Group

class LSS_Matrix_Tools_Observer < Sketchup::ToolsObserver
	def initialize
		@prev_state=0
	end
	def onActiveToolChanged(tools, tool_name, tool_id)
		#~ UI.messagebox("onActiveToolChanged: " + tool_name.to_s)
	end
		
	def onToolStateChanged(tools, tool_name, tool_id, tool_state)
		#~ 21048 = MoveTool
		#~ 21129 = RotateTool
		#~ 21236 = ScaleTool
		if (tool_id==21048 or tool_id==21129 or tool_id==21236 and @prev_state==1) or tool_id==21129 # Rotate Tool has always the same state "0"
			selection=Sketchup.active_model.selection
			lss_matrix_attr_dicts=Array.new
			selection.each{|ent|
				if ent.attribute_dictionaries.to_a.length>0
					ent.attribute_dictionaries.each{|attr_dict|
						if attr_dict.name.split("_")[0]=="lssmatrixdict"
							lss_matrix_attr_dicts<<attr_dict.name
						end
					}
				end
			}
			if lss_matrix_attr_dicts.length>0
				processed_grps_names=Array.new
				lss_matrix_attr_dicts.each{|lss_matrix_attr_dict_name|
					process_grp=true
					processed_grps_names.each{|dict_name|
						process_grp=false if lss_matrix_attr_dict_name==dict_name
					}
					if process_grp
						#~ if lss_matrix_attr_dict_name
							processed_grps_names<<lss_matrix_attr_dict_name
							lss_matrix_group=LSS_Matrix_Group.new(lss_matrix_attr_dict_name)
							lss_matrix_group.process_lss_matrix_grp
						#~ end
					end
				}
			end
		end
		
		@prev_state=tool_state
	end

end #class LSS_Matrix_Tools_Observer


class Lss_Matrix_Copy_Inst
	attr_accessor :copy_inst
	attr_accessor :copies_number
	attr_accessor :interpolate
	attr_accessor :connect_centers
	attr_accessor :supress_copying
	
	def initialize (copy_inst, copies_number, interpolate, connect_centers, supress_copying)
		@copy_inst=copy_inst
		@copies_number=copies_number
		@interpolate=interpolate
		@connect_centers=connect_centers
		@supress_copying=supress_copying
	end
end #class Lss_Matrix_Copy_Inst

class Lss_Matrix_Tool
	attr_accessor :zero_inst
	attr_accessor :copies_arr
	attr_accessor :attr_dict
	attr_accessor :surf_opt_arr
	
	def initialize(web_dial)
		@attr_dict=nil
		@web_dial=web_dial
		@model=Sketchup.active_model
		zero_cur_path=Sketchup.find_support_file("pick_zero_inst.png", "Plugins/lss_matrix/cursors/")
		@pick_zero_cur_id=UI.create_cursor(zero_cur_path, 0, 0)
		copy_cur_path=Sketchup.find_support_file("pick_copy_inst.png", "Plugins/lss_matrix/cursors/")
		@pick_copy_cur_id=UI.create_cursor(copy_cur_path, 0, 0)
		@zero_inst=nil
		@copies_arr=nil
		@under_cur_valid_bnds=nil
		@under_cur_invalid_bnds=nil
		@zero_bnds=nil
		@copies_bnds=nil
		@preview_bnds=nil
		@centers_arr=nil
		@preview_links=Array.new
		@preview_surf=Array.new
		
		@pick_zero_inst=false
		@pick_copy_inst=false
		
		@current_copy_no=0
		
		@copies_number=1
		@interpolate=false
		@connect_centers=false
		@supress_copying=false
		
		@surf_opt_arr=nil
		
		self.create_web_dial(web_dial) if @web_dial
	end
	
	def create_web_dial(web_dial)
		# Read defaults
		@copies_number = Sketchup.read_default("LSS_Matrix", "copies_number", "10")
		@interpolate = Sketchup.read_default("LSS_Matrix", "interpolate", "false")
		@connect_centers = Sketchup.read_default("LSS_Matrix", "connect_centers", "false")
		@supress_copying = Sketchup.read_default("LSS_Matrix", "supress_copying", "false")
		@dialog_size = Sketchup.read_default("LSS_Matrix", "dialog_size", "full") # Alternate value = "mini"
		
		if @dialog_size=="full"
			@web_dial="lss_matrix.html"
		else
			@web_dial="lss_matrix_mini.html"
		end
		
		# Create the WebDialog instance
		@my_dialog = UI::WebDialog.new("LSS Matrix", true, "LSS Matrix", 448, 608, 200, 200, false)
		@my_dialog.set_size(448, 608) if @web_dial=="lss_matrix.html"
		@my_dialog.set_size(260, 588) if @web_dial=="lss_matrix_mini.html"
		
		# Attach an action callback
		@my_dialog.add_action_callback("get_data") do |web_dialog,action_name|
			view=Sketchup.active_model.active_view
			if action_name=="read_defaults"
				@copies_number = Sketchup.read_default("LSS_Matrix", "copies_number", "10")
				@interpolate = Sketchup.read_default("LSS_Matrix", "interpolate", "false")
				@connect_centers = Sketchup.read_default("LSS_Matrix", "connect_centers", "false")
				@supress_copying = Sketchup.read_default("LSS_Matrix", "supress_copying", "false")
				@dialog_size = Sketchup.read_default("LSS_Matrix", "dialog_size", "full") # Alternate value = "mini"
				
				default_pair_str="copiescnt" + "|" + @copies_number.to_s
				js_command = "get_default('" + default_pair_str + "')"
				@my_dialog.execute_script(js_command) if js_command
				default_pair_str="interpolate" + "|" + @interpolate.to_s
				js_command = "get_default('" + default_pair_str + "')"
				@my_dialog.execute_script(js_command) if js_command
				default_pair_str="connectcntrs" + "|" + @connect_centers.to_s
				js_command = "get_default('" + default_pair_str + "')"
				@my_dialog.execute_script(js_command) if js_command
				default_pair_str="supresscopy" + "|" + @supress_copying.to_s
				js_command = "get_default('" + default_pair_str + "')"
				@my_dialog.execute_script(js_command) if js_command
			end
			if action_name.split(",")[0]=="erase_copy"
				erase_copy_no=action_name.split(",")[1].to_i
				@copies_arr.delete_at(erase_copy_no)
				@copies_bnds.delete_at(erase_copy_no)
				view.invalidate
			end
			if action_name=="pick_zero"
				@pick_zero_inst=true
				self.onSetCursor #does not work
				view.invalidate
			end
			if action_name.split("_")[0]=="copybody"
				@pick_copy_inst=true
				view.invalidate
			end
			if action_name.split(",")[0]=="copysettings"
				@current_copy_no=action_name.split(",")[1].to_i
				@copies_number=action_name.split(",")[2].to_i
				if action_name.split(",")[3]=="true"
					@interpolate=true
				else
					@interpolate=false
				end
				if action_name.split(",")[4]=="true"
					@connect_centers=true
				else
					@connect_centers=false
				end
				if action_name.split(",")[5]=="true"
					@supress_copying=true
				else
					@supress_copying=false
				end
				if @current_copy_no<@copies_arr.length
					curr_ext_copy=@copies_arr[@current_copy_no]
					curr_ext_copy.copies_number=@copies_number
					curr_ext_copy.interpolate=@interpolate
					curr_ext_copy.connect_centers=@connect_centers
					curr_ext_copy.supress_copying=@supress_copying
				end
				self.generate_preview_bnds
				view.invalidate
			end
			if action_name=="generate_surf_opt_arr"
				@surf_opt_arr=Array.new
			end
			if action_name.split(",")[0]=="add_surf_opt"
				@surf_opt_arr<<[action_name.split(",")[1], action_name.split(",")[2]]
				view.invalidate
			end
			if action_name.split(",")[0]=="reset"
				@web_dial=action_name.split(",")[1]
				@my_dialog.close
				lss_matrix_tool=Lss_Matrix_Tool.new(@web_dial)
				Sketchup.active_model.select_tool(lss_matrix_tool)
			end
			if action_name=="apply_settings"
				self.apply_settings
				@my_dialog.close
				lss_matrix_tool=Lss_Matrix_Tool.new(@web_dial)
				Sketchup.active_model.select_tool(lss_matrix_tool)
			end
		end
		self.show_dlg
		@my_dialog.set_on_close{ 
			Sketchup.active_model.select_tool(nil)
			if @web_dial=="lss_matrix.html"
				@dialog_size="full"
			else
				@dialog_size="mini"
			end
			Sketchup.write_default("LSS_Matrix", "dialog_size", @dialog_size)
		}
	end
	
	def show_dlg
		# Find and show html file
		if @web_dial
			resource_dir = File.dirname(Sketchup.get_resource_path("lss_matrix.strings"))
			html_path = "#{resource_dir}/lss_matrix/#{@web_dial}"
			@my_dialog.set_file(html_path)
			@my_dialog.show() 
		end
	end
	
	def apply_settings
		@model.start_operation("LSS Matrix")
		@attr_dict="lssmatrixdict_" + Time.now.to_f.to_s if @attr_dict.nil?
		entities=Sketchup.active_model.active_entities
		if @preview_links.length>0
			@links_grp=entities.add_group
			@preview_links.each{|link|
				if link
					@links_grp.entities.add_line(link[0], link[1]) if link[0] and link[1]
				end
			}
		end
		if @preview_surf
			if @preview_surf.length>0
				@surf_grp=entities.add_group
				prgr_bar=Lss_Matrix_Progr_Bar.new(@preview_surf.length,"|","_",2)
				@preview_surf.each_index{|fc_ind|
					prgr_bar.update(fc_ind)
					Sketchup.status_text = "#{$lssmatrixStrings.GetString("Bulding surface:")} #{prgr_bar.progr_string}"
					fc=@preview_surf[fc_ind]
					begin
						@surf_grp.entities.add_face(fc)
					rescue
						puts "Failed to add face..."
					end
				}
				Sketchup.status_text = ""
			end
		end
		@preview_bnds.each_index{|node_ind|
			neighbours=@links_arr[node_ind]
			supress_arr=Array.new(@copies_arr.length)
			@copies_arr.each_index{|copy_ind|
				supress_copying=@copies_arr[copy_ind].supress_copying
				if supress_copying
					supress_arr[copy_ind]=true
				end
			}
			process_this_bound=true
			supress_arr.each_index{|copy_ind|
				chk_crd=@centers_crds[node_ind][copy_ind]
				if supress_arr[copy_ind] and chk_crd!=-1
					process_this_bound=false
				end
			}
			if process_this_bound
				copy_inst=@zero_inst.copy
				#~ copy_inst.transform!(@zero_trans.inverse)
				copy_inst.transform!(@transformations_arr[node_ind])
				copy_inst.set_attribute(@attr_dict, "inst_type", "result_copy")
				@copies_arr.each{|ext_copy_inst|
					c_pt=ext_copy_inst.copy_inst.bounds.center
					if not copy_inst.deleted?
						if copy_inst.bounds.center==c_pt
							copy_inst.erase!
						end
					end
				}
			end
		}
		self.write_lss_matrix_props
		@model.commit_operation
		@my_dialog.close if @my_dialog
	end
	
	def write_lss_matrix_props
		copy_inst_cnt=@copies_arr.length
		@zero_inst.set_attribute(@attr_dict, "inst_type", "zero_inst")
		@zero_inst.set_attribute(@attr_dict, "copy_inst_cnt", copy_inst_cnt.to_s)
		surf_opt_str=""
		if @surf_opt_arr
			@surf_opt_arr.each{|opt|
				surf_opt_str+=opt[0].to_s  + "," + opt[1].to_s + ";"
			}
		end
		@zero_inst.set_attribute(@attr_dict, "surf_opt_str", surf_opt_str)
		@copies_arr.each_index{|copy_ind|
			ext_copy_inst=@copies_arr[copy_ind]
			copy_inst=ext_copy_inst.copy_inst
			copy_inst.set_attribute(@attr_dict, "inst_type", "copy_inst")
			copy_inst.set_attribute(@attr_dict, "copy_ind", copy_ind.to_s)
			copy_inst.set_attribute(@attr_dict, "copies_number", ext_copy_inst.copies_number.to_s)
			copy_inst.set_attribute(@attr_dict, "interpolate", ext_copy_inst.interpolate.to_s)
			copy_inst.set_attribute(@attr_dict, "connect_centers", ext_copy_inst.connect_centers.to_s)
			copy_inst.set_attribute(@attr_dict, "supress_copying", ext_copy_inst.supress_copying.to_s)
		}
		@links_grp.set_attribute(@attr_dict, "inst_type", "links_grp") if @links_grp
		@surf_grp.set_attribute(@attr_dict, "inst_type", "surf_grp") if @surf_grp
	end
	
	def activate
		@copies_arr=Array.new
		@copies_bnds=Array.new
		@ip = Sketchup::InputPoint.new
		@ip1 = Sketchup::InputPoint.new
		# @model.set_attribute("LSS_Matrix", "lss_matrix_grp", time.now) #
	end
	  
	def onSetCursor
		UI.set_cursor(@pick_zero_cur_id) if @pick_zero_inst #it does not work itself, so onSetCursor call was added in onMouseMove handler
		UI.set_cursor(@pick_copy_cur_id) if @pick_copy_inst
	end
	  
	def onMouseMove(flags, x, y, view)
		@ip1.pick view, x, y
		if( @ip1 != @ip )
			view.invalidate
			@ip.copy! @ip1
			view.tooltip = @ip.tooltip
		end
		if @pick_zero_inst or @pick_copy_inst
			self.onSetCursor #try to enforce setting and it works, but it's not good because each mouse movement fires onSetCursor
			ph=view.pick_helper
			ph.do_pick x,y
			under_cur=ph.best_picked
			if under_cur
				if under_cur.typename=="Group" or under_cur.typename=="ComponentInstance"
					@under_cur_valid_bnds=under_cur.bounds
				else
					@under_cur_invalid_bnds=under_cur.bounds
				end
			else
				@under_cur_valid_bnds=nil
				@under_cur_invalid_bnds=nil
			end
		else
			@under_cur_valid_bnds=nil
			@under_cur_invalid_bnds=nil
		end
	end
	
	def draw_bnds(bnds, pnt_size, pnt_type, pnt_col, view)
		bnd_pnts=Array.new
		crn_no=0
		while crn_no<8
			pt=bnds.corner(crn_no)
			bnd_pnts<<pt
			crn_no+=1
		end
		bnd_pnts.each{|pt|
			status = view.draw_points(pt, pnt_size, pnt_type, pnt_col)
		}
	end
	
	def draw_under_cur_valid(view)
		self.draw_bnds(@under_cur_valid_bnds, 8, 1, "green", view)
	end
	
	def draw_under_cur_invalid(view)
		self.draw_bnds(@under_cur_invalid_bnds, 8, 4, "red", view)
	end
	
	def draw_zero_bnds(view)
		self.draw_bnds(@zero_bnds, 8, 2, "green", view)
	end
	
	def draw_copy_bnds(view, copy_bnds)
		self.draw_bnds(copy_bnds, 8, 7, "green", view)
	end
	
	def draw_copies_bnds(view)
		@copies_bnds.each{|copy_bnds|
			self.draw_copy_bnds(view, copy_bnds)
		}
	end
	
	def draw_copies_texts(view)
		@copies_bnds.each_index{|copy_no|
			copy_bnds=@copies_bnds[copy_no]
			txt_pt=view.screen_coords(copy_bnds.max) + [10,10]
			status = view.draw_text(txt_pt, "Copy #{copy_no+1}")
			status = view.draw_text(txt_pt, "Copy #{copy_no+1}")
		}
	end
	
	def draw_zero_text(view)
		txt_pt=view.screen_coords(@zero_bnds.max) + [10,10]
		status = view.draw_text(txt_pt, "The Initial Instance")
		status = view.draw_text(txt_pt, "The Initial Instance")
	end
	
	def draw_preview_bnds(view)
		status = view.drawing_color="gray"
		@preview_bnds.each_index{|node_ind|
			preview_bnds=@preview_bnds[node_ind]
			neighbours=@links_arr[node_ind]
			supress_arr=Array.new(@copies_arr.length)
			@copies_arr.each_index{|copy_ind|
				supress_copying=@copies_arr[copy_ind].supress_copying
				if supress_copying
					supress_arr[copy_ind]=true
				end
			}
			process_this_bound=true
			supress_arr.each_index{|copy_ind|
				chk_crd=@centers_crds[node_ind][copy_ind]
				if supress_arr[copy_ind] and chk_crd!=-1
					process_this_bound=false
				end
			}
			if process_this_bound
				pt1=preview_bnds[0]; pt2=preview_bnds[1]
				status = view.draw_line(pt1, pt2)
				txt_pt=view.screen_coords(pt1) + [10,10]
				# status = view.draw_text(txt_pt, @preview_bnds.index(preview_bnds).to_s)
				pt1=preview_bnds[1]; pt2=preview_bnds[3]
				status = view.draw_line(pt1, pt2)
				pt1=preview_bnds[3]; pt2=preview_bnds[2]
				status = view.draw_line(pt1, pt2)
				pt1=preview_bnds[2]; pt2=preview_bnds[0]
				status = view.draw_line(pt1, pt2)
				
				pt1=preview_bnds[4]; pt2=preview_bnds[5]
				status = view.draw_line(pt1, pt2)
				pt1=preview_bnds[5]; pt2=preview_bnds[7]
				status = view.draw_line(pt1, pt2)
				pt1=preview_bnds[7]; pt2=preview_bnds[6]
				status = view.draw_line(pt1, pt2)
				pt1=preview_bnds[6]; pt2=preview_bnds[4]
				status = view.draw_line(pt1, pt2)
				
				pt1=preview_bnds[0]; pt2=preview_bnds[4]
				status = view.draw_line(pt1, pt2)
				pt1=preview_bnds[1]; pt2=preview_bnds[5]
				status = view.draw_line(pt1, pt2)
				pt1=preview_bnds[3]; pt2=preview_bnds[7]
				status = view.draw_line(pt1, pt2)
				pt1=preview_bnds[2]; pt2=preview_bnds[6]
				status = view.draw_line(pt1, pt2)
			end
		}
		status = view.drawing_color="black"
	end
	
	def draw_tip(tip_str,view)
		txt_pt=view.screen_coords(@ip.position) + [21,21]
		view.draw_text(txt_pt, tip_str)
		view.draw_text(txt_pt, tip_str)
	end
	
	def draw_centers(view)
		@centers_arr.each{|pt|
			status = view.draw_points(pt, 8, 3, "red")
		}
	end
	
	def draw_links(view)
		if @preview_links.length>0
			@preview_links.each{|link|
				if link
					status = view.draw_line(link[0], link[1]) if link[0] and link[1]
				end
			}
		end
		# puts @centers_crds.inspect
	end
	
	def draw_surface(view, link1, link2)
		@preview_surf=Array.new
		@links_arr.each_index{|node_ind|
			neighbours=@links_arr[node_ind]
			face=Array.new
			pt1=@centers_arr[node_ind]
			pt2=@centers_arr[neighbours[link1]] if neighbours[link1]
			pt3=@centers_arr[neighbours[link2]] if neighbours[link2]
			face=[pt1, pt2, pt3]
			@preview_surf<<face
			next_ngb1=nil; next_ngb2=nil
			next_ngb1=@links_arr[neighbours[link1]] if neighbours[link1]
			next_ngb2=@links_arr[neighbours[link2]] if neighbours[link2]
			chk_ngb1=next_ngb1[link2] if next_ngb1
			chk_ngb2=next_ngb2[link1] if next_ngb2
			if chk_ngb1==chk_ngb2
				pt4=@centers_arr[chk_ngb1] if chk_ngb1
				face=[pt4, pt2, pt3]
				@preview_surf<<face
			end
			
		}
		col=Sketchup::Color.new(100, 100, 100)
		col.alpha=0.5
		status = view.drawing_color=col
		@preview_surf.each{|fc|
			status=view.draw(GL_POLYGON, fc)
		}
		status = view.drawing_color="black"
	end
	
	def draw_surfs(view)
		@surf_opt_arr.each{|opt|
			if opt[1]=="true"
				link1=(opt[0].split("-")[0].to_i-1)
				link2=(opt[0].split("-")[1].to_i-1)
				draw_surface(view, link1, link2)
			end
		}
	end
	
	def draw(view)
		self.draw_under_cur_valid(view) if @under_cur_valid_bnds
		self.draw_under_cur_invalid(view) if @under_cur_invalid_bnds
		self.draw_zero_bnds(view) if @zero_bnds
		self.draw_copies_bnds(view) if @copies_bnds
		self.draw_zero_text(view) if @zero_bnds
		self.draw_copies_texts(view) if @copies_bnds
		self.draw_preview_bnds(view) if @preview_bnds
		self.draw_tip("The Initial Instance", view) if @pick_zero_inst
		self.draw_tip("Copy #{@current_copy_no+1}", view) if @pick_copy_inst
		self.draw_links(view) if @centers_arr
		self.draw_centers(view) if @centers_arr
		self.draw_surfs(view) if @surf_opt_arr
	end
	
	def reset(view)
		@ip.clear
		@ip1.clear
		if( view )
			view.tooltip = nil
			view.invalidate
		end
		@zero_inst=nil
		@copies_arr=nil
		@under_cur_valid_bnds=nil
		@under_cur_invalid_bnds=nil
		@zero_bnds=nil
		@copies_bnds=nil
		@preview_bnds=nil
		@preview_links=nil
		@preview_surf=nil
		
		@pick_zero_inst=false
		@pick_copy_inst=false
		
		@current_copy_no=0
		
		@copies_number=1
		@interpolate=false
		@connect_centers=false
		@supress_copying=false
	end

	def deactivate(view)
		self.reset(view)
		@my_dialog.close if @my_dialog
	end

	# Pick entities by single click
	def onLButtonUp(flags, x, y, view)
		@ip.pick view, x, y
		ph=view.pick_helper
		ph.do_pick x,y
		if @pick_zero_inst
			if ph.best_picked
				if ph.best_picked.typename=="Group" or ph.best_picked.typename=="ComponentInstance"
					@zero_inst=ph.best_picked
					@zero_bnds=@zero_inst.bounds
					# Does not work when I try to pass 'selection_info' as argument of js_command = "set_zero_inst_chkd(selection_info)"
					# if @zero_inst.name
						# selection_info="#{@zero_inst.name} #{@zero_inst.typename} is picked"
						# selection_info=@zero_inst.name
					# else
						# selection_info="#{@zero_inst.typename} is picked"
						# selection_info=@zero_inst.typename
					# end
					js_command = "set_zero_inst_chkd('The initial instance is picked')"
					@my_dialog.execute_script(js_command)
				else
					UI.messagebox("Try to pick group or component instance.")
				end
			else
				UI.messagebox("Try to pick group or component instance.")
			end
			@pick_zero_inst=false
		end
		if @pick_copy_inst
			if ph.best_picked
				if ph.best_picked.typename=="Group" or ph.best_picked.typename=="ComponentInstance"
					copy_inst=ph.best_picked
					ext_copy_inst=Lss_Matrix_Copy_Inst.new(copy_inst, @copies_number, @interpolate, @connect_centers, @supress_copying)
					if (@current_copy_no+1)>@copies_arr.length
						@copies_arr+=[ext_copy_inst]
						@copies_bnds+=[copy_inst.bounds]
					else
						@copies_arr[@current_copy_no]=ext_copy_inst
						@copies_bnds[@current_copy_no]=copy_inst.bounds
					end
					js_command = "set_copy_inst_chkd("+ @current_copy_no.to_s + ")"
					@my_dialog.execute_script(js_command)
				else
					UI.messagebox("Try to pick group or component instance.")
				end
			else
				UI.messagebox("Try to pick group or component instance.")
			end
			@pick_copy_inst=false
		end
		if @copies_arr.length>0 and @zero_inst
			self.generate_preview_bnds
		end
	end
	
	def generate_preview_bnds
		return if @zero_inst.nil?
		@zero_trans=@zero_inst.transformation
		@zero_inst_pnts=Array.new
		bnds=@zero_inst.bounds
		crn_no=0
		while crn_no<8
			pt=bnds.corner(crn_no)
			@zero_inst_pnts<<pt
			crn_no+=1
		end
		@preview_bnds=Array.new
		@centers_arr=Array.new
		@centers_crds=Array.new
		@crds_arr=Array.new(@copies_arr.length, -1)
		@transformations_arr=Array.new
		@result_copies=Array.new
		@init_origin=@zero_inst.bounds.center
		
		self.iterate_trans(0)
		# Add center of the initial instance
		@centers_arr<<@zero_inst.bounds.center
		@centers_crds<<Array.new(@copies_arr.length, -1)
		
		@crds_arr=Array.new(@copies_arr.length, -1)
		self.build_links_arr
		@result_copies.each{|grp| grp.erase!}
	end
	
	def build_links_arr
		@links_arr=Array.new(@centers_crds.length)
		prgr_bar=Lss_Matrix_Progr_Bar.new(@centers_crds.length,"|","_",2)
		@centers_crds.each_index{|ind|
			prgr_bar.update(ind)
			Sketchup.status_text = "#{$lssmatrixStrings.GetString("Bulding links array:")} #{prgr_bar.progr_string}"
			curr_pt_crds=@centers_crds[ind]
			neighb_no=Array.new(@copies_arr.length)
			for ind1 in (0)..(@centers_crds.length-1)
				@copies_arr.each_index{|copy_ind|
					chk_pt_crds=@centers_crds[ind1]
					is_neighb=false
					eval=0
					chk_pt_crds.each_index{|crd_ind|
						crd1=curr_pt_crds[crd_ind]
						crd2=chk_pt_crds[crd_ind]
						eval+=1 if crd1-crd2==-1 and crd_ind==copy_ind
						eval+=1 if crd_ind!=copy_ind and crd1-crd2==0
						is_neighb=true if eval==chk_pt_crds.length
					}
					if is_neighb
						neighb_no[copy_ind]=ind1
						break
					end
				}
			end
			
			@links_arr[ind]=neighb_no
		}
		@preview_links=Array.new
		@links_arr.each_index{|node_ind|
			neighbours=@links_arr[node_ind]
			@copies_arr.each_index{|copy_ind|
				connect_centers=@copies_arr[copy_ind].connect_centers
				if connect_centers
					link=Array.new
					pt1=@centers_arr[node_ind]
					pt2=@centers_arr[neighbours[copy_ind]] if neighbours[copy_ind]
					link<<pt1
					link<<pt2
				end
				@preview_links<<link
			}
		}
		Sketchup.status_text = "#{$lssmatrixStrings.GetString("")}"
	end
	
	def iterate_trans(copy_ind)
		return if @copies_arr[copy_ind].nil?
		copy_tr=@copies_arr[copy_ind].copy_inst.transformation
		copies_number=@copies_arr[copy_ind].copies_number
		times=copies_number
		prgr_bar=Lss_Matrix_Progr_Bar.new(times,"|","_",2)
		for tr in 0..times do
			prgr_bar.update(tr)
			Sketchup.status_text = "#{$lssmatrixStrings.GetString("Bulding transformation array:")} #{prgr_bar.progr_string}"
			if copy_ind<@copies_arr.length-1
				copy_ind2=copy_ind+1
				self.iterate_trans(copy_ind2)
			end
			if @crds_arr[copy_ind]>=0
				@curr_tr=Geom::Transformation.new
				@prev_tr=Geom::Transformation.new(@curr_tr)
				supress_copy_ind=copy_ind
				@crds_arr.each_index{|ind|
					copy_tr=@copies_arr[ind].copy_inst.transformation
					shift_vec=@zero_inst.bounds.center.vector_to(@copies_arr[ind].copy_inst.bounds.center)
					interpolate=@copies_arr[ind].interpolate
					interpolate_rate=1.0/(@copies_arr[ind].copies_number.to_f)
					shift_vec.length=shift_vec.length/(@copies_arr[ind].copies_number.to_f)
					shift_tr=Geom::Transformation.new(shift_vec)
					if interpolate
						copy_tr=Geom::Transformation.interpolate(Geom::Transformation.new, copy_tr*@zero_trans.inverse, interpolate_rate*tr.to_f)
						
						x_ax=Geom::Vector3d.new(1,0,0)
						x_ax_zero=x_ax.transform(@zero_trans)
						x_ax_copy=x_ax.transform(@copies_arr[ind].copy_inst.transformation)

						x_sc_copy=x_ax_copy.length
						x_sc_zero=x_ax_zero.length
						x_sc=estimate_sc(1.0, x_sc_copy/x_sc_zero, @crds_arr[ind], times)
						
						y_ax=Geom::Vector3d.new(0,1,0)
						y_ax_zero=y_ax.transform(@zero_trans)
						y_ax_copy=y_ax.transform(@copies_arr[ind].copy_inst.transformation)
						
						y_sc_copy=y_ax_copy.length
						y_sc_zero=y_ax_zero.length
						y_sc=estimate_sc(1.0, y_sc_copy/y_sc_zero, @crds_arr[ind], times)
						
						z_ax=Geom::Vector3d.new(0,0,1)
						z_ax_zero=z_ax.transform(@zero_trans)
						z_ax_copy=z_ax.transform(@copies_arr[ind].copy_inst.transformation)
						
						z_sc_copy=z_ax_copy.length
						z_sc_zero=z_ax_zero.length
						z_sc=estimate_sc(1.0, z_sc_copy/z_sc_zero, @crds_arr[ind], times)
						
						sc_tr=Geom::Transformation.scaling(Geom::Point3d.new(0,0,0), x_sc, y_sc, z_sc)
						
						sc_tr_copy=Geom::Transformation.scaling(@zero_trans.origin, x_sc_copy, y_sc_copy, z_sc_copy)
						sc_tr_zero=Geom::Transformation.scaling(@copies_arr[ind].copy_inst.transformation.origin, x_sc_zero, y_sc_zero, z_sc_zero)
						
						sc_tr_1=Geom::Transformation.scaling(Geom::Point3d.new(0,0,0), x_sc_copy/x_sc_zero, y_sc_copy/y_sc_zero, z_sc_copy/z_sc_zero)
						
						@curr_tr=sc_tr*@curr_tr.clone
						
						rot_tr_x=Geom::Transformation.new
						rot_tr_y=Geom::Transformation.new
						rot_tr_x_total=Geom::Transformation.new
						
						x_ang=x_ax_zero.angle_between(x_ax_copy)
						rot_ax=x_ax_zero.cross(x_ax_copy)
						rot_tr_x_total=Geom::Transformation.rotation(Geom::Point3d.new(0,0,0), rot_ax, x_ang) if rot_ax.length>0
						if x_ang>0
							rot_ax=x_ax_zero.cross(x_ax_copy)
							ang=estimate_sc(0.0, x_ang, @crds_arr[ind], times)
							if rot_ax.length>0
								rot_tr_x=Geom::Transformation.rotation(Geom::Point3d.new(0,0,0), rot_ax, ang)
							else
								if x_ang==Math::PI
									y_ang=y_ax_zero.angle_between(y_ax_copy)
									if y_ang==0
										rot_ax=y_ax_zero
										rot_tr_x=Geom::Transformation.rotation(Geom::Point3d.new(0,0,0), rot_ax, ang)
									else
										z_ang=z_ax_zero.angle_between(z_ax_copy)
										if z_ang==0
											rot_ax=z_ax_zero
											rot_tr_x=Geom::Transformation.rotation(Geom::Point3d.new(0,0,0), rot_ax, ang)
										else
											rot_ax=x_ax_zero.cross(y_ax_copy)
											rot_tr_x=Geom::Transformation.rotation(Geom::Point3d.new(0,0,0), rot_ax, ang)
										end
									end
								end
							end
							@curr_tr=rot_tr_x*@curr_tr.clone
						end
						y_ang=y_ax_zero.transform(rot_tr_x_total).angle_between(y_ax_copy)
						if y_ang>0
							rot_ax=y_ax_zero.transform(rot_tr_x_total).cross(y_ax_copy)
							ang=estimate_sc(0.0, y_ang, @crds_arr[ind], times)
							if rot_ax.length>0
								rot_tr_y=Geom::Transformation.rotation(Geom::Point3d.new(0,0,0), rot_ax, ang)
							else
								if y_ang==Math::PI and z_ang!=0
									rot_ax=x_ax_copy
									rot_tr_y=Geom::Transformation.rotation(Geom::Point3d.new(0,0,0), rot_ax, ang)
								end
							end
							@curr_tr=rot_tr_y*@curr_tr.clone
						end
						back_vec=@init_origin.transform(@curr_tr).vector_to(@init_origin.transform(@prev_tr))
						back_tr=Geom::Transformation.new(back_vec)
						@curr_tr=back_tr*@curr_tr.clone
						
						self.perform_trans(shift_tr, @crds_arr[ind])
					else
						self.perform_trans(copy_tr*@zero_trans.inverse, @crds_arr[ind])
					end
					@prev_tr=Geom::Transformation.new(@curr_tr)
				}
				@transformations_arr<<Geom::Transformation.new(@curr_tr)
				bnds_arr=Array.new
				for i in 0..7 do
					bnds_arr<<@zero_inst_pnts[i].transform(@curr_tr)
				end
				@preview_bnds<<bnds_arr
				@centers_arr<<Geom::Point3d.new(@zero_inst.bounds.center.transform(@curr_tr))
				@centers_crds<<Array.new(@crds_arr)
			end
			@crds_arr[copy_ind]=tr
			@crds_arr[copy_ind]=-1 if tr==copies_number
		end
	end
	
	def estimate_sc(sc_0, sc_1, pos, tot_cnt)
		sc=(sc_1-sc_0)*(pos+1.0)/(tot_cnt)+sc_0
		sc
	end
	
	def perform_trans(trans, times)
		if times>=0
			for i in 0..times do
				@curr_tr=trans*@curr_tr.clone
			end
		end
	end
	
	# 
	def onLButtonDoubleClick(flags, x, y, view)
		@ip.pick view, x, y
		
	end

	# Handle some hot-key strokes while the tool is active
	def onKeyUp(key, repeat, flags, view)

	end

	def onCancel(reason, view)

	end

	def enableVCB?
		return true
	end

	# Use entered from the keyboard number
	def onUserText(text, view)

	end

	# Tool context menu
	def getMenu(menu)

	end

	def getInstructorContentDirectory
		dir_path="../../lss_matrix/instruct/dialog"
		return dir_path
	end
end #class Lss_Matrix_Tool

if( not file_loaded?("lssmatrix_tools.rb") )
  Lss_Matrix_Cmds.new
end

#-----------------------------------------------------------------------------
file_loaded("lssmatrix_tools.rb")