#------------------------------------------------------------------------------------------------
# Permission to use, copy, modify, and distribute this software for 
# any purpose and without fee is hereby granted.
#
# 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.
#------------------------------------------------------------------------------------------------
#	THE STAIRS CREATED BY THIS PLUGIN ARE FOR ILLUSTRATION PURPOSES ONLY AND ARE NOT ENTENDED TO
# MEET ANY STRUCTURAL OR BUILDING CODES.
#------------------------------------------------------------------------------------------------
# THIS PLUGIN WAS DEVELOPED AND TESTED UNDER WINDOWS VISTA ONLY AND MAY OR MAY NOT WORK ON A MAC. 
#------------------------------------------------------------------------------------------------
#    Name:	Stair Maker
#      By:	sdmitch
#   Usage:	Create simple straight, spiral, L-shaped and U-shaped stair cases.
#	   Note:	The steps in the Normal, L-shape and U-shape open stairs are components created as
#						needed and given a name based on the step dimensions.  When you edit one you edit all!
#    Date:	Aug 2011
#------------------------------------------------------------------------------------------------
#
require 'sketchup'
#
if not file_loaded?(File.basename(__FILE__))
	UI.menu("Plugins").add_item("Stair Maker") { Sketchup.active_model.select_tool Stair_Maker.new }
	file_loaded(File.basename(__FILE__))
end
#
class Stair_Maker

	def initialize
		@ip = Sketchup::InputPoint.new
		@ip1 = Sketchup::InputPoint.new
		@file =  __FILE__.gsub(/.rb$/,'.txt')
		@separator = begin;'1.0'.to_l;'.';rescue;',';end
		@unit=Sketchup.active_model.options["UnitsOptions"]["LengthUnit"]
		if !File.exist?(@file)
			if @unit< 2
				@@step_width = 3.feet
				@@step_tread = 1.feet
				@@step_riser = 9.inch
				@@step_count = 12
				@@step_depth = 2.inch
				@@step_nturn = 0
				@@step_trngp = 1.feet
				@@rail_level = 2.5.feet
				@@rail_inset = 3.inch
				@@ss_width_max = 6.feet
				@@ss_width_min = 4.feet
				@@ss_height = 9.feet
				@@ss_anginc = 15.0
			else
				@@step_width = 1.m
				@@step_tread = 35.cm
				@@step_riser = 20.cm
				@@step_count = 12
				@@step_depth = 5.cm
				@@step_nturn = 0
				@@step_trngp = 35.cm
				@@rail_level = 90.cm
				@@rail_inset = 5.cm
				@@ss_width_max = 2.m
				@@ss_width_min = 1.m
				@@ss_height = 3.m
				@@ss_anginc = 15.0
			end
		end
		self.reset
	end

	def reset
		ans=UI.inputbox(["Stair Type:"],["Normal"],["Normal|Spiral|Lshape|Ushape|Ladder"],"Stair Maker 4")
		if !ans then Sketchup.send_action "selectSelectionTool:";return;end
		@stair_type=ans[0]
		case @stair_type
			when "Normal"
				self.get_defaults if File.exist?(@file)
				prompts=["Step Width:","Tread Depth:","Riser Height:","Num of Steps:","Step Depth:","Rail Height:", "Rail Offset:","Height of Stairs:"]
				defaults=[@@step_width,@@step_tread,@@step_riser,@@step_count,@@step_depth,@@rail_level,@@rail_inset,@@ss_height]
				results=UI.inputbox(prompts,defaults,"Normal Stairs")
				if !results then; onCancel(nil,nil);return;end
				@@step_width=results[0].to_l;@@step_tread=results[1].to_l;@@step_riser=results[2].to_l;@@step_count=results[3].to_i
				@@step_depth=results[4].to_l; @@rail_level=results[5].to_l; @@rail_inset=results[6].to_l;@@ss_height=results[7].to_l
				if @@ss_height > 0
					if @@step_count > 0
						@@step_riser=@@ss_height/@@step_count
						self.reset if UI.messagebox("Riser is now #{@@step_riser.to_l}.  Continue?",MB_YESNO)==7
					elsif @@step_riser > 0
						@@step_count=(@@ss_height/@@step_riser).floor
						self.reset if UI.messagebox("Num of steps is now #{@@step_count}.  Continue?",MB_YESNO)==7
					else
						UI.messagebox "Enter number of steps or riser hieght"
						self.reset
					end
				end
				self.put_defaults
			when "Spiral"
				self.get_defaults if File.exist?(@file)
				prompts=["Step Max Width:","Step Min Width:","Riser Height:","Step Depth:","Rail Height:","Rail Offset:","Stair Height:","Num of Steps:","Step AngInc:"]
				defaults=[@@ss_width_max,@@ss_width_min,@@step_riser,@@step_depth,@@rail_level,@@rail_inset,@@ss_height,@@step_count,@@ss_anginc]
				results=UI.inputbox(prompts,defaults,"Spiral Stairs")
				if !results then; onCancel(nil,nil);return;end
				@@ss_width_max=results[0].to_l; @@ss_width_min=results[1].to_l;@@step_riser = results[2].to_l; 
				@@step_depth= results[3].to_l;@@rail_level=results[4].to_l; @@rail_inset=results[5].to_l; 
				@@ss_height = results[6].to_l; @@step_count = results[7].to_i;	@@ss_anginc = results[8].to_f
				if @@step_count > 0
					if @@ss_height > 0.0
						@@step_riser = @@ss_height/@@step_count
						self.reset if UI.messagebox("Riser is now #{@@step_riser.to_l}.  Continue?",MB_YESNO)==7
					else
						@@ss_height = @@step_riser * @@step_count
						self.reset if UI.messagebox("Height is now #{@@ss_height.to_l}.  Continue?",MB_YESNO)==7
					end
				end
				self.put_defaults
			when "Lshape"
				ans=UI.inputbox(["Type:"],["Open"],["Open|In-Situ"],"Type of construction")
				if !ans then; onCancel(nil,nil);return;end
				@design=ans[0]
				self.get_defaults if File.exist?(@file)
				if @design == "Open"
					prompts=["Step Width:","Tread Depth:","Riser Height:","Risers2Landing:", \
					"Step Depth:","Rail Height:","Rail Offset:","Stair Height:"]
					defaults=[@@step_width,@@step_tread,@@step_riser,@@step_count,@@step_depth,@@rail_level,@@rail_inset,@@ss_height]
					results=UI.inputbox(prompts,defaults,"L-Shaped Open Stairs")
					if !results then self.reset end
					@@step_width=results[0].to_l; @@step_tread=results[1].to_l; @@step_riser=results[2].to_l;
					@@step_count=results[3].to_i; @@step_nturn=0; @@step_depth=results[4].to_l; 
					@@rail_level=results[5].to_l; @@rail_inset=results[6].to_l;@@ss_height=results[7].to_l
					@Step_Name="Step"+@@step_width.to_i.to_s+@@step_tread.to_i.to_s+@@step_depth.to_i.to_s
					make_step_comp;#puts "component made"
				else
					prompts=["Step Width:","Tread Depth:","Riser Height:","Risers2Landing:","Rail Height:","Rail Offset:","Stair Height:"]
					defaults=[@@step_width,@@step_tread,@@step_riser,@@step_count,@@rail_level,@@rail_inset,@@ss_height]
					results=UI.inputbox(prompts,defaults,"L-Shaped In-Situ Stairs")
					if !results then self.reset end
					@@step_width=results[0].to_l;@@step_tread=results[1].to_l;@@step_riser=results[2].to_l
					@@step_count=results[3].to_i;  @@step_nturn=0;
					@@rail_level=results[4].to_l; @@rail_inset=results[5].to_l;@@ss_height=results[6].to_l
				end
				if @@ss_height > 0
					if @@step_count > 0
						@@step_riser=@@ss_height/@@step_count/2.0
						self.reset if UI.messagebox("Riser is now #{@@step_riser.to_l}.  Continue?",MB_YESNO)==7
					elsif @@step_riser > 0
						@@step_count=(@@ss_height/@@step_riser/2.0).floor
						self.reset if UI.messagebox("Num of steps is now #{@@step_count}.  Continue?",MB_YESNO)==7
					else
						UI.messagebox "Enter number of steps or riser height"
						self.reset
					end
				end
				self.put_defaults
			when "Ushape"
				ans=UI.inputbox(["Type:"],["Open"],["Open|In-Situ"],"Type of construction")
				if !ans then; onCancel(nil,nil);return;end
				@design=ans[0]
				self.get_defaults if File.exist?(@file)
				if @design == "Open"
					prompts=["Step Width:","Tread Depth:","Riser Height:","Risers2Landing:","Steps in Turn:","Gap Run2Run:", \
					"Step Depth:","Rail Height:","Rail Offset:","Stair Height:"]
					defaults=[@@step_width,@@step_tread,@@step_riser,@@step_count,@@step_nturn,@@step_trngp,@@step_depth,@@rail_level,@@rail_inset,@@ss_height]
					results=UI.inputbox(prompts,defaults,"U-Shaped Open Stairs")
					if !results then self.reset end
					@@step_width=results[0].to_l;@@step_tread=results[1].to_l;@@step_riser=results[2].to_l;
					@@step_count=results[3].to_i; @@step_nturn=results[4].to_i; @@step_trngp=results[5].to_l
					@@step_depth=results[6].to_l; @@rail_level=results[7].to_l; @@rail_inset=results[8].to_l;@@ss_height=results[9].to_l
					@Step_Name="Step"+@@step_width.to_i.to_s+@@step_tread.to_i.to_s+@@step_depth.to_i.to_s
					make_step_comp;#puts "component made"
				else
					prompts=["Step Width:","Tread Depth:","Riser Height:","Risers2Landing:","Gap Run2Run:","Rail Height:","Rail Offset:","Stair Height:"]
					defaults=[@@step_width,@@step_tread,@@step_riser,@@step_count,@@step_trngp,@@rail_level,@@rail_inset,@@ss_height]
					results=UI.inputbox(prompts,defaults,"U-Shaped In-Situ Stairs")
					if !results then self.reset end
					@@step_width=results[0].to_l;@@step_tread=results[1].to_l;@@step_riser=results[2].to_l
					@@step_count=results[3].to_i;  @@step_trngp=results[4].to_l;@@step_nturn=0;
					@@rail_level=results[5].to_l; @@rail_inset=results[6].to_l;@@ss_height=results[7].to_l
				end
				if @@ss_height > 0
					if @@step_count > 0
						@@step_riser=(@@ss_height/@@step_count/2.0).to_l
						self.reset if UI.messagebox("Riser is now #{@@step_riser.to_l}.  Continue?",MB_YESNO)==7
					elsif @@step_riser > 0
						@@step_count=(@@ss_height/@@step_riser/2.0).floor
						self.reset if UI.messagebox("Num of steps is now #{@@step_count}.  Continue?",MB_YESNO)==7
					else
						UI.messagebox "Enter number of steps or riser height"
						self.reset
					end
				end
				self.put_defaults
			else
				self.get_defaults if File.exist?(@file)
				prompts=["Ladder Rail Type:","Ladder Height:","Ladder Width:","Rung2Rung:","Wall Offset:"]
				defaults=["Tube",@@ss_height,@@step_width,@@step_riser,@@rail_inset]
				results=UI.inputbox(prompts,defaults,["Tube|Rect|Line"],"Wall Ladder")
				if !results then;onCancel(nil,nil);end
				@ladder_type=results[0].to_s;@@ss_height=results[1];@@step_width=results[2]
				@@step_riser=results[3];@@rail_inset=results[4]
				self.put_defaults
				if @ladder_type == "Tube"
					ans=UI.inputbox(["Rail Diameter:","Rung Diameter:"],[1.5.inch,1.0.inch],"Tube rail Ladder Specs")
					if !ans then;return;end
					rail_dia=ans[0].to_l;@rail_rad=rail_dia/2;rung_dia=ans[1].to_l;@rung_rad=rung_dia/2
				elsif @ladder_type == "Rect"
					ans=UI.inputbox(["Rail Dimensions","Rung Dimensions"],['5",1"','4",1"'],"Rect rail Ladder Specs")
					if !ans then;return;end
					rail,rung=ans;w,d=rail.split(",");@rail_wid=w.to_l/2;@rail_dep=d.to_l/2
					w,d=rung.split(",");@rung_wid=w.to_l/2;@rung_dep=d.to_l/2
				else
					#centerlines only
				end
		end
	end

	def onMouseMove(flags, x, y, view)
		self.set_current_point(x, y, view)
		view.invalidate if @drawn
	end
	
	def set_current_point(x, y, view)
		if( !@ip.pick(view, x, y, @ip1) )
			return false
		end
		@ip1.copy! @ip
		@ip0 = @ip.position
		view.tooltip = @ip.tooltip     
		Sketchup::set_status_text("Select location for #{@stair_type} stairs or Right Click to change stair type.  ESC to exit", SB_PROMPT)
		Sketchup::set_status_text("Current XYZ=", SB_VCB_LABEL)
		Sketchup::set_status_text("#{@ip0.x.to_l},#{@ip0.y.to_l},#{@ip0.z.to_l}", SB_VCB_VALUE)
		view.invalidate
	end
	
	def onLButtonDown(flags, x, y, view)
		case @stair_type
			when "Normal" ; self.straight_run(@ip.position)
			when "Spiral" ; self.spiral_stair(@ip.position)
			when "Lshape" ; self.lshape_stair(@ip.position)
			when "Ushape" ; self.ushape_stair(@ip.position)
			when "Ladder" ; self.ladder(@ip.position)
		end
	end

	def draw(view)
		@drawn = false
		# Show the current input point
		if( @ip.valid? && @ip.display? )
			@ip.draw(view)
			@drawn = true
		end
		view.draw_points @ip.position,10,3,'red'
	end
	
	def onCancel(flag, view)
		view.invalidate if @drawn
		Sketchup.send_action "selectSelectionTool:"
	end

	def onRButtonDown(flags,x,y,view)
		self.reset
	end
	
	def get_defaults
			f = File.open(@file, "r"); results = f.readlines; f.close
			@@step_width = results[0].strip.to_l
			@@step_tread = results[1].strip.to_l
			@@step_riser = results[2].strip.to_l
			@@step_count = results[3].strip.to_i
			@@step_depth = results[4].strip.to_l
			@@step_nturn = results[5].to_i
			@@step_trngp = results[6].strip.to_l
			@@rail_level = results[7].strip.to_l
			@@rail_inset = results[8].strip.to_l
			@@ss_width_max = results[9].strip.to_l
			@@ss_width_min = results[10].strip.to_l
			@@ss_height = results[11].strip.to_l
			@@ss_anginc = results[12].to_f
	end
	
	def put_defaults
			results=[]
			results[0]=@@step_width.to_s; results[0].gsub!('.',',') if @separator==','
			results[1]=@@step_tread.to_s; results[1].gsub!('.',',') if @separator==','
			results[2]=@@step_riser.to_l.to_s; results[2].gsub!('.',',') if @separator==','
			results[3]=@@step_count
			results[4]=@@step_depth.to_s; results[4].gsub!('.',',') if @separator==','
			results[5]=@@step_nturn
			results[6]=@@step_trngp.to_s; results[6].gsub!('.',',') if @separator==','
			results[7]=@@rail_level.to_s; results[7].gsub!('.',',') if @separator==','
			results[8]=@@rail_inset.to_s; results[8].gsub!('.',',') if @separator==','
			results[9]=@@ss_width_max.to_s; results[9].gsub!('.',',') if @separator==','
			results[10]=@@ss_width_min.to_s; results[10].gsub!('.',',') if @separator==','
			results[11]=@@ss_height.to_s; results[11].gsub!('.',',') if @separator==','
			results[12]=@@ss_anginc.to_s; results[12].gsub!('.',',') if @separator==','
			f = File.open(@file, "w"); f.puts results; f.close
	end
###############################################################################################################################
	
	def straight_run(origin)
	
		@Step_Name="Step"+@@step_width.to_i.to_s+@@step_tread.to_i.to_s+@@step_depth.to_i.to_s
		p0 = origin; rail_pts=[];pp_dist=@@step_depth;rv_gap=Geom::Vector3d.new(0,0,0.01.inch)
		make_step_comp;#puts "component made"
		mod=Sketchup.active_model;ent=mod.entities;sel=mod.selection;sel.clear
		mod.start_operation "Straight Run"
		steps=ent.add_group; sents=steps.entities; steps.name="Steps"
		rails=ent.add_group; rents=rails.entities; rails.name="Rails"
		for i in 1..@@step_count
			p1=p0.offset(Z_AXIS,@@step_riser);#puts "p1=#{p1}"
			tr=Geom::Transformation.axes(p1,X_AXIS,Y_AXIS,Z_AXIS);#puts "tr=#{tr}"
			sents.add_instance @step_comp,tr; #puts "step added"
			p0=p1.offset(Y_AXIS,@@step_tread);#puts "p0=#{p0}"
			p5=p1.offset(X_AXIS,@@step_width-@@rail_inset)
			p6=p5.offset(Z_AXIS,@@rail_level)
			rents.add_line(p5,p6);rail_pts.push p6+rv_gap;
		end
		p5=p0.offset(X_AXIS,@@step_width-@@rail_inset)
		p6=p5.offset(Z_AXIS,@@rail_level)
		rents.add_line(p5,p6);rail_pts.push p6+rv_gap
		rents.add_curve(rail_pts); #add railing
		# @comp.erase!
		mod.commit_operation
		return
	end
	
###############################################################################################################################

	def spiral_stair(origin)
	
		mod=Sketchup.active_model; ent=mod.entities; sel=mod.selection; sel.clear
		pp_dist=@@step_depth;p0=p3=origin;rail_pts=[];rv_gap=Geom::Vector3d.new(0,0,0.01.inch)
		xaxis=Geom::Vector3d.new(1,0,0); xaxis.length=@@ss_width_max+3.inch
		yaxis=Geom::Vector3d.new(0,1,0); yaxis.length=@@ss_width_min+3.inch
		mod.start_operation("Spiral Stair")
		steps=ent.add_group; sents=steps.entities; steps.name="Spiral Stairs"
		start_el = @@step_riser; angle = 0; angle_increment=@@ss_anginc
		cosa = Math.cos(angle.degrees); sina = Math.sin(angle.degrees)
		vec = Geom::Vector3d.linear_combination(cosa,xaxis,sina,yaxis)
		start_el.step(@@ss_height,@@step_riser) do |el|
			p1=p0.offset(Z_AXIS,el);angle += @@ss_anginc; angle %= 360.0
			p2=p1.offset(vec); line=sents.add_line(p1,p2)
			p5=p2.offset(vec,-@@rail_inset);p6=p5.offset(Z_AXIS,@@rail_level); 
			sents.add_line(p5,p6); rail_pts.push p6+rv_gap; #add railing point
			cosa = Math.cos(angle.degrees); sina = Math.sin(angle.degrees)
			vec = Geom::Vector3d.linear_combination(cosa,xaxis,sina,yaxis)
			p3=p1.offset(vec); face=sents.add_face(p1,p2,p3); face.pushpull -pp_dist
		end
		p5=p3.offset(vec,-@@rail_inset);p6=p5.offset(Z_AXIS,@@rail_level); 
		sents.add_line(p5,p6); rail_pts.push p6+rv_gap; #add railing point
		curve=sents.add_curve(rail_pts); #add railing
		p0=origin.offset(Z_AXIS,@@ss_height+@@ss_width_max)
		cir=sents.add_circle(p0,Z_AXIS,3.inch,16)
		face=sents.add_face(cir); face.pushpull -(@@ss_height+@@ss_width_max)
		mod.commit_operation
	end
	
###############################################################################################################################
	
	def lshape_stair(origin)
	
		mod=Sketchup.active_model;ent=mod.entities;sel=mod.selection;sel.clear
		rail_pts=[];rs_pts=[];ls_pts=[];p0=origin;rv_gap=Geom::Vector3d.new(0,0,0.01.inch)
		mod.start_operation "lshape stair"
		steps=ent.add_group; sents=steps.entities
		if @design == "Open"
			pp_dist = @@step_depth
			for i in 1..@@step_count
				p1=p0.offset(Z_AXIS,@@step_riser);#puts "p1=#{p1}"
				tr=Geom::Transformation.axes(p1,X_AXIS,Y_AXIS,Z_AXIS);#puts "tr=#{tr}"
				sents.add_instance @step_comp,tr; #puts "step added"
				p0=p1.offset(Y_AXIS,@@step_tread);#puts "p0=#{p0}"
				p5=p1.offset(X_AXIS,@@step_width-@@rail_inset)
				p6=p5.offset(Z_AXIS,@@rail_level)
				sents.add_line(p5,p6);rail_pts.push p6+rv_gap;
			end
			p5=p0.offset(X_AXIS,@@step_width-@@rail_inset)
			p6=p5.offset(Z_AXIS,@@rail_level)
			sents.add_line(p5,p6);rail_pts.push p6+rv_gap; 
			p5=p1.offset(Y_AXIS,@@step_tread)
			p3=p5.offset(X_AXIS,@@step_width)
		else
			pp_dist=@@step_riser
			for i in 1..@@step_count
				p1=p0.offset(Z_AXIS,@@step_riser)
				p2=p1.offset(X_AXIS,@@step_width)
				p3=p0.offset(X_AXIS,@@step_width)
				face=sents.add_face(p0,p1,p2,p3);face.reverse! if i==1
				p3=p2.offset(Y_AXIS,@@step_tread)
				p4=p1.offset(Y_AXIS,@@step_tread)
				face=sents.add_face(p1,p2,p3,p4);
				p5=p2.offset(X_AXIS,-@@rail_inset)
				p6=p5.offset(Z_AXIS,@@rail_level)
				sents.add_line(p5,p6);rail_pts.push p6+rv_gap;
				ls_pts.push p0; ls_pts.push p1;  p0=p4
			end
			p5=p3.offset(X_AXIS,-@@rail_inset)
			p6=p5.offset(Z_AXIS,@@rail_level)
			sents.add_line(p5,p6);rail_pts.push p6+rv_gap;p5=p4
			p6=p4.offset(Z_AXIS,-@@step_riser);
			ls_pts.push p4;ls_pts.push p6;
			p7=p6.offset(Z_AXIS,-@@step_riser*(@@step_count-1)).offset(Y_AXIS,-@@step_tread*(@@step_count-1))
			ls_pts.push p7; 
			for i in 0...ls_pts.length
				rs_pts[i]=ls_pts[i].offset(X_AXIS,@@step_width)
			end
		end
		rp_cnt = rail_pts.length;
		xgap=0.0;zcpy=p1.z;zgap=0
		scpy = steps.parent.entities.add_instance(steps.entities.parent, steps.transformation)
		scpyents=scpy.entities
		if @design !="Open"
			left_face = sents.add_face(ls_pts)
			right_face = sents.add_face(rs_pts)
			sents.add_face(rs_pts[0],ls_pts[0],ls_pts[-1],rs_pts[-1])
			sents.add_face(rs_pts[-1],ls_pts[-1],ls_pts[-2],rs_pts[-2])
			sents.add_face(rs_pts[-2],ls_pts[-2],ls_pts[-3],rs_pts[-3])
			ls_pts.push ls_pts[0].offset(Z_AXIS,-@@step_riser)
			rs_pts.push rs_pts[0].offset(Z_AXIS,-@@step_riser)
			scpyents.add_face(ls_pts)
			scpyents.add_face(rs_pts)
			scpyents.add_face(rs_pts[-1],ls_pts[-1],ls_pts[-3],rs_pts[-3])
			scpyents.add_face(rs_pts[-4],ls_pts[-4],ls_pts[-3],rs_pts[-3])
		end
		p1=p5
		p2=p1.offset(Y_AXIS,@@step_width)
		p3=p2.offset(X_AXIS,@@step_width+xgap)
		p4=p1.offset(X_AXIS,@@step_width+xgap)
		face=sents.add_face(p1,p2,p3,p4)
		face.pushpull pp_dist if face
		trn=Geom::Transformation.new(p3-origin)
		scpy.transform! trn
		trr=Geom::Transformation.rotation(scpy.bounds.corner(0),Z_AXIS,-90.degrees)
		scpy.transform! trr;	
		for i in 0...rp_cnt
			rp = rail_pts[i].transform(trn)
			rail_pts.push rp.transform(trr)
		end
		sents.add_curve(rail_pts);#add top railing
		dump=steps.explode;dump.each{|e| sel.add e if e.is_a?(Sketchup::Edge)||e.is_a?(Sketchup::Face)||e.is_a?(Sketchup::ComponentInstance)}
		dump=scpy.explode;dump.each{|e| sel.add e if e.is_a?(Sketchup::Edge)||e.is_a?(Sketchup::Face)||e.is_a?(Sketchup::ComponentInstance)}
		grp=ent.add_group sel; grp.name="L-Shaped Stairs"; sel.clear;
		mod.commit_operation
	
	end
	
###############################################################################################################################

	def ushape_stair(origin)
	
		mod=Sketchup.active_model;ent=mod.entities;sel=mod.selection;sel.clear
		rail_pts=[];rs_pts=[];ls_pts=[];p0=origin;rv_gap=Geom::Vector3d.new(0,0,0.01.inch)
		mod.start_operation "ushape stair"
		steps=ent.add_group; sents=steps.entities
		if @design == "Open"
			pp_dist = @@step_depth
			for i in 1..@@step_count
				p1=p0.offset(Z_AXIS,@@step_riser);#puts "p1=#{p1}"
				tr=Geom::Transformation.axes(p1,X_AXIS,Y_AXIS,Z_AXIS);#puts "tr=#{tr}"
				sents.add_instance @step_comp,tr; #puts "step added"
				p0=p1.offset(Y_AXIS,@@step_tread);#puts "p0=#{p0}"
				p5=p1.offset(X_AXIS,@@step_width-@@rail_inset)
				p6=p5.offset(Z_AXIS,@@rail_level)
				sents.add_line(p5,p6);rail_pts.push p6+rv_gap;
			end
			p5=p0.offset(X_AXIS,@@step_width-@@rail_inset)
			p6=p5.offset(Z_AXIS,@@rail_level)
			sents.add_line(p5,p6);rail_pts.push p6+rv_gap; 
			p5=p1.offset(Y_AXIS,@@step_tread)
			p3=p5.offset(X_AXIS,@@step_width)
		else
			pp_dist=@@step_riser
			for i in 1..@@step_count
				p1=p0.offset(Z_AXIS,@@step_riser)
				p2=p1.offset(X_AXIS,@@step_width)
				p3=p0.offset(X_AXIS,@@step_width)
				face=sents.add_face(p0,p1,p2,p3);face.reverse! if i==1
				p3=p2.offset(Y_AXIS,@@step_tread)
				p4=p1.offset(Y_AXIS,@@step_tread)
				face=sents.add_face(p1,p2,p3,p4);
				p5=p2.offset(X_AXIS,-@@rail_inset)
				p6=p5.offset(Z_AXIS,@@rail_level)
				sents.add_line(p5,p6);rail_pts.push p6+rv_gap;
				ls_pts.push p0; ls_pts.push p1;  p0=p4
			end
			p5=p3.offset(X_AXIS,-@@rail_inset)
			p6=p5.offset(Z_AXIS,@@rail_level)
			sents.add_line(p5,p6);rail_pts.push p6+rv_gap;p5=p4
			p6=p4.offset(Z_AXIS,-@@step_riser);
			ls_pts.push p4;ls_pts.push p6;
			p7=p6.offset(Z_AXIS,-@@step_riser*(@@step_count-1)).offset(Y_AXIS,-@@step_tread*(@@step_count-1))
			ls_pts.push p7; 
			for i in 0...ls_pts.length
				rs_pts[i]=ls_pts[i].offset(X_AXIS,@@step_width)
			end
		end
		rp_cnt = rail_pts.length;
		xgap=@@step_trngp;zcpy=p1.z;zgap=0
		xgap=@@step_tread*@@step_nturn if @@step_nturn > 0
		zgap=@@step_riser*@@step_nturn if @@step_nturn > 0
		trn=Geom::Transformation.new([@@step_width+xgap,0,zcpy+zgap-origin.z])
		scpy = steps.parent.entities.add_instance(steps.entities.parent, steps.transformation)
		scpyents=scpy.entities
		if @design !="Open"
			left_face = sents.add_face(ls_pts)
			right_face = sents.add_face(rs_pts)
			sents.add_face(rs_pts[0],ls_pts[0],ls_pts[-1],rs_pts[-1])
			sents.add_face(rs_pts[-1],ls_pts[-1],ls_pts[-2],rs_pts[-2])
			sents.add_face(rs_pts[-2],ls_pts[-2],ls_pts[-3],rs_pts[-3])
			ls_pts.push ls_pts[0].offset(Z_AXIS,-@@step_riser)
			rs_pts.push rs_pts[0].offset(Z_AXIS,-@@step_riser)
			scpyents.add_face(ls_pts)
			scpyents.add_face(rs_pts)
			scpyents.add_face(rs_pts[-1],ls_pts[-1],ls_pts[-3],rs_pts[-3])
			scpyents.add_face(rs_pts[-4],ls_pts[-4],ls_pts[-3],rs_pts[-3])
		end
		scpy.transform! trn
		trr=Geom::Transformation.rotation(scpy.bounds.center,Z_AXIS,180.degrees)
		scpy.transform! trr
		if @@step_nturn == 0
			p1=p5
			p2=p1.offset(Y_AXIS,@@step_width)
			p3=p2.offset(X_AXIS,@@step_width*2.0+xgap)
			p4=p1.offset(X_AXIS,@@step_width*2.0+xgap)
			face=sents.add_face(p1,p2,p3,p4)
			face.pushpull pp_dist if face
		else
			p1=p5
			p2=p1.offset(Y_AXIS,@@step_width)
			p3=p2.offset(X_AXIS,@@step_width)
			p4=p1.offset(X_AXIS,@@step_width)
			face=sents.add_face(p1,p2,p3,p4)
			face.pushpull pp_dist if face
			for i in 1..@@step_nturn #add turn steps
				p1=p3.offset(Z_AXIS,@@step_riser)
				tr=Geom::Transformation.axes(p1,Y_AXIS.reverse,X_AXIS,Z_AXIS);#puts "tr=#{tr}"
				sents.add_instance @step_comp,tr; #puts "step added"
				p3=p1.offset(X_AXIS,@@step_tread)
				p5=p1.offset(Y_AXIS,@@rail_inset-@@step_width)
				p6=p5.offset(Z_AXIS,@@rail_level)
				sents.add_line(p5,p6);rail_pts.push p6+rv_gap
			end
			p5=p3.offset(Y_AXIS,@@rail_inset-@@step_width)
			p6=p5.offset(Z_AXIS,@@rail_level)
			sents.add_line(p5,p6);rail_pts.push p6+rv_gap
			p2=p3.offset(X_AXIS,@@step_width)
			p4=p3.offset(Y_AXIS,-@@step_width)
			p1=p2.offset(Y_AXIS,-@@step_width)
			face=sents.add_face(p1,p2,p3,p4)
			face.pushpull -pp_dist if face
		end
		for i in 0...rp_cnt
			rp = rail_pts[i].transform(trn)
			rail_pts.push rp.transform(trr)
		end
		sents.add_curve(rail_pts);#add top railing
		dump=steps.explode;dump.each{|e| sel.add e if e.is_a?(Sketchup::Edge)||e.is_a?(Sketchup::Face)||e.is_a?(Sketchup::ComponentInstance)}
		dump=scpy.explode;dump.each{|e| sel.add e if e.is_a?(Sketchup::Edge)||e.is_a?(Sketchup::Face)||e.is_a?(Sketchup::ComponentInstance)}
		grp=ent.add_group sel; grp.name="U-Shaped Stairs"; sel.clear;
		mod.commit_operation
	end
	
###############################################################################################################################

	def ladder(origin)
		mod=Sketchup.active_model;ent=mod.entities;sel=mod.selection
		mod.start_operation "ladder"; grp=ent.add_group;ge=grp.entities
		push_pull=@@ss_height+@@step_riser/2
		if @ladder_type == "Tube"
			p0=origin.offset(Y_AXIS,-(@@rail_inset+@rail_rad));p1=p0.offset(X_AXIS,@@step_width)
			cir=ge.add_circle(p0,Z_AXIS,@rail_rad)
			face=ge.add_face(cir);face.reverse! if face.normal.z < 0;face.pushpull push_pull
			cir=ge.add_circle(p1,Z_AXIS,@rail_rad)
			face=ge.add_face(cir);face.reverse! if face.normal.z < 0;face.pushpull push_pull
			@@step_riser.step(@@ss_height,@@step_riser) do |el|
				p1 = p0.offset(Z_AXIS,el)
				cir=ge.add_circle(p1,X_AXIS,@rung_rad)
				face=ge.add_face(cir);face.pushpull @@step_width
			end
		elsif @ladder_type == "Rect"
			pt=p0=origin.offset(Y_AXIS,-(@@rail_inset+@rail_wid))
			p1=p0.offset(X_AXIS,@rail_dep).offset(Y_AXIS,@rail_wid)
			p2=p0.offset(X_AXIS,@rail_dep).offset(Y_AXIS,-@rail_wid)
			p3=p0.offset(X_AXIS,-@rail_dep).offset(Y_AXIS,-@rail_wid)
			p4=p0.offset(X_AXIS,-@rail_dep).offset(Y_AXIS,@rail_wid)
			face=ge.add_face(p1,p2,p3,p4);face.reverse! if face.normal.z < 0;face.pushpull push_pull
			vec=[@@step_width,0,0];p1+=vec;p2+=vec;p3+=vec;p4+=vec
			face=ge.add_face(p1,p2,p3,p4);face.reverse! if face.normal.z < 0;face.pushpull push_pull
			@@step_riser.step(@@ss_height,@@step_riser) do |el|
				p0 = pt.offset(Z_AXIS,el)
				p1=p0.offset(Z_AXIS,@rung_dep).offset(Y_AXIS,-@rung_wid)
				p2=p0.offset(Z_AXIS,@rung_dep).offset(Y_AXIS,@rung_wid)
				p3=p0.offset(Z_AXIS,-@rung_dep).offset(Y_AXIS,@rung_wid)
				p4=p0.offset(Z_AXIS,-@rung_dep).offset(Y_AXIS,-@rung_wid)
				face=ge.add_face(p1,p2,p3,p4);face.reverse! if face.normal.x < 0;face.pushpull @@step_width
			end
		else
			p0=origin.offset(Y_AXIS,-@@rail_inset);p1=p0.offset(X_AXIS,@@step_width)
			pt=p0.offset(Z_AXIS,push_pull);ge.add_line(p0,pt)
			pt=p1.offset(Z_AXIS,push_pull);ge.add_line(p1,pt)
			@@step_riser.step(@@ss_height,@@step_riser) do |el|
				p1=p0.offset(Z_AXIS,el);p2=p1.offset(X_AXIS,@@step_width)
				ge.add_line(p1,p2)
			end
		end
		mod.commit_operation
	end
###############################################################################################################################

	def make_step_comp
		mod=Sketchup.active_model;ent=mod.entities;sel=mod.selection
		comp_defs=mod.definitions;@step_comp=nil
		comp_defs.each{|d| @step_comp=d if d.name==@Step_Name}
		if !@step_comp
			grp=ent.add_group; ge=grp.entities
			p0 = ORIGIN; p1=p0.offset(Y_AXIS,@@step_tread);p2=p1.offset(X_AXIS,@@step_width);p3=p0.offset(X_AXIS,@@step_width)
			face=ge.add_face(p0,p1,p2,p3); face.pushpull @@step_depth
			@comp=grp.to_component;@comp.definition.name=@Step_Name;@comp.hidden=true
			@step_comp=@comp.definition
		end
	end
	
	end#of class
