=begin
#-------------------------------------------------------------------------------------------------------------------------------------------------
#*************************************************************************************************
# Copyright 2009 - Designed September 2009 by Fredo6

# Permission to use this software for any purpose and without fee is hereby granted
# Distribution of this software for commercial purpose is subject to:
#  - the expressed, written consent of the author
#  - the inclusion of the present copyright notice in all copies.

# THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#-----------------------------------------------------------------------------
# Name			:   CurviloftPalette
# Original Date	:   24 Sep 2009 - version 1.0
# Description	:   Manage the palette and contextual menus for all Curviloft tools
#-------------------------------------------------------------------------------------------------------------------------------------------------
#*************************************************************************************************
=end

module F6_Curviloft

#Constants for Palette management (do not translate)
T6[:MNU_Exit] = "Exit Tool"
T6[:MNU_LineOnly] = "Line Only"
T6[:MNU_Finish] = "Finish"
T6[:MNU_Done] = "Done and Exit (RETURN)"
T6[:MNU_Redo] = "Redo operation with %1 (Double Click)"
T6[:MNU_UndoLast] = "Undo Last input (ESC)"

T6[:TITLE_FloatPal] = "Properties of the Edited Junction"

T6[:BOX_Simplify] = "Simplify"
T6[:TIP_Simplify] = "Simplify junctions by merging liaisons"
T6[:TOG_Simplify] = "Toggle simplify junctions"
T6[:DLG_Simplify] = "Proximity for merge in %"

T6[:BOX_Interpolate] = "Interpol."
T6[:TIP_Interpolate] = "Factor for interpolating junctions"
T6[:TOG_Interpolate] = "Toggle Interpolation of junctions"
T6[:DLG_Interpolate] = "Interpolation factor"

T6[:BOX_Sample] = "Sampling"
T6[:TIP_Sample] = "Factor for oversampling rails"
T6[:TOG_Sample] = "Toggle oversampling of rails"
T6[:DLG_Sample] = "Oversampling factor"

T6[:TIP_Global_Loop] = "Close all contours into a loop"
T6[:TIP_Swap_Rail] = "Swap Rails and Profiles"

T6[:BOX_AlongMethod] = "Method"
T6[:TIP_AlongMethod] = "Method for junction of contours along the rail"
T6[:TIP_AlongMethod_Offset] = "Offset contours along the rail"
T6[:TIP_AlongMethod_Stretch] = "Stretch rail between contours"
T6[:TIP_AlongMethod_Sweep] = "Sweep rail between contours (with rotation)"

T6[:BOX_SplineMethod] = "Spline Method"
T6[:TIP_SplineMethod] = "Method for Spline junctions"
T6[:TIP_SplineMethod_Droite] = "Junction by connected lines"
T6[:TIP_SplineMethod_Bezier1] = "Bezier curves - Direct Contour to Contour (Method 1)"
T6[:TIP_SplineMethod_Bezier2] = "Bezier curves - Respect tangency (Method 2)"
T6[:TIP_SplineMethod_Orthospline] = "Junction by Orthogonal Bezier curves"
T6[:TIP_SplineMethod_Elliptic] = "Junction by Orthogonal Elliptic curves"
T6[:TIP_SplineMethod_Catmull] = "Smooth junction by a single Catmull cuve"
T6[:TIP_SplineMethod_Cubic] = "Smooth junction by a single Cubic Bezier cuve"
T6[:TIP_SplineMethod_BSpline] = "Smooth Global junction by a single B-Spline cuve"
T6[:TIP_SplineMethod_FSpline] = "Smooth Global junction by a single F-Spline cuve"

T6[:TIP_VertexMatch_Title] = "Vx Matching"
T6[:TIP_VertexMatch] = "Method for matching vertices between 2 contours"
T6[:TIP_VertexMatch_Same] = "Match Vertex to Vertex (when possible)"
T6[:TIP_VertexMatch_Linear] = "Curvi-linear vertex matching"
T6[:TIP_VertexMatch_Spline] = "Non Linear vertex matching (spline type)"
T6[:TIP_VertexMatch_Bezier] = "Non Linear vertex matching (bezier type)"
T6[:TIP_VertexMatch_Best] = "Orientate contours to their best-fit box"

T6[:TIP_Geometry] = "Options for generation of Geometry"
T6[:TIP_Geometry_Title] = "Geometry"
T6[:TIP_Geometry_LineOnly] = "Generate the junction edges (no face)"
T6[:TIP_Geometry_InterOnly] = "Generate the intermediate edges (no face)"
T6[:TIP_Geometry_MakeCurves] = "Generate the junctions as SU Curves (for interactive deformation). May take long..."
T6[:TIP_Geometry_PseudoQuads] = "Generate the surfaces with Pseudo Quads"

T6[:TIP_SplineMaster] = "Smooth mode"

T6[:BOX_Twisting] = "Twist %1°"
T6[:TIP_Twisting] = "Twist contours apart for vertex matching by a multiple of %1 degrees (%2)"
T6[:DLG_Twisting] = "Twist angle as a multiple of %1 degrees (%2)"

T6[:BOX_NumSeg] = "# Seg."
T6[:TIP_NumSeg] = "Number of segments linking in a section"
T6[:DLG_NumSeg] = "Number of segments"

T6[:BOX_NumSeg_Global] = "# Seg.G"
T6[:TIP_NumSeg_Global] = "Number of segments across All sections"
T6[:DLG_NumSeg_Global] = "Number of segments (Global spline)"

T6[:BOX_NumSeg_Ortho] = "# Seg.O"
T6[:TIP_NumSeg_Ortho] = "Number of segments in a section sections (Ortho Elliptic method)"
T6[:DLG_NumSeg_Ortho] = "Number of segments (Ortho Elliptic)"

T6[:BOX_Tension] = "Tension"
T6[:DLG_Tension] = "Tension in % (%1)"
T6[:TIP_Tension] = "Tension of Bezier curves linking two sections (%1)"

T6[:TEX_Preview] = "Preview"
T6[:TIP_Preview] = "The Preview zone allows to see the current junction in 2D or 3D"
T6[:TIP_Preview_2d] = "Preview in 2D normalized projection"
T6[:TIP_Preview_3d] = "Preview in 3D perspective"
T6[:TIP_Preview_Hide] = "Hide Preview zone"


T6[:MSG_Error] = "Error:"
				
T6[:VCB_Line] = "Plain Lines"

#--------------------------------------------------------------------------------------------------------------
# Class PaletteManager
#--------------------------------------------------------------------------------------------------------------			 				   

class PaletteManager

attr_reader :linemode

@@persistence = nil

#Managing the generic launcher
@@generic_tool = nil
@@generic_running = false
	
def PaletteManager.launch_generic(code=nil, generic=false, linemode=true)
	#Managing the generic launcher
	if generic
		@@generic_tool = 'loft' unless @@generic_tool
		code = @@generic_tool unless code
		@@generic_tool = code
		@@generic_running = true
	else
		@@generic_running = false
	end
	
	#Launching the tool
	case code
	when /loft/i
		F6_Curviloft.launch_loft
	end
end

# Initialization of the palette manager
def initialize(itself, tool_type, *args, &refresh_proc)
	@itself = itself
	@tool_type = tool_type.to_s
	@symb_curviloft_float = :curviloft_float

	@model = Sketchup.active_model
	@view = @model.active_view
	
	#parsing the arguments
	args.each do |arg|	
		arg.each { |key, value|  parse_palette_args(key, value) } if arg.class == Hash
	end
	
	@refresh_proc = refresh_proc
	@hsh_options = {}
	@lst_options.each { |opt| @hsh_options[opt] = true }
	
	@ogl = Traductor::OpenGL_6.new
end

#Assign the individual propert for the palette manager
def parse_palette_args(key, value)
	skey = key.to_s
	case skey
	when /notify_proc/i
		@notify_proc = value
	when /selmode/i
		@selmode = value
	when /linemode/i
		@linemode = value
		@linemode = true if @linemode == nil
	when /list_options/i
		@lst_options = value
	when /title/i
		@title = value
	when /refresh_proc/i
		@refresh_proc = value
	when /loft_reset_proc/i
		@loft_reset_proc = value
	when /loft_set_proc/i
		@loft_set_proc = value
	when /loft_get_proc/i
		@loft_get_proc = value
	when /hidden_float_proc/i
		@hidden_float_proc = value
		
	end	
end

#Notify the palette manager of termination (for saving parameters)
def initiate
	#Restoring the option parameters
	persistence_restore
	
	#Initialization of the palette
	init_text
	init_palette
	@itself.set_palette @palette
end

def palette
	@palette
end
	
def long_click?
	@palette.long_click? 1
end
	
def set_algo(algo)	
	@algo = algo
end

#Notify the palette manager of termination (for saving parameters)
def terminate
	persistence_save
end

#Initialize all texts
def init_text
	@mnu_exit = T6[:MNU_Exit]
	@mnu_line_only = T6[:MNU_LineOnly]
	@mnu_finish = T6[:MNU_Finish]
	@mnu_undo_last = T6[:MNU_UndoLast]
	@mnu_done = T6[:MNU_Done]
	
	@tip_simplify = T6[:TIP_Simplify]
	@tog_simplify = T6[:TOG_Simplify]
	@box_simplify = T6[:BOX_Simplify]
	@dlg_simplify = T6[:DLG_Simplify]
	
	@tip_interpolate = T6[:TIP_Interpolate]
	@tog_interpolate = T6[:TOG_Interpolate]
	@box_interpolate = T6[:BOX_Interpolate]
	@dlg_interpolate = T6[:DLG_Interpolate]

	@tip_sample = T6[:TIP_Sample]
	@tog_sample = T6[:TOG_Sample]
	@box_sample = T6[:BOX_Sample]
	@dlg_sample = T6[:DLG_Sample]
	
	@tip_global_loop = T6[:TIP_Global_Loop]
	@tip_swap_rail = T6[:TIP_Swap_Rail]

	@box_along_method = T6[:BOX_AlongMethod]
	@tip_along_method = T6[:TIP_AlongMethod]
	
	@box_spline_method = T6[:BOX_SplineMethod]
	@tip_spline_method = T6[:TIP_SplineMethod]
	
	@tip_spline_master = T6[:TIP_SplineMaster]
	
	@tip_numseg = T6[:TIP_NumSeg]
	@box_numseg = T6[:BOX_NumSeg]
	@dlg_numseg = T6[:DLG_NumSeg]
	
	@tip_numseg_global = T6[:TIP_NumSeg_Global]
	@box_numseg_global = T6[:BOX_NumSeg_Global]
	@dlg_numseg_global = T6[:DLG_NumSeg_Global]
	
	@tip_numseg_ortho = T6[:TIP_NumSeg_Ortho]
	@box_numseg_ortho = T6[:BOX_NumSeg_Ortho]
	@dlg_numseg_ortho = T6[:DLG_NumSeg_Ortho]

	@tip_tension1 = T6[:TIP_Tension, @algo.tcolor_plates[0]]
	@tip_tension2 = T6[:TIP_Tension, @algo.tcolor_plates[1]]
	@dlg_tension1 = T6[:DLG_Tension, @algo.tcolor_plates[0]]
	@dlg_tension2 = T6[:DLG_Tension, @algo.tcolor_plates[1]]
	@box_tension = T6[:BOX_Tension]
	
	@msg_error = T6[:MSG_Error] = "Error:"
	
	@vcb_line = T6[:VCB_Line]
	
end

def auto_hide_floating(on=false)
	@palette.auto_hide_floating on
end

#construct the title for the start operation label
def make_title_operation(title, flinemode=true)
	txt = title 
	txt
end

#Create the visual palette
def make_proc(&proc) ; proc ; end

def declare_fkey(symb_key, menutext, lst_names=nil, &proc)
	Traductor::FKeyOption.new(menutext, MYDEFPARAM[symb_key], lst_names, &proc)
end

#Separator for the Main and floating palette
def pal_separator ;	@palette.declare_separator ; end
def pal_separator_float ; @palette.declare_separator_floating @symb_curviloft_float ; end
def pal_separator_twin ; pal_separator ; pal_separator_float ; end

#Return the native palette object
def get_palette
	@palette
end

#Declare buttons common to the Main and to the Floating palette
def declare_twin(symb_val, symb_flag, wid, irow, hsht, hshb, hshi, color=nil, hidden_proc=nil, long_click=nil, &proc)
	height = 16
	wid = 60 unless wid
	symb = ('pal_' + symb_val.to_s).intern
	hshhidden = { :hidden_proc => hidden_proc }
	hshfloat = { :floating => @symb_curviloft_float, :row => irow }
	hshwid = hshwidt = {}
	color_proc = make_proc() { @loft_get_proc.call(1, symb_val, true) ? color : nil }
	local_proc = make_proc() { @loft_get_proc.call(1, symb_val, true)}
	grayed_proc = make_proc() { !@loft_get_proc.call(1, symb_val, true)}
	reset_proc = make_proc() { @loft_set_proc.call(1, symb_val, nil) }
	if wid
		widx = 10
		hshwid = { :height => height, :width => wid }
		hshwidt = { :height => height, :width => wid - widx }
	end	
	
	#Top button if required
	symbt = (symb.to_s + '_txt').intern
	symbtf = (symbt.to_s + '_float').intern
	symbtd = (symbt.to_s + '_def').intern
	symbtfd = (symbtf.to_s + '_def').intern
	
	hshtt = hshttf = {}
	if symb_flag
		flag_proc0 = make_proc() { @loft_get_proc.call(0, symb_flag) }
		top_proc0 = make_proc() { @loft_set_proc.call(0, symb_flag) }
		flag_proc1 = make_proc() { @loft_get_proc.call(1, symb_flag) }
		top_proc1 = make_proc() { @loft_set_proc.call(1, symb_flag) }
		hshtt = { :value_proc => flag_proc0, :action_proc => top_proc0 }
		hshttf = { :value_proc => flag_proc1, :action_proc => top_proc1 }
	end
	
	#Long click
	hshlg = {}
	hshlgf = {}
	if long_click
		lgproct = make_proc() { @loft_reset_proc.call(0, symb_flag) }
		lgproctf = make_proc() { @loft_reset_proc.call(1, symb_flag) }
		lgproc = make_proc() { @loft_reset_proc.call(0, symb_val) }
		lgprocf = make_proc() { @loft_reset_proc.call(1, symb_val) }
		hshlgt = { :long_click_proc => lgproct }
		hshlgtf = { :long_click_proc => lgproctf }
		hshlg = { :long_click_proc => lgproc }
		hshlgf = { :long_click_proc => lgprocf }
	end
	
	#Top buttons
	@palette.declare_button(symbt, hsht, hshwid, { :rank => 1 }, hshtt, hshlgt, hshhidden)
	@palette.declare_button(symbtf, hshfloat, hsht, hshwidt, { :rank => 1 }, hshttf, hshlgtf, hshhidden)
	hshdef = { :value_proc => local_proc, :grayed_proc => grayed_proc, :height => height, :width => widx, :rank => 1,  
			   :hi_color => color, :tooltip => "restore global value"}
	@palette.declare_button(symbtfd, hshfloat, hshdef, hshhidden) { reset_proc.call }
	
	#Input Fields
	if hshi
		get_proc = make_proc() { @loft_get_proc.call(0, symb_val) }
		set_proc = make_proc() { |val| transfer_numeric(val, 0, symb_val) }
		input = Traductor::InputField.new hshi, { :get_proc => get_proc, :set_proc => set_proc }
		
		get_proc = make_proc() { @loft_get_proc.call(1, symb_val) }
		set_proc = make_proc() { |val| transfer_numeric(val, 1, symb_val) }
		inputf = Traductor::InputField.new hshi, { :get_proc => get_proc, :set_proc => set_proc } 
	end
	
	#Field buttons
	symbf = (symb.to_s + '_float').intern
	@palette.declare_button(symb, hshb, hshwid, hshlg, hshhidden, { :bk_color => color, :input => input }, &proc)	
	hshs = { :bk_color => color_proc }
	@palette.declare_button(symbf, hshfloat, hshb, hshwid, hshs, hshlgf, hshhidden, { :input => inputf }, &proc)	
end

def concat_symb(symb, text)
	s = symb.to_s + '___' + text
	s.intern
end

def set_visible_families(*visi)
	@palette.visible_family *visi
end

#---------------------------------------------------------------------
# Creation of the palette
#---------------------------------------------------------------------

#Initialize the main palette and top level method
def init_palette
	hshpal = { :width_message => 250, :key_registry => :curviloft }
	@palette = Traductor::Palette.new hshpal
	@draw_local = self.method "draw_button_opengl"
	draw_blason = self.method "draw_button_blason"
	sblason = "blason_" + @tool_type.to_s
	symb_blason = sblason.intern

	#Declare floating palette
	flpal = @symb_curviloft_float
	hshfloat = { :floating => flpal, :row => 0 }
	@palette.declare_floating @symb_curviloft_float, { :title => T6[:TITLE_FloatPal], :hidden_proc => @hidden_float_proc }
	
	#Blason Button
	hsh = { :blason => true, :tooltip => @title, :draw_proc => draw_blason, :passive => true }
	@palette.declare_button(symb_blason, hsh)

	#Modifiers for Selection mode
	pal_separator
	@palette.set_current_family :selection
	@selmode.contribute_palette @palette if @selmode

	#Family for the Algo buttons
	@palette.set_current_family :algo

	#Global Loop toggle for Spline mode
	if @hsh_options[:option_global_loop]
		pal_separator
		proc = make_proc() { @algo.hprop_get :option_global_loop }
		grayed_proc = make_proc() { @algo.check_interdictions :loop }
		hsh = { :value_proc => proc, :grayed_proc => grayed_proc, :tooltip => @tip_global_loop, :draw_proc => :loop }
		@palette.declare_button(:pal_global_loop, hsh) { @loft_set_proc.call 0, :option_global_loop }
	end

	#Swap Rail and Profiles
	if @hsh_options[:swap_rail]
		pal_separator
		hshfloat = { :floating => @symb_curviloft_float, :row => 0 }
		hidden_proc = make_proc() { @algo.skinning_swap_forbidden? }
		hsh = { :tooltip => @tip_swap_rail, :draw_proc => @draw_local, :hidden_proc => hidden_proc }
		@palette.declare_button(:pal_swap_rail, hshfloat, hsh) { @algo.skinning_swap_rail }
	end

	#Spline methods
	if @hsh_options[:option_spline_method]
		pal_family_spline_method
	end

	#Along methods
	if @hsh_options[:option_along_method]
		pal_family_along_method
	end
	
	#Nb of Segments between 2 plates
	if @hsh_options[:option_numseg]
		pal_family_num_seg
		pal_family_num_seg_ortho
		pal_family_num_seg_global
	end

	#Set option: Simplify
	if @hsh_options[:option_simplify]
		pal_family_simplify
	end

	#Set option: over-sampling
	if @hsh_options[:option_sample]
		pal_separator_twin
		hshi = { :vtype => :integer, :vmin => 0, :vmax => 40, :vincr => 1, :vsprintf => "%d", :vprompt => @dlg_sample }
		hsht = { :passive => false, :text => @box_sample, :tooltip => @tog_sample }
		hshb = { :tooltip => @tip_sample }
		declare_twin(:factor_sample, :option_sample, 72, 0, hsht, hshb, hshi, 'yellow', nil, true)
	end
	
	#Set option: Interpolate
	if @hsh_options[:option_interpolate]
		pal_separator_twin
		hshi = { :vtype => :integer, :vmin => 0, :vmax => 40, :vincr => 1, :vsprintf => "%d", :vprompt => @dlg_interpolate }
		hsht = { :passive => false, :text => @box_interpolate, :tooltip => @tog_interpolate }
		hshb = { :tooltip => @tip_interpolate }
		declare_twin(:factor_interpolate, :option_interpolate, nil, 0, hsht, hshb, hshi, 'lightblue', nil, true)
	end
	
	#Tension for Bezier Loft
	if @hsh_options[:option_tension]
		pal_family_tension
	end

	#Set option: Vertex Match Method
	if @hsh_options[:option_match_method]
		pal_family_vertex_matching
	end

	#Set options for generation of geometry
	if @hsh_options[:geometry]
		pal_family_geometry
	end
	
	#Set options for twisting
	if @hsh_options[:option_twist]
		pal_separator_float
		pal_family_twist_angle 0
		pal_family_twist_angle 1
	end
	
	#Drawing zone 2D and 3D
	if @hsh_options[:draw_zone]
		pal_family_preview_zone
	end
	
	#Buttons always visible
	@palette.set_current_family
	
	#Exit tool
	pal_separator
	hsh = { :tooltip => @mnu_exit, :draw_proc => :std_exit }
	@palette.declare_button(:pal_exit, hsh) { @model.select_tool nil }
		
	#Execute
	ssb = :back
	tip_proc = make_proc() { @notify_proc.call :tip, ssb }
	grayed_proc = make_proc() { @notify_proc.call :gray, ssb }
	hsh = { :tip_proc => tip_proc, :draw_proc => :rollback, :grayed_proc => grayed_proc }
	@palette.declare_button(:pal_back, hsh) { @notify_proc.call :exec, ssb}
	
	ssv = :validate
	tip_proc = make_proc() { @notify_proc.call :tip, ssv }
	grayed_proc = make_proc() { @notify_proc.call :gray, ssv }
	hsh = { :tip_proc => tip_proc, :draw_proc => :valid, :grayed_proc => grayed_proc }
	@palette.declare_button(:pal_validate, hsh) { @notify_proc.call :exec, ssv}
	
	#Declaring side palette

end

def transfer_numeric(val, scope, prop)
	@loft_set_proc.call scope, prop, val
end

#Method to switch tool from the side palette
def switch_tool(code)
	persistence_save
	PaletteManager.launch_generic(code, @@generic_running)
end

def hsh_long_click_proc(symb)
	lgproc = make_proc() { @loft_reset_proc.call 0, symb }
	lgprocf = make_proc() { @loft_reset_proc.call 1, symb }
	hshlg = { :long_click_proc => lgproc }
	hshlgf = { :long_click_proc => lgprocf }
	[hshlg, hshlgf]
end

#--------------------------------------------------------------
# Routines for individual button families
#--------------------------------------------------------------

#Number of segments (for Slaves)
def pal_family_num_seg
	pal_separator_twin
	hidden_proc = make_proc() { @algo.spline_which_numseg? }
	hshi = { :vtype => :integer, :vmin => 1, :vmax => 99, :vincr => 5, :vsprintf => "%ds", :vprompt => @dlg_numseg }
	hsht = { :passive => true, :text => @box_numseg, :tooltip => @tip_numseg }
	hshb = { :tooltip => @tip_numseg }
	declare_twin(:num_bz, nil, 54, 0, hsht, hshb, hshi, 'lightgreen', hidden_proc, true)
end

#Number of segments (for global splines in master mode)
def pal_family_num_seg_global
	pal_separator_twin
	hidden_proc = make_proc() { @algo.spline_which_numseg? != :master }
	hshi = { :vtype => :integer, :vmin => 1, :vmax => 99, :vincr => 5, :vsprintf => "%ds", :vprompt => @dlg_numseg_global }
	hsht = { :passive => true, :text => @box_numseg_global, :tooltip => @tip_numseg_global }
	hshb = { :tooltip => @tip_numseg_global }
	declare_twin(:num_bz_global, nil, 54, 0, hsht, hshb, hshi, 'lightgreen', hidden_proc, true)
end

#Number of segments (for global splines in master mode)
def pal_family_num_seg_ortho
	pal_separator_twin
	hidden_proc = make_proc() { @algo.spline_which_numseg? != :ortho }
	hshi = { :vtype => :integer, :vmin => 1, :vmax => 99, :vincr => 5, :vsprintf => "%ds", :vprompt => @dlg_numseg_ortho }
	hsht = { :passive => true, :text => @box_numseg_ortho, :tooltip => @tip_numseg_ortho }
	hshb = { :tooltip => @tip_numseg_ortho }
	declare_twin(:num_bz_ortho, nil, 54, 0, hsht, hshb, hshi, 'lightgreen', hidden_proc, true)
end

#Simplify option
def pal_family_simplify
	pal_separator
	wid = 60
	hgt = 16
	hshw = { :width => wid, :height => hgt }
	
	symb_val = :factor_simplify
	get_proc = make_proc() { @loft_get_proc.call(0, symb_val) }
	set_proc = make_proc() { |val| transfer_numeric(val, 0, symb_val) }
	hshi = { :vtype => :percent, :vmin => 0, :vmax => 0.15, :vincr => 0.01, :vsprintf => "%d%", :vprompt => @dlg_simplify,
             :get_proc => get_proc, :set_proc => set_proc }
	input = Traductor::InputField.new hshi 
	
	symb_toggle = :option_simplify
	val_proc = make_proc() { @loft_get_proc.call(1, symb_toggle) }
	hsht = { :value_proc => val_proc, :rank => 1, :text => @box_simplify, :tooltip => @tog_simplify }
	@palette.declare_button(:pal_simplify, hshw, hsht) { @loft_set_proc.call 0, :option_simplify }
	
	hshb = { :input => input, :tooltip => @tip_simplify, :bk_color => 'beige' }
	@palette.declare_button(:pal_simplify_val, hshw, hshb)
end

#Twist Matching
def pal_family_twist_angle(iplate)
	hidden_proc = make_proc() { !@algo.morph_twisting_allowed?(iplate) }
	hshfloat = { :floating => @symb_curviloft_float, :row => 1, :height => 16, :hidden_proc => hidden_proc }
	
	symb_head = [:pal_twist_head1, :pal_twist_head2][iplate]
	symb_but = [:pal_twist_but1, :pal_twist_but2][iplate]
	symb_val = [:nb_twisting1, :nb_twisting2][iplate]
	symb_box = [:twisting_box1, :twisting_box2][iplate]
	symb_dlg = [:twisting_dlg1, :twisting_dlg2][iplate]
	symb_tip = [:twisting_tip1, :twisting_tip2][iplate]
	
	get_proc = make_proc() { @loft_get_proc.call(1, symb_val) }
	set_proc = make_proc() { |val| transfer_numeric(val, 1, symb_val) }
	dlg_proc = make_proc() { @algo.hprop_get symb_dlg, true }
	vb_proc = make_proc() { |code| @algo.vbound_twisting code, iplate }
	hshi = { :vtype => :integer, :vsprintf => "%d", :vprompt_proc => dlg_proc,
             :get_proc => get_proc, :set_proc => set_proc, :vbound_proc => vb_proc	}
	input = Traductor::InputField.new hshi 
	
	wid = 48
	tip_proc = make_proc() { @algo.hprop_get symb_tip, true }
	box_proc = make_proc() { @algo.hprop_get symb_box, true }
	hsht = { :width => wid, :passive => true, :rank => 1, :tip_proc => tip_proc, :text_proc => box_proc, :draw_proc => @draw_local }
	@palette.declare_button(symb_head, hshfloat, hsht)
	
	hshv = { :width => wid, :input => input, :tip_proc => tip_proc, :bk_color => @algo.color_plates_light[iplate] }
	@palette.declare_button(symb_but, hshfloat, hshv)	
end


#Tension for Bezier Junctions
def pal_family_tension
	pal_separator_float
	wid = 60
	hidden_proc = make_proc() { @algo.check_interdictions :tension }

	hshfloat = { :floating => @symb_curviloft_float, :row => 0, :height => 16, :width => wid, :hidden_proc => hidden_proc }
	
	tip = 
	get_proc = make_proc() { @loft_get_proc.call(1, :tension1) }
	set_proc = make_proc() { |val| transfer_numeric(val, 1, :tension1) }	
	hshi = { :vtype => :percent, :vmin => 0, :vmax => 1.5, :vincr => 0.1, :vsprintf => "%d%", :vprompt => @dlg_tension1,
            :get_proc => get_proc, :set_proc => set_proc }
	input = Traductor::InputField.new hshi 			
	hsht = { :passive => true, :text => @box_tension, :tooltip => @tip_tension1, :rank => 1 }	
	hshv = { :width => wid, :input => input, :tooltip => @tip_tension1, :bk_color => @algo.color_plates_light[0] }	
	@palette.declare_button(:pal_head_tension1, hshfloat, hsht)
	@palette.declare_button(:pal_tension1, hshfloat, hshv)
	
	get_proc = make_proc() { @loft_get_proc.call(1, :tension2) }
	set_proc = make_proc() { |val| transfer_numeric(val, 1, :tension2) }	
	hshi = { :vtype => :percent, :vmin => 0, :vmax => 1.5, :vincr => 0.1, :vsprintf => "%d%", :vprompt => @dlg_tension2,
            :get_proc => get_proc, :set_proc => set_proc }
	input = Traductor::InputField.new hshi 			
	hsht = { :passive => true, :text => @box_tension, :tooltip => @tip_tension2, :rank => 1 }	
	hshv = { :width => wid, :input => input, :tooltip => @tip_tension2, :bk_color => @algo.color_plates_light[1] }	
	@palette.declare_button(:pal_head_tension2, hshfloat, hsht)
	@palette.declare_button(:pal_tension2, hshfloat, hshv)
	
end

#Vertex matching
def pal_family_vertex_matching
	pal_separator_twin
	hshfloat = { :floating => @symb_curviloft_float, :row => 1 }
	ss = :pal_type_match
	ssf = concat_symb(ss, '_float')
	wid = 20
	#proc = make_proc() { @algo.hprop_get :type_match }
	proc = make_proc() { get_type_match }
	procf = make_proc() { get_type_match true }
	#procf = make_proc() { @algo.hprop_get :type_match, true }
	hsh = { :type => 'multi', :radio => false, :passive => true, :tooltip => T6[:TIP_VertexMatch], 
			:text => T6[:TIP_VertexMatch_Title], :default_value => '=;;B' }
	hshp = { :value_proc => proc }
	
	hidden_proc = make_proc() { @algo.no_vertex_matching? }
	hidden_procf = make_proc() { @algo.no_vertex_matching?(true) }
	hshhid = { :hidden_proc => hidden_proc }
	hshhidf = { :hidden_proc => hidden_procf }
	
	lgproc = make_proc() { reset_type_match 0 }
	lgprocf = make_proc() { reset_type_match 1 }
	hshlg = { :long_click_proc => lgproc }
	hshlgf = { :long_click_proc => lgprocf }

	@palette.declare_button(ss, hsh, hshhid, hshp, hshlg) { set_type_match 0 }
	hshp = { :value_proc => procf }
	@palette.declare_button(ssf, hsh, hshhidf, hshp, hshfloat, hshlgf) { set_type_match 1 }

	lst = [[:same, '=', :TIP_VertexMatch_Same],
		   [:linear, 'L', :TIP_VertexMatch_Linear],
		   [:cubic, '3', :TIP_VertexMatch_Spline],
		   [:bezier, 'Z', :TIP_VertexMatch_Bezier]]
	lst.push [:sepa1], [:best, 'B', :TIP_VertexMatch_Best] unless @tool_type == 'skinning'
	
	lst.each do |ll|
		if ll[1]
			ssb = concat_symb(ss, ll[0].to_s)
			ssbf = concat_symb(ssb, '_float')
			hshb = { :width => wid, :draw_proc => @draw_local, :value => ll[1], :tooltip => T6[ll[2]], :grayed_proc => ll[3] }
			hshp = { :parent => ss }
			hshpf = { :parent => ssf }
		else
			hshb = { :passive => true, :draw_proc => :separator_V, :width => 6 }
		end
		@palette.declare_button ssb, hshhid, hshp, hshb
		@palette.declare_button ssbf, hshhidf, hshpf, hshb
	end			
end

def get_type_match(scope=nil)
	case @algo.hprop_get(:type_match, scope)
	when :same
		type = '='
	when :bezier
		type = 'Z'
	when :cubic
		type = '3'
	else
		type = 'L'
	end	
	type += ';;B' if @algo.hprop_get(:option_match_best, scope)
	type
end

def set_type_match(scope=0)
	val = @palette.button_get_value
	case val
	when 'B'
		@loft_set_proc.call scope, :option_match_best
		return
	when '='
		type = :same
	when '3'
		type = :cubic
	when 'Z'
		type = :bezier
	else
		type = :linear
	end	
	@loft_set_proc.call scope, :type_match, type
end

def reset_type_match(scope=0)
	val = @palette.button_get_value
	case val
	when 'B'
		@loft_reset_proc.call 0, :option_match_best
	else
		@loft_reset_proc.call 0, :type_match
	end	
end

#Spline method
def pal_family_spline_method
	pal_separator
	ss = :pal_spline_method
	wid = 24
	proc = make_proc() { @algo.hprop_get :spline_method }
	hsh = { :type => 'multi', :radio => true, :passive => true, :tooltip => @tip_spline_method, 
			:text => @box_spline_method, :default_value => 'B', :value_proc => proc }
	@palette.declare_button(ss, hsh) { @loft_set_proc.call 0, :spline_method, @palette.button_get_value }
	
	#grayed_proc = make_proc() { @algo.grayed_master? }
	grayed_proc = make_proc() { @algo.check_interdictions :master }
	lst = [[:droite, :TIP_SplineMethod_Droite, 'orange'],
	       [:bezier1, :TIP_SplineMethod_Bezier1, 'purple'],
		   [:bezier2, :TIP_SplineMethod_Bezier2, 'green'],
		   [:sepa3],
		   [:ortho_spline, :TIP_SplineMethod_Orthospline, 'orange'],
		   [:ortho_elliptic, :TIP_SplineMethod_Elliptic, 'red'],
		   [:sepa1],
		   [:catmull, :TIP_SplineMethod_Catmull, 'green'],
		   [:cubic, :TIP_SplineMethod_Cubic, 'blue'],
		   [:sepa2],
		   [:fspline, :TIP_SplineMethod_FSpline, 'firebrick', grayed_proc],
		   [:bspline, :TIP_SplineMethod_BSpline, 'blue', grayed_proc]]
	lst.each do |ll|
		if ll[1]
			hshb = { :parent => ss, :width => wid, :draw_proc => @draw_local, :value => ll[0], 
					 :tooltip => T6[ll[1]], :frame_color => ll[2], :grayed_proc => ll[3] }
		else
			hshb = { :parent => ss, :passive => true, :draw_proc => :separator_V, :width => 6 }
		end	
		@palette.declare_button concat_symb(ss, ll[0].to_s), hshb
	end	
end

#Spline method
def pal_family_along_method
	pal_separator
	ss = :pal_along_method
	wid = 24
	proc = make_proc() { @algo.hprop_get :along_method }
	hsh = { :type => 'multi', :radio => true, :passive => true, :tooltip => @tip_along_method, 
			:text => @box_along_method, :default_value => 'B', :value_proc => proc }
	@palette.declare_button(ss, hsh) { @loft_set_proc.call 0, :along_method, @palette.button_get_value }
	
	#grayed_proc = make_proc() { @algo.grayed_master? }
	grayed_proc = make_proc() { @algo.check_interdictions :along_method }
	lst = [[:offset, :TIP_AlongMethod_Offset, 'orange'],
	       [:sweep, :TIP_AlongMethod_Sweep, 'purple'],
		   [:stretch, :TIP_AlongMethod_Stretch, 'purple']]
	lst.each do |ll|
		if ll[1]
			hshb = { :parent => ss, :width => wid, :draw_proc => @draw_local, :value => ll[0], 
					 :tooltip => T6[ll[1]], :frame_color => ll[2], :grayed_proc => ll[3] }
		else
			hshb = { :parent => ss, :passive => true, :draw_proc => :separator_V, :width => 6 }
		end	
		@palette.declare_button concat_symb(ss, ll[0].to_s), hshb
	end	
end

#Set and check the options for Geometry
def set_option_geometry(level, value)
	lopt = value.split ';;'
	v = lopt.last
	if v =~ /Q/
		lopt = [v]
	elsif v =~ /I|L|C/
		lopt = lopt.find_all { |a| a !~ /Q/ }
	end	
	@loft_set_proc.call level, :param_geometry, lopt.join(';;')
end


#Buttons for parameters of generation of geometry
def pal_family_geometry
	pal_separator_twin
	hshfloat = { :floating => @symb_curviloft_float, :row => 1 }
	ss = :pal_geometry
	ssf = concat_symb(ss, '_float')
	wid = 24
	proc = make_proc() { @algo.hprop_get :param_geometry }
	procf = make_proc() { @algo.hprop_get :param_geometry, true }
	hsh = { :type => 'multi', :passive => true, :tooltip => T6[:TIP_Geometry], :text => T6[:TIP_Geometry_Title], 
			:height => 16 }
	hshp = { :value_proc => proc }		
	hshpf = { :value_proc => procf }		
	hshlg, hshlgf = hsh_long_click_proc(:param_geometry)
	@palette.declare_button(ss, hsh, hshp, hshlg) {  set_option_geometry 0, @palette.button_get_value(ss) }
	@palette.declare_button(ssf, hsh, hshpf, hshfloat, hshlgf) { set_option_geometry 1, @palette.button_get_value(ssf) }

	hshp = { :parent => ss }
	hshpf = { :parent => ssf }
	lst = [[:option_line_only, :TIP_Geometry_LineOnly, 'L'],
		   [:option_inter_only, :TIP_Geometry_InterOnly, 'I'],
		   [:sepa10],
		   [:option_pseudoquads1, :TIP_Geometry_PseudoQuads, 'Q1'],
		   [:option_pseudoquads2, :TIP_Geometry_PseudoQuads, 'Q2'],
		   [:sepa11],
		   [:option_make_curves, :TIP_Geometry_MakeCurves, 'C']]
	lst.each do |ll|
		ssb = concat_symb(ss, ll[0].to_s)
		ssbf = concat_symb(ssb, '_float')
		if ll[1]
			hshb = { :width => wid, :value => ll[2], :draw_proc => @draw_local, :tooltip => T6[ll[1]] }
			@palette.declare_button ssb, hshp, hshb
			@palette.declare_button ssbf, hshpf, hshb
		else
			hshb = { :passive => true, :draw_proc => :separator_V, :width => 6 }
			@palette.declare_button ssb, hshp, hshb
			@palette.declare_button ssbf, hshpf, hshb			
		end	
	end			
end

#Buttons related to the Preview zone
def pal_family_preview_zone
	hshfloat = { :floating => @symb_curviloft_float, :row => 2 }
	wid = 32
	hgt = 16
	
	#header button
	pal_separator_float
	ss = :pal_preview
	value_proc = make_proc() { @algo.hprop_get(:preview_mode) }
	hsh = { :type => 'multi', :radio => true, :passive => true, :tooltip => T6[:TIP_Preview], 
			:text => T6[:TEX_Preview], :value_proc => value_proc, :default_value => 3, :height => 0}
	@palette.declare_button(ss, hshfloat, hsh) { @loft_set_proc.call 0, :preview_mode, @palette.button_get_value(:pal_preview) }

	#View mode buttons
	hshp = { :parent => :pal_preview, :height => hgt, :tab_style => true }
	
	hshb = { :width => wid, :text => '2D', :value => 2, :tooltip => T6[:TIP_Preview_2d] }
	@palette.declare_button(:pal_preview_2d, hshp, hshb)

	hshb = { :width => wid, :text => '3D', :value => 3, :tooltip => T6[:TIP_Preview_3d] }
	@palette.declare_button(:pal_preview_3d, hshp, hshb)

	grayed_proc = make_proc() { @algo.hprop_get(:preview_mode) == 0 }
	hshb = { :width => 20, :draw_proc => @draw_local, :main_color => 'blue', :value => 0,
			 :grayed_proc => grayed_proc, :tooltip => T6[:TIP_Preview_Hide] }
	@palette.declare_button(:pal_preview_close, hshp, hshb)
	
	#History Buttons
	hshb = { :width => 120, :height => hgt, :passive => true }
	@palette.declare_button(:pal_edit_history_void, hshfloat, hshb)
	
	#History buttons
	pal_separator
	grayed_proc = @algo.method 'history_gray_proc'
	tip_proc = @algo.method 'history_tip_proc'
	action_proc = make_proc() { |code| @algo.history_action_proc code }
	hshp = { :grayed_proc => grayed_proc, :tip_proc => tip_proc }
	hshh = { :compact => true }
	@palette.declare_historical(:pal_history_link, hshp, hshh) { |code| @algo.history_action_proc code }
	hshhf = { :title => nil }
	@palette.declare_historical(:pal_history_link_float, hshfloat, hshp, hshhf) { |code| @algo.history_action_proc code }
	
	#Preview Zone
	pal_separator_float
	hidden_proc = make_proc() { @algo.hprop_get(:preview_mode) == 0 }
	draw_morph_proc = self.method "draw_morphing"
	hshfloat = { :floating => @symb_curviloft_float, :row => 3 }
	vw = @view.vpwidth
	vh = @view.vpheight
	wid = 270
	hgt = 270
	ss = :pal_preview_zone
	hshb = { :passive => true, :width => wid, :height => hgt, :draw_proc => draw_morph_proc, 
			 :draw_refresh => true, :hidden_proc => hidden_proc, :tooltip => T6[:TIP_Preview] }
	@palette.declare_button ss, hshfloat, hshb	
	
end

#--------------------------------------------------------------
# Def Dialog boxes
#--------------------------------------------------------------

#--------------------------------------------------------------
# Persistence of parameters
#--------------------------------------------------------------

#Saving parameters across sessions
def persistence_save
	@@persistence = {} unless @@persistence
	type = @tool_type
	typeall = 'All'

	#Common to all tools
	@@persistence[typeall] = {} unless @@persistence[typeall]
	hsh = @@persistence[typeall]
	
	#Specific to the tool
	@@persistence[type] = {} unless @@persistence[type]
	hsh = @@persistence[type]
	
	#Parameters specific of the tool
	hsh["Linemode"] = @linemode
	
	#Save permanently
	persistence_write hsh	
end

def symb_from_letter(letter=nil)
	letter = '0' unless letter
	symb = '_Reg_' + @tool_type + letter
	symb.intern
end

#Restoring parameters across sessions
def persistence_restore
	type = @tool_type
	typeall = 'All'
	@@persistence = {} unless @@persistence
	
	#common to all tools
	hsh = @@persistence[typeall]
	unless hsh
		hsh = @@persistence[typeall] = {}
	end
	
	#Specific to the tool
	hsh = @@persistence[type]
	unless hsh
		hsh = @@persistence[type] = {}
		hsh["Linemode"] = (@linemode == nil) ? true : @linemode
		persistence_load
		hsh = @@persistence[type]
	end	
	
	@linemode = hsh["Linemode"]
end

def persistence_load(letter=nil)
	return unless MYDEFPARAM[:TOS_DEFAULT_Persistence]
	symb = symb_from_letter letter
	sval = MYDEFPARAM[symb]
	return unless sval
	begin
		hshload = eval sval
		hsh = @@persistence[@tool_type]
		hshload.each { |key, val| hsh[key] = val }
	rescue
	end
end

def persistence_write(hsh, letter=nil)
	return unless MYDEFPARAM[:TOS_DEFAULT_Persistence]
	symb = symb_from_letter(letter)
	@@persistence[symb] = hsh.clone
	if MYDEFPARAM[symb] != hsh.inspect
		MYDEFPARAM[symb] = hsh.inspect
		MYDEFPARAM.save_to_file
	end
end

#--------------------------------------------------------------
# Contextual menu and short cuts
#--------------------------------------------------------------

def contextual_menu(cxmenu)

end

#display information in the Sketchup status bar
def info_show(message, hsh_param)
	msgtit = @title

	msgopt = ""
	if @palette.shrinked
	end
	
	Sketchup.set_status_text msgtit + message + msgopt 
	
	#Scanning the values
	hsh_param = {} unless hsh_param
	
	length = hsh_param['length']
	slen = Sketchup.format_length(length) if length

	offset = hsh_param['offset']
	soffset = Sketchup.format_length(offset) if offset

	angle = hsh_param['angle']
	sangle = sprintf("%3.1f ", angle.radians) + "°" if angle
	
	nbseg = hsh_param['nbseg']
	snbseg = @vcb_edges + "=" + nbseg.to_s if nbseg
	
	precision = hsh_param['precision']
	sprecision = "px=" + precision.to_s if precision
			
	#Compute the label and VCB displayed value
	if nbseg && precision
		label = @vcb_edges
		txval = snbseg + ' ' + sprecision
		tip = @vcb_edges + " = " + nbseg.to_s + '   ' + @vcb_pixel + " = " + precision.to_s
	elsif nbseg 
		label = @vcb_edges
		txval = snbseg
		tip = @vcb_edges + " = " + nbseg.to_s
	elsif length && angle
		label = @vcb_lengangle
		txval = slen + ", " + sangle
		tip = @vcb_length + " = " + slen + "  " + @vcb_angle + " = " + sangle
	elsif length
		label = @vcb_length
		txval = slen
		tip = @vcb_length + " = " + slen 
	elsif offset
		label = @vcb_offset
		txval = soffset
		tip = @vcb_offset + " = " + soffset 
	elsif angle
		label = @vcb_angle
		txval = sangle
		tip = @vcb_angle + " = " + sangle
	else
		label = nil
		tip = ""
	end

	#Transfering text to VCB
	dlabel = hsh_param['label'] 
	label = dlabel if dlabel 
	if label
		Sketchup.set_status_text label, SB_VCB_LABEL
		Sketchup.set_status_text txval, SB_VCB_VALUE
	end	
	
	#Updating the palette information area
	splus = hsh_param['msg_comp']
	splus = (splus) ? "  --  " + splus : ""
	@palette.set_tooltip @title + splus + "\n" + tip	
end

#Set an error
def set_error(message=nil)
	message = @msg_error + ' ' + message if message
	@palette.set_message message, 'E'
	#@view.invalidate
end

#Set an error
def set_message(message=nil, code='I')
	message = message if message
	@palette.set_message message, code
	#@view.invalidate
end

#Set an error
def set_tooltip(tooltip=nil, level=nil)
	@palette.set_tooltip tooltip, level
end
	
#--------------------------------------------------------------
# Draw morphing zone
#--------------------------------------------------------------

def draw_morphing(symb, dx, dy)
	lst_gl = []
	color = 'silver'
	
	pts = []
	pts.push Geom::Point3d.new(0, 0, 0)
	pts.push Geom::Point3d.new(dx, 0, 0)
	pts.push Geom::Point3d.new(dx, dy, 0)
	pts.push Geom::Point3d.new(0, dy, 0)
	lst_gl.push [GL_LINE_LOOP, pts, color, 1, '']
	
	pts = []
	pts.push Geom::Point3d.new(dx/2, 0, 0)
	pts.push Geom::Point3d.new(dx/2, dy, 0)
	lst_gl.push [GL_LINE_STRIP, pts, color, 1, '-']

	pts = []
	pts.push Geom::Point3d.new(0, dy/2, 0)
	pts.push Geom::Point3d.new(dx, dy/2, 0)
	lst_gl.push [GL_LINE_STRIP, pts, color, 1, '-']
	
	@algo.morph_draw lst_gl, dx, dy
	
	lst_gl
end
#--------------------------------------------------------------
# Custom drawing for palette buttons
#--------------------------------------------------------------

#Custom drawing of buttons
def draw_button_opengl(symb, dx, dy, main_color, frame_color)
	code = symb.to_s
	lst_gl = []
	xmid = dx / 2
	ymid = dy / 2
	grayed = @palette.button_is_grayed?(symb)
	color = (grayed) ? 'gray' : frame_color
	
	case code
	
	when /pal_preview_close/
		pts = G6.pts_triangle xmid, ymid+1, 4
		color = (@algo.hprop_get(:preview_mode) == 0) ? 'gray' : 'blue'
		lst_gl.push [GL_TRIANGLES, pts, color]

	#Along Method	
	when /pal_along_method(.*)/i
		dy2 = dy / 2
		dy4 = dy / 4
		dy3 = dy / 3
		dx2 = dx / 2
		dx5 = dx / 5
		dx3 = dx / 3
		case $1
		when /offset/
			pts = []
			pts.push Geom::Point3d.new(3, 1, 0)
			pts.push Geom::Point3d.new(3, dy-1, 0)
			lst_gl.push [GL_LINE_STRIP, pts, 'blue', 2, '']

			pts = []
			pts.push Geom::Point3d.new(dx-3, 1, 0)
			pts.push Geom::Point3d.new(dx-3, dy-1, 0)
			lst_gl.push [GL_LINE_STRIP, pts, 'red', 2, '']

			pts = []
			pts.push Geom::Point3d.new(5, dy2, 0)
			pts.push Geom::Point3d.new(dx2+3, dy2, 0)
			lst_gl.push [GL_LINE_STRIP, pts, 'green', 2, '']
			
			pts = G6.pts_triangle(dx2+3, dy2, 3, X_AXIS)
			lst_gl.push [GL_TRIANGLES, pts, 'green']

		when /stretch/
			pts = G6.pts_triangle(6, 4, 5, Y_AXIS.reverse)
			lst_gl.push [GL_TRIANGLES, pts, 'green']
			pts = G6.pts_triangle(dx-3, dy-3, 5, Y_AXIS)
			lst_gl.push [GL_TRIANGLES, pts, 'green']

		when /sweep/
			dec = 2
			pts = []
			pts.push Geom::Point3d.new(dec, 0, 0)
			pts.push Geom::Point3d.new(dx-dec, 0, 0)
			lst_gl.push [GL_LINE_STRIP, pts, 'blue', 2, '']
			pts = []
			pts.push Geom::Point3d.new(dec, dy, 0)
			pts.push Geom::Point3d.new(dx-dec, dy, 0)
			lst_gl.push [GL_LINE_STRIP, pts, 'blue', 2, '']
			pts = []
			pts.push Geom::Point3d.new(dec, 0, 0)
			pts.push Geom::Point3d.new(dec+5, dy2, 0)
			pts.push Geom::Point3d.new(dec, dy, 0)
			lst_gl.push [GL_LINE_STRIP, pts, 'red', 2, '']
			pts = []
			pts.push Geom::Point3d.new(dx-dec-1, 0, 0)
			pts.push Geom::Point3d.new(dx-dec-6, dy2, 0)
			pts.push Geom::Point3d.new(dx-dec-1, dy, 0)
			lst_gl.push [GL_LINE_STRIP, pts, 'red', 2, '']
		end	
		
	#Spline Method	
	when /pal_spline_method(.*)/i
		dy2 = dy / 2
		dy4 = dy / 4
		dy3 = dy / 3
		dx2 = dx / 2
		dx5 = dx / 5
		dx3 = dx / 3
		case $1
		when /droite/
			pts = []
			pts.push Geom::Point3d.new(1, ymid, 0)
			pts.push Geom::Point3d.new(dx-1, ymid, 0)
			lst_gl.push [GL_LINE_STRIP, pts, color, 2, '']

		when /elliptic/
			pts = G6.pts_circle 1, 1, dy-2, 20
			pts = pts[0..5]
			lst_gl.push [GL_LINE_STRIP, pts, color, 2, '']

		when /ortho_spline/
			pts = []
			pts.push Geom::Point3d.new(1, dy-2, 0)
			pts.push Geom::Point3d.new(dx-1, dy-2, 0)
			pts.push Geom::Point3d.new(dx2, 1, 0)
			pts = G6::BezierCurve.compute(pts, 8)
			lst_gl.push [GL_LINE_STRIP, pts, color, 2, '']

		when /bezier2/
			pts1 = []
			pts1.push Geom::Point3d.new(0, 0, 0)
			pts1.push Geom::Point3d.new(dx5, dy4, 0)
			pts1.push Geom::Point3d.new(dx2, dy2, 0)
			pts2 = []
			pts2.push Geom::Point3d.new(dx2+1, dy2, 0)
			pts2.push Geom::Point3d.new(4*dx5, dy2+dy4, 0)
			pts2.push Geom::Point3d.new(dx, dy, 0)
			lst_gl.push [GL_LINE_STRIP, pts1, color, 2, '']
			lst_gl.push [GL_LINE_STRIP, pts2, color, 2, '']
			pts3 = G6.pts_square dx2, dy2, 2
			lst_gl.push [GL_QUADS, pts3, color]
			pts = []
			pts.push Geom::Point3d.new(0, 0, 0)
			pts.push Geom::Point3d.new(2, dy-4, 0)
			lst_gl.push [GL_LINE_STRIP, pts, 'red', 2, '']
			pts = []
			pts.push Geom::Point3d.new(dx, dy, 0)
			pts.push Geom::Point3d.new(dx-2, 4, 0)
			lst_gl.push [GL_LINE_STRIP, pts, 'red', 2, '']
		
		when /bezier(\d)/
			pts1 = []
			pts1.push Geom::Point3d.new(0, 0, 0)
			pts1.push Geom::Point3d.new(dx5, dy4, 0)
			pts1.push Geom::Point3d.new(dx2, dy2, 0)
			pts2 = []
			pts2.push Geom::Point3d.new(dx2+1, dy2, 0)
			pts2.push Geom::Point3d.new(4*dx5, dy2+dy4, 0)
			pts2.push Geom::Point3d.new(dx, dy, 0)
			lst_gl.push [GL_LINE_STRIP, pts1, color, 2, '']
			lst_gl.push [GL_LINE_STRIP, pts2, color, 2, '']
			pts3 = G6.pts_square dx2, dy2, 2
			lst_gl.push [GL_QUADS, pts3, color]
			lst_gl += @ogl.digit_instructions($1, dx, 0, color, 1)
		
		when /catmull/, /cubic/
			pts = G6.pts_circle dx2, 2, dx2-2, 8
			lst_gl.push [GL_LINE_STRIP, pts[6..7] + pts[0..2], color, 2, '']
			color = (grayed) ? 'gray' : 'red'
			pts = G6.pts_square 2, 2, 1
			lst_gl.push [GL_QUADS, pts, color]
			pts = G6.pts_square dx2, 2 * dy3+1, 1
			lst_gl.push [GL_QUADS, pts, color]
			pts = G6.pts_square dx-2, 2, 1
			lst_gl.push [GL_QUADS, pts, color]

		when /spline/
			opengl_draw_spline lst_gl, dx, dy, color, grayed
		end
		
	#Vertex Matching	
	when /pal_type_match(.*)/i
		dy2 = dy / 2
		dy4 = dy / 4
		dy3 = dy / 3
		dx2 = dx / 2
		dx5 = dx / 5
		dx3 = dx / 3
		color = 'purple'
		case $1
		when /same/
			pts = []
			pts.push Geom::Point3d.new(3, dy4+1, 0)
			pts.push Geom::Point3d.new(dx-2, dy4+1, 0)
			pts.push Geom::Point3d.new(3, dy2+dy4-1, 0)
			pts.push Geom::Point3d.new(dx-2, dy2+dy4-1, 0)
			lst_gl.push [GL_LINES, pts, color, 2, '']
		when /linear/
			pts = []
			pts.push Geom::Point3d.new(1, 1, 0)
			pts.push Geom::Point3d.new(dx-1, dy-1, 0)
			lst_gl.push [GL_LINE_STRIP, pts, color, 2, '']
		when /cubic/
			opengl_draw_spline lst_gl, dx, dy, color, true
		when /bezier/
			pts = G6.pts_circle dx2, 2, dx2, 8
			lst_gl.push [GL_LINE_STRIP, pts[6..7] + pts[0..2], color, 2, '']
		when /best/
			pts = G6.pts_square dx2+1, dy2, 5
			lst_gl.push [GL_LINE_LOOP, pts, 'red', 1, '']
			pts = G6.pts_square dx2+1, dy2, 3
			lst_gl.push [GL_LINE_LOOP, pts, 'blue', 1, '']
		end

	when /pal_twist.*(\d)/
		decx = 8
		pts = []
		pts.push Geom::Point3d.new(0, 0, 0)
		pts.push Geom::Point3d.new(decx, 0, 0)
		pts.push Geom::Point3d.new(0, dy, 0)
		pts.push Geom::Point3d.new(decx, dy, 0)
		color = ($1 == '1') ? @algo.tcolor_plates[0] : @algo.tcolor_plates[1]
		lst_gl.push [GL_LINE_LOOP, pts, color, 1, '']	
	
	#Swap plates and Rails
	when /pal_swap/
		dx2 = dx / 2
		dy2 = dy / 2
		decx = 10
		dd = 5
		pts1 = []
		pts1.push Geom::Point3d.new(0, 0, 0)
		pts1.push Geom::Point3d.new(dx-dd, 0, 0)
		pts2 = []
		pts2.push Geom::Point3d.new(dd, dy, 0)
		pts2.push Geom::Point3d.new(dx, dy, 0)
		lst_gl.push [GL_LINE_STRIP, [pts1[0], pts2[0]], 'red', 2, '-']
		lst_gl.push [GL_LINE_STRIP, [pts1[1], pts2[1]], 'red', 2, '-']
		lst_gl.push [GL_LINE_STRIP, pts1, 'blue', 2, '']
		lst_gl.push [GL_LINE_STRIP, pts2, 'blue', 2, '']
		
	#Parameters for Geometry generation
	when /pal_geometry(.*)/
		dx2 = dx / 2
		dy2 = dy / 2
		dx4 = dx / 4
		dy4 = dy / 4
		dx3 = dx / 3
		dy3 = dy / 3
		code_geom = $1
		case code_geom
		when /make_curves/
			dec = 2
			pts = []
			pts.push Geom::Point3d.new(1, dy2, 0)
			pts.push Geom::Point3d.new(dx-1, dy2, 0)
			lst_gl.push [GL_LINE_STRIP, pts, 'blue', 2, '']
			pts = []
			pts.push Geom::Point3d.new(dx4, dec, 0)
			pts.push Geom::Point3d.new(dx4, dy-dec, 0)
			pts.push Geom::Point3d.new(dx2, dec, 0)
			pts.push Geom::Point3d.new(dx2, dy-dec, 0)
			pts.push Geom::Point3d.new(dx2+dx4, dec, 0)
			pts.push Geom::Point3d.new(dx2+dx4, dy-dec, 0)
			lst_gl.push [GL_LINES, pts, 'black', 1, '']

		when /quads(\d)/
			dec = 2
			pts = []
			pts.push Geom::Point3d.new(1, 1, 0)
			pts.push Geom::Point3d.new(dx-1, 1, 0)
			pts.push Geom::Point3d.new(dx-1, dy-1, 0)
			pts.push Geom::Point3d.new(1, dy-1, 0)
			lst_gl.push [GL_LINE_LOOP, pts, 'black', 1, '']
			if $1 == '1'
				lst_gl.push [GL_LINE_STRIP, [pts[1], pts[3]], 'black', 1, '-']
			else	
				lst_gl.push [GL_LINE_STRIP, [pts[0], pts[2]], 'black', 1, '-']
			end
			
		else
			pts = []
			pts.push Geom::Point3d.new(1, 1, 0)
			pts.push Geom::Point3d.new(dx-1, 1, 0)
			lst_gl.push [GL_LINE_STRIP, pts, 'blue', 1, '']

			pts = []
			pts.push Geom::Point3d.new(1, dy-1, 0)
			pts.push Geom::Point3d.new(dx-1, dy-1, 0)
			lst_gl.push [GL_LINE_STRIP, pts, 'red', 1, '']

			if code_geom =~ /line_only/i
				[0, dx4, dx2, dx-dx4, dx].each do |x|
					pts = []
					pts.push Geom::Point3d.new(x, 1, 0)
					pts.push Geom::Point3d.new(x, dy-1, 0)
					lst_gl.push [GL_LINE_STRIP, pts, 'black', 1, '']
				end
			end	
				
			if code_geom =~ /inter_only/i
				[dy4, dy2, dy-dy4].each do |y|
					pts = []
					pts.push Geom::Point3d.new(1, y, 0)
					pts.push Geom::Point3d.new(dx-1, y, 0)
					lst_gl.push [GL_LINE_STRIP, pts, 'black', 1, '']
				end
			end	
			
		end
	end
	lst_gl
end

#Draw a small spline curve for palette
def opengl_draw_spline(lst_gl, dx, dy, color, nosquare=false)
	dy2 = dy / 2
	dy4 = dy / 4
	dx2 = dx / 2
	pts = []
	pts.push Geom::Point3d.new(1, 1, 0)
	pts.push Geom::Point3d.new(dx2-1, dy4, 0)
	pts.push Geom::Point3d.new(dx2+1, dy2+dy4, 0)
	pts.push Geom::Point3d.new(dx-1, dy-1, 0)
	lst_gl.push [GL_LINE_STRIP, pts, color, 2, '']
	unless nosquare
		pts = G6.pts_square dx2+2, dy4, 1
		lst_gl.push [GL_QUADS, pts, 'green']
		pts = G6.pts_square dx2-2, dy2+dy4, 1
		lst_gl.push [GL_QUADS, pts, 'green']
		pts = G6.pts_square 2, 2, 1
		lst_gl.push [GL_QUADS, pts, 'red']
		pts = G6.pts_square dx-2, dy-2, 1
		lst_gl.push [GL_QUADS, pts, 'red']	
	end	
	lst_gl
end

#Compute the points of a square centered at x, y with side 2 * dim
def pts_square(x, y, dim)
	pts = []
	pts.push Geom::Point3d.new(x-dim, y-dim)
	pts.push Geom::Point3d.new(x+dim, y-dim)
	pts.push Geom::Point3d.new(x+dim, y+dim)
	pts.push Geom::Point3d.new(x-dim, y+dim)
	pts
end

#Compute the points of a circle centered at x, y with radius
def pts_circle(x, y, radius, n=12)
	pts = []
	angle = Math::PI * 2 / n
	for i in 0..n
		a = angle * i
		pts.push Geom::Point3d.new(x + radius * Math.sin(a), y + radius * Math.cos(a))
	end	
	pts
end

#Custom drawing of buttons for tools
def draw_button_blason(symb, dx, dy)
	code = symb.to_s
	lst_gl = []
	xmid = dx / 2
	
	case code

	#Loft by Spline
	when /loft/i
		dx3 = dx / 3
		dy3 = dy / 3
		pts = G6.pts_circle(2 * dx3, 2 * dy3, dx3-2, 8)
		lst_gl.push [GL_POLYGON, pts, 'red']
		lst_gl.push [GL_LINE_LOOP, pts, 'blue', 1, '']
		
		pts = G6.pts_square(dx3+2, dy3+2, dx/5)
		lst_gl.push [GL_POLYGON, pts, 'green']
		lst_gl.push [GL_LINE_LOOP, pts, 'blue', 1, '']

	#Loft Along Path
	when /along/i
		dx3 = dx / 3
		dy3 = dy / 3
		pts = G6.pts_circle(dx3, dy3, dx/5, 6)
		lst_gl.push [GL_POLYGON, pts, 'purple']
		lst_gl.push [GL_LINE_LOOP, pts, 'blue', 1, '']
		
		pts = G6.pts_square(dx-dx3, 2 * dy3, dx/6)
		lst_gl.push [GL_POLYGON, pts, 'green']
		lst_gl.push [GL_LINE_LOOP, pts, 'blue', 1, '']
		
		dd = dx3
		pts = []
		pts.push Geom::Point3d.new(dx3, dx3)
		pts.push Geom::Point3d.new(dx3, dy-dx3)
		pts.push Geom::Point3d.new(2*dx3, dy-dx3)
		lst_gl.push [GL_LINE_STRIP, pts, 'red', 2, '']

	#Skinning
	when /skin/i
		dx3 = dx / 3
		dy3 = dy / 3
		dx2 = dx / 2
		dy2 = dy / 2
		pts = G6.pts_circle(dx2, dy2+3, dx2-3, 8)
		pts.each { |pt| pt.y *= 0.5 }
		lst_gl.push [GL_LINE_LOOP, pts, 'blue', 1, '']

		pts = []
		pts.push Geom::Point3d.new(3, 8)
		pts.push Geom::Point3d.new(dx2-4, dy-6)
		pts.push Geom::Point3d.new(dx2+3, dy-2)
		pts.push Geom::Point3d.new(dx-2, 8)
		lst_gl.push [GL_LINE_STRIP, pts, 'blue', 1, '']

		pts = []
		pts.push Geom::Point3d.new(dx2-4, dy-6)
		pts.push Geom::Point3d.new(dx2+3, 4)
		lst_gl.push [GL_LINE_STRIP, pts, 'blue', 1, '']
		
	end
	
	lst_gl
end

end	#End Class PaletteManager

end	#End Module F6_Curviloft
