## Name : fur_en.rb
## Description : Make Fur( Grass )
## Auther : TAK2HATA畑拓 ( http://onigiriburning.so.land.to/ )
# Copyright TAK2
###[NOTICE]]####
#General disclaimer
#I MAKES NO GUARANTEE OF VALIDITY about this script.
#Please use this script at your own risk.
#Strongly Recommend Sketchup version 8 higher for using this.
#The copyright of this plug-in is in TAK2HATA. 
#Please use this plug-in in self-responsibility. 
#I do not take any responsibility. 
#You can use freely.
#################
#免責事項：このスクリプトによって如何なる損害が発生しても製作者は責任を負いません。各人の責任においてご使用ください。
#このスクリプトの著作権はTAK2HATAにあるものとします。
#ただし商用（販売など）の目的でない場合はご自由にお使いください。
#改変も自由ですが、配布の際はTAK2HATAまでご連絡ください。下記にブログのアドレスを掲示します。
# http://ameblo.jp/onigiri-burning/
#改変開発者の方へ：デフォルト値保存やクラス名など、名称が被らないようにご配慮お願いいたします。
#################

##Since : 2010-04-21--- v0.0
##Rev : 2010-05-05-- v0.1
##	speedup
##	add component     --
##  add menu for mac  -- v0.3
##Rev : 2010-05-06   -- v1.0
##  Because I did a big change, this plugin might have the problem.
##  use to be carefully. Especially, about saving file.
##  menu named "Fur!(MAC)" change to "Fur v1_0!(InputBox)"
##  menu named "Fur!(EN)" change to "Fur v1_0!(WebDialog)"
##  Type select to Name
##  fix problem:when length too small,it create also 50.mm
##  add Type for Box option
##  add fur model from Select Component option
##  Change Extra Upper force strength
##  add keep fur parameter.
##  add save & load preset.
##  How to save preset
##    Webdialog::Press "Save New Preset" button, and input preset name.
##    InputBox ::Select "Add" in "Select Preset"(listbox), and press "OK".
##  How to Load preset
##    Webdialog::Select Preset_name in "Select Preset"(listbox) and press load_preset button ,then update parameter in dialog.
##    InputBox ::Select Preset_name in "Select Preset"(listbox). and press OK to opdate parameter in dialog.
##  About Make_By_ComponentInstance(listbox)
##    "no" to make furs by mesh.it parts each 800 polgyon.
##    "yes" to make furs by component_instance.it is in one group.component_name is "fur_instance"
##    If ComponentDefinition is exist in model, then component_names are include in listbox.
##    (problem::please don't select component that always face to camera.)
##
## Language traslation file---fur_lang_****.txt (only one file can Effective in sketchup plugins folder)
##  fur_lang_es.txt---(Spanish language:Thanks Oxer!)http://forums.sketchucation.com/viewtopic.php?f=323&t=28092&start=210#p247640
##  fur_lang_fr.txt---(Franch language:Thanks Daredevil!)http://forums.sketchucation.com/viewtopic.php?f=323&t=28092&start=195#p247400
##  (Persian translation by Majid.Thanks!)http://forums.sketchucation.com/viewtopic.php?f=320&t=28179
##  fur_lang_pt 1.4a.rar--(Portuguese-BR translation:Thanks Paulower!)http://forums.sketchucation.com/viewtopic.php?f=323&t=28092&start=285#p249923
##  fur_lang_cn.txt---(Chinese translation:Thanks hebeijianke!)http://forums.sketchucation.com/viewtopic.php?f=323&t=28092&start=300#p250314
##  fur_lang_vn14b.txt---(Vietnam translation:Thanks ktslambieng!)http://forums.sketchucation.com/viewtopic.php?f=323&t=28092&start=300#p250660
##  fur_lang_ru.txt---(Russian translation:Thanks blajnov!)http://forums.sketchucation.com/viewtopic.php?f=323&t=28092&start=315#p253618
##  fur_lang_de.txt---(German translation:Thanks Burkhard!)http://forums.sketchucation.com/viewtopic.php?f=323&t=28092&start=330#p255389
##  fur_lang_srb.txt--(Serbian translation:Thanks srx!)http://sketchucation.com/forums/viewtopic.php?f=323&t=28092&start=480#p480168
##  fur_lang_en.txt---(English language:Upcase.example.)
##  fur_lang_jp.txt---(japanese language)
##
## Thanks for Very cool grass material by paulower.http://forums.sketchucation.com/viewtopic.php?f=323&t=28092&start=270#p249482

##Rev : 2010-05-07
##  operation go faster works on only sketchup7 upper.
##Rev : 2010-05-08
##  Add "Assign to Material"
##Rev : 2010-05-09   --- v1.2
##  Add  get_furmesh_by_mat( face , mat , ret_furmesh = [] ) for any exporters.
##  webdialog refresh method changed.
##Rev : 2010-05-18   --- v1.3a
##  Add new parameter "direction" and "force"
##  Add menu "imperial" and "metric"
##  Change preset ini format.(not Interchangeable before)
##Rev : 2010-05-19 --- v1.3b
##  Change Component Instance Place method.(ex. Direction change to "0,0,100" instance stand vertical)
##Rev : 2010-05-20 --- v1.3c
##  using "to_l" method.get active model units.but it has accuracy problem.
##  auto select imperial or metric.
##  too small density makes probability.
##Rev : 2010-05-20 --- v1.3d
##  plugin filename keep to "fur_en.rb"
##  ".to_l"method is decimals fixing.so check to value is 0.and calculate by macro.
##  problem about parameter includes blank is fixed.
##  Charset that script using change from "shift-jis" to "UTF-8"(I mistake. this still "shift-jis")
##  Quotation Problem in webdialog is fixed.
##Rev : 2010-05-20 --- v1.3e
##  Change getting delimiter from decimal_separater.(Thanks ThomThom)
##  Menu name keeps "fur_en..." for future.
##Rev : 2010-05-21 --- v1.3f
##  Problem about LengthFormat Architectural ,and LengthPrecision 0.
##  s_to_l defn changes.but it has problem still.
##Rev : 2010-05-21 --- v1.3g
##  vetcor parameter like Direction and force ,split to 3 parametr each other.
##  string to length has problem.Few are fixed.
##  But Units Type "Industrial" is error.Minus value change to "-0".
##Rev : 2010-05-22 --- v1.3h
##  Web dialog become smaller.
##  Defn for any exporter is fixed.
##Rev : 2010-05-23 --- v1.3i
##  Webdialog layout changed.(Thanks Diego.)
##  Local Lang file(fur_lang_**.txt) use to change parameter names.
##Rev : 2010-05-24 --- v1.3j
##  Translate word are increment in local language file.
##  Textcode change from Shift-JIS to UTF-8.

##Rev : 2010-0528 -- v1.3k
##  Change using Transform.scaling(a) to Transform.scaling(a,a,a)
##  Webdialog html add "....charset = 'UTF-8'"
##  Save this plugin in UTF-8(withoutBOM) format.
##  It don't work on my sketchup when using UTF8(withBOM).
##Rev : 2010-0529 -- v1.3L
##  The defn code to convert value change.(older type)
##Rev : 2010-0530 -- v1.3s
##  The defn code to convert value problem fixed.
##  Temporary change to LengthPrecision.
##Rev : 2010-0603 -- v1.4
##  Webdialog use prefkey.
##  Add Crowd Dialog.(Only Webdialog)
##Rev : 2010-0603 -- v1.4a
##  Change s_to_l(sorry, I forgat changing.)
##Rev : 2010-0606 -- v1.4b
##  Temporary folder for This plugin.
##  Add Toolbar.
##  Webdialog change.
##  Crowd dialog add "update button".
##Rev : 2010-0624 -- v1.4c(test webdialog for mac)
##  fixing webdialog problem on mac os.
##  (referred to forum "[Web dialog] switch snippet for pc / mac" and jim's "protrude.rb")
##Rev : 2010-0625 -- v1.4d(test2)
## webdialog is opened on mac.
## but crowd do not work.
##Rev : 2010-0626 -- v1.4e
##Remove from context menu.
##Rev : 2010-1027 -- v1.5
##Add preview mode.
##Width of some buttons in webdialog increased.
## "Preview Fur"and"Back to Dialog" added to translation word
##Rev : 2013-05-28--v1.6
##Match to Sketchup Extension Class.
##Bugfix.

require 'sketchup.rb'
module TAK2HATA::T2H_FUR
class FUR_EN
	FUR_DIC_PREFIX = "FUR_DIC2"
	FUR_PRESET_FILE = "fur_param3.ini"
	FUR_DIALOG_FILE = "fur_wdlg.htm"
	CROWD_DIALOG_FILE = "crowd_wdlg.htm"
	@delim = "," if @delim == nil
	class PREVIEW_PTS
		def initialize(pts,ibox = false)
			@pts = pts
			@ibox = ibox
			view = Sketchup.active_model.active_view
			view.invalidate
		    if @ibox == true
				@fur = FUR_EN.new
				@menu1 = @fur.langconv('Make Fur')
				@menu2 = @fur.langconv('Back to Dialog')
				@msg = "[ESC]or[DCLICK]:#{@menu2}|[ENTER]:#{@menu1}"
			end
		end
		def activate()
			#view.invalidate
		end
		def deactivate(view)
		    view.invalidate# if @drawn
		    #view.refresh
		end
		def onCancel(flag, view)
			Sketchup.active_model.select_tool nil
		    if @ibox == true
		    	@fur.fur_inputbox( true  )
		    end
			#self.deactivate(view)
		end
		def draw(view)
			if @ibox == true
				Sketchup.set_status_text @msg, SB_PROMPT
			end
			draw_geom view
		end
		def draw_geom(view)
 			#view.draw_points @pts, 5, 2, "green"
			view.line_width = 2
			view.drawing_color = "green"
			@pts.each{|pts|
				view.draw_polyline pts
			}
		end

		def start_input
		end
		def onReturn(view)
			#model = Sketchup.active_model
			#ents = model.entities
			#@mgsgrp = ents.add_group
			#@mgsgrp.entities.fill_from_mesh @mesh
			Sketchup.active_model.select_tool nil
		    if @ibox == true
				@fur.fur_autostart
		    end
			#deactivate view
		end
		
		#def onMouseEnter(view)
		#	puts "onMouseEnter: view = " + view.to_s
		#end
		#def onMouseLeave(view)
		#	puts "onMouseLeave: view = " + view.to_s
		#end
		#def onMouseMove(flags, x, y, view)
		#end
		def getMenu(menu)
			if @ibox == true
				menu.add_item(@menu1) {
					@fur.fur_autostart
					Sketchup.active_model.select_tool nil
				} 
				menu.add_item(@menu2) {
					Sketchup.active_model.select_tool nil
				    if @ibox == true
				    	@fur.fur_inputbox( true  )
				    end
				} 
			end
		end
		#key event
		#def onKeyDown(key, repeat, flags, view)
			#VK_ALT,VK_COMMAND,VK_CONTROL,VK_DELETE,VK_DOWN,VK_END,VK_HOME,VK_INSERT,VK_LEFT,VK_MENU,VK_NEXT,VK_PRIOR,VK_RIGHT,VK_SHIFT,VK_SPACE,VK_UP
		#end
		#def onKeyUp(key, repeat, flags, view)
		#end
		
		def onLButtonDoubleClick(flags, x, y, view)
			#self.deactivate(view)
			Sketchup.active_model.select_tool nil
		    if @ibox == true
		    	@fur.fur_inputbox( true  )
		    end
		end
		#def onLButtonDown(flags, x, y, view)
		#end
		#def onLButtonUp(flags, x, y, view)
		#end
		#def onRButtonDoubleClick(flags, x, y, view)
		#end
		#def onRButtonDown(flags, x, y, view)
		#end
		#def onRButtonUp(flags, x, y, view)
		#end
		#def onMButtonDoubleClick(flags, x, y, view)
		#end
		#def onMButtonDown(flags, x, y, view)
		#	draw_geom view
		#end
		#def onMButtonUp(flags, x, y, view)
		#	draw_geom view
		#end
		#def onSetCursor(view)
		#	puts "onSetCursor: view = " + view.to_s
		#	# You would set your cursor here. See UI.set_cursor method.
		#	UI.set_cursor(@cursor_id)
   		#end
		#def onUserText(text, view)
		#	puts "onSetCursor: text = " + text.to_s + ", view = " + view.to_s
		#end
		#def resume(view)
		#	puts "resume: view = " + view.to_s
		#end
		#def suspend(view)
		#	puts "suspend: view = " + view.to_s
		#end
	end#class

	def initialize
		@lprec = Sketchup.active_model.options["UnitsOptions"]["LengthPrecision"]
		@fur_deflist = []
		@fur_units_metric = false
		lunit = Sketchup.active_model.options["UnitsOptions"]["LengthUnit"]
		@fur_units_metric = true if lunit >= 2
		#def get_langconvert
		load_langtxt()
	end
	def init_units
		@lprec = Sketchup.active_model.options["UnitsOptions"]["LengthPrecision"]
		@fur_deflist = []
		@fur_units_metric = false
		lunit = Sketchup.active_model.options["UnitsOptions"]["LengthUnit"]
		@fur_units_metric = true if lunit >= 2
	end
	def default_lang_search()
		@langhash = Hash.new
		#@delanghash = Hash.new
		fur_lang_file = "fur_lang_\*.txt"
		#thisdir =File.dirname(File.expand_path(__FILE__))
		thisdir = File.dirname(File.dirname(File.expand_path(__FILE__)))
		langfilelist = []
		Dir::chdir(thisdir)
		#path = thisdir + "\/#{fur_lang_file}"
		path = File.join( thisdir , fur_lang_file )
		langpath = ""
		Dir::glob(path).each{|path| langpath = path }
		return langpath

	end
	def select_langfile
		lang_dir = File.join( File.dirname( File.expand_path(__FILE__) ), "language","lang_en.txt" )
		lang_path=UI.openpanel(langconv("Select Language File(*.txt)"),lang_dir)
		return false if lang_path == "" or lang_path == false
		return false if not lang_path
		lang_path = File.expand_path( lang_path )
		if not FileTest.exist?( lang_path )
			UI.messagebox( "File is not exists!(or The file-path includes special characters)::#{lang_path}" )
		end
		Sketchup.write_default( "T2H_FUR_EN", "lang_path", lang_path )
		load_langtxt( )
		UI.messagebox langconv("The language convert will be effective after Sketchup restarted")
	end
	def load_langtxt( )
		#lang_path =  File.join( File.dirname( File.expand_path(__FILE__) ), "language" , "fur_lang.txt")
		lang_path = Sketchup.read_default( "T2H_FUR_EN", "lang_path", lang_path )
		if not lang_path or File.exists?( lang_path ) != true
			lang_path = default_lang_search 
		end
		return nil if not lang_path or lang_path == ""
		lang_path = File.expand_path( lang_path )
		
		return nil if not FileTest.exist?( lang_path )
		@langhash = Hash.new
		lang_file=File.new(lang_path,"r")##read mode
		lang_file.each{|line|
			if line != "" and line[0] != "#"
				splt = ( line.chomp ).split("\|")
				if splt[0] != "" and splt[1] != ""
					@langhash[splt[0]] = splt[1]
				end
			end
		}
		lang_file.close
	end
	def langconv(tstr)
		ret = ""
		#load_langtxt if @langhash == nil
		return tstr if @langhash == nil
		if @langhash.size > 0
			ret = @langhash[tstr] if @langhash[tstr] != nil
			ret = tstr if ret == ""
		else
			ret = tstr
		end
		return ret
	end


	def get_dialogitems()
		prefix = "%.4g"
		dlg = []
	
		dlg.push ["#{langconv('Type')}",langconv("Arch"),"#{langconv('Linear')}|#{langconv('Arch')}|#{langconv('Leaf')}|#{langconv('Rectanguler')}|#{langconv('Box')}","ftype"]#10
		if @fur_units_metric == true
			dlg.push ["#{langconv('Density')}(#{langconv('Num/m2')})","200","","fdensity"]#0
		else
			dlg.push ["#{langconv('Density')}(#{langconv('Num/sq.yd')})","170","","fdensity"]#0
		end
		dlg.push ["#{langconv('MaxNumber')}(/#{langconv('Face')})","200","","maxnum"]#1
		dlg.push ["#{langconv('Length')}(#{0.to_l})",s_to_l('200mm'),"","flength"]#2
		dlg.push ["#{langconv('RootWidth')}(#{0.to_l})",s_to_l('40mm'),"","frootw"]#3
		dlg.push ["#{langconv('Stiffness')}","8","","fstrong"]#4
		dlg.push ["#{langconv('TopJitter')}(%)","40","","fljitter"]#5
		dlg.push ["#{langconv('WidthJitter')}(%)","25","","fwjitter"]#6
		dlg.push ["#{langconv('StiffnessJitter')}(%)","50","","fsjitter"]#7
		dlg.push ["#{langconv('Divide')}","3","","fdivs"]#8
		dlg.push ["#{langconv('Valid Distance')}(#{0.to_l})",s_to_l('0mm'),"","fvradius"]#9
		#
		dlg.push ["#{langconv('direction')}(X)","#{(0.mm).to_l}","","fdirectionx"]#11
		dlg.push ["#{langconv('direction')}(Y)","#{(0.mm).to_l}","","fdirectiony"]#11
		dlg.push ["#{langconv('direction')}(Z)","#{s_to_l('50mm')}","","fdirectionz"]#11
		dlg.push ["#{langconv('force')}(X)","#{(0.mm).to_l}","","fforcex"]#12
		dlg.push ["#{langconv('force')}(Y)","#{(0.mm).to_l}","","fforcey"]#12
		dlg.push ["#{langconv('force')}(Z)","-#{s_to_l('50mm')}","","fforcez"]#12
		dfnames = []
		dfnames = get_complist
		#defs = Sketchup.active_model.definitions
		#dfnames = []
		#defs.each{|df|
		#	dfnames.push df.name if df.group? == false and df.name != "fur_instance"
		#}
		#alist = "yes|no|fur_instance"
		#alist = alist + "|" + dfnames.join("|") if dfnames.length > 0
	    dlg.push ["#{langconv('Make by Component')}",langconv("no"),dfnames.join("|"),"instance"]#11
		if @fur_units_metric == true
			dlg.push [langconv('Units'),langconv("metric"),langconv("metric"),"funits"]#12
		else
			dlg.push [langconv('Units'),langconv("imperial"),langconv("imperial"),"funits"]#12
		end
	    return dlg
	end
	def get_complist
		defs = Sketchup.active_model.definitions
		dfnames = [langconv("yes"),langconv("no"),langconv("fur_instance")]
		defs.each{|df|
			dfnames.push df.name if df.group? == false and df.name != langconv("fur_instance")
		}
		return dfnames
	end
	def get_param( ent )
		#model = Sketchup.active_model
		#fdic = model.attribute_dictionary FUR_DIC_PREFIX

		fdic = ent.attribute_dictionary FUR_DIC_PREFIX
		return nil if fdic == nil
		phash = Hash.new
		fdic.each{|key ,val| phash[key] = val }
		prefix = "%.4g"
		phash["funits"] = "metric" if phash["funits"] == ""
		
		phash['flength'] = "#{s_to_l((phash['flength']).to_f.inch)}" if phash['flength'] != ""
		phash['frootw'] = "#{s_to_l((phash['frootw']).to_f.inch)}" if phash['frootw'] != ""
		phash['fvradius'] = "#{s_to_l((phash['fvradius']).to_f.inch)}" if phash['fvradius'] != ""
		phash['fdirectionx'] = "#{s_to_l((phash['fdirectionx']).to_f.inch)}" if phash['fdirectionx'] != ""
		phash['fdirectiony'] = "#{s_to_l((phash['fdirectiony']).to_f.inch)}" if phash['fdirectiony'] != ""
		phash['fdirectionz'] = "#{s_to_l((phash['fdirectionz']).to_f.inch)}" if phash['fdirectionz'] != ""
		phash['fforcex'] = "#{s_to_l((phash['fforcex']).to_f.inch)}" if phash['fforcex'] != ""
		phash['fforcey'] = "#{s_to_l((phash['fforcey']).to_f.inch)}" if phash['fforcey'] != ""
		phash['fforcez'] = "#{s_to_l((phash['fforcez']).to_f.inch)}" if phash['fforcez'] != ""
		
		phash["fdirection"] = "#{phash['fdirectionx']}&&#{phash['fdirectiony']}&&#{phash['fdirectionz']}"
		phash["fforce"] = "#{phash['fforcex']}&&#{phash['fforcey']}&&#{phash['fforcez']}"
		phash["funits"] = langconv(phash["funits"]) if phash["funits"] == "metric" or phash["funits"] == "imperial"
		if phash["funits"] == "imperial" and @fur_units_metric == true
				phash['fdensity'] = "#{prefix % ( phash['fdensity'].to_f * 1.19596096 )}" if phash['fdensity'] != ""
				phash["funits"] = "metric"
		elsif phash["funits"] == "metric" and @fur_units_metric == false
				phash['fdensity'] = "#{prefix % ( phash['fdensity'].to_f / 1.19596096 )}" if phash['fdensity'] != ""
				phash["funits"] = "imperial"
		end
		phash["ftype"] = "" if phash["ftype"] == nil
		phash["instance"] = "" if phash["instance"] == nil
		phash["ftype"] = langconv(phash["ftype"]) if phash["ftype"] == "Arch" or phash["ftype"] == "Linear" or phash["ftype"] == "Rectanguler" or phash["ftype"] == "Leaf" or phash["ftype"] == "Box"
		phash["instance"] = langconv(phash["instance"]) if phash["instance"] == "yes" or phash["instance"] == "no" or phash["instance"] == "fur_instance"
		return nil if phash.length <= 0
		return phash
	end
	def put_param( ent ,rhash )
		#model=Sketchup.active_model
		attrdict = ent.attribute_dictionary( FUR_DIC_PREFIX , true )
		rhash.each{|key,val|
			if key.to_s != ""
				if key.to_s == "flength" or key.to_s == "frootw" or key.to_s == "fvradius"
					attrdict[ key ] = s_to_l(val).to_f.to_inch.to_s
				elsif key.to_s == "fforcex" or key.to_s == "fforcey" or key.to_s == "fforcez"
					attrdict[ key ] = s_to_l(val).to_f.to_inch.to_s
				elsif key.to_s == "fdirectionx" or key.to_s == "fdirectiony" or key.to_s == "fdirectionz"
					attrdict[ key ] = s_to_l(val).to_f.to_inch.to_s
				else
					attrdict[ key ] = val
				end
			end
		}
	end


	def del_param_from_scene(  )
		model = Sketchup.active_model
		fdics = model.attribute_dictionaries
		return nil if fdics == nil
		fdics.delete FUR_DIC_PREFIX
	end
	def savehtml( htmlname , shtm )
		html_file = File.new( htmlname , "w")
		html_file.puts shtm
		html_file.close
	end
	#def get_editor_code()
	#	a_filepath = char_conv( __FILE__ )
	#	parent = File.dirname( a_filepath )
	#	htmlfile = File.join( parent , "list_editor.html" )
	#	if File.exists?( htmlfile )
	#		f = open( htmlfile , "r" )
	#		htmlcode = f.read
	#		f.close
	#		return htmlcode
	#	end
	#	return nil
	#end
	def preset_editor()
		#htmlcode = get_htmlcode()
		thisdir = File.dirname(File.expand_path(__FILE__))
		thisparent = File.dirname( thisdir )
		prstfile = File.join( thisdir , FUR_PRESET_FILE )
		if not File.exists?(prstfile)
			prstfile = File.join( thisparent , FUR_PRESET_FILE )
		end
		htmlfile = File.join( thisdir , "list_editor.html" )
		return if not File.exists?( htmlfile ) or not File.exists?( prstfile )

		zval = 0.0
		prfkeys = { 
			:dialog_title => langconv('Prest List Editor'), 
			:scrollable => true, 
			:preferences_key => 'T2H_Prest_List_Editor', 
			:height => 300, 
			:width => 600, 
			:left => 150, 
			:top => 150, 
			:resizable => true, 
			:mac_only_use_nswindow => true
		} 
		wdlg = UI::WebDialog.new( prfkeys)
		wdlg.set_file( htmlfile )

		wdlg.add_action_callback("savelist"){|dlg,po|
			buff = wdlg.get_element_value("BUFFAREA")
			save_list(buff)
		}
		if RUBY_PLATFORM[/darwin/]
			wdlg.show_modal{ load_list(wdlg) }
		else
			wdlg.show{ load_list(wdlg) }
		end
	end
	def save_list(buff)
		thisdir = File.dirname(File.expand_path(__FILE__))
		path = File.join( thisdir , FUR_PRESET_FILE )
		ini_file=File.new(path,"w+")
		ini_file.write buff.gsub(/:::/,"&&&")
		ini_file.close
	end
	def load_list(wdlg)
		thisdir = File.dirname(File.expand_path(__FILE__))
		thisparent = File.dirname( thisdir)
		path = File.join( thisdir , FUR_PRESET_FILE )
		if not FileTest.exist?(path)
			path = File.join( thisparent , FUR_PRESET_FILE )
		end
		if FileTest.exist?(path)
			ini_file=File.new(path,"r")
			l = 0
			ini_file.each{|line|
				if line != ""
					tstr = ( line.chomp ).gsub(/&&&/,":::")
					cmd = 'document.getElementById("TEXTLIST").options[' + l.to_s + ']= new Option( "' + tstr + '" ,' + l.to_s + ');'
					wdlg.execute_script( cmd )
					l += 1
				end
			}
			ini_file.close
		end
	end

	def save_preset_to_ini( rhash , presetname )
		return if rhash == nil
		saveline = presetname.to_s
		rhash.each{|key , val|
				if key.to_s != ""
					if key.to_s == "flength" or key.to_s == "frootw" or key.to_s == "fvradius"
						val2 = s_to_l(val).to_f.to_inch.to_s
					elsif key.to_s == "fforcex" or key.to_s == "fforcey" or key.to_s == "fforcez"
						val2 = s_to_l(val).to_f.to_inch.to_s
					elsif key.to_s == "fdirectionx" or key.to_s == "fdirectiony" or key.to_s == "fdirectionz"
						val2 = s_to_l(val).to_f.to_inch.to_s
					else
						val2 = val
					end
				#val2 = val.gsub(@delim,"&&")
				#val2.gsub!(@decimal_sep,".")
				saveline =  saveline + "&&&#{key}|#{val2}"
				end
		}
		thisdir = File.dirname(File.expand_path(__FILE__))
		#path = thisdir + "\/#{FUR_PRESET_FILE}"
		path = File.join( thisdir , FUR_PRESET_FILE )
		ini_file=File.new(path,"a")##append mode
		ini_file.puts saveline
		ini_file.close
	end
	def load_preset( presetname , defaults ,idns )
		return if presetname == nil or presetname == ""
		params = []
		thisdir = File.dirname(File.expand_path(__FILE__))
		thisparent = File.dirname( thisdir )
		#path = thisdir + "\/#{FUR_PRESET_FILE}"
		path = File.join( thisdir , FUR_PRESET_FILE)
		if not File.exists?(path)
			path = File.join( thisparent , FUR_PRESET_FILE )
		end
		
		phash = Hash.new
		if FileTest.exist?(path)
			ini_file=File.new(path,"r")##read mode
			ini_file.each{|line|
				if line != ""
					splt = ( line.chomp ).split("&&&")
					if splt[0] == presetname
						splt.each_with_index{|pr , id|
							#UI.messagebox pr + "," + splt2.join(",")
							if pr["\|"] and id != 0
								splt2 = pr.split(/\|/)
								phash[splt2[0].to_s] = splt2[1].to_s #.gsub(".",@decimal_sep).gsub("&&",@delim)
							end
						}
					end
				end
			}
			ini_file.close
			prefix = "%.4g"
			phash["funits"] = langconv("metric") if phash["funits"] == nil
			phash["funits"] = langconv(phash["funits"]) if phash["funits"] == "metric" or phash["funits"] == "imperial"
			if phash["funits"] == langconv("imperial") and @fur_units_metric == true
				phash['fdensity'] = "#{prefix % ( phash['fdensity'].to_f * 1.19596096 )}" if phash['fdensity'] != ""
				phash["funits"] = langconv("metric")
			elsif phash["funits"] == langconv("metric") and @fur_units_metric == false
				phash['fdensity'] = "#{prefix % ( phash['fdensity'].to_f / 1.19596096 )}" if phash['fdensity'] != ""
				phash["funits"] = langconv("imperial")
			end
			phash['flength'] = "#{s_to_l(phash['flength'].to_f.inch)}" if phash['flength'] != ""
			phash['frootw'] = "#{s_to_l(phash['frootw'].to_f.inch)}" if phash['frootw'] != ""
			phash['fvradius'] = "#{s_to_l(phash['fvradius'].to_f.inch)}" if phash['fvradius'] != ""
			phash['fdirectionx'] = "#{s_to_l(phash['fdirectionx'].to_f.inch)}" if phash['fdirectionx'] != ""
			phash['fdirectiony'] = "#{s_to_l(phash['fdirectiony'].to_f.inch)}" if phash['fdirectiony'] != ""
			phash['fdirectionz'] = "#{s_to_l(phash['fdirectionz'].to_f.inch)}" if phash['fdirectionz'] != ""
			phash['fforcex'] = "#{s_to_l(phash['fforcex'].to_f.inch)}" if phash['fforcex'] != ""
			phash['fforcey'] = "#{s_to_l(phash['fforcey'].to_f.inch)}" if phash['fforcey'] != ""
			phash['fforcez'] = "#{s_to_l(phash['fforcez'].to_f.inch)}" if phash['fforcez'] != ""
			phash["fdirection"] = "#{phash['fdirectionx']}&&#{phash['fdirectiony']}&&#{phash['fdirectionz']}"
			phash["fforce"] = "#{phash['fforcex']}&&#{phash['fforcey']}&&#{phash['fforcez']}"
			phash["ftype"] = "" if phash["ftype"] == nil
			phash["instance"] = "" if phash["instance"] == nil
			phash["ftype"] = langconv(phash["ftype"]) if phash["ftype"] == "Arch" or phash["ftype"] == "Linear" or phash["ftype"] == "Rectanguler" or phash["ftype"] == "Leaf" or phash["ftype"] == "Box"
			phash["instance"] = langconv(phash["instance"]) if phash["instance"] == "yes" or phash["instance"] == "no" or phash["instance"] == "fur_instance"
			(0..(idns.size-1)).each{|i|
				if phash[idns[i]] != nil
					params[i] = phash[idns[i]]
				end
			}
			#UI.messagebox phash.keys.join(",") + phash.values.join(",")
			#UI.messagebox params.join(",")
			return nil if params.length <= 0
			return params
		else
			return nil
		end
	end
	def get_presetnames
		presetnames = ""
		thisdir = File.dirname(File.expand_path(__FILE__))
		path = thisdir + "\/#{FUR_PRESET_FILE}"
		if FileTest.exist?(path)
			ini_file=File.new(path,"r")##read mode
			ini_file.each{|line|
				pname = (line.chomp).split("&&&")
				presetnames = presetnames + "|" + pname[0] if pname[0] != ""
			}
			ini_file.close
			return presetnames
		else
			return nil
		end
	end
	def fur_autostart()
		lprec = Sketchup.active_model.options["UnitsOptions"]["LengthPrecision"]
		Sketchup.active_model.options["UnitsOptions"]["LengthPrecision"] = 3 if lprec < 3
		ohash = get_param( Sketchup.active_model )
		fdensity = ohash["fdensity"]
		maxnum = ohash["maxnum"]
		flength = ohash["flength"]
		frootw = ohash["frootw"]
		fstrong = ohash["fstrong"]
		fj = ohash["fljitter"]
		fwjitter = ohash["fwjitter"]
		fsjitter = ohash["fsjitter"]
		fdivs = ohash["fdivs"]
		fvradius = ohash["fvradius"]
		ftype = ohash["ftype"]
		finstance = ohash["instance"]
		fdirectionx = ohash["fdirectionx"]
		fdirectiony = ohash["fdirectiony"]
		fdirectionz = ohash["fdirectionz"]
		fdirection = "#{fdirectionx}&&#{fdirectiony}&&#{fdirectionz}"
		fforcex = ohash["fforcex"]
		fforcey = ohash["fforcey"]
		fforcez = ohash["fforcez"]
		fforce = "#{fforcex}&&#{fforcey}&&#{fforcez}"
		funits = ohash["funits"]
		is_df_exist = false
		if finstance == "#{langconv('yes')}" or finstance == "#{langconv('no')}" or finstance != "#{langconv('fur_instance')}"
			is_df_exist = true
		elsif finstance == "yes" or finstance == "no" or finstance == "fur_instance"
			is_df_exist = true
		else
			Sketchup.active_model.definitions.each{|df|
				is_df_exist = true if df.name == finstance and df.group? == false
			}
		end

		@fdensity = fdensity.to_f
		@flength = s_to_l(flength)
		@frootw = s_to_l(frootw)
		@fvradius = s_to_l(fvradius)

		@maxnum = maxnum.to_i
		@fj = fj.to_f / 100
		@flj = @fj * @flength.to_f
		@fljitter = Geom::Vector3d.new( @fj * @flength , @fj * @flength , @fj * @flength )
		@fwjitter = fwjitter.to_f * @frootw.to_f / 100
		@fdivs = fdivs.to_i
		@fstrong = fstrong.to_f
		@fsjitter = fsjitter.to_f * @fstrong.to_f / 100
		@finstance = finstance.to_s
		@ftype = ftype.to_s
		@fdirection = Geom::Vector3d.new( s_to_l(fdirectionx) , s_to_l(fdirectiony) , s_to_l(fdirectionz))
		@fforce = Geom::Vector3d.new( s_to_l(fforcex) , s_to_l(fforcey) , s_to_l(fforcez))
		@fur_deflist = []
		glowup

	end


	def fur_inputbox( fur_unit )
		#@fur_units_metric = fur_unit
		#fur_dialog_ini
		lprec = Sketchup.active_model.options["UnitsOptions"]["LengthPrecision"]
		Sketchup.active_model.options["UnitsOptions"]["LengthPrecision"] = 3 if lprec < 3
		dlg = get_dialogitems
	    prompts = []
	    defaults = []
	    lists = []
	    idns = Hash.new
	    ids = Hash.new
	    id = 0
	    dlg.each{|prp,dfl,lst,idn|
			prompts.push prp
			defaults.push dfl
			lists.push lst
			idns[id] = idn
			ids[idn] = id
			id += 1
		}
		params = []
		ohash = get_param( Sketchup.active_model )
		if ohash != nil
			idns.keys.each{|id|
				a = ohash[ idns[id] ]
				if a != nil
					params[id] = a
				end
			}
		end
		defaults1 =	defaults.map{|prp| prp }
		if params.size > 0
			( 0..(params.size-1) ).each{|id|
				defaults1[id] = params[id] if defaults1.length > id
			}
		end

		fdensity = ""
		maxnum = ""
		flength = ""
		frootw = ""
		fdivs = ""
		fstrong = ""

		fj = ""
		fwjitter = ""
		fsjitter = ""
		fdivs = ""
		fvradius = ""
		ftype = ""
		finstance = ""
		funits = ""
		save_preset = ""
		results = []
		reload = ""
		title = "#{langconv('Fur settings.')}"
		title1 = "#{langconv('Fur settings.')}"
		is_df_exist = false
		while( fdensity.to_f == 0 or maxnum.to_f == 0 or s_to_l(flength) == 0 or s_to_l(frootw) == 0 or fdivs.to_f == 0 or fstrong.to_f == 0 or reload == "" or is_df_exist == false)
			prompts2 = prompts.map{|prp| prp }
			prompts2.push "#{langconv('PRESET?')}(#{langconv('BLANK to Start Fur')})"
			defaults2 = defaults1.map{|prp|	prp	}
			defaults2.push ""
			lists2 = lists.map{|prp| prp }
			presetnames = get_presetnames
			if presetnames != nil
				lists2.push "|#{langconv('default')}|#{langconv('add')}|#{langconv('assign_material')}|#{langconv('get_from_material')}" + presetnames
			else
				lists2.push "|#{langconv('default')}|#{langconv('add')}|#{langconv('assign_material')}|#{langconv('get_from_material')}"
			end
			results = UI.inputbox prompts2 , defaults2, lists2, title1
			if results == false or results == nil
				Sketchup.active_model.options["UnitsOptions"]["LengthPrecision"] = lprec if lprec < 3
				return
			end
			rhash = Hash.new
			results.each_with_index{|res , i|
					rhash[idns[i]] = res
			}
			
			fdensity = results[ ids["fdensity"] ]
			maxnum = results[ ids["maxnum"] ]
			flength = results[ ids["flength"] ]
			frootw = results[ ids["frootw"] ]
			fstrong = results[ ids["fstrong"] ]
			fj = results[ ids["fljitter"] ]
			fwjitter = results[ ids["fwjitter"] ]
			fsjitter = results[ ids["fsjitter"] ]
			fdivs = results[ ids["fdivs"] ]
			fvradius = results[ ids["fvradius"] ]
			ftype = results[ ids["ftype"] ]
			finstance = results[ ids["instance"] ]
			
			fdirectionx = results[ ids["fdirectionx"] ]
			fdirectiony = results[ ids["fdirectiony"] ]
			fdirectionz = results[ ids["fdirectionz"] ]
			fdirection = "#{fdirectionx}&&#{fdirectiony}&&#{fdirectionz}"
			fforcex = results[ ids["fforcex"] ]
			fforcey = results[ ids["fforcey"] ]
			fforcez = results[ ids["fforcez"] ]
			fforce = "#{fforcex}&&#{fforcey}&&#{fforcez}"

			funits = results[ ids["funits"] ]
			save_preset = results[ results.size - 1 ]
			is_df_exist = false
			if finstance == "#{langconv('yes')}" or finstance == "#{langconv('no')}" or finstance != "#{langconv('fur_instance')}"
				is_df_exist = true
			elsif finstance == "yes" or finstance == "no" or finstance == "fur_instance"
				is_df_exist = true
			else
				Sketchup.active_model.definitions.each{|df|
					is_df_exist = true if df.name == finstance and df.group? == false
				}
			end

			if save_preset == ""
				reload = "continue"
			elsif save_preset == "#{langconv('add')}"
				presetname1 = ""
				pnames = get_presetnames
				pnames = "" if pnames == nil
				pnlist = pnames.split("|")
				while( presetname1 == "" or pnlist.index( presetname1 ) != nil )
					presetname = UI.inputbox ["#{langconv('PRESET_NAME')}"], [""], "#{langconv('Input preset name')}"
					break if presetname == false or presetname == nil
					presetname1 = presetname[0]
				end
				if presetname == false or presetname == nil or presetname1 == ""
				else
					save_preset_to_ini rhash , presetname[0]
					#results[13] = ""
					defaults1 = results.map{|prp| prp }
					reload = ""
					title1 = title + "--" + presetname[0]
				end
			elsif save_preset == "#{langconv('default')}"
				defaults1 = defaults.map{|prp| prp }
				reload = ""
				title1 = title + "--#{langconv('default')}"
			elsif save_preset == "#{langconv('assign_material')}"
				defaults1 = results.map{|prp| prp }
				cmat = Sketchup.active_model.materials.current
				put_param cmat , rhash if cmat != nil
				reload = ""
				title1 = title + cmat.name
			elsif save_preset == "#{langconv('get_from_material')}"
				lprec = Sketchup.active_model.options["UnitsOptions"]["LengthPrecision"]
				Sketchup.active_model.options["UnitsOptions"]["LengthPrecision"] = 3 if lprec < 3
				cmat = Sketchup.active_model.materials.current
				if cmat != nil
					ohash = get_param( cmat )
					if ohash != nil
						idns.keys.each{|id|
							a = ohash[ idns[id] ]
							if a != nil
								params[id] = a
							end
						}
					end
					defaults1 =	defaults.map{|prp| prp }
					if params != nil
						( 0..(params.size-1) ).each{|id|
							defaults1[id] = params[id] if defaults1.length > id
						}
					reload = ""
					title1 = title + cmat.name
					end
				end
				Sketchup.active_model.options["UnitsOptions"]["LengthPrecision"] = lprec if lprec < 3
			else
				prvalue = load_preset( save_preset , defaults , idns )
				defaults1 = prvalue.map{|prp| prp } if prvalue != nil
				reload = ""
				title1 = title + "--" + save_preset
			end
		end#while
		put_param Sketchup.active_model , rhash
		Sketchup.active_model.options["UnitsOptions"]["LengthPrecision"] = lprec if lprec < 3

		@fdensity = fdensity.to_f
		@flength = s_to_l(flength)
		@frootw = s_to_l(frootw)
		@fvradius = s_to_l(fvradius)

		@maxnum = maxnum.to_i
		@fj = fj.to_f / 100
		@flj = @fj * @flength.to_f
		@fljitter = Geom::Vector3d.new( @fj * @flength , @fj * @flength , @fj * @flength )
		@fwjitter = fwjitter.to_f * @frootw.to_f / 100
		@fdivs = fdivs.to_i
		@fstrong = fstrong.to_f
		@fsjitter = fsjitter.to_f * @fstrong.to_f / 100
		@finstance = finstance.to_s
		@ftype = ftype.to_s
		@fdirection = Geom::Vector3d.new( s_to_l(fdirectionx) , s_to_l(fdirectiony) , s_to_l(fdirectionz))
		@fforce = Geom::Vector3d.new( s_to_l(fforcex) , s_to_l(fforcey) , s_to_l(fforcez))
		@fur_deflist = []
		@prepts = []
		glowup(true)
		Sketchup.active_model.select_tool PREVIEW_PTS.new(@prepts,true)
	end

	def show_webdialog( prompts2 , defaults2 , lists2 , idns , ids, title1 , defaults1 , defaults ,prompts ,lists, title )
		prompts2 = prompts.map{|prp| prp }
		prompts2.push langconv("PRESET?")
		defaults2 = defaults1.map{|prp| prp }
		defaults2.push ""
		lists2 = lists.map{|prp| prp }
		presetnames = get_presetnames
		if presetnames != nil
			lists2.push "|#{langconv('default')}" + presetnames
		else
			lists2.push "|#{langconv('default')}"
		end
		thisdir = ""
		thisdir = File.dirname( __FILE__ ).gsub(/\\/,"/")
		icount = prompts2.length - 1
		dlg2 = (0..icount).map{|i| [ prompts2[i].to_s , defaults2[i].to_s , lists2[i].to_s , idns[i].to_s ] }
#dlg2[0..4][(-3)..(-1)]を先に取り出す
#dlg2[5,dlg2.length-8]が残り
maindlg = dlg2.slice!(0..5)
maindlg2 = dlg2.slice!(3,1)
seconddlg = dlg2.slice!((-3)..(-1))
maindlg.concat(maindlg2)
maindlg.concat(seconddlg)
maindlg.push ["DIVTAB","tabs-2","",""]
maindlg.concat(dlg2)

#slider_array:"name",min,max,step

unitscale = 1.0
#if @fur_units_metric == false
	#unitscale = 1.0 / 5.0
	unitscale = "#{1000.mm}".to_f / 1000
#end

slider_array = []
slider_array.push ["fdensity",0, 2000 ,10,"#{defaults2[ ids["fdensity"] ]}".to_i ]
slider_array.push ["maxnum",0, 2000,10,"#{defaults2[ ids["maxnum"] ]}".to_i ]
slider_array.push ["flength",1*unitscale,1000*unitscale,5*unitscale,"#{defaults2[ ids["flength"] ]}".to_f ]
slider_array.push ["frootw",1*unitscale,500*unitscale,5*unitscale,"#{defaults2[ ids["frootw"] ]}".to_f ]
slider_array.push ["fstrong",1,50,1,"#{defaults2[ ids["fstrong"] ]}".to_i ]
slider_array.push ["fdivs",1,10,1,"#{defaults2[ ids["fdivs"] ]}".to_i ]
slider_array.push ["fljitter",0,100,1,"#{defaults2[ ids["fljitter"] ]}".to_i ]
slider_array.push ["fwjitter",0,100,1,"#{defaults2[ ids["fwjitter"] ]}".to_i ]
slider_array.push ["fsjitter",0,100,1,"#{defaults2[ ids["fsjitter"] ]}".to_i ]
slider_array.push ["fvradius",0*unitscale,10000*unitscale,100*unitscale,"#{defaults2[ ids["fvradius"] ]}".to_i ]

slider_array.push ["fdirectionx",-500*unitscale,500*unitscale,10*unitscale,"#{defaults2[ ids["fdirectionx"] ]}".to_f ]
slider_array.push ["fdirectiony",-500*unitscale,500*unitscale,10*unitscale,"#{defaults2[ ids["fdirectiony"] ]}".to_f ]
slider_array.push ["fdirectionz",-500*unitscale,500*unitscale,10*unitscale,"#{defaults2[ ids["fdirectionz"] ]}".to_f ]

slider_array.push ["fforcex",-500*unitscale,500*unitscale,10*unitscale,"#{defaults2[ ids["fforcex"] ]}".to_f ]
slider_array.push ["fforcey",-500*unitscale,500*unitscale,10*unitscale,"#{defaults2[ ids["fforcey"] ]}".to_f ]
slider_array.push ["fforcez",-500*unitscale,500*unitscale,10*unitscale,"#{defaults2[ ids["fforcez"] ]}".to_f ]

		cr = "\n"
		shtm = "<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN'>
<html><head><meta http-equiv='Content-Type' content='text/html; charset=utf-8' >
"
		if thisdir and thisdir != ""
		shtm = shtm + "<link rel='stylesheet' type='text/css' media='screen' href='[FUR_FOLDER_PATH]/css/le-frog/jquery-ui-1.9.2.custom.css' />
		<script type='text/javascript' src='[FUR_FOLDER_PATH]/js/jquery-1.8.3.js'></script>
		<script type='text/javascript' src='[FUR_FOLDER_PATH]/js/jquery-ui-1.9.2.custom.js'></script>
		<script type='text/javascript'>" + cr
		shtm.gsub!(/\[FUR_FOLDER_PATH\]/,thisdir)
		shtm = shtm + "$(function(){
			$('#tabs').tabs();" + cr
		slider_array.each{|sname,smin,smax,sstep,val|
			scode = "$( '#slider_#{sname}' ).slider({range: false,min:#{smin},max:#{smax},step:#{sstep},value:#{val},
				slide: function( event, ui ){
					$('##{sname}').val( ui.value );
					if( $('#preview_check')[0].checked ){window.location='skp:preview_fur';}
				}
			});"
			shtm = shtm + scode + cr
		}
		shtm = shtm + "});
function change_textbox(obj){

	var v = parseFloat(obj.value);
	if( isNaN(v) == false ){
		$('#slider_' + obj.id).slider( 'option', 'value', v );
		if( $('#preview_check')[0].checked ){window.location='skp:preview_fur';}
	}
}" + cr
		
		else
			shtm = shtm + "<script type='text/javascript'>"
		end

		shtm = shtm + "
function start_fur(obj) {
  window.location='skp:start_fur';
}
function preview_fur(obj) {
  window.location='skp:preview_fur';
}
function save_new_preset(obj) {
  window.location='skp:save_new_preset';
}
function load_preset(obj) {
  window.location='skp:load_preset';
}
function assign_to_mat(obj) {
  window.location='skp:assign_to_mat';
}
function get_from_mat(obj) {
  window.location='skp:get_from_mat';
}
function update_complist(obj) {
  window.location='skp:update_complist';
}
</script>
<style type='text/css'>
<!--
#tabs {
	font-size: 10px;
}
#tabs .ui-tabs-panel {
	height: 150px;
}
table.fur{
    width:100%;
    border-top:0px;
    border-left:0px;
    border-collapse:collapse;
    border-spacing:0px;
    background-color:#f6f6f6;
    empty-cells:show;
}
.fur td{
    border-right:1px;
    border-bottom:1px;
    padding:0.2em 0.2em;
    font-size:8pt;
    font-family: sans-serif;
    text-align: right;
}
.textbox{
	color: #ffffff;
	background: #222222;
	font-size: 12px;
}
.cssButton{
	color: #ffffff;
	border-top:3px double #9cf;
	border-left:3px double #9cf;
	border-right:3px double #dfd9c3;
	border-bottom:3px double #dfd9c3;
	background: #459e00 url(../img/bg.gif) left bottom repeat-x;
	text-align: center;
	width: 150px;
	font-size: 12px;
}
.cssButton:hover{
	color: #fff;
	border-top:3px double #254A70;
	border-left:3px double #254A70;
	border-right:3px double #508AC5;
	border-bottom:3px double #508AC5;
	background: #369;
	width: 150px;
	font-size: 12px;
}
-->
</style>
</head><body bgcolor='#f6f6f6' >
<input type='checkbox' id='preview_check' value='TRUE' checked='true'>langconv('Preview Fur')<br>
<input type='button' class='cssButton' name='langconv('Make Fur')' value='langconv('Make Fur')' onClick='start_fur(this)' style='font-size:16px; width:95%;'>

<!-- Tabs -->
<div id='tabs' class='ul' >
	<ul>
		<li><a href='#tabs-1'>Main</a></li>
		<li><a href='#tabs-2'>Detail</a></li>
	</ul>
	<div id='tabs-1'>
"
#<input type='button' class='cssButton' name='langconv('Preview Fur')' value='langconv('Preview Fur')' onClick='preview_fur(this)' style='font-size:12px; width:95%;'>
#<br><input type='button' class='cssButton' name='langconv('Load Preset')' value='langconv('Load Preset')' onClick='load_preset(this)' style='font-size:12px; width:224px;'>
#<br><input type='button' class='cssButton' name='langconv('Assign to Material')' value='langconv('Assign to Material')' onClick='assign_to_mat(this)' style='font-size:12px; width:99%;'>
#<br><input type='button' class='cssButton' name='langconv('Get From Material')' value='langconv('Get From Material')' onClick='get_from_mat(this)' style='font-size:12px; width:99%;'>
    	shtm = shtm + "
<br><input type='button' class='cssButton' name='langconv('Save NewPreset')' value='langconv('Save NewPreset')' onClick='save_new_preset(this)' style='font-size:12px; width:99%;'>
<table class='fur'><tbody>"
	    cnt = 0
	    complist = []
		#dlg2.each{|prp,dfl,lst,idn|
	    maindlg.each{|prp,dfl,lst,idn|
		if prp and dfl and lst and idn
			if prp == "DIVTAB" and lst == "" and idn == ""
				shtm = shtm + "</div></div></body></html>
				</tbody></table></div><div id='#{dfl}'><table class='fur' ><tbody>"
			else
				if idn == "fdirectionx" or idn == "fforcex" or idn == "flength" or idn == "instance"
					shtm = shtm + "</tbody></table><hr size='1'><table class='fur' ><tbody>" + cr
				end
				shtm = shtm + "<tr>" +cr
				if lst == ""
					shtm = shtm + "<td><p align='right';>#{exchange_quot(prp)} :</p></td><td><input type='text' class='textbox' name='#{idn}' id='#{idn}' value='#{exchange_quot(dfl)}'"
					shtm = shtm + " style='width:75px; height: 20px; font-size: 10px; text-align: left; vertical-align: middle;' onChange='change_textbox(this);'></td></tr>"+cr
					shtm = shtm + "<tr><td colspan='2'><div id='slider_#{idn}'></div></td>" + cr
				else
					shtm = shtm + "<td><p align='right';>#{exchange_quot(prp)} :</p></td>" + cr
					shtm = shtm + "<td><select  class='textbox' name='#{idn}' id='#{idn}' style='width:75px; height: 20px; font-size: 10px; text-align: left; vertical-align: middle' "
					shtm = shtm + "onClick='update_complist(this)' " if idn == "instance"
					shtm = shtm + "onChange='load_preset(this)' " if idn == "save_preset"
					shtm = shtm + ">" + cr
					lst.split("|").each{|item|
						if item == dfl or item == langconv(dfl)
							shtm = shtm + "<OPTION selected value='#{exchange_quot(item)}'>#{exchange_quot(item)}</OPTION>"+cr
						else
							shtm = shtm + "<OPTION value='#{exchange_quot(item)}'>#{exchange_quot(item)}</OPTION>"+cr
						end
						if idn == "instance"
							complist.push item if item != ""
						end
					}
					shtm = shtm + "</select></td>"+cr
				end
				shtm = shtm + "</tr>" +cr
				#if idn == "fforcez"
				#	shtm = shtm + "</tbody></table><hr size='1'><table class='fur' ><tbody>" + cr
				#end
			end
		end
		}
		shtm = shtm + "<tr><td><div id='anglepicker'></div></td></tr>" + cr
    	shtm = shtm + "</tbody></table><br>"
		shtm.gsub!("langconv('Load Preset')",langconv('Load Preset'))
		shtm.gsub!("langconv('Save NewPreset')",langconv('Save NewPreset'))
		shtm.gsub!("langconv('Assign to Material')",langconv('Assign to Material'))
		shtm.gsub!("langconv('Get From Material')",langconv('Get From Material'))
		shtm.gsub!("langconv('Preview Fur')",langconv('Preview Fur'))
		shtm.gsub!("langconv('Make Fur')",langconv('Make Fur'))
		shtm.gsub!(/\'/,"\"")
		
		##pdir = File.dirname( File.expand_path(__FILE__) ) + '/fur_en/'
		##pdir = Sketchup.find_support_file("Plugins") + '/'
		##htmlname = pdir + FUR_DIALOG_FILE
		@wdlg = UI::WebDialog.new( title1, true, "T2H_FUR_DIALOG", 300, 680, 150, 150, true)
		
		##savehtml htmlname , shtm
		
		@wdlg.set_html(shtm)
		##@wdlg.set_url( htmlname )

	    @wdlg.add_action_callback("update_complist"){|d,p|
		    dfnames = []
		    addfname = []
		    dfnames = get_complist
		    dfnames.each{|dfname|
		    	if complist.index( dfname ) == nil
		    		addfname.push dfname
					@wdlg.execute_script( "document.getElementById('instance').options[document.getElementById('instance').length] = new Option('#{dfname}','#{dfname}')" )
				end
			}
			addfname.each{|adname| complist.push adname }
	    }
	    @wdlg.add_action_callback("save_new_preset"){|d,p|
			fdensity = @wdlg.get_element_value("fdensity")
			maxnum = @wdlg.get_element_value("maxnum")
			flength = @wdlg.get_element_value("flength")
			frootw = @wdlg.get_element_value("frootw")
			fj = @wdlg.get_element_value("fljitter")
			fwjitter = @wdlg.get_element_value("fwjitter")
			fdivs = @wdlg.get_element_value("fdivs")
			fvradius = @wdlg.get_element_value("fvradius")
			fstrong = @wdlg.get_element_value("fstrong")
			fsjitter = @wdlg.get_element_value("fsjitter")
			ftype = @wdlg.get_element_value("ftype")
			finstance = @wdlg.get_element_value("instance")
			funits = @wdlg.get_element_value("funits")

			fdirectionx = @wdlg.get_element_value("fdirectionx")
			fdirectiony = @wdlg.get_element_value("fdirectiony")
			fdirectionz = @wdlg.get_element_value("fdirectionz")
			fdirection = fdirectionx + "&&" + fdirectiony + "&&" + fdirectionz

			fforcex = @wdlg.get_element_value("fforcex")
			fforcey = @wdlg.get_element_value("fforcey")
			fforcez = @wdlg.get_element_value("fforcez")
			fforce = fforcex + "&&" + fforcey + "&&" + fforcez

			save_preset = @wdlg.get_element_value("save_preset")
			rhash = Hash.new
			results = []
			idns.each{|key,val|
					rhash[val.to_s] =  @wdlg.get_element_value("#{val}")
				#end
			}
			#results = [fdensity,maxnum ,flength,frootw,fstrong,fj,fwjitter,fsjitter,fdivs,fvradius,ftype,finstance,funits,save_preset]
			idns.keys.each{|id|
				a = rhash[ idns[id] ]
				if a != nil
					results[id] = a
				end
			}
			if  fdensity.to_f == 0 or maxnum.to_f == 0 or s_to_l(flength) == 0 or s_to_l(frootw) == 0 or fdivs.to_f == 0 or fstrong.to_f == 0
			else
				presetname1 = ""
				pnames = get_presetnames
				pnames = "" if pnames == nil
				pnlist = pnames.split("|")
				while( presetname1 == "" or pnlist.index( presetname1 ) != nil )
					presetname = UI.inputbox [langconv("PRESET_NAME")], [""], langconv("Input preset name")
					break if presetname == false or presetname == nil
					presetname1 = presetname[0]
				end
				if presetname == false or presetname == nil or presetname1 == ""
				else
					save_preset_to_ini rhash , presetname1
					#results[13] = ""
					defaults1 = results.map{|prp| prp }
					reload = ""
					title1 = title + "--" + presetname1
					@wdlg.execute_script( "document.getElementById('save_preset').options[document.getElementById('save_preset').length] = new Option('#{presetname1}','#{presetname1}')" )
					#@wdlg.close
					#show_webdialog prompts2 , defaults1 , lists2 , idns, title1 , defaults1 , defaults ,prompts ,lists, title 
				end
			end
		}
	    @wdlg.add_action_callback("load_preset"){|d,p|
			lprec = Sketchup.active_model.options["UnitsOptions"]["LengthPrecision"]
			Sketchup.active_model.options["UnitsOptions"]["LengthPrecision"] = 3 if lprec < 3
			save_preset = @wdlg.get_element_value("save_preset")
			if save_preset == langconv("default")
				defaults1 = defaults.map{|prp| prp }
				reload = ""
				title1 = title + "--" + langconv("default")
				defaults1.each_with_index{|prp,id|
					@wdlg.execute_script( "document.getElementById('#{idns[id]}').value = '#{exchange_quot2( prp )}'" )
				}
				@wdlg.execute_script( "document.title = '#{title1}'" )
				#@wdlg.close
				#show_webdialog prompts2 , defaults1 , lists2 , idns, title1 , defaults1 , defaults ,prompts ,lists, title 
			elsif save_preset != ""
				prvalue = load_preset( save_preset , defaults , idns)
				defaults1 = prvalue.map{|prp| prp } if prvalue != nil
				reload = ""
				title1 = title + "--" + save_preset
				defaults1.each_with_index{|prp,id|
					@wdlg.execute_script( "document.getElementById('#{idns[id]}').value = '#{exchange_quot2( prp )}'" )
				}
				@wdlg.execute_script( "document.title = '#{title1}'" )
				#@wdlg.close
				#show_webdialog prompts2 , defaults1 , lists2 , idns, title1 , defaults1 , defaults ,prompts ,lists, title 
			end
			Sketchup.active_model.options["UnitsOptions"]["LengthPrecision"] = lprec if lprec < 3
		}
	    @wdlg.add_action_callback("get_from_mat"){|d,p|
			cmat = Sketchup.active_model.materials.current
			lprec = Sketchup.active_model.options["UnitsOptions"]["LengthPrecision"]
			Sketchup.active_model.options["UnitsOptions"]["LengthPrecision"] = 3 if lprec < 3
			if cmat != nil
				ohash = get_param( cmat )
				if ohash != nil
					params = []
					idns.keys.each{|id|
						a = ohash[ idns[id] ]
						if a != nil
							params[id] = a
						end
					}
					if params != nil
						defaults1 =	defaults.map{|prp| prp }
						( 0..(params.size-1) ).each{|id|
							defaults1[id] = params[id] if defaults1.length > id
						}
						defaults1.each_with_index{|prp,id|
							@wdlg.execute_script( "document.getElementById('#{idns[id]}').value = '#{exchange_quot2(prp)}'" )
						}
						#wdlg.close
						#show_webdialog prompts2 , defaults1 , lists2 , idns, title1 , defaults1 , defaults ,prompts ,lists, title
					end
				end
			end
		Sketchup.active_model.options["UnitsOptions"]["LengthPrecision"] = lprec if lprec < 3
		}
	    @wdlg.add_action_callback("assign_to_mat"){|d,p|
			rhash = Hash.new
			idns.each{|key,val|
				rhash[val.to_s] =  @wdlg.get_element_value("#{val}")
			}
			cmat = Sketchup.active_model.materials.current
			put_param cmat , rhash if cmat != nil
		}
	    @wdlg.add_action_callback("preview_fur"){|d,p|
			start_fur_test idns , true
  	    }
	    @wdlg.add_action_callback("start_fur"){|d,p|
			start_fur_test idns , false
  	    }
		@dlg_possize = [250,700,200,200]
        if RUBY_PLATFORM[/darwin/]
            @wdlg.show_modal { }
        else
            @wdlg.show { }
        end
		#@wdlg.show
		#@wdlg.set_size 226,700
		#@wdlg.set_position 200,200
	end
	
	def start_fur_test( idns , preview = false )
		return if Sketchup.active_model.selection.find{|e| e.kind_of? Sketchup::Face } == nil
			rhash = Hash.new
			idns.each{|key,val|
					rhash[val.to_s] =  @wdlg.get_element_value("#{val}")
			}

			fdensity = @wdlg.get_element_value("fdensity")
			maxnum = @wdlg.get_element_value("maxnum")
			flength = @wdlg.get_element_value("flength")
			frootw = @wdlg.get_element_value("frootw")
			fj = @wdlg.get_element_value("fljitter")
			fwjitter = @wdlg.get_element_value("fwjitter")
			fdivs = @wdlg.get_element_value("fdivs")
			fvradius = @wdlg.get_element_value("fvradius")
			fstrong = @wdlg.get_element_value("fstrong")
			fsjitter = @wdlg.get_element_value("fsjitter")
			ftype = @wdlg.get_element_value("ftype")
			finstance = @wdlg.get_element_value("instance")
			funits = @wdlg.get_element_value("funits")
			fdirectionx = @wdlg.get_element_value("fdirectionx")
			fdirectiony = @wdlg.get_element_value("fdirectiony")
			fdirectionz = @wdlg.get_element_value("fdirectionz")
			fdirection = fdirectionx + "&&" + fdirectiony + "&&" + fdirectionz

			fforcex = @wdlg.get_element_value("fforcex")
			fforcey = @wdlg.get_element_value("fforcey")
			fforcez = @wdlg.get_element_value("fforcez")
			fforce = fforcex + "&&" + fforcey + "&&" + fforcez
			save_preset = @wdlg.get_element_value("save_preset")

			#results = [fdensity,maxnum ,flength,frootw,fstrong,fj,fwjitter,fsjitter,fdivs,fvradius,ftype,finstance,funits,save_preset]
			is_df_exist = false
			if finstance == langconv("yes") or finstance == langconv("no") or finstance == langconv("fur_instance")
				is_df_exist = true
			elsif finstance == "yes" or finstance == "no" or finstance == "fur_instance"
				is_df_exist = true
			else
				Sketchup.active_model.definitions.each{|df|
					is_df_exist = true if df.name == finstance and df.group? == false
				}
			end
			if  fdensity.to_f == 0 or maxnum.to_f == 0 or s_to_l(flength) == 0 or s_to_l(frootw) == 0 or fdivs.to_f == 0 or fstrong.to_f == 0 or is_df_exist == false
				#nothing execute
			else #if save_preset == ""
				@fdensity = fdensity.to_f
				@flength = s_to_l(flength)
				@frootw = s_to_l(frootw)
				@fvradius = s_to_l(fvradius)

				@maxnum = maxnum.to_i
				@fj = fj.to_f / 100
				@flj = @fj * @flength.to_f
				@fljitter = Geom::Vector3d.new( @fj * @flength , @fj * @flength , @fj * @flength )
				@fwjitter = fwjitter.to_f * @frootw.to_f / 100
				@fdivs = fdivs.to_i
				@fstrong = fstrong.to_f
				@fsjitter = fsjitter.to_f * @fstrong.to_f / 100
				@finstance = finstance.to_s
				@ftype = ftype.to_s
				@fdirection = Geom::Vector3d.new( s_to_l(fdirectionx) , s_to_l(fdirectiony) , s_to_l(fdirectionz))
				@fforce = Geom::Vector3d.new( s_to_l(fforcex) , s_to_l(fforcey) , s_to_l(fforcez))
				@fur_deflist = []
				put_param Sketchup.active_model ,rhash
				if preview == false
					glowup(false)
					Sketchup.active_model.select_tool nil
				else
					#bb= Sketchup.active_model.bounds
					#ca = Sketchup.active_model.active_view.camera.eye
					#if ca != nil and @fvradius == 0
					#	@fvradius = bb.center.distance( ca )
					#end
					@prepts = []
					glowup(true)
					Sketchup.active_model.select_tool PREVIEW_PTS.new(@prepts,false)
				end
			end

	end

	def exchange_quot( tstr )
		tstr1 = ""
		tstr1 = tstr.gsub("\'",'&#39;')#'
		tstr1.gsub!("\"","\&quot;")#"
		return tstr1
	end
	def exchange_quot2( tstr )
		tstr1 = ""
		tstr1 = tstr.to_s.gsub("\'","\\\'")#'
		tstr1.gsub!("\"","\\\"")#"
		return tstr1
	end

	
	def fur_webdialog( fur_unit )
		#@fur_units_metric = fur_unit
		#fur_dialog_ini
		lprec = Sketchup.active_model.options["UnitsOptions"]["LengthPrecision"]
		Sketchup.active_model.options["UnitsOptions"]["LengthPrecision"] = 3 if lprec < 3
	    lang = Sketchup.get_locale.upcase
		dlg = get_dialogitems
	    prompts = []
	    defaults = []
	    lists = []
	    idns = Hash.new
	    ids = Hash.new
	    id = 0
	    dlg.each{|prp,dfl,lst,idn|
			prompts.push prp
			defaults.push dfl
			lists.push lst
			idns[id] = idn
			ids[idn] = id
			id += 1
		}
		idns[dlg.length] = "save_preset"
		params = []
		ohash = get_param( Sketchup.active_model )
		if ohash != nil
			idns.keys.each{|id|
				a = ohash[ idns[id] ]
				if a != nil
					params[id] = a
				end
			}
		end
		defaults1 =	defaults.map{|prp| prp }
		
		if params.size > 0
			( 0..(params.size-1) ).each{|id|
				defaults1[id] = params[id] if defaults1.length > id
			}
		end

		fdensity = ""
		maxnum = ""
		flength = ""
		frootw = ""
		fdivs = ""
		fstrong = ""
		fj = ""
		fwjitter = ""
		fsjitter = ""
		fdivs = ""
		fvradius = ""
		ftype = ""
		finstance = ""
		funits = ""
		save_preset = ""
		#results = []
		reload = ""
		title = langconv("Fur settings.")
		title1 = langconv("Fur settings.")
		
		prompts2 = prompts.map{|prp| prp }
		defaults2 = defaults1.map{|prp| prp }
		lists2 = lists.map{|prp| prp }

		show_webdialog prompts2 , defaults2 , lists2 , idns , ids, title1 , defaults1 , defaults ,prompts ,lists, title
		Sketchup.active_model.options["UnitsOptions"]["LengthPrecision"] = lprec if lprec < 3
	end
	##Rev 2010-05-09 add for exporter.
	def get_furmesh_by_mat( face , mat , ret_furmesh = [] )
		#ret_furmesh = [ polygonmesh , uv ]
		if face.is_a?(Sketchup::Face)
		else
			return nil
		end
		if mat != nil
			#fdic = mat.attribute_dictionary FUR_DIC_PREFIX
			fdic = get_param( mat )
			return nil if fdic == nil
			a = fdic[ "fdensity" ]
			@finstance = fdic[ "instance" ].to_s
			if @finstance == langconv("yes") or @finstance == langconv("no") or @finstance == langconv("fur_instance")
			elsif @finstance == "yes" or @finstance == "no" or @finstance == "fur_instance"
			else
				return nil
			end
			@funits = fdic[ "funits" ].to_s
			@camera = Sketchup.active_model.active_view.camera

			@fdensity = fdic[ "fdensity" ].to_f
			@flength = s_to_l(fdic[ "flength" ])
			@frootw = s_to_l(fdic[ "frootw" ])
			@fvradius = s_to_l(fdic[ "fvradius" ])

			@maxnum = fdic[ "maxnum" ].to_i
			@fforce = Geom::Vector3d.new( 0.0 , 0.0 , 0.05 )
			@fdirection = Geom::Vector3d.new( 0.0 , 0.0 , 0.05 )
			@ftype = fdic[ "ftype" ].to_s

			@fj = fdic[ "fljitter" ].to_f / 100
			@flj = @fj.to_f / 100  * @flength.to_f
			@fljitter = Geom::Vector3d.new( @fj * @flength , @fj * @flength , @fj * @flength )
			@fwjitter = fdic[ "fwjitter"].to_f * @frootw.to_f / 100

			@fstrong = fdic[ "fstrong" ].to_f
			@fsjitter = fdic[ "fsjitter" ].to_f * @fstrong.to_f / 100
			@fdivs = fdic[ "fdivs"].to_i
			@fdivs = @fdivs + 1 if @fvradius != 0

			fdirectionx = s_to_l(fdic['fdirectionx']) if fdic['fdirectionx'] != ""
			fdirectiony = s_to_l(fdic['fdirectiony']) if fdic['fdirectiony'] != ""
			fdirectionz = s_to_l(fdic['fdirectionz']) if fdic['fdirectionz'] != ""
			fforcex = s_to_l(fdic['fforcex']) if fdic['fforcex'] != ""
			fforcey = s_to_l(fdic['fforcey']) if fdic['fforcey'] != ""
			fforcez = s_to_l(fdic['fforcez']) if fdic['fforcez'] != ""
			@fdirection = Geom::Vector3d.new( fdirectionx , fdirectiony , fdirectionz)
			@fforce = Geom::Vector3d.new( fforcex , fforcey , fforcez)
		else
			return nil
		end
		mesh = face.mesh(5)
		nvec = face.normal
		pmesh = Geom::PolygonMesh.new
		#pmeshes = []
		ocnt = 0
		if mesh != nil
			mesh.polygons.each{|poly|
				pt1 = mesh.point_at poly[0]
				pt2 = mesh.point_at poly[1]
				pt3 = mesh.point_at poly[2]
				uv1 = mesh.uv_at( poly[0] ,1 )
				uv2 = mesh.uv_at( poly[1] ,1 )
				uv3 = mesh.uv_at( poly[2] ,1 )
				nor1 = mesh.normal_at poly[0]
				nor2 = mesh.normal_at poly[1]
				nor3 = mesh.normal_at poly[2]
				len12 = pt1.distance pt2
				len13 = pt1.distance pt3
				vec12 = pt1.vector_to pt2
				vec13 = pt1.vector_to pt3
				ang23 = vec12.angle_between vec13
				area123 = len12.to_m * len13.to_m * Math.sin( ang23 ) * 0.5
				cnt = area123.to_f * @fdensity.to_f
				if cnt.to_f < 1.to_f
					if cnt.to_f > rand.to_f
						cnt = 1
					else
						cnt = 0
					end
				end
				cnt = cnt.to_i
				cnt = @maxnum if cnt > @maxnum
				(1..cnt).each{|i|
					pmesh = Geom::PolygonMesh.new
					ra = rand
					rb = 1.to_f - Math.sqrt( rand )
					pt4 = Geom::Point3d.new
					pt4 = point_add( vector_scale( pt2 , ra.to_f ) , vector_scale( pt3 ,( 1.to_f - ra.to_f ) ) )
					pt5 = Geom::Point3d.new
					pt5 = point_add( vector_scale( pt1 , rb.to_f ) , vector_scale( pt4 ,( 1.to_f - rb.to_f ) ) )
					uv4 = Geom::Point3d.new
					uv4.x = uv2.x * ra + uv3.x * (1-ra)
					uv4.y = uv2.y * ra + uv3.y * (1-ra)
					uv5 = Geom::Point3d.new
					uv5.x = uv1.x * rb + uv4.x * (1-rb)
					uv5.y = uv1.y * rb + uv4.y * (1-rb)
					nor4 = Geom::Point3d.new
					nor4 = point_add( vector_scale( nor2 , ra.to_f ) , vector_scale( nor3 ,( 1.to_f - ra.to_f ) ) )
					nor5 = Geom::Point3d.new
					nor5 = point_add( vector_scale( nor1 , rb.to_f ) , vector_scale( nor4 ,( 1.to_f - rb.to_f ) ) )
					divs = @fdivs
				#if @finstance == "no"
					if @fvradius == 0
						make_fur pmesh , pt5 , uv5, nor5 , mat , pt1 ,divs
					else
						cv1 = @camera.eye.vector_to @camera.target
						cv2 = @camera.eye.vector_to pt5
						if cv2.angle_between( cv1 ).to_f <= @camera.fov.degrees.to_f
							pdist = @fvradius.to_f - pt5.distance( @camera.eye )
							pdist = 0 if pdist < 0
							divs = ( @fdivs * Math.sqrt( pdist / @fvradius ) ) .to_i
							make_fur( pmesh , pt5 , uv5, nor5 , mat , pt1 ,divs ) if divs != 0
						end
					end
					if pmesh.count_polygons > 0
						ret_furmesh.push [ pmesh , uv5 ]
						ocnt += pmesh.count_polygons
					end
				#end
				}##density loop end
			}##polygons.each
		end##if mesh?
		#ret_furmesh = pmeshes.map{|pm,uv| [ pm , uv ] }
		Sketchup.set_status_text "Fur Calc #{ocnt} Polygons"
		return true
	end

	def glowup( preview = false )
		model = Sketchup.active_model
		ss = model.selection
		ents = model.entities
		if ss.empty? 
		  UI.messagebox( langconv("No selection.") )
		  return nil
		end

		return if ss.find{|selface| selface.kind_of? Sketchup::Face } == nil
		starttime = Time.now.to_f

		#@fforce = Geom::Vector3d.new( (0.0).m , (0.001).m , (-0.05).m )
		#@fdirection = Geom::Vector3d.new( (0.0).m , (0.0).m , @flength.to_f / 20 )
		@camera = Sketchup.active_model.active_view.camera
		@fdivs = @fdivs + 1 if @fvradius != 0
		cnt = 0
		
		sfaces = ss.find_all{|selface| selface.is_a?(Sketchup::Face) }
		spgs = sfaces.map{|pg| [pg.mesh(5) , pg.material , pg.normal] }
		ocnt = 0
		pmesh = Geom::PolygonMesh.new
		pmeshes = []
		pcmax = 600
		pcnext = pcmax
		pmat = Sketchup.active_model.materials.current

		fur_inss_list = []
		fur_inss = []
		fur_def = Sketchup.active_model.definitions[ "fur_instance" ]
		if @finstance == langconv("yes") or @finstance == "yes" or ( fur_def == nil and @finstance == langconv("fur_instance") ) or ( fur_def == nil and @finstance == "fur_instance" )
			fur_def = model.definitions.add( model.definitions.unique_name( langconv("fur_instance") ) )
			make_fur( pmesh , pointXYZ( 0,0,0 ) , pointXYZ( 0,0,0 ) , pointXYZ( 0,0,1 )  , nil , pointXYZ( 1,0,0 ) , @fdivs ,true )
			if @ftype == langconv("Box") or  @ftype == "Box"
				fur_def.entities.fill_from_mesh( pmesh , false ,0 )
			else
				fur_def.entities.fill_from_mesh( pmesh , false ,12 )
			end
			fur_def.insertion_point = pointXYZ( 0,0,0 )
			fi_pcount = pmesh.count_polygons.to_i + 1.to_i
		elsif @finstance == langconv("fur_crowd")
			fi_pcount = 1
		elsif @finstance != langconv("no") and @finstance != "no"
			fur_def = Sketchup.active_model.definitions[ @finstance ]
			@finstance = langconv("no") if fur_def == nil
			fi_pcount = 1
		end
		pmesh = Geom::PolygonMesh.new if preview == false
		prmax = 10000
		@prepts = []
		spgs.each{|mesh ,mat, nvec|
			if mesh != nil
				mesh.polygons.each{|poly|
					pt1 = mesh.point_at poly[0]
					pt2 = mesh.point_at poly[1]
					pt3 = mesh.point_at poly[2]
					#if preview == false
						uv1 = mesh.uv_at( poly[0] ,1 )
						uv2 = mesh.uv_at( poly[1] ,1 )
						uv3 = mesh.uv_at( poly[2] ,1 )
						nor1 = mesh.normal_at poly[0]
						nor2 = mesh.normal_at poly[1]
						nor3 = mesh.normal_at poly[2]
					#end
					len12 = pt1.distance pt2
					len13 = pt1.distance pt3
					vec12 = pt1.vector_to pt2
					vec13 = pt1.vector_to pt3
					ang23 = vec12.angle_between vec13
					area123 = len12.to_m * len13.to_m * Math.sin( ang23 ) * 0.5
					cnt = area123.to_f * @fdensity.to_f
					if cnt.to_f < 1.to_f
						if cnt.to_f > rand.to_f
							cnt = 1
						else
							cnt = 0
						end
					end
					cnt = cnt.to_i
					cnt = @maxnum if cnt > @maxnum
					(1..cnt).each{|i|
						ra = rand
						rb = 1.to_f - Math.sqrt( rand )
						pt4 = Geom::Point3d.new
						pt4 = point_add( vector_scale( pt2 , ra.to_f ) , vector_scale( pt3 ,( 1.to_f - ra.to_f ) ) )
						pt5 = Geom::Point3d.new
						pt5 = point_add( vector_scale( pt1 , rb.to_f ) , vector_scale( pt4 ,( 1.to_f - rb.to_f ) ) )
						#if preview == false
							uv4 = Geom::Point3d.new
							uv4.x = uv2.x * ra + uv3.x * (1-ra)
							uv4.y = uv2.y * ra + uv3.y * (1-ra)
							uv5 = Geom::Point3d.new
							uv5.x = uv1.x * rb + uv4.x * (1-rb)
							uv5.y = uv1.y * rb + uv4.y * (1-rb)
							nor4 = Geom::Point3d.new
							nor4 = point_add( vector_scale( nor2 , ra.to_f ) , vector_scale( nor3 ,( 1.to_f - ra.to_f ) ) )
							nor5 = Geom::Point3d.new
							nor5 = point_add( vector_scale( nor1 , rb.to_f ) , vector_scale( nor4 ,( 1.to_f - rb.to_f ) ) )
							divs = @fdivs
						#end
						if @finstance != langconv("no") and @finstance != "no"
							if preview == false
								fur_inss.push [ pt5 , nor5 , mat ]
								ocnt += fi_pcount
								pmat = mat
								if ( ocnt ) >= pcnext
									ocnt += fi_pcount
									fur_inss_list.push fur_inss
									fur_inss = []
									while pcnext < ( ocnt + pcmax / 2 )
										pcnext += pcmax
									end
									Sketchup.set_status_text "Calc #{ocnt} Polygons"
								end
							else
								#@prepts.push pt5
								make_preview( @prepts , pt5 , nor5 ,divs)
								break if @prepts.size > prmax
							end
						else
							if @fvradius == 0
								if preview == false
									make_fur pmesh , pt5 , uv5, nor5 , mat , pt1 ,divs
								else
									#@prepts.push pt5
									make_preview( @prepts , pt5 , nor5 ,divs)
									break if @prepts.size > prmax
								end
							else
								cv1 = @camera.eye.vector_to @camera.target
								cv2 = @camera.eye.vector_to pt5
								if cv2.angle_between( cv1 ).to_f <= @camera.fov.degrees.to_f
									pdist = @fvradius.to_f - pt5.distance( @camera.eye )
									pdist = 0 if pdist < 0
									divs = ( @fdivs * Math.sqrt( pdist / @fvradius ) ) .to_i
									if divs != 0
									if preview == false
										make_fur( pmesh , pt5 , uv5, nor5 , mat , pt1 ,divs )
									else
										#@prepts.push pt5
										make_preview( @prepts , pt5 , nor5 ,divs)
										break if @prepts.size > prmax
									end
									end
								end
							end
							pmat = mat
							if preview == false
								if ( ocnt + pmesh.count_polygons ) >= pcnext
									ocnt += pmesh.count_polygons
									pmeshes.push [ pmesh , mat ]
									pmesh = Geom::PolygonMesh.new
									while pcnext < ( ocnt + pcmax / 2 )
										pcnext += pcmax
									end
									Sketchup.set_status_text "Calc #{ocnt} Polygons"
								end
							end
						end
					break if @prepts.size > prmax
					}##density loop end
				break if @prepts.size > prmax
				}##polygons.each
			end##if mesh?
			break if @prepts.size > prmax
		}
		return if preview == true

		if Sketchup.version.to_f >= 7
			model.start_operation "fur glow" ,true
		else
			model.start_operation "fur glow"
		end
		oocnt = 0
		fgp = model.active_entities.add_group
		fgents = fgp.entities
		if @finstance != langconv("no") and @finstance != "no"
			if fur_inss.size > 0
				ocnt += fi_pcount
				fur_inss_list.push fur_inss
				Sketchup.set_status_text "Calc #{ocnt} Polygons"
			end

			fur_inss_list.each{|fur_inss|
				fur_inss.each{|pt5 , npt5 , mat|
					nor5 = pointXYZ( 0,0,0 ).vector_to( npt5 )
					nor5.length = @flength.to_f
					nor6 = vector_add( nor5 , vector_scale( @fdirection , 0.5 ) )
					#nor6.length = nor5.length
					flv = vectorXYZ( @fljitter.x * ( 0.5 -rand ),@fljitter.y * ( 0.5 -rand ),@fljitter.z * ( 0.5 -rand ) )
					nor7 = vector_add( nor6 , flv )
					nor7.length = nor5.length
					nor6.length = nor5.length
					if @fdirection.length == 0
						scale_deg = 180.degrees
					else
						scale_deg = ( 90.degrees - nor5.angle_between(nor6) ).abs
						#scale_deg = @fljitter.length.to_f / @fdirection.length.to_f
					end
					scale_deg = 180.degrees if scale_deg > 180.degrees
					scale_deg = 180.degrees if scale_deg < 0
					ra = ( ( 1.0 - rand * 2.0 ) * scale_deg )
					tr = Geom::Transformation.rotation( pointXYZ( 0,0,0 ), vectorXYZ( 0,0,1 ) , ra )
					#nor5 = vector_add( pointXYZ( 0,0,0 ).vector_to( npt5 ) , @fdirection )
					if nor7.samedirection?( vectorXYZ( 0,0,1 ) )
					elsif nor7.samedirection?( vectorXYZ( 0,0,-1 ) )
						tr = Geom::Transformation.rotation( pointXYZ( 0,0,0 ), vectorXYZ( 1,0,0 ) , 180.degrees ) * tr
					else
						zax = nor7
						yax = nor7.cross( vectorXYZ( 0,0,1 ) )
						xax = yax.cross( nor7 )
						##xax = nor7.cross( yax )##bug fixed in May 29,2013. X Axis reversed in transformation of component.
						tr = Geom::Transformation.axes( pointXYZ( 0,0,0 ), xax, yax, zax ) * tr
					end
					tsfactor = 1.to_f - @fj * ( 1.to_f - rand * 2.to_f )
					tsfactor = 0.01 if  tsfactor == 0
					ts = Geom::Transformation.scaling( tsfactor, tsfactor, tsfactor )
					tr = ts * tr
					tr = Geom::Transformation.translation( pointXYZ( 0,0,0 ).vector_to( pt5 ) ) * tr
					if @fur_deflist.length > 0
						fins = fgents.add_instance @fur_deflist[ (@fur_deflist.length * rand).to_i ], tr
					else
						fins = fgents.add_instance fur_def, tr
					end
					fins.material = mat if mat != nil
					Sketchup.set_status_text "Making #{oocnt} polygons / #{ocnt}"
					oocnt += fi_pcount
				}
			}
		else
			if pmesh.count_polygons > 0
				ocnt += pmesh.count_polygons
				pmeshes.push [ pmesh , pmat ]
				Sketchup.set_status_text "Calc #{ocnt} Polygons"
			end
			pmeshes.each{|pmesh , mat|
				if pmesh != nil
					tgp = fgents.add_group
					tgents = tgp.entities
					if @ftype == langconv("Box") or @ftype == "Box"
						tgents.fill_from_mesh( pmesh , false ,0 )
					else
						tgents.fill_from_mesh( pmesh , false ,12 )
					end
					tgp.material = mat
					oocnt += pmesh.count_polygons
					Sketchup.set_status_text "Making #{oocnt} polygons / #{ocnt}"
				end
			}
		end

		model.commit_operation
		wastetime = Time.now.to_f - starttime
		Sketchup.set_status_text "#{langconv('waste time is')} #{wastetime} #{langconv('sec')}"
	end##def
	def make_preview( pts , pt5 , nor5, divs )
=begin
		vec_l = Geom::Vector3d.new( nor5.x , nor5.y , nor5.z )
		vec_l.length = @flength.to_f
		vjitter = Geom::Vector3d.new( @fljitter.x.to_f - @fljitter.x.to_f * rand * 2, @fljitter.y.to_f - @fljitter.y.to_f * rand * 2 , @fljitter.z.to_f - @fljitter.z.to_f * rand * 2 )
		vec_l = vector_add( vec_l , vjitter )
		fdir = vector_scale( @fdirection , @flength.to_f )
		vec_l = vector_add( vec_l , @fdirection )
		vec_l = vector_add( vec_l , @fforce )
		vec_l.length = @flength.to_f
		pt6 = point_add( pt5 , vec_l )
		pts.push pt5
		pts.push pt6
=end
		vec_l = Geom::Vector3d.new( nor5.x , nor5.y , nor5.z )
		vec_l.length = @flength.to_f
		vjitter = Geom::Vector3d.new( @fljitter.x.to_f - @fljitter.x.to_f * rand * 2, @fljitter.y.to_f - @fljitter.y.to_f * rand * 2 , @fljitter.z.to_f - @fljitter.z.to_f * rand * 2 )
		vec_l = vector_add( vec_l , vjitter )
		fdir = vector_scale( @fdirection , @flength.to_f )
		vec_l = vector_add( vec_l , @fdirection )
		vec_l.length = @flength.to_f
		dvec_l = vector_scale( vec_l ,  ( 1.to_f / divs.to_f ) )
		fstr = @fstrong.to_f + ( 2.to_f * rand - 1.to_f ) * @fsjitter.to_f
		if fstr > 0
			force = vector_scale( @fforce , 1.to_f / fstr.to_f )
		else
			force = vector_scale( @fforce , 1 )
		end
		dforce = vector_scale( force , ( vec_l.length.to_f / divs.to_f ) )
		dvec_l2 = vector_add( dvec_l , dforce )
		dvec_l2.length = dvec_l.length
		pts2 = []
		pts2.push pt5
		pt6 = pt5
		(1..divs).each{|div|
			dvec_l2 = vector_add( dvec_l2 , dforce )
			dvec_l2.length = dvec_l.length
			pt6 = point_add( pt6 , dvec_l2 )
			pts2.push pt6
		}
		pts.push pts2
		#pts.push pt6
	end
	def make_fur( pmesh , pt5 , uv5 , nor5 , mat ,pt1 ,divs , inss = false )
		vec_l = Geom::Vector3d.new( nor5.x , nor5.y , nor5.z )
		vec_l.length = @flength.to_f
		if inss == true
			vjitter = Geom::Vector3d.new( @fljitter.x.to_f * ( 3.0 ** 0.5 ) / 2 , 0 , 0 )
			vec_l = vector_add( vec_l , vjitter )
			fdir = vector_scale( @fdirection , @flength.to_f )
		else
			vjitter = Geom::Vector3d.new( @fljitter.x.to_f - @fljitter.x.to_f * rand * 2, @fljitter.y.to_f - @fljitter.y.to_f * rand * 2 , @fljitter.z.to_f - @fljitter.z.to_f * rand * 2 )
			vec_l = vector_add( vec_l , vjitter )
			fdir = vector_scale( @fdirection , @flength.to_f )
			vec_l = vector_add( vec_l , @fdirection )
		end
		vec_l.length = @flength.to_f
		##chk_per = false
		w = (( @frootw.to_f + rand * @fwjitter.to_f ) / 2.to_f ).to_f
		if @fforce.length == 0
			vec_w = pt5.vector_to pt1
			vec_w.length = w
			t = Geom::Transformation.rotation pt5, vec_l, rand * 360.degrees
			vec_w.transform! t
		elsif @fforce.samedirection?( vec_l ) or @fforce.samedirection?( vec_l.reverse )
			vec_w = pt5.vector_to pt1
			vec_w.length = w
			t = Geom::Transformation.rotation pt5, vec_l, rand * 360.degrees
			vec_w.transform! t
		else
			vec_w = vec_l.cross @fforce
			vec_w.length = w
		end
		##pmesh = Geom::PolygonMesh.new
		dvec_l = vector_scale( vec_l ,  ( 1.to_f / divs.to_f ) )
		fstr = @fstrong.to_f + ( 2.to_f * rand - 1.to_f ) * @fsjitter.to_f
		if fstr > 0
			force = vector_scale( @fforce , 1.to_f / fstr.to_f )
		else
			force = vector_scale( @fforce , 1 )
		end
		dforce = vector_scale( force , ( vec_l.length.to_f / divs.to_f ) )
		dvec_l2 = vector_add( dvec_l , dforce )
		dvec_l2.length = dvec_l.length
		pvts0 = Geom::Point3d.new
		pvts1 = Geom::Point3d.new
		pvts2 = Geom::Point3d.new
		pvts3 = Geom::Point3d.new
		dw = Geom::Vector3d.new
		if @ftype == langconv("Box") or @ftype == "Box"
			vts = []
			vts2 = []
			vec_d = vec_l.cross vec_w
			vec_d.length = vec_w.length
			vts[0] = point_add( pt5 , vec_w )
			vts[1] = point_add( pt5 , vec_d )
			vts[2] = point_add( pt5 , vec_w.reverse )
			vts[3] = point_add( pt5 , vec_d.reverse )
			pmesh.add_polygon vts
			vts[4] = vts[0]
			(0..3).each{|div|
				vts2[0] = vts[ div ]
				vts2[1] = vts[ div + 1]
				vts2[2] = point_add( vts[ div + 1 ] , vec_l )
				vts2[3] = point_add( vts[ div ] , vec_l )
				pmesh.add_polygon vts2
			}
			(0..3).each{|div|
				vts2[div] = point_add(  vts[ div ] , vec_l )
			}
			pmesh.add_polygon vts2
		else
		(1..divs).each{|div|
			vts = []
			if div == 1
				if @ftype == langconv("Arch") or @ftype == "Arch" #Linear|Arch|Leaf|Rectanguler
					dw = vector_scale( vec_w , Math.sqrt( 1 - div.to_f / divs.to_f ) )
				elsif @ftype == langconv("Leaf") or @ftype == "Leaf"
					fdy = ( 1.to_f - ( div.to_f + 1.to_f ) / divs.to_f * 2.to_f ).abs ** 0.5
					dw = vector_scale( vec_w , Math.sqrt( fdy ) )
				elsif @ftype == langconv("Rectanguler") or @ftype == "Rectanguler"
					dw = vec_w
				else
					dw = vector_scale( vec_w , ( 1.to_f - div.to_f / divs.to_f ) )
				end

				if @ftype == langconv("Leaf") or @ftype == "Leaf"
					pvts0 = pt5
					pvts3 = point_add( pt5 , dvec_l2 )
					vts[0] = pvts0
					vts[1] = point_add( pvts3 , dw.reverse )
					vts[2] = point_add( pvts3 , dw )
					pvts1 =  point_add( pvts3 , dw )
					pvts2 = point_add( pvts3 , dw.reverse )
					pvts0 = pvts3
					dvec_l2 = vector_add( dvec_l2 , dforce )
					dvec_l2.length = dvec_l.length
					pvts3 = point_add( pvts3 , dvec_l2 )
				else
					pvts0 = pt5
					pvts1 = point_add( pt5 , vec_w )
					pvts2 = point_add( pt5 , vec_w.reverse )
					pvts3 = point_add( pt5 , dvec_l2 )
					vts[0] = pvts1
					vts[1] = pvts2
					vts[2] = point_add( pvts3 , dw.reverse )
					vts[3] = point_add( pvts3 , dw )
					pvts1 = vts[3]
					pvts2 = vts[2]
					pvts0 = pvts3
					dvec_l2 = vector_add( dvec_l2 , dforce )
					dvec_l2.length = dvec_l.length
					pvts3 = point_add( pvts3 , dvec_l2 )
				end
			elsif div == divs
				if @ftype == langconv("Rectanguler") or @ftype == "Rectanguler"
					vts[0] = pvts1
					vts[1] = pvts2
					vts[2] = point_add( pvts3 , dw.reverse )
					vts[3] = point_add( pvts3 , dw )
				else
					vts[0] = pvts1
					vts[1] = pvts2
					vts[2] = pvts3
				end
			else
				if @ftype == langconv("Arch") or @ftype == "Arch"
					dw = vector_scale( vec_w , Math.sqrt( 1.0 - div.to_f / divs.to_f ) )
				elsif @ftype == langconv("Leaf") or @ftype == "Leaf"
					fdy = ( 1.0 - div.to_f / divs.to_f * 2.0 ).abs ** 0.5
					dw = vector_scale( vec_w , Math.sqrt( 1.to_f - fdy ) )
				elsif @ftype == langconv("Rectanguler") or @ftype == "Rectanguler"
					dw = vec_w
				else
					dw = vector_scale( vec_w , ( 1.0 - div.to_f / divs.to_f ) )
				end
					vts[0] = pvts1
					vts[1] = pvts2
					vts[2] = point_add( pvts3 , dw.reverse )
					vts[3] = point_add( pvts3 , dw )
					pvts1 = vts[3]
					pvts2 = vts[2]
					pvts0 = pvts3
					dvec_l2 = vector_add( dvec_l2 , dforce )
					dvec_l2.length = dvec_l.length
					pvts3 = point_add( pvts3 , dvec_l2 )
			end
			pmesh.add_polygon vts
		}
		end
	end

	def crowd_webdialog
		defs = Sketchup.active_model.definitions
		cdic = Sketchup.active_model.attribute_dictionary( "CROWD_DIC" , true )
		cdensity = "1"
	    csjitter = "10"
	    cstand = "yes"
	    if cdic != nil
	    	cdensity = cdic["Density"] if cdic["Density"]
	    	csjitter = cdic["SizeJitter"] if cdic["SizeJitter"]
	    	cstand = cdic["Standup"] if cdic["Standup"]
	    end
		dflist = defs.find_all{|df| df.group? == false and not df.hidden? }
		cr = "\n"

		shtm = "<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN'>
<html><head><meta http-equiv='Content-Type' content='text/html; charset=utf-8' >
"		
		thisdir = ""
		thisdir = File.dirname( __FILE__ ).gsub(/\\/,"/")
		slider_array = []
		slider_array.push ["fdensity",0.1, 20 ,0.1,"#{cdensity}".to_i ]
		slider_array.push ["fszjitter",0,100,1,"#{csjitter}".to_i ]
		
		if thisdir and thisdir != ""
			shtm = shtm + "<link rel='stylesheet' type='text/css' media='screen' href='[FUR_FOLDER_PATH]/css/le-frog/jquery-ui-1.9.2.custom.css' />
			<script type='text/javascript' src='[FUR_FOLDER_PATH]/js/jquery-1.8.3.js'></script>
			<script type='text/javascript' src='[FUR_FOLDER_PATH]/js/jquery-ui-1.9.2.custom.js'></script>
			<script type='text/javascript'>" + cr
			shtm.gsub!(/\[FUR_FOLDER_PATH\]/,thisdir)
			shtm = shtm + "$(function(){
				$('#tabs').tabs();" + cr
			slider_array.each{|sname,smin,smax,sstep,val|
				scode = "$( '#slider_#{sname}' ).slider({range: false,min:#{smin},max:#{smax},step:#{sstep},value:#{val},
					slide: function( event, ui ){
						$('##{sname}').val( ui.value );
						if( $('#preview_check')[0].checked ){ preview_crowd();}
					}
				});"
				shtm = shtm + scode + cr
			}
			shtm = shtm + "});
function change_textbox(obj){
	var v = parseFloat(obj.value);
	if( isNaN(v) == false ){
		$('#slider_' + obj.id).slider( 'option', 'value', v );
		if( $('#preview_check')[0].checked ){preview_crowd();}
	}
}" + cr
		else
			shtm = shtm + "<script type='text/javascript'>"
		end

		
		#shtm = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">' + cr
	    #shtm = shtm + '<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" >' +cr ## lang="en"
	    #shtm = shtm + "<script type='text/javascript'>"+ cr
	    shtm = shtm +"function changechk(obj){
			obj.value = obj.checked;
		}"
	 	shtm = shtm + "function checkon_all(obj) {"+ cr
		dfcnt = 0
		dflist.each{|df|
			#shtm = shtm + "    document.getElementById('chk_#{dfcnt}').checked= true;" + cr
			shtm = shtm + "   $('#chk_#{dfcnt}')[0].checked= true;" + cr
			shtm = shtm + "   $('#chk_#{dfcnt}')[0].value= 'true';" + cr
			dfcnt += 1
		}
	 	shtm = shtm + "}"+ cr
	 	shtm = shtm + "function checkoff_all(obj) {"+ cr
		dfcnt = 0
		dflist.each{|df|
			#shtm = shtm + "    document.getElementById('chk_#{dfcnt}').checked= false;" + cr
			shtm = shtm + "   $('#chk_#{dfcnt}')[0].checked= false;" + cr
			shtm = shtm + "   $('#chk_#{dfcnt}')[0].value= 'false';" + cr
			dfcnt += 1
		}
	 	shtm = shtm + "}"+ cr
	 	shtm = shtm + "function preview_crowd() {"+ cr
		#shtm = shtm + "  window.location='skp:clearcomplist'" + cr
		dfcnt = 0
		#dflist.each{|df|
			#shtm = shtm + "    var chk = document.getElementById('chk_#{dfcnt}');" + cr
			#shtm = shtm + "    var chk = $('#chk_#{dfcnt}')[0].checked;" + cr
			#shtm = shtm + "    if( chk ) { window.location='skp:addcomplist@#{dfcnt}' ; }" + cr
		#	dfcnt += 1
		#}
		shtm = shtm + "  window.location='skp:preview_crowd';"+ cr
	 	shtm = shtm + "}"+ cr

	 	shtm = shtm + "function start_crowd(obj) {"+ cr
		#shtm = shtm + "  window.location='skp:clearcomplist'" + cr
		dfcnt = 0
		#dflist.each{|df|
			#shtm = shtm + "    var chk = document.getElementById('chk_#{dfcnt}');" + cr
			#shtm = shtm + "    var chk = $('#chk_#{dfcnt}')[0].checked;" + cr
			#shtm = shtm + "    if( chk ) { window.location='skp:addcomplist@#{dfcnt}' ; }" + cr
		#	dfcnt += 1
		#}
		shtm = shtm + "  window.location='skp:start_crowd';
		}"+cr
		shtm = shtm + "
function update_complist(obj) {
  window.location='skp:update_complist';
}
--></script>
<style type='text/css'>
<!--
table.crowd{
    width:100%;
    border-top:0px;
    border-left:0px;
    border-collapse:collapse;
    border-spacing:0px;
    background-color:#f6f6f6;
    empty-cells:show;
}
.crowd td{
    border-right:1px;
    border-bottom:1px;
    padding:0.2em 0.2em;
    font-size:8pt;
    font-family: sans-serif;
    text-align: right;
}
.textbox{
color: #ffffff;
	background: #222222;
	font-size: 12px;
}
.cssButton{
	color: #ffffff;
	border-top:3px double #9cf;
	border-left:3px double #9cf;
	border-right:3px double #dfd9c3;
	border-bottom:3px double #dfd9c3;
	background: #459e00 url(../img/bg.gif) left bottom repeat-x;
	text-align: center;
	width: 150px;
	font-size: 12px;
}
.cssButton:hover{
	color: #fff;
	border-top:3px double #254A70;
	border-left:3px double #254A70;
	border-right:3px double #508AC5;
	border-bottom:3px double #508AC5;
	background: #369;
	width: 150px;
	font-size: 12px;
}
-->
</style>
</head><body bgcolor='#f6f6f6' >
<table class='crowd'><tbody>" + cr
	    cnt = 0
	    complist = []

		shtm = shtm + "<input type='checkbox' id='preview_check' value='TRUE' checked='true'>" + langconv('Preview crowd') + "<br>"+cr
	    shtm = shtm + "<input type='button' class='cssButton' name='Make crowd' value='" + langconv('Make crowd') + "' onClick='start_crowd(this)' style='font-size:12px; width:95%;'>"+cr
	    shtm = shtm + "<hr size='1'>" + cr
	    shtm = shtm + "<tr>" +cr
		
	    prp = langconv( "Density" )
	    idn = "fdensity"
	    dfl = cdensity
		shtm = shtm + "<td><p align='right';>#{exchange_quot(prp)} :</p></td><td><input type='text' class='textbox' name='#{idn}' id='#{idn}' value='#{exchange_quot(dfl)}'"
		shtm = shtm + " style='width:75px; height: 20px; font-size: 10px; text-align: left; vertical-align: middle;' onChange='change_textbox(this);'></td>"+cr
	    shtm = shtm + "</tr>" +cr
		shtm = shtm + " <tr><td colspan='2'><div id='slider_#{idn}'></div></td></tr>"

	    prp = langconv( "SizeJitter" ) + "(%)"
	    idn = "fszjitter"
	    dfl = csjitter
	    shtm = shtm + "<tr>" +cr
		shtm = shtm + "<td><p align='right';>#{exchange_quot(prp)} :</p></td><td><input type='text' class='textbox' name='#{idn}' id='#{idn}' value='#{exchange_quot(dfl)}'"
		shtm = shtm + " style='width:75px; height: 20px; font-size: 10px; text-align: left; vertical-align: middle;' onChange='change_textbox(this);'></td>"+cr
	    shtm = shtm + "</tr>" +cr
		shtm = shtm + " <tr><td colspan='2'><div id='slider_#{idn}'></div></td></tr>"

	    shtm = shtm + "<tr>" +cr
	    prp = langconv("StandUp")
	    idn = "standup"
		shtm = shtm + "<td><p align='right';>#{exchange_quot(prp)} :</p></td>"
	    shtm = shtm + "<td><select class='textbox' name='#{idn}' id='#{idn}' style='width:75px; height: 20px; font-size: 10px; text-align: left; vertical-align: middle' >" + cr
		dfl = langconv("yes")
	    shtm = shtm + "<OPTION "
	    shtm = shtm + "selected" if cstand == "yes"
	    shtm = shtm + " value='#{exchange_quot(dfl)}'>#{exchange_quot(dfl)}</OPTION>"+cr 
	    dfl = langconv("no")
	    shtm = shtm + "<OPTION "
	    shtm = shtm + "selected" if cstand == "no"
	    shtm = shtm + " value='#{exchange_quot(dfl)}'>#{exchange_quot(dfl)}</OPTION>"+cr 
	    shtm = shtm + "</select></td>"+cr
	    shtm = shtm + "</tr>" +cr
    	shtm = shtm + "</tbody></table>" + cr
	    shtm = shtm + "<hr size='1'>" + cr
	    prp = langconv( "CompList" )
	    idn = "complist"
	    shtm = shtm + "#{exchange_quot(prp)} :<BR>" + cr
		dfcnt = 0
		dflist.each{|df|
			shtm = shtm + "<INPUT type='checkbox' name='chk_#{dfcnt}' id='chk_#{dfcnt}' value='false' onChange='changechk(this)'>#{exchange_quot(df.name)}<BR>" + cr
			dfcnt += 1
		}
	    shtm = shtm + "<hr size='1'>" + cr
	    shtm = shtm + "<input type='button' class='cssButton' name='Check On ALL' value='" + langconv('Check On ALL') + "' onClick='checkon_all(this)' style='font-size:12px; width:95%;'><BR>"+cr
	    shtm = shtm + "<input type='button' class='cssButton' name='Check Off ALL' value='" + langconv('Check Off ALL') + "' onClick='checkoff_all(this)' style='font-size:12px; width:95%;'><BR>"+cr
	    shtm = shtm + "<input type='button' class='cssButton' name='Update complist' value='" + langconv('Update complist') + "' onClick='update_complist(this)' style='font-size:12px; width:95%;'><BR>"+cr
	    shtm = shtm + "</body></html>"
		title1 = langconv("crowd place setting")
		@wcdlg = UI::WebDialog.new( title1, true, "fur_crowd_dialog", 250, 400, 150, 150, true)

		shtm.gsub!(/\'/,"\"")

		#pdir = File.dirname( File.expand_path(__FILE__) ) + '/fur_en/'
		#pdir = Sketchup.find_support_file("Plugins") + '/'
		##htmlname = pdir + CROWD_DIALOG_FILE
		##savehtml htmlname , shtm

    	@fur_deflist = []
		@wcdlg.set_html(shtm)
		##@wcdlg.set_url( htmlname )
		@wcdlg.set_on_close{
			fdensity = @wcdlg.get_element_value("fdensity")
			fj = @wcdlg.get_element_value("fszjitter")
			cdic = Sketchup.active_model.attribute_dictionary( "CROWD_DIC", true )
	    	cdic["Standup"] = "yes" if @wcdlg.get_element_value("standup") == langconv("yes")
	    	cdic["Standup"] = "no" if @wcdlg.get_element_value("standup") == langconv("no")
		    cdic["Density"] = fdensity
		    cdic["SizeJitter"] = fj
		}
	    @wcdlg.add_action_callback("update_complist"){|d,p|
			@wcdlg.close
		     crowd_webdialog
	    }
	    @wcdlg.add_action_callback("clearcomplist"){|d,p|
	    	#@fur_deflist = []
		}
	    @wcdlg.add_action_callback("addcomplist"){|d,p|
			#UI.messagebox "#{p} , #{dflist[p.to_i].name}"
	    	#@fur_deflist.push dflist[p.to_i]
		}
	    @wcdlg.add_action_callback("preview_crowd"){|d,p|
			@fur_deflist = []
			dflist.each_with_index{|df,i|
				if  @wcdlg.get_element_value("chk_#{i}") == "true"
					@fur_deflist.push df
				end
			}
			start_crowd_before true
	    }
	    @wcdlg.add_action_callback("start_crowd"){|d,p|
			@fur_deflist = []
			dflist.each_with_index{|df,i|
				if  @wcdlg.get_element_value("chk_#{i}") == "true"
					@fur_deflist.push df
				end
			}
			if not @fur_deflist == []
				start_crowd_before false
			end
  	    }
        if RUBY_PLATFORM[/darwin/]
            @wcdlg.show_modal { }
        else
            @wcdlg.show { }
        end

		#@wcdlg.show

	end
	def start_crowd_before(preview = false)
		if not Sketchup.active_model.selection.find{|e| e.kind_of? Sketchup::Face }
			return
		end
		fdensity = @wcdlg.get_element_value("fdensity")
		fj = @wcdlg.get_element_value("fszjitter")

		@flength = 0.1.m
		@frootw = 0.1.m
		@fvradius = 0.0
		@maxnum = 5000
		@fwjitter = 0.0
		@fdivs = 1
		@fstrong = 10
		@fsjitter = 0
		@finstance = "fur_crowd"
		@ftype = "Arch"
		@fdensity = fdensity.to_f
		@fj = fj.to_f / 100 #---instance size jitter
		@flj = @fj * @flength.to_f
		@fljitter = Geom::Vector3d.new( @fj * @flength , @fj * @flength , @fj * @flength ) #---instance roll jitter (fdirection too large ,then this is no valid.)
		if  @wcdlg.get_element_value("standup") == langconv("yes")
			@fdirection = Geom::Vector3d.new( 0 , 0 , 100.m)
		else
			@fdirection = Geom::Vector3d.new( 0 , 0 , 0)
		end
		@fforce = Geom::Vector3d.new( 0 , 0 , 0 )
		#@fur_deflist = []
		dfcnt = 0
		if preview == false
			glowup(false)
			Sketchup.active_model.select_tool nil
		else
			@prepts = []
			glowup(true)
			Sketchup.active_model.select_tool PREVIEW_PTS.new(@prepts,false)
		end
	end
	def s_to_l( tstr1 )
		if tstr1
			tstr = tstr1.to_s.gsub(/\~ /,"")
			#return 0 if tstr.to_f == 0
			begin
				ans = tstr.to_l
				if tstr.to_l == 0
					unit = ""
					if tstr["\""]#inch
						ans = tstr.gsub("\"","").to_f.inch
					elsif tstr["'"]#feet
						ans = tstr.gsub("'","").to_f.feet
					elsif tstr["mm"]#mm
						ans = tstr.gsub("mm","").to_f.mm
					elsif tstr["cm"]
						ans = tstr.gsub("cm","").to_f.cm
					elsif tstr["m"]
						ans = tstr.gsub("m","").to_f.m
					else
						if 0.to_l.to_s["\""]
							ans = tstr.to_f.inch
						elsif 0.to_l.to_s["'"]
							ans = tstr.to_f.feet
						elsif 0.to_l.to_s["mm"]
							ans = tstr.to_f.mm
						elsif 0.to_l.to_s["cm"]
							ans = tstr.to_f.cm
						elsif 0.to_l.to_s["m"]
							ans = tstr.to_f.m
						else
							ans = tstr.to_f.inch
						end
					end
				end
			rescue
				ans = tstr.to_f.inch
			end
			return ans
		else
			return 0
		end
		return 0
	end

	def s_to_vec( xyz )
		splt = xyz.split("&&")
		if splt.size > 2
			return Geom::Vector3d.new( s_to_l(splt[0]) , s_to_l(splt[1]) , s_to_l(splt[2]) )
		elsif splt.size > 1
			return Geom::Vector3d.new( s_to_l(plt[0]) , s_to_l(splt[1]), 0 )
		else
			return Geom::Vector3d.new( 0 , 0 , s_to_l(xyz) )
		end
	end
	def pointXYZ( x , y , z)
		Geom::Point3d.new( x, y ,z )
	end
	def vectorXYZ( x , y , z)
		Geom::Vector3d.new( x, y ,z )
	end
	def point_add( vec1 , vec2 )
		Geom::Point3d.new( vec1.x.to_f + vec2.x.to_f , vec1.y.to_f + vec2.y.to_f , vec1.z.to_f + vec2.z.to_f )
	end

	def vector_add( vec1 , vec2 )
		Geom::Vector3d.new( vec1.x.to_f + vec2.x.to_f , vec1.y.to_f + vec2.y.to_f , vec1.z.to_f + vec2.z.to_f )
	end

	def vector_subtract( vec1 , vec2 )
		Geom::Vector3d.new( vec1.x.to_f - vec2.x.to_f , vec1.y.to_f - vec2.y.to_f , vec1.z.to_f - vec2.z.to_f )
	end

	def vector_scale( vec1 , tf )
		Geom::Vector3d.new( vec1.x.to_f * tf.to_f , vec1.y.to_f * tf.to_f , vec1.z.to_f * tf.to_f )
	end

	def add_menu()
		mainmenu = "fur_en"
		menuitem = langconv("fur_en") + langconv("(WebDialog)")
		menuitem_mac = langconv("fur_en") + langconv("(InputBox)")
		menuitem_crowd = langconv("crowd") + langconv("(webdialog)")
		menuitem_edit = langconv("edit preset list")
		menuitem_langchange = langconv("select language file")
		menuitem_translators = langconv("About Translators")
		mm = UI.menu("Plugins").add_submenu( mainmenu )
		mm.add_item( menuitem ) {
			Sketchup.active_model.select_tool nil
			#fur.fur_webdialog( true  )
			init_units()
			fur_webdialog( true  )
		}
		mm.add_item( menuitem_mac ) {
			Sketchup.active_model.select_tool nil
			#fur.fur_inputbox( true  )
			init_units()
			fur_inputbox( true  )
		}
		mm.add_item( menuitem_crowd ) {
			Sketchup.active_model.select_tool nil
			#fur.crowd_webdialog
			init_units()
			crowd_webdialog
		}
		mm.add_item( menuitem_edit ){
			Sketchup.active_model.select_tool nil
			init_units()
			preset_editor
		}
		mm.add_item( menuitem_langchange){
			Sketchup.active_model.select_tool nil
			select_langfile()
		}
		mm.add_item( menuitem_translators){
			Sketchup.active_model.select_tool nil
			about_translators
		}
		pdir = File.dirname( File.expand_path(__FILE__) )
		#pdir = Sketchup.find_support_file("Plugins")
		cmd_fw = UI::Command.new( menuitem ) {
			Sketchup.active_model.select_tool nil
			#fur.fur_webdialog( true  )
			init_units()
			fur_webdialog( true  )
			}
		cmd_fi = UI::Command.new( menuitem_mac ) {
			Sketchup.active_model.select_tool nil
			#fur.fur_inputbox( true  )
			init_units()
			fur_inputbox( true  )
		}
		cmd_cw = UI::Command.new( menuitem_crowd ) {
			Sketchup.active_model.select_tool nil
			#fur.crowd_webdialog
			init_units()
			crowd_webdialog
		}
		cmd_fw.large_icon = cmd_fw.small_icon = pdir + "/fur_wd24.png"
		cmd_fw.status_bar_text = cmd_fw.tooltip = "Make fur (WebDialog)"
		cmd_fi.large_icon = cmd_fi.small_icon = pdir + "/fur_ib24.png"
		cmd_fi.status_bar_text = cmd_fi.tooltip = "Make fur (Input Box)"
		cmd_cw.large_icon = cmd_cw.small_icon = pdir + "/fur_cw24.png"
		cmd_cw.status_bar_text = cmd_cw.tooltip = "Make Crowd (WebDialog)"
		fur_tb = UI::Toolbar.new("Fur_tools")
		fur_tb.add_item cmd_fw
		fur_tb.add_item cmd_fi
		fur_tb.add_item cmd_cw
		fur_tb.show if fur_tb.get_last_state != 0
	end
	def about_translators()
		translators_info ={
"1" => "Spanish translation(fur_lang_esv2.0.4.txt)
Jun 03 ,2013.
Oxer
http://sketchucation.com/forums/viewtopic.php?f=323&t=28092&start=480#p478694",
"2" => "Franch translation(fur_lang_fr.txt)
Jul 13, 2010
Daredevil
http://forums.sketchucation.com/viewtopic.php?f=323&t=28092&start=195#p247400",
"3" => "Persian translation(fur_lang_farsi.txt)
Jun 02,2013
Majid
http://forums.sketchucation.com/viewtopic.php?f=320&t=28179",
"4" => "Viet nam translation(fur_lang_vn14b.txt)
Jun 08, 2010
ktslambieng
http://forums.sketchucation.com/viewtopic.php?f=323&t=28092&start=300#p250660",
"5" =>"Portuguese-BR (Brazil) translation(fur_lang_pt 1.5a.txt)
Nov 05, 2010
Paulower
http://forums.sketchucation.com/viewtopic.php?f=323&t=28092&start=285#p249923",
"6" => "Chinese translation(fur_lang_cn.txt)
Jun 03,2013.
hebeijianke
http://sketchucation.com/forums/viewtopic.php?f=323&t=28092&start=480#p478727",
"7" => "Russian translation(fur_lang_ru.txt)

blajnov
http://forums.sketchucation.com/viewtopic.php?f=323&t=28092&start=315#p253618",
"8" => "German translation(fur_lang_de.txt)

Burkhard
http://sketchucation.com/forums/viewtopic.php?f=323&t=28092&start=300#p255389",
"9" => "Czech translation(fur_lang_cz.txt)
Jun 02,2013.
pepa
http://sketchucation.com/forums/viewtopic.php?f=323&t=28092&start=480#p478540",
"10" => "Serbian translation(fur_lang_srb.txt)
Jun 12,2013.
srx
http://sketchucation.com/forums/viewtopic.php?f=323&t=28092&start=480#p480168"
	}
		htmlcode = []
		htmlcode << '<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />'
		htmlcode << '<script type="text/javascript">'
		htmlcode << 'function openurl(utxt){'
		htmlcode << 'cmd = "skp:openurl@" + utxt;'
		htmlcode << 'window.location = cmd;}'
		htmlcode << '</script>'

		htmlcode << '</head><body><table border="1px" width="100%"><tbody>'
		htmlcode << "<tr><td>#{langconv('Thanks a lot for All Authors of Translation!!')}</td></tr>"
		htmlcode << "<tr><td>Language</td><td>Date</td><td>Auther</td><td>Link</td></tr>"
		t = 0
		translators_info.sort.each{|num,trstring|
			t += 1
			trarr = trstring.split("\n")
			htmlcode << "<tr>"
			htmlcode << "<td>" + trarr[0] + "</td>" if trarr[0]
			htmlcode << "<td>" + trarr[1] + "</td>" if trarr[1]
			htmlcode << "<td>" + trarr[2] + "</td>" if trarr[2]

			htmlcode << "<td><input type='button' name='linkbtn#{t}' value='LINK' onClick='openurl(\"" + trarr[3] + "\")' class='cssButton'>"  if trarr[3]
			htmlcode << "</tr>"
		}

		htmlcode << '</tbody></table></body></html>'

		prfkeys = { 
			:dialog_title => langconv('Thanks a lot for All Authors of Translation!!'), 
			:scrollable => true, 
			:preferences_key => 'T2H_FUR_TRANSLATORS', 
			:height => 300, 
			:width => 600, 
			:left => 150, 
			:top => 150, 
			:resizable => true, 
			:mac_only_use_nswindow => true
		} 
		bst_athr_wdlg = UI::WebDialog.new( prfkeys)
		bst_athr_wdlg.set_html( htmlcode.join("\n") )
		bst_athr_wdlg.add_action_callback("openurl"){|d,p|
			UI.openURL p
		}
		if RUBY_PLATFORM[/darwin/]
			bst_athr_wdlg.show_modal
		else
			bst_athr_wdlg.show
		end
	end
end##of class
## add a menu
#if( not file_loaded?( File.basename(__FILE__) ) )
	fur = FUR_EN.new
	
	fur.add_menu()
	
#end
def test_furmesh_by_mat()
	model = Sketchup.active_model
	ss = model.selection
	ents = model.entities
	if ss.empty? 
	  UI.messagebox( langconv("No selection.") )
	  return nil
	end
	ret_furmesh = []
	fgents = Sketchup.active_model.entities
	oocnt = 0

	fur = FUR_EN.new ####create new FUR_EN class
	ss.each{|face|
		mat = face.material
		if fur.get_furmesh_by_mat( face , mat , ret_furmesh ) != nil ###get furmesh array::ret_furmesh = [ polymesh , uv ]
			Sketchup.set_status_text "create mesh"
			ret_furmesh.each{|mesh , uv|
				if mesh != nil
					tgp = fgents.add_group
					tgents = tgp.entities
					#if @ftype == langconv("Box")
					#	tgents.fill_from_mesh( mesh , false ,0 )
					#else
						tgents.fill_from_mesh( mesh , false ,12 )
					#end
					tgp.material = mat
					oocnt += mesh.count_polygons
					Sketchup.set_status_text "Making #{oocnt} polygons"
				end
			}
		end
	}
end

end#module
##file_loaded(File.basename(__FILE__))
