=begin
#-------------------------------------------------------------------------------------------------------------------------------------------------
#*************************************************************************************************
# Designed July 2013 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			:   JointPushPullPalette.rb
# Original Date	:   15 Jul 2013
# Description	:   JointPushPull Button Palette
#-------------------------------------------------------------------------------------------------------------------------------------------------
#*************************************************************************************************
=end

module F6_JointPushPull

T6[:TIP_DragToPushPull] = "or Click and Drag (or long click) to Push Pull"
T6[:TIP_DragReselect] = "Click, Release, Drag (or Click and Drag) to Push Pull"

T6[:BOX_OptionFinishing] = "Finishing"
T6[:TIP_OptionFinishing] = "Option for Finishing push-pull"
T6[:TIP_OptionFinishingThicken] = "THICKEN: Keep original face and reverse if necessary"
T6[:TIP_OptionFinishingPush] = "PUSH-PULL: Erase original face (classic push pull)"

T6[:BOX_OptionBorders] = "Borders"
T6[:TIP_OptionBorders] = "Options for generating borders"
T6[:TIP_OptionBordersGrid] = "GRID: Individual borders for each face"
T6[:TIP_OptionBordersContour] = "CONTOUR: borders only at Contours"
T6[:TIP_OptionBordersNone] = "NONE: NO borders"

T6[:TIP_MiscTitle] = "Miscellaneous Options"
T6[:TIP_MiscGenGroup] = "Generate as a Group"
T6[:TIP_NeighbourInfluence] = "Outside neighbour faces influences directions at border"
T6[:TIP_ExtrudeFlat] = "Flatten the top faces of the extruded shape"
T6[:TIP_VectorProjected] = "Project the shape on a plane"

T6[:TIP_ReleaseToGeom] = "Release to generate geometry"
T6[:TIP_ClickReleaseToGeom] = "Click/Release to generate geometry"
T6[:TIP_ReleaseToPreview] = "Release to go to Preview mode"
T6[:TIP_ClickReleaseToPreview] = "Click/Release to go to Preview mode"
T6[:TIP_ValidateToGeometry] = "Click (or press RETURN) to Generate Geometry"
T6[:TIP_ClickExit] = "Click (or press RETURN) to Exit"

T6[:BOX_Offset] = "Offset"
T6[:TIP_Offset] = "Offset in current units"
T6[:PROMPT_Offset] = "Offset value (positive or negative)"

T6[:BOX_AngleRound] = "Joint Angle"
T6[:TIP_AngleRound] = "Minimum Angle for which faces are connected by a rounding (versus joined) "
T6[:PROMPT_AngleRound] = "Minimum Angle for Rounding "

T6[:BOX_SegmentRound] = "#seg 90°"
T6[:TIP_SegmentRound] = "Number of segments for rounding (base 90 degrees) "

T6[:BOX_Random] = "Random"
T6[:TIP_RandomTitle] = "Set random push-pull based on Min and Max scaling factors"
T6[:TIP_RandomMax] = "Random Maximum scaling factor"
T6[:TIP_RandomMin] = "Random Minimum scaling factor"
T6[:TIP_RandomPlus] = "Go to Next Random pattern"
T6[:TIP_RandomMinus] = "Go to Previous Random pattern"

T6[:TIP_NormalCoquad] = "Keep triangles jointed when forming a PseudoQuad"

T6[:BOX_RadialScaling] = "Tapering"
T6[:TIP_RadialScalingNormal] = "Tapering ratio for individual faces"
T6[:TIP_RadialScalingExtrude] = "Tapering ratio for extruded group of faces"
T6[:TIP_RadialScalingVCB] = "type value followed by s in VCB"

#=============================================================================================
#=============================================================================================
# Class JointPushPullTool: main class for the Interactive tool
#=============================================================================================
#=============================================================================================

class JointPushPullTool < Traductor::PaletteSuperTool

#--------------------------------------------------------------
#--------------------------------------------------------------
# Palette Management
#--------------------------------------------------------------
#--------------------------------------------------------------

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

#PALETTE: Separator for the Main and floating palette
def pal_separator ;	@palette.declare_separator ; end

#PALETTE: Initialize the main palette and top level method
def init_palette
	hshpal = { :width_message => 200, :width_message_min => 150, :key_registry => :jointpushpull }
	@palette = Traductor::Palette.new hshpal
	notify_proc = self.method 'notify_from_palette'
	@draw_local = self.method "draw_button_opengl"
	@blason_proc = self.method "draw_button_blason"
	@symb_blason = :blason
	@bk_color_tool = "lemonchiffon"
	@info_text1 = ""
	@info_text2 = ""
	@info_message = ""
		
	#Blason Button
	tip = "JointPushPull" + ' ' + T6[:T_STR_DefaultParamDialog]
	hsh = { :blason => true, :draw_proc => @blason_proc, :tooltip => tip }
	@palette.declare_button(@symb_blason, hsh) { MYPLUGIN.invoke_default_parameter_dialog }
	
	#Modifiers for Selection mode
	@palette.set_current_family
	pal_separator
	grayed_proc = proc { @mode != :selection || @dirman.ask_mode? }
	hsh = { :bk_color => 'thistle', :grayed_proc => grayed_proc }
	@facepicker.palette_contribution @palette, hsh
	
	#Palette for offset
	palette_offset
	
	#Subpalette for planar selection
	pal_separator
	hsh = { :bk_color => 'thistle', :grayed_proc => grayed_proc }
	@dirman.palette_contribution @palette, hsh
	
	#Subpalette for Options
	palette_finishing
	palette_borders
	palette_misc_options
	palette_angle_round
	palette_segment_round
	palette_radial_scaling
	palette_random
	
	#Abort and Exit
	@palette.set_current_family
	pal_separator
	hsh = { :draw_proc => :std_abortexit, :main_color => 'red', :frame_color => 'green', 
	        :tooltip => T6[:T_STR_AbortTool] }
	@palette.declare_button(:pal_abort, hsh) { abort_tool }

	#Rollback
	@palette.set_current_family
	tip_proc = proc { notify_proc.call :tip, :back }
	grayed_proc = proc { notify_proc.call(:gray, :back) || @dirman.ask_mode? }
	hsh = { :tip_proc => tip_proc, :draw_proc => :rollback, :grayed_proc => grayed_proc }
	@palette.declare_button(:pal_back, hsh) { notify_proc.call :exec, :back }

	#Execute
	@palette.set_current_family
	tip_proc = proc { notify_proc.call :tip, :validate }
	grayed_proc = proc { notify_proc.call(:gray, :validate) || @dirman.ask_mode? }
	hsh = { :tip_proc => tip_proc, :draw_proc => :valid, :grayed_proc => grayed_proc }
	@palette.declare_button(:pal_validate, hsh) { notify_proc.call :exec, :validate }
	
	#Exit tool
	@palette.set_current_family
	grayed_proc = proc { @mode != :selection || !@geometry_generated || @dirman.ask_mode? }
	hsh = { :draw_proc => :std_exit, :tooltip => T6[:T_STR_ExitTool], :grayed_proc => grayed_proc }
	@palette.declare_button(:pal_exit, hsh) { exit_tool }
		
	#Associating the palette
	set_palette @palette
end

#PALETTE: Miscellaneous options
def palette_misc_options
	pal_separator
	
	#Title bandeau
	nbut = 1
	wbut = 24
	
	symb_master = :pal_misc_bandeau
	hsh = { :type => 'multi_free', :passive => true, :draw_proc => @draw_local, :bk_color => @pal_bk_color,
	        :height => 8, :tooltip => T6[:TIP_MiscTitle] }
	@palette.declare_button(symb_master, hsh)
	hshp = { :parent => symb_master, :height => 24, :width => wbut, :hi_color => @pal_hi_color }
	
	#Generate in group
	vproc = proc { option_get :gen_group }
	hsh = { :value_proc => vproc, :draw_proc => :std_group, :tooltip => T6[:TIP_MiscGenGroup], :main_color => 'darkred' }
	@palette.declare_button(:pal_gen_group, hshp, hsh) { modify_option_gen_group }	
	
	#Neighbour influence (Joint mode)
	hidden_proc = proc { @jpp_mode != :joint }
	vproc = proc { option_get :neighbour_influence }
	hsh = { :value_proc => vproc, :hidden_proc => hidden_proc, :draw_proc => @draw_local,
            :tooltip => T6[:TIP_NeighbourInfluence], :hi_color => @pal_hi_color }
	@palette.declare_button(:pal_neighbour_influence, hshp, hsh) { option_toggle :neighbour_influence, :vertices }	

	#Extrude Flat (Extrude mode)
	hidden_proc = proc { @jpp_mode != :extrude }
	vproc = proc { option_get :extrude_flat }
	hsh = { :value_proc => vproc, :hidden_proc => hidden_proc, :draw_proc => @draw_local,
            :tooltip => T6[:TIP_ExtrudeFlat], :hi_color => @pal_hi_color }
	@palette.declare_button(:pal_extrude_flat, hshp, hsh) { option_toggle :extrude_flat }

	#Vector Projected (Vector mode)
	hidden_proc = proc { @jpp_mode != :vector }
	vproc = proc { option_get :vector_projected }
	hsh = { :value_proc => vproc, :hidden_proc => hidden_proc, :draw_proc => @draw_local,
            :tooltip => T6[:TIP_VectorProjected], :hi_color => @pal_hi_color }
	@palette.declare_button(:pal_vector_projected, hshp, hsh) { option_toggle :vector_projected }

	#Normal Coquad
	hidden_proc = proc { @jpp_mode != :normal }
	vproc = proc { option_get :coquad }
	hsh = { :value_proc => vproc, :hidden_proc => hidden_proc, :draw_proc => @draw_local,
            :tooltip => T6[:TIP_NormalCoquad], :hi_color => @pal_hi_color }
	@palette.declare_button(:pal_coquad, hshp, hsh) { option_toggle :coquad, [:vertices, :shield] }

end

#PALETTE: Push Pull directives
def palette_finishing
	pal_separator
	
	box_text = T6[:BOX_OptionFinishing]
	w, = G6.simple_text_size(box_text)
	wid = [w / 2, 24].max + 6

	vproc = proc { option_get :thickening }
	hsh = { :type => 'multi', :radio => true, :passive => true, :bk_color => @pal_bk_color, 
	        :value_proc => vproc, :text => box_text, :tooltip => T6[:TIP_OptionFinishing] }
	@palette.declare_button(:pal_finishing, hsh) { modify_option_thickening }
	
	hp = { :parent => :pal_finishing, :width => wid, :draw_proc => @draw_local, :hi_color => @pal_hi_color }
	
	hsh = { :value => false, :tooltip => T6[:TIP_OptionFinishingPush] }
	@palette.declare_button(:pal_finishing_push, hp, hsh)
	
	hsh = { :value => true, :tooltip => T6[:TIP_OptionFinishingThicken] }
	@palette.declare_button(:pal_finishing_thicken, hp, hsh)
end

#PALETTE: Options for borders
def palette_borders
	pal_separator
	
	box_text = T6[:BOX_OptionBorders]
	w, = G6.simple_text_size(box_text)
	wid = [w / 3, 24].max

	vproc = proc { option_get :borders }
	hsh = { :type => 'multi', :radio => true, :passive => true, :bk_color => @pal_bk_color, 
	        :value_proc => vproc, :text => box_text, :tooltip => T6[:TIP_OptionBorders] }
	@palette.declare_button(:pal_borders, hsh) { option_set :borders, @palette.button_get_value, :shield }
	
	hp = { :parent => :pal_borders, :width => wid, :draw_proc => @draw_local, :hi_color => @pal_hi_color }
	
	hsh = { :value => :contour, :tooltip => T6[:TIP_OptionBordersContour], :text => 'C' }
	@palette.declare_button(:pal_borders_contour, hp, hsh)
	
	hsh = { :value => :grid, :tooltip => T6[:TIP_OptionBordersGrid], :text => 'G' }
	@palette.declare_button(:pal_borders_grid, hp, hsh)
	
	hsh = { :value => :none, :tooltip => T6[:TIP_OptionBordersNone], :text => 'N' }
	@palette.declare_button(:pal_borders_none, hp, hsh)	
end

#PALETTE: Button for offset
def palette_offset
	pal_separator

	#Title button
	title = T6[:BOX_Offset]
	wid, = G6.simple_text_size(title)
	wid = [70, wid].max
	tip = T6[:TIP_Offset]
	prompt = T6[:PROMPT_Offset]

	hsh_dim = { :height => 16, :width => wid }
	hsht = { :passive => true, :text => title, :bk_color => @pal_bk_color, :tooltip => tip, :rank => 1 }
	@palette.declare_button :pal_offset_title, hsh_dim, hsht
	
	#Input field
	hshi = { :vtype => :len, :vprompt => prompt }
	get_proc = proc { @offset }
	set_proc = proc { |val| modify_offset val }
	show_proc = proc { |val| Sketchup.format_length val }
	input = Traductor::InputField.new hshi, { :get_proc => get_proc, :set_proc => set_proc, :show_proc => show_proc }
	
	hsh = { :bk_color => 'lightgreen', :input => input, :tooltip => tip }
	@palette.declare_button :pal_offset_value, hsh_dim, hsh 
end

#PALETTE: Button for Angle Round
def palette_angle_round
	pal_separator

	#Title button
	hidden_proc = proc { @jpp_mode != :round }
	title = T6[:BOX_AngleRound]
	wid, = G6.simple_text_size(title)
	wid = [80, wid].max
	tip = T6[:TIP_AngleRound]
	prompt = T6[:PROMPT_AngleRound]

	hsh_dim = { :height => 16, :width => wid, :hidden_proc => hidden_proc }
	hsht = { :passive => true, :text => title, :bk_color => @pal_bk_color, :tooltip => tip, :rank => 1 }
	@palette.declare_button :pal_angle_round_title, hsh_dim, hsht
	
	#Input field
	hshi = { :vtype => :float, :vmin => @angle_round_min, :vmax => @angle_round_max, :vincr => 5, :default => 20,
	         :vsprintf => "%0.0f\°", :vprompt => prompt }
	get_proc = proc { @angle_round }
	set_proc = proc { |val| modify_angle_round val }
	input = Traductor::InputField.new hshi, { :get_proc => get_proc, :set_proc => set_proc }
	
	hsh = { :bk_color => 'lightgreen', :input => input, :tooltip => tip }
	@palette.declare_button :pal_angle_round_value, hsh_dim, hsh 
end

#PALETTE: Button for Angle Round
def palette_segment_round
	pal_separator

	#Title button
	hidden_proc = proc { @jpp_mode != :round }
	title = T6[:BOX_SegmentRound]
	wid, = G6.simple_text_size(title)
	wid = [80, wid].max
	tip = prompt = T6[:TIP_SegmentRound]

	hsh_dim = { :height => 16, :width => wid, :hidden_proc => hidden_proc }
	hsht = { :passive => true, :text => title, :bk_color => @pal_bk_color, :tooltip => tip, :rank => 1 }
	@palette.declare_button :pal_segment_round_title, hsh_dim, hsht
	
	#Input field
	hshi = { :vtype => :integer, :vmin => @segment_round_min, :vmax => @segment_round_max, :vincr => 2, :default => 6,
	         :vsprintf => "%ds", :vprompt => prompt }
	get_proc = proc { @segment_round }
	set_proc = proc { |val| modify_segment_round val }
	input = Traductor::InputField.new hshi, { :get_proc => get_proc, :set_proc => set_proc }
	
	hsh = { :bk_color => 'lightgreen', :input => input, :tooltip => tip }
	@palette.declare_button :pal_segment_round_value, hsh_dim, hsh 
end

#PALETTE: Button for Angle Round
def palette_radial_scaling
	return unless @jpp_mode == :normal || @jpp_mode == :extrude
	pal_separator

	#Title button
	title = T6[:BOX_RadialScaling]
	wid, = G6.simple_text_size(title)
	wid = [80, wid].max
	case @jpp_mode
	when :normal
		prompt = T6[:TIP_RadialScalingNormal]
		tip = prompt + " (#{T6[:TIP_RadialScalingVCB]})"
	when :extrude
		prompt = T6[:TIP_RadialScalingExtrude]
		tip = prompt + " (#{T6[:TIP_RadialScalingVCB]})"
	end
	
	hsh_dim = { :height => 16, :width => wid }
	hsht = { :text => title, :bk_color => @pal_bk_color, :tooltip => tip, :rank => 1 }
	@palette.declare_button(:pal_radial_scaling_title, hsh_dim, hsht) { option_set :radial_scaling, 1.0, :shield }
	
	#Input field
	#hshi = { :vtype => :float, :vmin => @segment_round_min, :vmax => @segment_round_max, :vincr => 2, :default => 6,
	hshi = { :vtype => :float, :vincr => 0.1,
	         :vsprintf => "%0.2f", :vprompt => prompt }
	get_proc = proc { option_get :radial_scaling }
	set_proc = proc { |val| option_set :radial_scaling, val, :shield }
	input = Traductor::InputField.new hshi, { :get_proc => get_proc, :set_proc => set_proc }
	
	hsh = { :bk_color => 'lightgreen', :input => input, :tooltip => tip }
	@palette.declare_button :pal_radial_scaling, hsh_dim, hsh 
end

#PALETTE: Button for Random properties
def palette_random
	pal_separator

	#Title button
	hidden_proc = proc { !@jpp_prop_random }
	title = T6[:BOX_Random]
	wid, = G6.simple_text_size(title)
	wid = [140, wid].max
	tip_tit = prompt_tit = T6[:TIP_RandomTitle]
	tip_min = T6[:TIP_RandomMin]
	tip_max = T6[:TIP_RandomMax]
	wid2 = wid / 2
	widp = 25
	widt = wid - 2 * widp
	hgt = 16

	#Top button for title and seed
	hshb = { :height => hgt, :bk_color => 'thistle', :hi_color => 'violet', :rank => 1, :hidden_proc => hidden_proc,
             :draw_proc => @draw_local }
	
	hsh = { :width => widp, :tooltip => T6[:TIP_RandomMinus] }
	@palette.declare_button(:pal_random_title_minus, hshb, hsh) { modify_random_seed -1 } 

	value_proc = proc {option_get :random_on }
	hsh = { :value_proc => value_proc, :width => widt, :text => T6[:BOX_Random], :tooltip => tip_tit }
	@palette.declare_button(:pal_random_title, hshb, hsh) { toggle_random_mode  } 

	hsh = { :width => widp, :tooltip => T6[:TIP_RandomPlus] }
	@palette.declare_button(:pal_random_title_plus, hshb, hsh) { modify_random_seed +1 } 

	#Button for random range
	hsh_dim = { :height => hgt, :width => wid2, :hidden_proc => hidden_proc, :bk_color => 'lightgreen' }
	
	hshi = { :vtype => :float, :default => 6, :vsprintf => "%0.2f", :vincr => 1, :vprompt => tip_min }
	get_proc = proc { option_get :randf_min}
	set_proc = proc { |val| modify_random_range :randf_min, val }
	input = Traductor::InputField.new hshi, { :get_proc => get_proc, :set_proc => set_proc }
	
	hsh = { :input => input, :tooltip => tip_min }
	@palette.declare_button :pal_random_min, hsh_dim, hsh

	hshi = { :vtype => :float, :default => 6, :vsprintf => "%0.2f", :vincr => 1, :vprompt => tip_min }
	get_proc = proc { option_get :randf_max}
	set_proc = proc { |val| modify_random_range :randf_max, val }
	input = Traductor::InputField.new hshi, { :get_proc => get_proc, :set_proc => set_proc }
	
	hsh = { :input => input, :tooltip => tip_max }
	@palette.declare_button :pal_random_max, hsh_dim, hsh
	
end
	
#--------------------------------------------------------------
# Custom drawing for palette buttons
#--------------------------------------------------------------

#PALETTE: Drawing the Blason
def draw_button_blason(symb, dx, dy)
	lst_gl = []
	draw_button_plugin(symb, dx, dy, @jpp_letter, lst_gl)
	
	lst_gl
end

#PALETTE: Draw the icon for Push Pull
def draw_button_plugin(symb, dx, dy, letter, lst_gl)
	dx2 = dx/2
	dy2 = dy/2
	dy3 = dy/3
	h = 6
	pts = []
	pts.push Geom::Point3d.new(2, dy3)
	pts.push Geom::Point3d.new(dx2, 0)
	pts.push Geom::Point3d.new(dx2, h)
	pts.push Geom::Point3d.new(2, dy3 + h)
	lst_gl.push [GL_POLYGON, pts, 'maroon']
	
	pts = [pts[1], pts[2]]
	pts.push Geom::Point3d.new(dx-2, dy3+h)
	pts.push Geom::Point3d.new(dx-2, dy3)
	lst_gl.push [GL_POLYGON, pts, 'maroon']
	
	pts = []
	pts.push Geom::Point3d.new(2, dy3+h)
	pts.push Geom::Point3d.new(dx2, dy2+h)
	pts.push Geom::Point3d.new(dx-2, dy3+h)
	pts.push Geom::Point3d.new(dx2, h)
	lst_gl.push [GL_POLYGON, pts, 'burlywood']

	w = 2
	w2 = 6
	h = 4
	pts = []
	pts.push Geom::Point3d.new(dx2-w, dy2)
	pts.push Geom::Point3d.new(dx2-w, dy2+h)
	pts.push Geom::Point3d.new(dx2+w, dy2+h)
	pts.push Geom::Point3d.new(dx2+w, dy2)
	lst_gl.push [GL_POLYGON, pts, 'crimson']
	lst_gl.push [GL_LINE_LOOP, pts, 'gray', 1, '']
	pts = []
	pts.push Geom::Point3d.new(dx2-w2, dy2+h)
	pts.push Geom::Point3d.new(dx2, dy)
	pts.push Geom::Point3d.new(dx2+w2, dy2+h)
	lst_gl.push [GL_POLYGON, pts, 'crimson']
	lst_gl.push [GL_LINE_LOOP, pts, 'gray', 1, '']
	
	ptx = Geom::Point3d.new(dx-5, dy+2)
	lst_gl.push ['T', ptx, letter]

	lst_gl
end

#PALETTE: Custom drawing of buttons
def draw_button_opengl(symb, dx, dy, main_color, frame_color, selected, grayed)
	code = symb.to_s
	lst_gl = []
	dx2 = dx / 2
	dy2 = dy / 2
	#grayed = @palette.button_is_grayed?(symb)
	color = (grayed) ? 'gray' : frame_color
	
	case code
	
	when /_bandeau/i
		pts = []
		pts.push Geom::Point3d.new(0, 0)
		pts.push Geom::Point3d.new(dx, 0)
		pts.push Geom::Point3d.new(dx, dy)
		pts.push Geom::Point3d.new(0, dy)
		lst_gl.push [GL_POLYGON, pts, 'green']
		
	when /finishing_push/
		pts = [Geom::Point3d.new(2, 2), Geom::Point3d.new(dx-2, 2)]
		lst_gl.push [GL_LINE_STRIP, pts, 'black', 1, '-']
		pts = [Geom::Point3d.new(2, dy-2), Geom::Point3d.new(dx-2, dy-2)]
		lst_gl.push [GL_LINES, pts, 'blue', 3, '']
		
	when /finishing_keep/
		pts = [Geom::Point3d.new(2, 2), Geom::Point3d.new(dx-2, 2), Geom::Point3d.new(2, dy-2), Geom::Point3d.new(dx-2, dy-2)]
		lst_gl.push [GL_LINES, pts, 'blue', 3, '']
		
	when /finishing_thicken/
		pts = [Geom::Point3d.new(2, 2), Geom::Point3d.new(dx-2, 2), Geom::Point3d.new(2, dy-2), Geom::Point3d.new(dx-2, dy-2)]
		lst_gl.push [GL_LINES, pts, 'blue', 2, '']
		pts = [Geom::Point3d.new(2, 1), Geom::Point3d.new(dx-2, 1), Geom::Point3d.new(2, dy-1), Geom::Point3d.new(dx-2, dy-1)]
		lst_gl.push [GL_LINES, pts, 'red', 1, '']
		pts = [Geom::Point3d.new(dx2, 3), Geom::Point3d.new(dx2, dy-3)]
		lst_gl.push [GL_LINES, pts, 'black', 2, '-']

	when /extrude_flat/i, /vector_projected/i
		dx4 = dx / 4
		dy8 = dy / 8
		lipt = [[0,0], [dx4, dy8+2], [dx2-4, dy8+4], [dx2, dy8+6], [dx2+4, dy8+4], [dx2+dx4, dy8+2], [dx, 0]]
		pts = lipt.collect { |a| Geom::Point3d.new a.first, a.last }
		lst_gl.push [GL_LINE_STRIP, pts, 'black', 1, '']
		lipt = [[dx4, dy8+2], [dx4, dy-dy8], [dx2+dx4, dy8+2], [dx2+dx4, dy-dy8]]
		pts = lipt.collect { |a| Geom::Point3d.new a.first, a.last }
		lst_gl.push [GL_LINES, pts, 'blue', 2, '']
		lipt = [[dx4-2, dy-dy8], [dx2+dx4+2, dy-dy8]]
		pts = lipt.collect { |a| Geom::Point3d.new a.first, a.last }
		lst_gl.push [GL_LINE_STRIP, pts, 'red', 3, '']
	
	when /neighbour_influence/i
		color_neighbour = 'yellow'
		pts = G6.pts_square dx2+6, dy2, 4
		lst_gl.push [GL_POLYGON, pts, color_neighbour]
		pts = G6.pts_square dx2-6, dy2, 4
		lst_gl.push [GL_POLYGON, pts, color_neighbour]
		pts = G6.pts_square dx2, dy2+6, 4
		lst_gl.push [GL_POLYGON, pts, color_neighbour]
		pts = G6.pts_square dx2, dy2-6, 4
		lst_gl.push [GL_POLYGON, pts, color_neighbour]
		pts = G6.pts_square dx2, dy2, 4
		lst_gl.push [GL_POLYGON, pts, 'blue']
		lst_gl.push [GL_LINE_LOOP, pts, 'red', 2, '']
		
	when /random_title_plus/i, /random_title_minus/i
		w = 6
		color = 'black'
		pts = G6.pts_rectangle dx2-w, dy2-2, 2 * w, 4
		lst_gl.push [GL_POLYGON, pts, color]
		if code =~ /plus/i
			pts = G6.pts_rectangle dx2-2, dy2-w, 4, 2 * w
			lst_gl.push [GL_POLYGON, pts, color]
		end

	when /coquad/
		pts = G6.pts_square dx2, dy2, dx2 - 3
		lst_gl.push [GL_POLYGON, pts, 'yellow']
		lst_gl.push [GL_LINE_LOOP, pts, 'black', 1, '']
		lst_gl.push [GL_LINE_LOOP, [pts[0], pts[2]], 'blue', 1, '-']
		
	end	#case code
	
	lst_gl
end

end	#class JointPushPullTool

end	#End Module F6_JointPushPull
