Widgets

Alright, I’ve started a widgets system, similar to widgets on most OSes. I’ve never done this kind of thing, but I was wondering how I’d get this to work.

[lua]
Widget = {}
Widgets = {}

function Widget.Position(x,y)
	return {x,y}
end

function Widget.Add(widgtable)
	Widgets[widgtable.Name] = widgtable
	return Widgets[widgtable.Name]
end

function Widget.GetByName(name)
	return Widgets[name]
end

function Widget.GetByKValue(key)
	return Widgets[k]
end

function Widget:RemoveWidget()
	self = nil
end

function Widget:GetWidgetPos()
	return {self.YPos, self.XPos}
end

function Widget:SetWidgetPos(pos)
	if pos.x == 0 or pos.x == nil then pos.x = self:GetPos()[1] end
	if pos.y == 0 or pos.y == nil then pos.y = self:GetPos()[2] end
	self:SetWidgetXPos(pos.x)
	self:SetWidgetYPos(pos.y)
end

function Widget:ScaleWidget(newscale)
	self.Scale = newscale
end

function Widget:SetWidgetXPos(newpos)
	self.Xpos = newpos
end

function Widget:SetSetWidgetYPos(newpos)
	self.Ypos = newpos
end

function Widget:DrawWidget()
	Scale = self.Scale 
	DrawYPos = self.Ypos
	DrawXPos = self.Xpos
	for k,v in pairs(self.Parts) do
		print(k)
		print(v)
		v.Func(Scale,DrawYPos,DrawXPos)
	end
end

function Widget.HUDThink()
	for k,v in pairs(Widgets) do
		print(v)
		v:DrawWidget()
	end
end
hook.Add("HUDPaint", "HUD_WIDGETS", Widget.HUDThink)

function Widget.DrawWidgetBox( RoundBy, PercX, PercY, PercWidth, PercHeight, BoxColor, Scalar, DrawYpos, DrawXPos, AdjustX, AdjustY)

	-- Doing some checks
	if PercWidth == 0 or PercHeight == 0 then
		print("Percentages can't be 0!")
		return
	end
	
	if DrawYPos == nil then DrawYPos = 0 end
	if DrawXPos == nil then DrawXPos = 0 end
	
	if AdjustX == nil then AdjustX = 0 end
	if AdjustY == nil then AdjustY = 0 end
	-- Done doing checks

	-- Some simple math to decide how big the box will be
	ScrHe = ScrH()
	ScrWe = ScrW()
	BoxHeight = ((ScrHe*PercHeight)/100)*Scalar
	BoxWidth = ((ScrWe*PercWidth)/100)*Scalar
	--
	print(BoxHeight)

	-- Some simple math to decide where the box will be placed
	if DrawYPos != 0 and PercY != 0 then
		BoxY = (ScrHe*(PercY-DrawYPos))/100 
	elseif DrawYPos != 0 then
		BoxY = (ScrHe*DrawYPos)/100
	elseif PercY != 0 then
		BoxY = (ScrHe*PercY)/100
	else
		BoxY = 0 
	end
	
	if DrawXPos != 0 and PercX != 0 then
		BoxX = (ScrWe*(PercX-DrawXPos))/100 
	elseif DrawXPos != 0 then
		BoxX = (ScrWe*DrawXPos)/100
	elseif PercX != 0 then
		BoxX = (ScrWe*PercX)/100
	else
		BoxX = 0 
	end
	--

	draw.RoundedBox( RoundBy, BoxX, BoxY, BoxWidth, BoxHeight, BoxColor)

end

-- This part is SUPER messy, so watch out!
WIDG = {}
WIDG.Name = "TestWidget" -- Almost all work on widgets is done with their names.
WIDG.Parts = {}
WIDG.Parts.One = {} -- Defind the parts, can be named anything
WIDG.Parts.Two = {}

function WIDG.Parts.One.Func(Scalar, DrawYPos, DrawXPos) -- Define the part one function
	Widget.DrawWidgetBox( 8, 0, 0, 10, 2, Color(2,2,2,255), Scalar, DrawYpos, DrawXPos)
end
WIDG.Parts.One.Adjust = false

function WIDG.Parts.Two.Func(Scalar, DrawYPos, DrawXPos) -- Define the part two function
	Widget.DrawWidgetBox( 8, 0, 2, 10, 2, Color(255,50,50,255), Scalar, DrawYpos, DrawXPos)
end
WIDG.Parts.Two.Adjust = true
WIDG.Parts.Two.X = 0 
WIDG.Parts.Two.Y = 1 -- Parenting the Y axis placement of this object to the first part.
-- This makes it so part 1 and part 2 will NEVER overlap. This uhh isn't done yet.

WIDG.Scale = 1 -- The default scale of the boxes.
WIDG.YPos = 0 -- The default Y position modifier.
WIDG.XPos = 0 -- The default X position modifier.
testwidg = Widget.Add(WIDG) -- And tada we create our widget

[/lua]

None of the Widget:Function()s work. Do I have to create a metatable for them?

This is my vector meta table for Gmod 9. Should work for Gmod10, all you gotta do is deform it for your addon.

[lua]
vec = {}

function vec.new (t)
  local vector = {}
  setmetatable(vector, vec.mt)
  for _, l in ipairs(t) do vector[l] = true end
  return vector
end

function vec.add (a,b)
	if ( tonumber(b) ) then
		return Vector( tonumber(a.x)+tonumber(b), tonumber(a.y)+tonumber(b), tonumber(a.z)+tonumber(b) )	
	elseif ( tonumber(v1) ) then
		return Vector( v2.x-v1, v2.y-v1, v2.z-v1 )	
	end
	return Vector( tonumber(a.x)+tonumber(b.x), tonumber(a.y)+tonumber(b.y), tonumber(a.z)+tonumber(b.z) )
end

function vec.multiply (a,b)
	if ( tonumber(b) ) then
		return Vector( tonumber(a.x)*tonumber(b), tonumber(a.y)*tonumber(b), tonumber(a.z)*tonumber(b) )	
	elseif ( tonumber(v1) ) then
		return Vector( v2.x*v1, v2.y*v1, v2.z*v1 )	
	end
	return Vector( tonumber(a.x)*tonumber(b.x), tonumber(a.y)*tonumber(b.y), tonumber(a.z)*tonumber(b.z) )
end

function vec.divide (a,b)
	if ( tonumber(b) ) then
		return Vector( tonumber(a.x)/tonumber(b), tonumber(a.y)/tonumber(b), tonumber(a.z)/tonumber(b) )	
	elseif ( tonumber(v1) ) then
		return Vector( v2.x*v1, v2.y*v1, v2.z*v1 )	
	end
	return Vector( tonumber(a.x)/tonumber(b.x), tonumber(a.y)/tonumber(b.y), tonumber(a.z)/tonumber(b.z) )
end

function Vector(x,y,z)
	VEC = vec.new{}
	VEC.x = x
	VEC.y = y
	VEC.z = z
	
	_OpenScript( "includes/vector.lua" );
	
	return VEC
end

vec.mt = {}

vec.mt.__add = vec.add
vec.mt.__mul = vec.multiply
vec.mt.__div = vec.divide
[/lua]

Well, I’m going with that approach I’ve decided, thanks much.

[lua]

Widget = {}
Widgets = {}
Widgets.mt = {}
Widgets.Proto = {}
Widgets.Proto.Scale = 1
Widgets.Proto.DrawYPos = 0
Widgets.Proto.DrawXPos = 0
Widgets.Proto.Func = function() end

Widgets.mt.__index = 
function (table, key)
  return Widgets.Proto[key]
end

-- Adding/Removing
function Widget.Add(name)
	Widgets[name] = {}
	setmetatable(Widgets[name],Widgets.mt)
	Widgets[name].Parts = {}
	return Widgets[name]
end

function Widget.AddPart(widget,name,drawfunc)
	widget.Parts[name].Func = drawfunc
end

function Widget.Remove(widget)
	widget = nil
end

-- Referencing widgets by other things...
function Widget.GetByName(name)
	return Widgets[name]
end

function Widget.GetByKValue(key)
	return Widgets[k]
end

-- Working with position
function Widget.Position(x,y)
	return {x,y}
end

function Widget.GetPos(widget)
	return {widget.YPos, widget.XPos}
end

function Widget.SetPos(widget,pos)
	if pos[1] == 0 or pos[1] == nil then pos[1] = Widget.GetPos(widget)[1] end
	if pos[2] == 0 or pos[2] == nil then pos[2] = self:GetPos(widget)[2] end
	Widget.SetXPos(widget,pos[1])
	Widget.SetYPos(widget,pos[2])
end

function Widget.Scale(widget,newscale)
	widget.Scale = newscale
end

function Widget.SetXPos(widget,newpos)
	widget.Xpos = newpos
end

function Widget.SetYPos(widget,newpos)
	widget.Ypos = newpos
end

-- Working with parts.

function Widget.SetParent(p1,p2,relation)
	p1.Adjust = true
	

-- Drawing and HUD stuff

function Widget.Draw(widget)
	Scale = widget.Scale 
	DrawYPos = widget.Ypos
	DrawXPos = widget.Xpos
	for k,v in pairs(widget.Parts) do
		print(k)
		print(v)
		v.Func(Scale,DrawYPos,DrawXPos)
	end
end

function Widget.HUDThink()
	for k,v in pairs(Widgets) do
		print(v)
		v:DrawWidget()
	end
end
hook.Add("HUDPaint", "HUD_WIDGETS", Widget.HUDThink)

function Widget.DrawWidgetBox( RoundBy, PercX, PercY, PercWidth, PercHeight, BoxColor, Scalar, DrawYPos, DrawXPos, AdjustX, AdjustY)

	-- Doing some checks
	if PercWidth == 0 or PercHeight == 0 then
		print("Percentages can't be 0!")
		return
	end
	
	if DrawYPos == nil then DrawYPos = 0 end
	if DrawXPos == nil then DrawXPos = 0 end
	
	if AdjustX == nil then AdjustX = 0 end
	if AdjustY == nil then AdjustY = 0 end
	-- Done doing checks

	-- Some simple math to decide how big the box will be
	ScrHe = ScrH()
	ScrWe = ScrW()
	BoxHeight = ((ScrHe*PercHeight)/100)*Scalar
	BoxWidth = ((ScrWe*PercWidth)/100)*Scalar
	--
	print(BoxHeight)

	-- Some simple math to decide where the box will be placed
	if DrawYPos != 0 and PercY != 0 then
		BoxY = (ScrHe*(PercY-DrawYPos))/100 
	elseif DrawYPos != 0 then
		BoxY = (ScrHe*DrawYPos)/100
	elseif PercY != 0 then
		BoxY = (ScrHe*PercY)/100
	else
		BoxY = 0 
	end
	
	if DrawXPos != 0 and PercX != 0 then
		BoxX = (ScrWe*(PercX-DrawXPos))/100 
	elseif DrawXPos != 0 then
		BoxX = (ScrWe*DrawXPos)/100
	elseif PercX != 0 then
		BoxX = (ScrWe*PercX)/100
	else
		BoxX = 0 
	end
	--

	draw.RoundedBox( RoundBy, BoxX, BoxY, BoxWidth, BoxHeight, BoxColor)

end

WIDG = Widget.Add("TestWidg")
TestWidgP1 = Widget.AddPart(WIDG,
			   "Part1",
			   function(Scalar, DrawYPos, DrawXPos) 
			   Widget.DrawWidgetBox( 8, 0, 0, 10, 2, Color(0,0,0,255), Scalar, DrawYPos, DrawXPos, AdjustX, AdjustY)
			   end)
TestWidgP2 = Widget.AddPart(WIDG,
			   "Part1",
			   function(Scalar, DrawYPos, DrawXPos) 
			   Widget.DrawWidgetBox( 8, 0, 0, 10, 2, Color(0,0,0,255), Scalar, DrawYPos, DrawXPos, AdjustX, AdjustY)
			   end)

[/lua]

Dunno if this works. Will try in the morning. Also suggestions and critique would be awesome.