// Alphafix method by MDave

--[[   _                                
    ( )                               
   _| |   __   _ __   ___ ___     _ _ 
 /'_` | /'__`\( '__)/' _ ` _ `\ /'_` )
( (_| |(  ___/| |   | ( ) ( ) |( (_| |
`\__,_)`\____)(_)   (_) (_) (_)`\__,_) 

--]]
local PANEL = {}

AccessorFunc( PANEL, "m_fAnimSpeed", 	"AnimSpeed" )
AccessorFunc( PANEL, "Entity", 			"Entity" )
AccessorFunc( PANEL, "vCamPos", 		"CamPos" )
AccessorFunc( PANEL, "fFOV", 			"FOV" )
AccessorFunc( PANEL, "vLookatPos", 		"LookAt" )
AccessorFunc( PANEL, "aLookAngle", 		"LookAng" )
AccessorFunc( PANEL, "colAmbientLight", "AmbientLight" )
AccessorFunc( PANEL, "colColor", 		"Color" )
AccessorFunc( PANEL, "bAnimated", 		"Animated" )


--[[---------------------------------------------------------
   Name: Init
-----------------------------------------------------------]]
function PANEL:Init()

	self.Entity = nil
	self.LastPaint = 0
	self.DirectionalLight = {}
	self.FarZ = 4096
	
	self:SetCamPos( Vector( 50, 50, 50 ) )
	self:SetLookAt( Vector( 0, 0, 40 ) )
	self:SetFOV( 70 )
	
	self:SetText( "" )
	self:SetAnimSpeed( 0.5 )
	self:SetAnimated( false )
	
	self:SetAmbientLight( Color( 50, 50, 50 ) )
	
	self:SetDirectionalLight( BOX_TOP, Color( 255, 255, 255 ) )
	self:SetDirectionalLight( BOX_FRONT, Color( 255, 255, 255 ) )
	
	self:SetColor( Color( 255, 255, 255, 255 ) )

end

--[[---------------------------------------------------------
   Name: SetDirectionalLight
-----------------------------------------------------------]]
function PANEL:SetDirectionalLight( iDirection, color )
	self.DirectionalLight[iDirection] = color
end

--[[---------------------------------------------------------
   Name: OnSelect
-----------------------------------------------------------]]
function PANEL:SetModel( strModelName )

	-- Note - there's no real need to delete the old 
	-- entity, it will get garbage collected, but this is nicer.
	if ( IsValid( self.Entity ) ) then
		self.Entity:Remove()
		self.Entity = nil		
	end
	
	-- Note: Not in menu dll
	if ( !ClientsideModel ) then return end
	
	self.Entity = ClientsideModel( strModelName, RENDER_GROUP_OPAQUE_ENTITY )
	if ( !IsValid(self.Entity) ) then return end

	self.Entity:SetNoDraw( true )
	
	-- Try to find a nice sequence to play
	local iSeq = self.Entity:LookupSequence( "walk_all" )
	if ( iSeq <= 0 ) then iSeq = self.Entity:LookupSequence( "WalkUnarmed_all" ) end
	if ( iSeq <= 0 ) then iSeq = self.Entity:LookupSequence( "walk_all_moderate" ) end
	
	if ( iSeq > 0 ) then self.Entity:ResetSequence( iSeq ) end
	
	
end

--[[---------------------------------------------------------
   Name: DrawModel
-----------------------------------------------------------]]
function PANEL:DrawModel()
	local curparent = self
	local rightx = self:GetWide()
	local leftx = 0
	local topy = 0
	local bottomy = self:GetTall()
	local previous = curparent
	while(curparent:GetParent() != nil) do
		curparent = curparent:GetParent()
		local x,y = previous:GetPos()
		topy = math.Max(y, topy+y)
		leftx = math.Max(x, leftx+x)
		bottomy = math.Min(y+previous:GetTall(), bottomy + y)
		rightx = math.Min(x+previous:GetWide(), rightx + x)
		previous = curparent
	end
	render.SetScissorRect(leftx,topy,rightx, bottomy, true)
	self.Entity:DrawModel()
	render.SetScissorRect(0,0,0,0, false)
end

--[[---------------------------------------------------------
   Name: OnMousePressed
-----------------------------------------------------------]]
function PANEL:Paint()

	if ( !IsValid( self.Entity ) ) then return end
	
	local x, y = self:LocalToScreen( 0, 0 )
	
	self:LayoutEntity( self.Entity )
	
	local ang = self.aLookAngle
	if ( !ang ) then
		ang = (self.vLookatPos-self.vCamPos):Angle()
	end
	
	local w, h = self:GetSize()
	cam.Start3D( self.vCamPos, ang, self.fFOV, x, y, w, h, 5, self.FarZ )
	cam.IgnoreZ( true )
	
	render.SuppressEngineLighting( true )
	render.SetLightingOrigin( self.Entity:GetPos() )
	render.ResetModelLighting( self.colAmbientLight.r/255, self.colAmbientLight.g/255, self.colAmbientLight.b/255 )
	render.SetColorModulation( self.colColor.r/255, self.colColor.g/255, self.colColor.b/255 )
	render.SetBlend( self.colColor.a/255 )
	
	for i=0, 6 do
		local col = self.DirectionalLight[ i ]
		if ( col ) then
			render.SetModelLighting( i, col.r/255, col.g/255, col.b/255 )
		end
	end
	self:DrawModel()
	
	render.SuppressEngineLighting( false )
	cam.IgnoreZ( false )
	cam.End3D()
	
	self.LastPaint = RealTime()
	
end

--[[---------------------------------------------------------
   Name: RunAnimation
-----------------------------------------------------------]]
function PANEL:RunAnimation()
	self.Entity:FrameAdvance( (RealTime()-self.LastPaint) * self.m_fAnimSpeed )	
end

--[[---------------------------------------------------------
   Name: RunAnimation
-----------------------------------------------------------]]
function PANEL:StartScene( name )
	
	if ( IsValid( self.Scene ) ) then
		self.Scene:Remove()
	end
	
	self.Scene = ClientsideScene( name, self.Entity )
	
end



--[[---------------------------------------------------------
   Name: LayoutEntity
-----------------------------------------------------------]]
function PANEL:LayoutEntity( Entity )

	--
	-- This function is to be overriden
	--

	if ( self.bAnimated ) then
		self:RunAnimation()
	end
	
	Entity:SetAngles( Angle( 0, RealTime()*10,  0) )

end

function PANEL:OnRemove()
	if ( IsValid( self.Entity ) ) then
		self.Entity:Remove()
	end
end

--[[---------------------------------------------------------
   Name: GenerateExample
-----------------------------------------------------------]]
function PANEL:GenerateExample( ClassName, PropertySheet, Width, Height )

	local ctrl = vgui.Create( ClassName )
		ctrl:SetSize( 300, 300 )
		ctrl:SetModel( "models/error.mdl" )
		
	PropertySheet:AddSheet( ClassName, ctrl, nil, true, true )

end

derma.DefineControl( "DFixedModelPanel", "A panel containing a model", PANEL, "DButton" )


do return end

local PANEL = {}

function PANEL:Init( )

end

local modelRt = GetRenderTarget( "libk_rt_modelpanel", ScrW( ), ScrH( ) )
local modelMat = CreateMaterial( "libk_rt_mat", "UnlitGeneric", {
	["$basetexture"] = modelRt
} )

function PANEL:Paint3D( )
	
end

function PANEL:Paint(w, h)
	render.PushRenderTarget( modelRt )
		render.Clear( 0,0,0, 255 )
		render.ClearDepth()
		
		cam.Start3D( view )
			render.ClearStencil( )
			
			render.SetStencilEnable( true )

			render.SetStencilReferenceValue( 1 )

			--stencil.PassOperation( STENCIL_REPLACE )
			render.SetStencilPassOperation( STENCILOPERATION_REPLACE )
			--stencil.FailOperation( STENCIL_KEEP )
			--stencil.ZFailOperation( STENCIL_KEEP )
			render.SetStencilFailOperation( STENCILOPERATION_KEEP )
			render.SetStencilZFailOperation( STENCILOPERATION_KEEP )
			render.SetStencilCompareFunction( STENCILCOMPARISONFUNCTION_ALWAYS )

			-- Render model
			render.OverrideAlphaWriteEnable( true, false )
				self:Paint3D( )
			render.OverrideAlphaWriteEnable( false )
	
			-- Hack to make the RT transparent
			render.SetStencilCompareFunction( STENCILCOMPARISONFUNCTION_NOTEQUAL )
			stencil.ClearBuffers( 0,0,0, 0 )
			render.ClearBuffersObeyStencil( 0, 0, 0, 0, 1 )

			render.SetStencilEnable( false )

		cam.End3D()
	render.PopRenderTarget()
end

vgui.Register( "DRTModelPanel", PANEL, "DModelPanel" )