DModelPanel Holding Weapons Script

Hey everyone,

It took many hours scouring the forums and asking for help in the discord to finally get a working solution for allowing DModelPanel models to hold weapons. Alot of the older posts on this subject had broken or outdated code. I kind of just spliced it all together and made it work.

How you use it is use ExtModelPanel instead of DModelPanel or you can rename it at the bottom of the code. Then you would use panel:SetWeaponModel(mdl) to call it. Hope this helps.

local PANEL = {}

AccessorFunc(PANEL, "Weapon", "Weapon")

function PANEL:SetModel(mdl)
	if IsValid(self.Entity) then
		self.Entity:Remove()
		self.Entity = nil
	end
	if IsValid(self.Weapon) then
		self.Weapon:Remove()
		self.Weapon = nil
	end
	if not ClientsideModel then return end
	
	self.Entity = ClientsideModel(mdl, RENDER_GROUP_OPAQUE_ENTITY)
	if not IsValid(self.Entity) then return end
	self.Entity:SetNoDraw(true)

	local seq = self.Entity:LookupSequence("walk_all")
	if seq <= 0 then seq = self.Entity:LookupSequence("WalkUnarmed_all") end
	if seq <= 0 then seq = self.Entity:LookupSequence("walk_all_moderate") end
	if seq > 0 then self.Entity:ResetSequence(seq) end
end

function PANEL:SetWeaponModel(mdl)
	if not IsValid(self.Entity) then return end
	
	if IsValid(self.Weapon) then
		self.Weapon:Remove()
		self.Weapon = nil
	end
	if not ClientsideModel then return end

	self.Weapon = ClientsideModel(mdl, RENDER_GROUP_OPAQUE)

	if not IsValid(self.Weapon) then return end
	self.Weapon:SetNoDraw(true)
	self.Weapon:SetParent(self.Entity)
	self.Weapon:AddEffects(EF_BONEMERGE)
end

function PANEL:GetWeaponModel()
	return IsValid(self.Weapon) and self.Weapon:GetModel()
end

function PANEL:DrawModel()
	local curparent = self
	local leftx, topy = self:LocalToScreen( 0, 0 )
	local rightx, bottomy = self:LocalToScreen( self:GetWide(), self:GetTall() )
	while ( curparent:GetParent() != nil ) do
		curparent = curparent:GetParent()

		local x1, y1 = curparent:LocalToScreen( 0, 0 )
		local x2, y2 = curparent:LocalToScreen( curparent:GetWide(), curparent:GetTall() )

		leftx = math.max( leftx, x1 )
		topy = math.max( topy, y1 )
		rightx = math.min( rightx, x2 )
		bottomy = math.min( bottomy, y2 )
		previous = curparent
	end

	render.SetScissorRect(leftx, topy, rightx, bottomy, true)

	self.Entity:DrawModel()
	if IsValid(self.Weapon) then
		self.Weapon:DrawModel()
	end

	render.SetScissorRect(0, 0, 0, 0, false)
end

function PANEL:Paint()
	if not IsValid(self.Entity) then return end
	
	self:LayoutEntity(self.Entity, self.Weapon)
	
	local x, y = self:LocalToScreen(0, 0)
	local w, h = self:GetSize()
	local ang = self.aLookAngle or (self.vLookatPos - self.vCamPos):Angle()
	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

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

vgui.Register("ExtModelPanel", PANEL, "DModelPanel")
1 Like