

include('glon.lua')



surface.CreateFont("12ptFont", {font = "Arial", size = 12, width = 500, antialias = true, additive = false})

surface.CreateFont("24ptFont", {font = "Arial", size = 24, width = 500, antialias = true, additive = false})



SWEP.useThirdPerson = false

SWEP.thirdPersonAngle = Angle(0,-90,0)

SWEP.thirdPersonDis = 100

SWEP.mlast_x = ScrW()/2

SWEP.mlast_y = ScrH()/2



local playerBones = { 

	"ValveBiped.Bip01_Head1", 

	"ValveBiped.Bip01_Pelvis",

	"ValveBiped.Bip01_Spine", 

	"ValveBiped.Bip01_Spine1",

	"ValveBiped.Bip01_Spine2",

	"ValveBiped.Bip01_Spine4",

	"ValveBiped.Anim_Attachment_RH", 

	"ValveBiped.Bip01_R_Hand", 

	"ValveBiped.Bip01_R_Forearm",

	"ValveBiped.Bip01_R_UpperArm",

	"ValveBiped.Bip01_R_Clavicle",

	"ValveBiped.Bip01_R_Foot", 

	"ValveBiped.Bip01_R_Toe0",

	"ValveBiped.Bip01_R_Thigh", 

	"ValveBiped.Bip01_R_Calf", 

	"ValveBiped.Bip01_R_Shoulder", 

	"ValveBiped.Bip01_R_Elbow",

	"ValveBiped.Bip01_Neck1",

	"ValveBiped.Anim_Attachment_LH", 

	"ValveBiped.Bip01_L_Hand", 

	"ValveBiped.Bip01_L_Forearm",

	"ValveBiped.Bip01_L_UpperArm",

	"ValveBiped.Bip01_L_Clavicle",

	"ValveBiped.Bip01_L_Foot", 

	"ValveBiped.Bip01_L_Toe0",

	"ValveBiped.Bip01_L_Thigh", 

	"ValveBiped.Bip01_L_Calf", 

	"ValveBiped.Bip01_L_Shoulder", 

	"ValveBiped.Bip01_L_Elbow"

	}

	

SWEP.v_models = {}

SWEP.v_panelCache = {}

SWEP.v_modelListing = nil

SWEP.v_bonemods = {}

SWEP.v_modelbonebox = nil



SWEP.w_models = {}

SWEP.w_panelCache = {}

SWEP.w_modelListing = nil



SWEP.world_model = nil

SWEP.cur_wmodel = nil



SWEP.browser_callback = nil

SWEP.modelbrowser = nil

SWEP.modelbrowser_list = nil

SWEP.matbrowser = nil

SWEP.matbrowser_list = nil



SWEP.tpsfocusbone = "ValveBiped.Bip01_R_Hand"



SWEP.save_data = {}

local save_data_template = {

	ViewModel = SWEP.ViewModel,

	CurWorldModel = SWEP.CurWorldModel,

	w_models = {},

	v_models = {},

	v_bonemods = {},

	ViewModelFOV = SWEP.ViewModelFOV,

	HoldType = SWEP.HoldType,

	ViewModelFlip = SWEP.ViewModelFlip,

	IronSightsEnabled = true,

	IronSightsPos = SWEP.IronSightsPos,

	IronSightsAng = SWEP.IronSightsAng,

	ShowViewModel = true,

	ShowWorldModel = true

}



SWEP.ir_drag = {

	x = { true, "-x", 25 },

	y = { false, "y", 25 },

	z = { true, "y", 25 },

	pitch = { false, "y", 10 },

	yaw = { false, "x", 10 },

	roll = { false, "y", 10 }

}



SWEP.Frame = nil

SWEP.cur_drag_mode = "x / z"

SWEP.basecode = "FAILED TO READ BASE CODE"

	

function SWEP:ClientInit()

	

	SCKDebug("Client init start")

	

	if (IsValid(self.Owner)) then

		// init view model bone mods

		local vm = self.Owner:GetViewModel()

		if IsValid(vm) then

			self:ResetBonePositions(vm)

		end

	end

	

	local basecodepath = "lua/weapons/swep_construction_kit/base_code.lua"

	self.basecode = file.Read(basecodepath, "GAME")

	

	SCKDebug("Loaded base code")

	

end



function SimplePanel( parent )



	local p = vgui.Create("DPanel", parent)

	p.Paint = function() end

	return p

	

end



function PrintVec( vec )

	local px, py, pz = math.floor(vec.x*1000)/1000,math.floor(vec.y*1000)/1000,math.floor(vec.z*1000)/1000

	return "Vector("..px..", "..py..", "..pz..")"

end



function PrintAngle( angle )

	local pp, py, pr = math.floor(angle.p*1000)/1000,math.floor(angle.y*1000)/1000,math.floor(angle.r*1000)/1000

	return "Angle("..pp..", "..py..", "..pr..")"

end



function PrintColor( col )

	return "Color("..col.r..", "..col.g..", "..col.b..", "..col.a..")"

end	



// Populates a DChoiceList with all the bones of the specified entity

// returns if it has a first option

function PopulateBoneList( choicelist, ent )

	if (!IsValid(choicelist)) then return false end

	if (!IsValid(ent)) then return end

	

	SCKDebug("Populating bone list for entity "..tostring(ent))

	

	if (ent == LocalPlayer()) then

		// if the local player is in third person, his bone lookup is all messed up so

		// we just use the predefined playerBones table

		for k, v in pairs(playerBones) do

			choicelist:AddChoice(v)

		end

		

		return true

	else

		local hasfirstoption

		for i = 0, ent:GetBoneCount() - 1 do

			local name = ent:GetBoneName(i)

			if (ent:LookupBone(name)) then // filter out invalid bones

				choicelist:AddChoice(name)

				if (!firstoption) then hasfirstoption = true end

			end

		end

		

		return hasfirstoption

	end

end



function SWEP:CreateWeaponWorldModel()

	

	local model = self.CurWorldModel

	SCKDebug("Creating weapon world model")

	

	if ((!self.world_model or (IsValid(self.world_model) and self.cur_wmodel != model)) and 

		string.find(model, ".mdl") and file.Exists(model,"GAME") ) then

		

		if IsValid(self.world_model) then self.world_model:Remove() end

		self.world_model = ClientsideModel(model, RENDERGROUP_TRANSLUCENT)

		if (IsValid(self.world_model)) then

			self.world_model:SetParent(self.Owner)

			self.world_model:SetNoDraw(true)

			self.cur_wmodel = model

			if (self.world_model:LookupBone( "ValveBiped.Bip01_R_Hand" )) then

				self.world_model:AddEffects(EF_BONEMERGE)

			end

		else

			self.world_model = nil

			self.cur_wmodel = nil

		end



	end

	

end



function SWEP:CreateModels( tab )

	

	//if true then return end

	

	// Create the clientside models here because Garry says we can't do it in the render hook

	for k, v in pairs( tab ) do

		if (v.type == "Model" and v.model and v.model != "" and (!IsValid(v.modelEnt) or v.createdModel != v.model) and 

				string.find(v.model, ".mdl") and file.Exists(v.model,"GAME") ) then

			

			SCKDebug("Creating new ClientSideModel "..v.model)

			

			v.modelEnt = ClientsideModel(v.model, RENDERGROUP_TRANSLUCENT)

			if (IsValid(v.modelEnt)) then

				v.modelEnt:SetPos(self:GetPos())

				v.modelEnt:SetAngles(self:GetAngles())

				v.modelEnt:SetParent(self)

				v.modelEnt:SetNoDraw(true)

				v.createdModel = v.model

			else

				v.modelEnt = nil

			end

			

		elseif (v.type == "Sprite" and v.sprite and v.sprite != "" and (!v.spriteMaterial or v.createdSprite != v.sprite) and file.Exists("materials/"..v.sprite..".vmt", "GAME")) then

			

			SCKDebug("Creating new sprite "..v.sprite)

			

			local name = v.sprite.."-"

			local params = { ["$basetexture"] = v.sprite }

			// make sure we create a unique name based on the selected options

			local tocheck = { "nocull", "additive", "vertexalpha", "vertexcolor", "ignorez" }

			for i, j in pairs( tocheck ) do

				if (v[j]) then

					params["$"..j] = 1

					name = name.."1"

				else

					name = name.."0"

				end

			end



			v.createdSprite = v.sprite

			v.spriteMaterial = CreateMaterial(name,"UnlitGeneric",params)

			

		end

	end

	

end



function SWEP:Think()

	

	self:CreateModels( self.v_models )

	self:CreateModels( self.w_models )

	

	// Some hacky shit to get 3rd person view compatible with 

	// other addons that override CalcView

	self:CalcViewHookManagement()

	

	/************************

		Camera fiddling

	************************/

	self.useThirdPerson = self:GetThirdPerson()

	

	local mx, my = gui.MousePos()

	local diffx, diffy = (mx - self.mlast_x), (my - self.mlast_y)

	

	if (input.IsMouseDown(MOUSE_RIGHT) and !(diffx > 40 or diffy > 40) and self.Frame and self.Frame:IsVisible()) then // right mouse press without sudden jumps

	

		if (self.useThirdPerson) then

		

			if (input.IsKeyDown(KEY_E)) then

				self.thirdPersonDis = math.Clamp( self.thirdPersonDis + diffy, 10, 500 )

			else

				self.thirdPersonAngle = self.thirdPersonAngle + Angle( diffy/2, diffx/2, 0 )

			end

			

		else

			// ironsight adjustment

			for k, v in pairs( self.ir_drag ) do

				if (v[1]) then

					local temp = GetConVar( "_sp_ironsight_"..k ):GetFloat()

					if (v[2] == "x") then

						local add = -(diffx/v[3])

						if (self.ViewModelFlip) then add = add*-1 end

						RunConsoleCommand( "_sp_ironsight_"..k, temp + add )

					elseif (v[2] == "-x") then

						local add = diffx/v[3]

						if (self.ViewModelFlip) then add = add*-1 end

						RunConsoleCommand( "_sp_ironsight_"..k, temp + add )

					elseif (v[2] == "y") then

						RunConsoleCommand( "_sp_ironsight_"..k, temp - diffy/v[3] )

					end

				end

			end

		

		end

		

	end

	

	self.mlast_x, self.mlast_y = mx, my

end



function SWEP:RemoveModels()



	SCKDebug("Removing models")



	for k, v in pairs( self.v_models ) do

		if (IsValid( v.modelEnt )) then v.modelEnt:Remove() end

	end

	for k, v in pairs( self.w_models ) do

		if (IsValid( v.modelEnt )) then v.modelEnt:Remove() end

	end

	self.v_models = {}

	self.w_models = {}

	

	if (IsValid(self.world_model)) then

		self.world_model:Remove()

		self.world_model = nil

		self.cur_wmodel = nil

	end

end



function SWEP:GetBoneOrientation( basetab, name, ent, bone_override, buildup )

	

	local bone, pos, ang

	local tab = basetab[name]

	

	if (tab.rel and tab.rel != "") then



		local v = basetab[tab.rel]

		

		if (!v) then return end

		

		if (!buildup) then

			buildup = {}

		end

		

		table.insert(buildup, name)

		if (table.HasValue(buildup, tab.rel)) then return end

		

		// Technically, if there exists an element with the same name as a bone

		// you can get in an infinite loop. Let's just hope nobody's that stupid.

		pos, ang = self:GetBoneOrientation( basetab, tab.rel, ent, nil, buildup )

		

		if (!pos) then return end

		

		pos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z

		if (v.angle) then

			ang:RotateAroundAxis(ang:Up(), v.angle.y)

			ang:RotateAroundAxis(ang:Right(), v.angle.p)

			ang:RotateAroundAxis(ang:Forward(), v.angle.r)

		end

			

	else

	

		bone = ent:LookupBone(bone_override or tab.bone)



		if (!bone) then return end

		

		pos, ang = Vector(0,0,0), Angle(0,0,0)

		local m = ent:GetBoneMatrix(bone)

		if (m) then

			pos, ang = m:GetTranslation(), m:GetAngles()

		end

		

		if (IsValid(self.Owner) and self.Owner:IsPlayer() and 

			ent == self.Owner:GetViewModel() and self.ViewModelFlip) then

			ang.r = -ang.r // Fixes mirrored models

		end

	

	end

	

	return pos, ang

end



local allbones

local hasGarryFixedBoneScalingYet = false



function SWEP:UpdateBonePositions(vm)

	

	if self.v_bonemods then

		

		if (!vm:GetBoneCount()) then return end

		

		// !! WORKAROUND !! //

		// We need to check all model names :/

		local loopthrough = self.v_bonemods

		if (!hasGarryFixedBoneScalingYet) then

			allbones = {}

			for i=0, vm:GetBoneCount() do

				local bonename = vm:GetBoneName(i)

				if (self.v_bonemods[bonename]) then 

					allbones[bonename] = self.v_bonemods[bonename]

				else

					allbones[bonename] = { 

						scale = Vector(1,1,1),

						pos = Vector(0,0,0),

						angle = Angle(0,0,0)

					}

				end

			end

			

			loopthrough = allbones

		end

		// !! ----------- !! //

		

		for k, v in pairs( loopthrough ) do

			local bone = vm:LookupBone(k)

			if (!bone) then continue end

			

			// !! WORKAROUND !! //

			local s = Vector(v.scale.x,v.scale.y,v.scale.z)

			local p = Vector(v.pos.x,v.pos.y,v.pos.z)

			local ms = Vector(1,1,1)

			if (!hasGarryFixedBoneScalingYet) then

				local cur = vm:GetBoneParent(bone)

				while(cur >= 0) do

					local pscale = loopthrough[vm:GetBoneName(cur)].scale

					ms = ms * pscale

					cur = vm:GetBoneParent(cur)

				end

			end

			

			//local bpos = vm:GetBonePosition(bone)

			//local par = vm:GetBoneParent(bone)

			s = s * ms

			

			//SCKDebug("Bone ("..bone..") "..vm:GetBoneName(bone).." rel to p ("..par.."): "..tostring(bpos - (vm:GetBonePosition(vm:GetBoneParent(bone)) or bpos)))

			//local relp = bpos - (vm:GetBonePosition(vm:GetBoneParent(bone)) or bpos)

			//p = relp * ms - relp

			//SCKDebug("Bone ("..bone..") scale = "..tostring(ms).." | newpos = "..tostring(p))

			

			// !! ----------- !! //

			

			if vm:GetManipulateBoneScale(bone) != s then

				vm:ManipulateBoneScale( bone, s )

			end

			if vm:GetManipulateBoneAngles(bone) != v.angle then

				vm:ManipulateBoneAngles( bone, v.angle )

			end

			if vm:GetManipulateBonePosition(bone) != p then

				vm:ManipulateBonePosition( bone, p )

			end

		end

	else

		self:ResetBonePositions(vm)

	end

       

end

 

function SWEP:ResetBonePositions(vm)

	

	if (!vm:GetBoneCount()) then return end

	

	for i=0, vm:GetBoneCount() do

		vm:ManipulateBoneScale( i, Vector(1, 1, 1) )

		vm:ManipulateBoneAngles( i, Angle(0, 0, 0) )

		vm:ManipulateBonePosition( i, Vector(0, 0, 0) )

	end

	

end



/********************************

	All viewmodel drawing magic

*********************************/

SWEP.vRenderOrder = nil

function SWEP:ViewModelDrawn()

	

	//if true then return end

	//SCKDebugRepeat( "SWEP:VMD", "Drawing viewmodel!" )

	

	local vm = self.Owner:GetViewModel()

	if !IsValid(vm) then return end

	

	self:UpdateBonePositions(vm)

	/*if vm.BuildBonePositions ~= self.BuildViewModelBones then

		vm.BuildBonePositions = self.BuildViewModelBones

	end*/



	if (!self.vRenderOrder) then

		

		// we build a render order because sprites need to be drawn after models

		self.vRenderOrder = {}



		for k, v in pairs( self.v_models ) do

			if (v.type == "Model") then

				table.insert(self.vRenderOrder, 1, k)

			elseif (v.type == "Sprite" or v.type == "Quad") then

				table.insert(self.vRenderOrder, k)

			end

		end

		

	end

	

	for k, name in ipairs( self.vRenderOrder ) do

	

		local v = self.v_models[name]

		if (!v) then self.vRenderOrder = nil break end

	

		local model = v.modelEnt

		local sprite = v.spriteMaterial

		

		if (!v.bone) then continue end

		

		local pos, ang = self:GetBoneOrientation( self.v_models, name, vm )

		

		if (!pos) then continue end

		

		if (v.type == "Model" and IsValid(model)) then



			model:SetPos(pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z )

			ang:RotateAroundAxis(ang:Up(), v.angle.y)

			ang:RotateAroundAxis(ang:Right(), v.angle.p)

			ang:RotateAroundAxis(ang:Forward(), v.angle.r)



			model:SetAngles(ang)

			//model:SetModelScale(v.size)

			local matrix = Matrix()

			matrix:Scale(v.size)

			model:EnableMatrix( "RenderMultiply", matrix )

			

			if (v.material == "") then

				model:SetMaterial("")

			elseif (model:GetMaterial() != v.material) then

				model:SetMaterial( v.material )

			end

			

			if (v.skin != model:GetSkin()) then

				model:SetSkin(v.skin)

			end

			

			for k, v in pairs( v.bodygroup ) do

				if (model:GetBodygroup(k) != v) then

					model:SetBodygroup(k, v)

				end

			end

			

			// Ain't working :/

			/*halo.Render({

				Ents = {model},

				Color = Color(255,0,0,200),

				BlurX = 2,

				BlurY = 2,

				DrawPasses = 1,

				Additive = true,

				IgnoreZ = true

			})*/

	

			if (v.surpresslightning) then

				render.SuppressEngineLighting(true)

			end

			

			render.SetColorModulation(v.color.r/255, v.color.g/255, v.color.b/255)

			render.SetBlend(v.color.a/255)

			model:DrawModel()

			render.SetBlend(1)

			render.SetColorModulation(1, 1, 1)

			

			if (v.surpresslightning) then

				render.SuppressEngineLighting(false)

			end

			

		elseif (v.type == "Sprite" and sprite) then

			

			local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z

			render.SetMaterial(sprite)

			render.DrawSprite(drawpos, v.size.x, v.size.y, v.color)

			

		elseif (v.type == "Quad") then

		

			local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z

			ang:RotateAroundAxis(ang:Up(), v.angle.y)

			ang:RotateAroundAxis(ang:Right(), v.angle.p)

			ang:RotateAroundAxis(ang:Forward(), v.angle.r)

			

			cam.Start3D2D(drawpos, ang, v.size)

				draw.RoundedBox( 0, -20, -20, 40, 40, Color(200,0,0,100) )

				surface.SetDrawColor( 255, 255, 255, 100 )

				surface.DrawOutlinedRect( -20, -20, 40, 40 )

				draw.SimpleTextOutlined("12pt arial","12ptFont",0, -12, Color(255,255,255,255), TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP, 1, Color(0,0,0,255))

				draw.SimpleTextOutlined("40x40 box","12ptFont",0, 2, Color(255,255,255,255), TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP, 1, Color(0,0,0,255))

				surface.SetDrawColor( 0, 255, 0, 230 )

				surface.DrawLine( 0, 0, 0, 8 )

				surface.DrawLine( 0, 0, 8, 0 )

			cam.End3D2D()



		end

		

	end

	

end



/********************************

	All worldmodel drawing science

*********************************/

SWEP.wRenderOrder = nil

function SWEP:DrawWorldModel()

	

	//if true then return end

	//SCKDebugRepeat( "SWEP:WMD", "Drawing worldmodel!" )

	

	local wm = self.world_model

	if !IsValid(wm) then return end

	

	if (!self.wRenderOrder) then



		self.wRenderOrder = {}



		for k, v in pairs( self.w_models ) do

			if (v.type == "Model") then

				table.insert(self.wRenderOrder, 1, k)

			elseif (v.type == "Sprite" or v.type == "Quad") then

				table.insert(self.wRenderOrder, k)

			end

		end



	end



	local bone_ent

	

	if (IsValid(self.Owner)) then

		self:SetColor(Color(255,255,255,255))

		self:SetRenderMode(0) 

		wm:SetNoDraw(true)

		if (self.Owner:GetActiveWeapon() != self.Weapon) then return end

		wm:SetParent(self.Owner)

		if (self.ShowWorldModel) then

			wm:DrawModel()

		end

		bone_ent = self.Owner

	else

		// this only happens if the weapon is dropped, which shouldn't happen normally.

		self:SetColor(Color(255,0,0,0))

		self:SetRenderMode(1)

		wm:SetNoDraw(false) // else DrawWorldModel stops being called for some reason

		wm:SetParent(self)

		//wm:SetPos(opos)

		//wm:SetAngles(oang)

		if (self.ShowWorldModel) then

			wm:DrawModel()

		end

	

		// the reason that we don't always use this bone is because it lags 1 frame behind the player's right hand bone when held

		bone_ent = wm

	end

	

	/* BASE CODE FOR NEW SWEPS */

	/*self:DrawModel()

	if (IsValid(self.Owner)) then

		bone_ent = self.Owner

	else

		// when the weapon is dropped

		bone_ent = self

	end*/

	

	for k, name in pairs( self.wRenderOrder ) do

	

		local v = self.w_models[name]

		if (!v) then self.wRenderOrder = nil break end

		

		local pos, ang

		

		if (v.bone) then

			pos, ang = self:GetBoneOrientation( self.w_models, name, bone_ent )

		else

			pos, ang = self:GetBoneOrientation( self.w_models, name, bone_ent, "ValveBiped.Bip01_R_Hand" )

		end

		

		if (!pos) then continue end

		

		local model = v.modelEnt

		local sprite = v.spriteMaterial



		if (v.type == "Model" and IsValid(model)) then



			model:SetPos(pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z )

			ang:RotateAroundAxis(ang:Up(), v.angle.y)

			ang:RotateAroundAxis(ang:Right(), v.angle.p)

			ang:RotateAroundAxis(ang:Forward(), v.angle.r)



			model:SetAngles(ang)

			//model:SetModelScale(v.size)

			local matrix = Matrix()

			matrix:Scale(v.size)

			model:EnableMatrix( "RenderMultiply", matrix )

			

			if (v.material == "") then

				model:SetMaterial("")

			elseif (model:GetMaterial() != v.material) then

				model:SetMaterial( v.material )

			end

			

			if (v.skin != model:GetSkin()) then

				model:SetSkin(v.skin)

			end

			

			for k, v in pairs( v.bodygroup ) do

				if (model:GetBodygroup(k) != v) then

					model:SetBodygroup(k, v)

				end

			end

			

			if (v.surpresslightning) then

				render.SuppressEngineLighting(true)

			end

			

			render.SetColorModulation(v.color.r/255, v.color.g/255, v.color.b/255)

			render.SetBlend(v.color.a/255)

			model:DrawModel()

			render.SetBlend(1)

			render.SetColorModulation(1, 1, 1)

			

			if (v.surpresslightning) then

				render.SuppressEngineLighting(false)

			end

			

		elseif (v.type == "Sprite" and sprite) then

			

			local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z

			render.SetMaterial(sprite)

			render.DrawSprite(drawpos, v.size.x, v.size.y, v.color)

			

		elseif (v.type == "Quad") then

		

			local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z

			ang:RotateAroundAxis(ang:Up(), v.angle.y)

			ang:RotateAroundAxis(ang:Right(), v.angle.p)

			ang:RotateAroundAxis(ang:Forward(), v.angle.r)

			

			cam.Start3D2D(drawpos, ang, v.size)

				draw.RoundedBox( 0, -20, -20, 40, 40, Color(200,0,0,100) )

				surface.SetDrawColor( 255, 255, 255, 100 )

				surface.DrawOutlinedRect( -20, -20, 40, 40 )

				draw.SimpleTextOutlined("12pt arial","12ptFont",0, -12, Color(255,255,255,255), TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP, 1, Color(0,0,0,255))

				draw.SimpleTextOutlined("40x40 box","12ptFont",0, 2, Color(255,255,255,255), TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP, 1, Color(0,0,0,255))

				surface.SetDrawColor( 0, 255, 0, 230 )

				surface.DrawLine( 0, 0, 0, 8 )

				surface.DrawLine( 0, 0, 8, 0 )

			cam.End3D2D()



		end

		

	end

	

end



function SWEP:Holster()

	self.useThirdPerson = false

	

	local vm = self.Owner:GetViewModel()

	if IsValid(vm) then

		self:ResetBonePositions(vm)

	end

	

	return true

end



local function DrawDot( x, y )



	surface.SetDrawColor(100, 100, 100, 255)

	surface.DrawRect(x - 2, y - 2, 4, 4)

	

	surface.SetDrawColor(255, 255, 255, 255)

	surface.DrawRect(x - 1, y - 1, 2, 2)

	

end



SWEP.FirstTimeOpen = true



function SWEP:DrawHUD()

	

	DrawDot( ScrW()/2, ScrH()/2 )

	DrawDot( ScrW()/2 + 10, ScrH()/2 )

	DrawDot( ScrW()/2 - 10, ScrH()/2 )

	DrawDot( ScrW()/2, ScrH()/2 + 10 )

	DrawDot( ScrW()/2, ScrH()/2 - 10 )

	

	if (self.Frame and self.Frame:IsVisible()) then

		

		self.FirstTimeOpen = false

		local text = ""

		if (self.useThirdPerson) then

			text = "Hold right mouse and drag to rotate. Additionally hold E key to zoom."

		else

			text = "Hold right mouse and drag to adjust ironsights (mode: "..self.cur_drag_mode..")"

		end

		draw.SimpleTextOutlined(text, "default", ScrW()/2, ScrH()/4, Color(255,255,255,255), TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP, 1, Color(20,20,20,255))

		

	elseif (self.FirstTimeOpen) then

		draw.SimpleTextOutlined("Press right mouse to open menu", "default", ScrW()/2, ScrH()/4, Color(255,255,255,255), TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP, 1, Color(20,20,20,255))

	end

	

end



/****** Create model browser *****/

// callback = function( selected_model )

function SWEP:OpenBrowser( current, browse_type, callback )

	

	local wep = self

	wep.browser_callback = callback

	wep.Frame:SetVisible( false )

	

	if (browse_type == "model" and wep.modelbrowser) then

		wep.modelbrowser:SetVisible(true)

		wep.modelbrowser:MakePopup()

		wep.modelbrowser_list.OnRowSelected(nil,nil,current)

		return

	elseif (browse_type == "material" and wep.matbrowser) then

		wep.matbrowser:SetVisible(true)

		wep.matbrowser:MakePopup()

		wep.matbrowser_list.OnRowSelected(nil,nil,current)

		return

	end



	local browser = vgui.Create("DFrame")

	browser:SetSize( 480, ScrH()*0.8 )

	browser:SetPos( 50, 50 )

	browser:SetDraggable( true )

	browser:ShowCloseButton( false )

	browser:SetSizable( true )

	browser:SetDeleteOnClose( false )



	if (browse_type == "model") then

		browser:SetTitle( "Model browser" )

		wep.modelbrowser = browser

	elseif (browse_type == "material") then

		browser:SetTitle( "Material browser" )

		wep.matbrowser = browser

	end

	

	local tree = vgui.Create( "DTree", browser )

	//tree:SetPos( 5, 30 )

	//tree:SetSize( browser:GetWide() - 10, browser:GetTall()-355 )

		tree:SetTall(300)

	tree:DockPadding(5,5,5,5)

	tree:Dock(TOP)

	

	local nodelist = {}

	local filecache = {}

	local checked = {}

	

	local modlist = vgui.Create("DListView", browser)

		modlist:SetMultiSelect(false)

		modlist:SetDrawBackground(true)

		if (browse_type == "model") then

			modlist:AddColumn("Model")

		elseif (browse_type == "material") then

			modlist:AddColumn("Material")

		end

	modlist:DockPadding(5,5,5,0)

	modlist:Dock(FILL)

	

	local bpanel = vgui.Create("DPanel", browser)

		bpanel:SetTall(200)

		bpanel:SetDrawBackground(false)

	bpanel:DockMargin(5,5,5,5)

	bpanel:Dock(BOTTOM)

	

	local modzoom = 30

	local modview 

	

	if (browse_type == "model") then

		modview = vgui.Create("DModelPanel", bpanel)

		modview:SetModel("")

		modview:SetCamPos( Vector(modzoom,modzoom,modzoom/2) )

		modview:SetLookAt( Vector( 0, 0, 0 ) )

	elseif (browse_type == "material") then

		modview = vgui.Create("DImage", bpanel)

		//modview:SetImage("")

	end

	

	modview:SetSize(200, 200)

	modview:Dock(LEFT)

	

	local rpanel = vgui.Create("DPanel", bpanel)

		rpanel:SetDrawBackground(false)

	rpanel:DockPadding(5,0,0,0)

	rpanel:Dock(FILL)

	

	local mdlabel = vgui.Create("DLabel", rpanel)

		mdlabel:SetText( current )

		mdlabel:SizeToContents()

	mdlabel:Dock(TOP)

	

	if (browse_type == "model") then

	

		local zoomslider = vgui.Create( "DNumSlider", rpanel)

			zoomslider:SetText( "Zoom" )

			zoomslider:SetMin( 8 )

			zoomslider:SetMax( 256 )

			zoomslider:SetDecimals( 0 )

			zoomslider:SetValue( modzoom )

			zoomslider.Wang.ConVarChanged = function( panel, value )

				local modzoom = tonumber(value)

				modview:SetCamPos( Vector(modzoom,modzoom,modzoom/2) )

				modview:SetLookAt( Vector( 0, 0, 0 ) )

			end

		zoomslider:Dock(FILL)

		

	end

	

	local selected = ""

	

	modlist.OnRowSelected = function( panel, line, override )

		if (type(override) != "string") then override = nil end // for some reason the list itself throws a panel at it in the callback

		local path = override or modlist:GetLine(line):GetValue(1)



		if (browse_type == "model") then

			modview:SetModel(path)

		elseif (browse_type == "material") then

			if (path:sub( 1, 10 ) == "materials/") then

				path = path:sub( 11 ) // removes the "materials/" part

			end

			path = path:gsub( "%.vmt", "" )

			if (file.Exists( "materials/"..path..".vmt", "GAME" )) then

				modview:SetImage(path)

			end

		end



		mdlabel:SetText(path)

		selected = path

	end

	

	// set the default

	modlist.OnRowSelected(nil,nil,current)

	if (browse_type == "model") then

		wep.modelbrowser_list = modlist

	elseif (browse_type == "material") then

		wep.matbrowser_list = modlist

	end

	

	local cancelbtn = vgui.Create("DButton", rpanel)

		cancelbtn:SetTall(20)

		cancelbtn:SetText("cancel")

		cancelbtn.DoClick = function()

			if (wep.Frame) then

				wep.Frame:SetVisible(true)

			end

			browser:Close()

		end

	cancelbtn:Dock(BOTTOM)

	

	local choosebtn = vgui.Create("DButton", rpanel)

		choosebtn:SetTall(20)

		if (browse_type == "model") then

			choosebtn:SetText("DO WANT THIS MODEL")

		elseif (browse_type == "material") then

			choosebtn:SetText("DO WANT THIS MATERIAL")

		end

	

		choosebtn.DoClick = function()

			if (wep.browser_callback) then

				pcall(wep.browser_callback, selected)

			end

			if (wep.Frame) then

				wep.Frame:SetVisible(true)

			end

			browser:Close()

		end

	choosebtn:DockMargin(0,0,0,5)

	choosebtn:Dock(BOTTOM)

	

	

	

	local LoadDirectories

	local AddNode = function( base, dir, tree_override )

		

		local newpath = base.."/"..dir

		local basenode = nodelist[base]

		

		if (tree_override) then

			newpath = dir

			basenode = tree_override

		end

		

		if (!basenode) then

			print("No base node for \""..tostring(base).."\", \""..tostring(dir).."\", "..tostring(tree_override))

		end

		

		nodelist[newpath] = basenode:AddNode( dir )

		nodelist[newpath].DoClick = function()

			LoadDirectories( newpath )

			modlist:Clear()

			modlist:SetVisible(true)

			

			if (filecache[newpath]) then

				for k, f in pairs(filecache[newpath]) do

					modlist:AddLine(f)

				end

			else

				filecache[newpath] = {}

				local files, folders

				if (newpath:sub(1,9) == "materials") then

					files, folders = file.Find(newpath.."/*.vmt", "GAME")

				else

					files, folders = file.Find(newpath.."/*.mdl", "GAME")

				end

				table.sort(files)

				for k, f in pairs(files) do

					local newfilepath = newpath.."/"..f

					modlist:AddLine(newfilepath)

					table.insert(filecache[newpath], newfilepath)

				end

			end

		end

			

	end

	

	if (browse_type == "model") then

		AddNode( "", "models", tree )

	elseif (browse_type == "material") then

		AddNode( "", "materials", tree )

	end

	

	LoadDirectories = function( v )

		

		if (table.HasValue(checked,v)) then return end

		local files

		files, newdirs = file.Find(v.."/*", "GAME")

		table.insert(checked, v)

		

		table.sort(newdirs)

		

		for _, dir in pairs(newdirs) do

			AddNode( v, dir )

		end



	end

	

	if (browse_type == "model") then

		LoadDirectories( "models" )

	elseif (browse_type == "material") then

		LoadDirectories( "materials" )

	end



	browser:SetVisible( true )

	browser:MakePopup()

	

end



/***************************

			Menu

***************************/

local function CreateMenu( preset )

	

	local wep = GetSCKSWEP( LocalPlayer() )

	if !IsValid(wep) then return nil end

	

	wep.save_data = table.Copy(save_data_template)

	

	if (preset) then

		// use the preset

		for k, v in pairs( preset ) do

			wep.save_data[k] = v

		end

	end



	// Now for the actual menu:		

	local f = vgui.Create("DFrame")

	f:SetSize( 480, ScrH()*0.8 )

	f:SetPos( 50, 50 )

	f:SetTitle( "SWEP Construction Kit" )

	f:SetDraggable( true )

	f:ShowCloseButton( true )

	f:SetSizable( true )

	f:SetDeleteOnClose( false )

	

	local tpanel= vgui.Create( "DPanel", f )

		tpanel:SetDrawBackground(false)

		tpanel:SetTall(20)

	tpanel:DockMargin(0,0,0,5)

	tpanel:Dock(TOP)

	

	local tpsbonelist = vgui.Create( "DComboBox", tpanel )

		tpsbonelist:SetWide(150)

		tpsbonelist:SetToolTip("Bone to focus third person view on")

		tpsbonelist.OnSelect = function( p, index, value )

			wep.tpsfocusbone = value

		end

		tpsbonelist:SetText( wep.tpsfocusbone )

	tpsbonelist:DockMargin(5,0,0,0)

	tpsbonelist:Dock(RIGHT)

	

	local tlabel = vgui.Create( "DLabel", tpanel )

		tlabel:SetText( "Focus:" )

		tlabel:SizeToContents()

		tlabel:SetTall(20)

	tlabel:DockMargin(10,0,0,0)

	tlabel:Dock(RIGHT)

	

	PopulateBoneList( tpsbonelist, LocalPlayer() )

	

	local tbtn = vgui.Create( "DButton", tpanel )

		tbtn:SetText( "Toggle thirdperson" )

		tbtn.DoClick = function()

			RunConsoleCommand("swepck_togglethirdperson")

		end

		

	tbtn:Dock(FILL)

	

	local tab = vgui.Create( "DPropertySheet", f )

	

		wep.ptool = vgui.Create("DPanel", tab)

		wep.ptool.Paint = function() surface.SetDrawColor(70,70,70,255) surface.DrawRect(0,0,wep.ptool:GetWide(),wep.ptool:GetTall()) end

		wep.pweapon = vgui.Create("DPanel", tab)

		wep.pweapon.Paint = function() surface.SetDrawColor(70,70,70,255) surface.DrawRect(0,0,wep.pweapon:GetWide(),wep.pweapon:GetTall()) end

		wep.pironsight = vgui.Create("DPanel", tab)

		wep.pironsight.Paint = function() surface.SetDrawColor(70,70,70,255) surface.DrawRect(0,0,wep.pironsight:GetWide(),wep.pironsight:GetTall()) end

		wep.pmodels = vgui.Create("DPanel", tab)

		wep.pmodels.Paint = function() surface.SetDrawColor(70,70,70,255) surface.DrawRect(0,0,wep.pmodels:GetWide(),wep.pmodels:GetTall()) end

		wep.pwmodels = vgui.Create("DPanel", tab)

		wep.pwmodels.Paint = function() surface.SetDrawColor(70,70,70,255) surface.DrawRect(0,0,wep.pwmodels:GetWide(),wep.pwmodels:GetTall()) end

		

		tab:AddSheet( "Tool", wep.ptool, nil, false, false, "Modify tool settings" )

		tab:AddSheet( "Weapon", wep.pweapon, nil, false, false, "Modify weapon settings" )

		tab:AddSheet( "Ironsights", wep.pironsight, nil, false, false, "Modify ironsights" )

		tab:AddSheet( "View Models", wep.pmodels, nil, false, false, "Modify view models" )

		tab:AddSheet( "World Models", wep.pwmodels, nil, false, false, "Modify world models" )

		

		wep.ptool:DockPadding(5, 5, 5, 5)

		wep.pweapon:DockPadding(5, 5, 5, 5)

		wep.pironsight:DockPadding(5, 5, 5, 5)

		wep.pmodels:DockPadding(5, 5, 5, 5)

		wep.pwmodels:DockPadding(5, 5, 5, 5)

		

	tab:Dock(FILL)

	

	/*****************

		Tool page

	*****************/

	include("weapons/"..wep:GetClass().."/menu/tool.lua")

	

	/*****************

		Weapon page

	*****************/

	include("weapons/"..wep:GetClass().."/menu/weapon.lua")

	

	/*********************

		Ironsights page

	*********************/

	include("weapons/"..wep:GetClass().."/menu/ironsights.lua")

	

	/****************************************

		View models and World models page

	****************************************/

	include("weapons/"..wep:GetClass().."/menu/models.lua")

	

	// finally, return the frame!

	return f



end



function SWEP:OpenMenu( preset )

	if (!self.Frame) then

		self.Frame = CreateMenu( preset )

	end

	

	if (IsValid(self.Frame)) then

		self.Frame:SetVisible(true)

		self.Frame:MakePopup()

	else

		self.Frame = nil

	end

	

end



function SWEP:OnRemove()

	self:CleanMenu()

end



function SWEP:OnDropWeapon()

	self.useThirdPerson = false

	self.LastOwner = nil

	if (!self.Frame) then return end

	self.Frame:Close()

end



function SWEP:CleanMenu()

	self:RemoveModels()

	if (!self.Frame) then return end

	

	self.v_modelListing = nil

	self.w_modelListing = nil

	self.v_panelCache = {}

	self.w_panelCache = {}

	self.Frame:Remove()

	self.Frame = nil

end



function SWEP:HUDShouldDraw( el )

	return el != "CHudAmmo" and el != "CHudSecondaryAmmo"

end



/***************************

	Third person view

***************************/

function TPCalcView(pl, pos, angles, fov)



	local wep = pl:GetActiveWeapon()

	if (!IsValid(wep) or !wep.IsSCK or !wep.useThirdPerson) then

		wep.useThirdPerson = false

		return 

	end

	

	local look_pos = pos

	local rhand_bone = pl:LookupBone(wep.tpsfocusbone)

	if (rhand_bone) then

		look_pos = pl:GetBonePosition( rhand_bone )

	end

	

	local view = {}

	view.origin = look_pos + ((pl:GetAngles()+wep.thirdPersonAngle):Forward()*wep.thirdPersonDis)

	view.angles = (look_pos - view.origin):Angle()

	view.fov = fov

 

	return view

end



oldCVHooks = {}

hooksCleared = false

local function CVHookReset()

	

	//print("Hook reset")

	hook.Remove( "CalcView", "TPCalcView" )

	for k, v in pairs( oldCVHooks ) do

		hook.Add("CalcView", k, v)

	end

	oldCVHooks = {}

	hooksCleared = false

		

end	



function SWEP:CalcViewHookManagement()

	

	if (!hooksCleared) then

		

		local CVHooks = hook.GetTable()["CalcView"]

		if CVHooks then

		

			for k, v in pairs( CVHooks ) do

				oldCVHooks[k] = v

				hook.Remove( "CalcView", k )

			end

		

		end

		

		hook.Add("CalcView", "TPCalcView", TPCalcView)

		hooksCleared = true

	else

		timer.Create("CVHookReset", 2, 1, CVHookReset)

	end

	

end	



hook.Add("ShouldDrawLocalPlayer", "ThirdPerson", function(pl)

	local wep = pl:GetActiveWeapon()

	if (wep.useThirdPerson) then

		return true

	end

end)