### Hatching Tool
#
module Tools2D
class HatchingTool2D

def db(string)
  dir=File.dirname(__FILE__) ### adjust folder to suit tool
  toolname="2Dtools"  ### adjust xxx to suit tool...
  locale=Sketchup.get_locale.upcase
  path=File.join(dir, toolname+locale+".lingvo")
  unless File.exist?(path)
     return string
  else
    deBabelizer(string,path)
  end 
end#def
def HatchingTool2D::db(string)
  dir=File.dirname(__FILE__) ### adjust folder to suit tool
  toolname="2Dtools"  ### adjust xxx to suit tool...
  locale=Sketchup.get_locale.upcase
  path=File.join(dir, toolname+locale+".lingvo")
  unless File.exist?(path)
     return string
  else
    deBabelizer(string,path)
  end 
end#def

###@@hatchjpg=nil

def getExtents
    bbox=Sketchup.active_model.bounds
    bbox.add(@ip.position)if @ip and @ip.valid?
    bbox.add(@ip1.position)if @ip1 and @ip1.valid?
    bbox.add(@ip2.position)if @ip2 and @ip2.valid?
    bbox.add(@ip3.position)if @ip3 and @ip3.valid?
    return bbox
end

@@cursor=nil
def initialize()
    @ip1 = nil
    @xdown = 0
    @ydown = 0
	@@cursor=nil
    curpath=File.join(File.dirname(__FILE__), "Icons", "2Dhatching_cursor.png")
    @@cursor=UI::create_cursor(curpath, 0, 31) if File.exist?(curpath)
end

def activate
    ### get/set reference plane 'z'
    @z=Sketchup.active_model.get_attribute("2Dtools","z",nil)
    Sketchup.active_model.set_attribute("2Dtools","z",0.0.mm)if not @z
    @z=Sketchup.active_model.get_attribute("2Dtools","z",nil)
    @zmsg=" [ Z="+@z.to_s+" ] "
    ###
    @ip1 = Sketchup::InputPoint.new
    @ip = Sketchup::InputPoint.new
    @drawn = false
    @exface=nil ### existing face checker
    model=Sketchup.active_model
    model.selection.clear
    Sketchup.send_action("renderTextures:") ### set to show textures
    ### Check if have patt set - if not open dialog on activation
    @hatchjpg=model.get_attribute("2DHatching","jpgname",nil)
    if @hatchjpg
      mats=[];model.materials.each{|mat|mats<<mat.display_name}
      if mats.include?(@hatchjpg)
        @mat=nil;model.materials.each{|mat|@mat=mat if mat.display_name==@hatchjpg}
        self.reset(nil)
      else
        self.dialog()
      end#if
    else
      self.dialog()
    end#if
    ###
end

def dialog()
    model=Sketchup.active_model
    Sketchup::set_status_text((db("2D Hatching: Choose Hatch PATT jpg...")), SB_PROMPT)
    Sketchup::set_status_text("",SB_VCB_LABEL)
    folder=File.dirname(__FILE__)+"/Hatching/"
    if not @hatchjpg
      file1=File.basename(Dir[folder+"*.jpg"].last) ### v3.5
    else
      file1=@hatchjpg+".jpg" ###
    end#if
    ###jpg=folder+file1###
    folder=folder.tr("/","\\")if RUBY_PLATFORM =~ /mswin|mingw/ ### v3.5
    jpg=UI.openpanel((db("Choose Hatch PATT jpg...")),folder,file1)###
    while jpg and (not File.exist?(jpg) or not jpg.split(".").last=="jpg")
      puts db("Select a Hatch PATT jpg file OR Cancel !")
      UI.messagebox(db("Choose a Hatch PATT jpg file OR Cancel !"))
      jpg=UI.openpanel((db("Choose HATCHING...")),folder,file1)###
    end#while
    if not jpg
      puts db("Cancelled 2D Hatching.")
      Sketchup::set_status_text("",SB_PROMPT)
      Sketchup::set_status_text("",SB_VCB_LABEL)
      Sketchup::set_status_text("",SB_VCB_VALUE)
      Sketchup.send_action("selectSelectionTool:")
      return nil
    else
      jpgname=File.basename(jpg,".jpg")
      @hatchjpg=jpgname
      materials=model.materials
      matnames=[];materials.each{|mat|matnames<<mat.display_name}
      if matnames.include?(jpgname)
        @mat=nil;materials.each{|mat|@mat=mat if mat.display_name==jpgname}
      else
        @mat=materials.add(jpgname)
        @mat.texture=jpg
        @mat.color=@mat.texture.average_color
        ###@mat.texture.size=### get size from image " v pixels ?
        @mat.texture=nil if jpgname=="PATT__SOLID" ### plain black, NO texture
      end#if
      model.set_attribute("2DHatching","jpgname",jpgname)
      self.reset(nil)
     end#if
end

def deactivate(view)
    view.invalidate if @drawn and view
    Sketchup::set_status_text("",SB_PROMPT)
    Sketchup::set_status_text("",SB_VCB_LABEL)
    Sketchup::set_status_text("",SB_VCB_VALUE)
end

def onReturn(view)
    view.invalidate
    Sketchup::set_status_text("",SB_PROMPT)
    Sketchup.send_action("selectSelectionTool:")
end

def onSetCursor()
    #return nil if RUBY_PLATFORM =~ /darwin/
	UI::set_cursor(@@cursor)if @@cursor
end

def onMouseMove(flags, x, y, view)
    view.model.selection.clear
    Sketchup::set_status_text((db("2D Hatching: "))+@zmsg+"["+@mat.display_name+(db("] Pick in Loop or Face. End=<Enter> Dialog=Right-click[in empty-space]")), SB_PROMPT)
    Sketchup::set_status_text("",SB_VCB_LABEL)
    @ip.pick view, x, y
    if @ip != @ip1
        view.invalidate if @ip.display? or @ip1.display?
        @ip1.copy! @ip
        view.tooltip = @ip1.tooltip
    end
end

def onLButtonDown(flags, x, y, view)
    view.model.selection.clear
    @ip1.pick view, x, y
    if @ip1.valid?
        p1=@ip1.position;p1.z=@z
        Sketchup::set_status_text((db("2D Hatching: "))+@zmsg+"["+@mat.display_name+(db("] Pick Point in Loop or on Face for Hatching. End=<Enter>. Dialog=Right-click [in empty-space]")), SB_PROMPT)
        Sketchup::set_status_text("",SB_VCB_LABEL)
        @xdown = x
        @ydown = y
    end
    ### check if extg face
    ph=view.pick_helper
    ph.do_pick(x,y)
    picked_face=ph.picked_face
    @exface=nil
    @exface=picked_face if picked_face and picked_face.bounds.min.z==picked_face.bounds.max.z and picked_face.bounds.min.z==@z
    ###
    self.make_n_hatch_face(p1, view)
end

def onLButtonUp(flags, x, y, view)
    view.model.selection.clear
    Sketchup::set_status_text((db("2D Hatching: "))+@zmsg+"["+@mat.display_name+(db("] Pick Point in Loop or on Face for Hatching. End=<Enter>. Dialog=Right-click [in empty-space]")), SB_PROMPT)
    Sketchup::set_status_text("",SB_VCB_LABEL)
end

def onRButtonDown(flags, x, y, view)
  view.model.selection.clear
  self.reset(view)
end
def onRButtonUp(flags, x, y, view)
  view.model.selection.clear
  self.dialog()
end

def onKeyDown(key, repeat, flags, view)
  ### nothing
end

def onKeyUp(key, repeat, flags, view)
  ### nothing
end

def enableVCB?
   return false
end

def onUserText(text, view)
 ### nothing    
end

def draw(view)
   ### nothing
end

def onCancel(flag, view)
    view.invalidate if @drawn
    self.reset(view)
end

def reset(view)
    Sketchup::set_status_text((db("2D Hatching: "))+@zmsg+"["+@mat.display_name+(db("] Pick Point in Loop or on Face for Hatching. End=<Enter>. Dialog=Right-click [in empty-space]")), SB_PROMPT)
    Sketchup::set_status_text("",SB_VCB_LABEL)
    @ip1.clear
    if view
      view.model.selection.clear
      view.tooltip = nil
      view.invalidate if @drawn
    end
    @drawn = false
end


def make_n_hatch_face(pt, view)
    view.model.start_operation(db("2D Hatching"))
    ray=[pt,Geom::Vector3d.new(1,0,0)]
    raytest=Sketchup.active_model.raytest(ray)
    edge1=nil
    edge1=raytest[1].last if raytest and raytest[1].last.class==Sketchup::Edge
    return if not edge1
    ray=[pt,Geom::Vector3d.new(-1,0,0)]
    raytest=Sketchup.active_model.raytest(ray)
    edge2=nil
    edge2=raytest[1].last if raytest and raytest[1].last.class==Sketchup::Edge
    return if not edge2
    ###
    exfaces=[]
    edge1.parent.entities.each{|e|exfaces<<e if e.class==Sketchup::Face}
    edge2s=[]
    edge2.all_connected.each{|e|edge2s<<e if e.class==Sketchup::Edge}
    edge2s.each{|e|e.find_faces}
    edges=[]
    edge1.all_connected.each{|e|edges<<e if e.class==Sketchup::Edge}
    edges.each{|e|e.find_faces}
    nowfaces=[]
    edge1.parent.entities.each{|e|nowfaces<<e if e.class==Sketchup::Face and not exfaces.include?(e)}
    nowfaces.each{|face|
      face.erase! if not face.outer_loop.edges.include?(edge1)
      face.erase! if face.valid? and not face.classify_point(pt)==1
      face.reverse! if face.valid? and face.normal==[0,0,-1]
      face.material=@mat if face.valid?
    }
    ### if not made a face then try another ray vector and see if that works
    validface=false
    nowfaces.each{|face|
      if face.valid?
        validface=true; break
      end#if
    }
    if not validface ###########################
      ray=[pt,Geom::Vector3d.new(-1,0,0)]
      raytest=Sketchup.active_model.raytest(ray)
     edge1=nil
    edge1=raytest[1].last if raytest and raytest[1].last.class==Sketchup::Edge
    return if not edge1
    ray=[pt,Geom::Vector3d.new(1,0,0)]
    raytest=Sketchup.active_model.raytest(ray)
    edge2=nil
    edge2=raytest[1].last if raytest and raytest[1].last.class==Sketchup::Edge
    return if not edge2
    ###
    exfaces=[]
    edge1.parent.entities.each{|e|exfaces<<e if e.class==Sketchup::Face}
    edge2s=[]
    edge2.all_connected.each{|e|edge2s<<e if e.class==Sketchup::Edge}
    edge2s.each{|e|e.find_faces}
    edges=[]
    edge1.all_connected.each{|e|edges<<e if e.class==Sketchup::Edge}
    edges.each{|e|e.find_faces}
    nowfaces=[]
    edge1.parent.entities.each{|e|nowfaces<<e if e.class==Sketchup::Face and not exfaces.include?(e)}
    nowfaces.each{|face|
      face.erase! if not face.outer_loop.edges.include?(edge1)
      face.erase! if face.valid? and not face.classify_point(pt)==1
      face.reverse! if face.valid? and face.normal==[0,0,-1]
      face.material=@mat if face.valid?
    }
    end#if
    #####################
    ###
    if @exface
      @exface.material=@mat
      @exface.reverse! if @exface.normal.z<0
    end#if
    ###
    view.invalidate
    view.model.commit_operation
    reset(view)
end

def resume(view)
  view.invalidate
end

def draw_geometry(points, view)
  ### nothing
end

#############################
def HatchingTool2D::context_dialog()
	model=Sketchup.active_model
	Sketchup::set_status_text((db("2D Hatching: Choose Hatch PATT jpg...")), SB_PROMPT)
	Sketchup::set_status_text("",SB_VCB_LABEL)
	folder=File.dirname(__FILE__)+"/Hatching/"
	if not @hatchjpg
		file1=File.basename(Dir[folder+"*.jpg"].last) ### v3.5
	else
		file1=@hatchjpg+".jpg" ###
	end#if
	###jpg=folder+file1###
	folder=folder.tr("/","\\")if RUBY_PLATFORM =~ /mswin|mingw/ ### v3.5
	jpg=UI.openpanel((db("Choose Hatch PATT jpg...")),folder,file1)###
	while jpg and (not File.exist?(jpg) or not jpg.split(".").last=="jpg")
		puts db("Select a Hatch PATT jpg file OR Cancel !")
		UI.messagebox(db("Choose a Hatch PATT jpg file OR Cancel !"))
		jpg=UI.openpanel((db("Choose HATCHING...")),folder,file1)###
	end#while
	if not jpg
		puts db("Cancelled 2D Hatching.")
		Sketchup::set_status_text("",SB_PROMPT)
		Sketchup::set_status_text("",SB_VCB_LABEL)
		Sketchup::set_status_text("",SB_VCB_VALUE)
		Sketchup.send_action("selectSelectionTool:")
		return nil
	else
		jpgname=File.basename(jpg,".jpg")
		@hatchjpg=jpgname
		materials=model.materials
		matnames=[];materials.each{|mat|matnames<<mat.display_name}
		if matnames.include?(jpgname)
			@mat=nil;materials.each{|mat|@mat=mat if mat.display_name==jpgname}
		else
			@mat=materials.add(jpgname)
			@mat.texture=jpg
			@mat.color=@mat.texture.average_color
			###@mat.texture.size=### get size from image " v pixels ?
			@mat.texture=nil if jpgname=="PATT__SOLID" ### plain black, NO texture
		end#if
		model.set_attribute("2DHatching","jpgname",jpgname)
		###
		tools=model.tools
		tol=tools.pop_tool
		tools.push_tool(tol)
		###
	 end#if
end
#############################

end # class

end#mod
#-----------------------------------------------------------------------------
# shortcut
#def hatchingtool2D
    #Sketchup.active_model.select_tool HatchingTool2D.new
#end
######-----------------------------------------------

