It is currently March 29th, 2024, 1:22 pm

Lua Abstraction & Hardware Detection & Dynamic Skin Layout

Tips and Tricks from the Rainmeter Community
ailia
Posts: 34
Joined: August 6th, 2012, 9:56 pm
Location: Lurking

Lua Abstraction & Hardware Detection & Dynamic Skin Layout

Post by ailia »

Rainmeter 2.4 beta (r1593) REQUIRED
Definetly still a work in progress (lets call it beta 1). Autodetect CPU physical and logical core count, hard drive letters and set up everything for automated lua skin layout. The lua abstraction using metatables makes accessing and modifying meters, measures and variables from lua very simple.

Currently supports:
16 Logial/physical CPU cores (temp, activity, hyperthreading detection, intel core parking)
12 hard disks (total space, free space, activity)
Ram space & Activity
Network i/o with moving average for max value (helps with display on bar/roundline)
Pushes cpu/disk count to variables for skins to be able to generate layout for the users exact hardware
Autodetect Hardware Network Interface

To do:
Detect and make avaliable GPU count and properties (working on a plugin to handle ati & nvidia)
Support multiple network interfaces, seperate wired from wireless

measures.inc

Code: Select all

[IsLogical]
Measure=Registry

[IsPhysical]
Measure=Plugin
Plugin=CoreTemp

[IsDisk]
Measure=FreeDiskSpace

[IsNetwork]
Measure=Registry

[Full]
Measure=CALC
Formula=1
UpdateDivider=-1

[Script]
Measure=Script
DynamicVariables=1
ScriptFile=measures.lua
UpdateDivider=-1

[debug]
Meter=String

[CPU1]
Measure=CPU
[CPUp1]
Measure=Plugin
Plugin=Perfmon
[CPUt1]
Measure=Plugin
Plugin=CoreTemp
[CPU2]
Measure=CPU
[CPUp2]
Measure=Plugin
Plugin=Perfmon
[CPUt2]
Measure=Plugin
Plugin=CoreTemp
[CPU3]
Measure=CPU
[CPUp3]
Measure=Plugin
Plugin=Perfmon
[CPUt3]
Measure=Plugin
Plugin=CoreTemp
[CPU4]
Measure=CPU
[CPUp4]
Measure=Plugin
Plugin=Perfmon
[CPUt4]
Measure=Plugin
Plugin=CoreTemp
[CPU5]
Measure=CPU
[CPUp5]
Measure=Plugin
Plugin=Perfmon
[CPUt5]
Measure=Plugin
Plugin=CoreTemp
[CPU6]
Measure=CPU
[CPUp6]
Measure=Plugin
Plugin=Perfmon
[CPUt6]
Measure=Plugin
Plugin=CoreTemp
[CPU7]
Measure=CPU
[CPUp7]
Measure=Plugin
Plugin=Perfmon
[CPUt7]
Measure=Plugin
Plugin=CoreTemp
[CPU8]
Measure=CPU
[CPUp8]
Measure=Plugin
Plugin=Perfmon
[CPUt8]
Measure=Plugin
Plugin=CoreTemp
[CPU9]
Measure=CPU
[CPUp9]
Measure=Plugin
Plugin=Perfmon
[CPUt9]
Measure=Plugin
Plugin=CoreTemp
[CPU10]
Measure=CPU
[CPUp10]
Measure=Plugin
Plugin=Perfmon
[CPUt10]
Measure=Plugin
Plugin=CoreTemp
[CPU11]
Measure=CPU
[CPUp11]
Measure=Plugin
Plugin=Perfmon
[CPUt11]
Measure=Plugin
Plugin=CoreTemp
[CPU12]
Measure=CPU
[CPUp12]
Measure=Plugin
Plugin=Perfmon
[CPUt12]
Measure=Plugin
Plugin=CoreTemp
[CPU13]
Measure=CPU
[CPUp13]
Measure=Plugin
Plugin=Perfmon
[CPUt13]
Measure=Plugin
Plugin=CoreTemp
[CPU14]
Measure=CPU
[CPUp14]
Measure=Plugin
Plugin=Perfmon
[CPUt14]
Measure=Plugin
Plugin=CoreTemp
[CPU15]
Measure=CPU
[CPUp15]
Measure=Plugin
Plugin=Perfmon
[CPUt15]
Measure=Plugin
Plugin=CoreTemp
[CPU16]
Measure=CPU
[CPUp16]
Measure=Plugin
Plugin=Perfmon
[CPUt16]
Measure=Plugin
Plugin=CoreTemp

[RS]
Measure=PhysicalMemory
AverageSize=4

[RA]
Measure=Plugin
Plugin=Perfmon
PerfMonObject="Memory"
PerfMonCounter="Pages/sec"
AverageSize=4

[Disk1s]
Measure=FREEDISKSPACE
[Disk1a]
Measure=Plugin
Plugin=Perfmon
[Disk2s]
Measure=FREEDISKSPACE
[Disk2a]
Measure=Plugin
Plugin=Perfmon
[Disk3s]
Measure=FREEDISKSPACE
[Disk3a]
Measure=Plugin
Plugin=Perfmon
[Disk4s]
Measure=FREEDISKSPACE
[Disk4a]
Measure=Plugin
Plugin=Perfmon
[Disk5s]
Measure=FREEDISKSPACE
[Disk5a]
Measure=Plugin
Plugin=Perfmon
[Disk6s]
Measure=FREEDISKSPACE
[Disk6a]
Measure=Plugin
Plugin=Perfmon
[Disk7s]
Measure=FREEDISKSPACE
[Disk7a]
Measure=Plugin
Plugin=Perfmon
[Disk8s]
Measure=FREEDISKSPACE
[Disk8a]
Measure=Plugin
Plugin=Perfmon
[Disk9s]
Measure=FREEDISKSPACE
[Disk9a]
Measure=Plugin
Plugin=Perfmon
[Disk10s]
Measure=FREEDISKSPACE
[Disk10a]
Measure=Plugin
Plugin=Perfmon
[Disk11s]
Measure=FREEDISKSPACE
[Disk11a]
Measure=Plugin
Plugin=Perfmon
[Disk12s]
Measure=FREEDISKSPACE
[Disk12a]
Measure=Plugin
Plugin=Perfmon

[NIs]
Measure=NetIn
MaxValue=([NIsmm])
AverageSize=20
DynamicVariables=1
[NIsC]
Measure=Calc
Formula=([NIs])
MaxValue=([NIsmm])
DynamicVariables=1
[NIsm]
Measure=Calc
Formula=([NIs])
AverageSize=40
DynamicVariables=1
[NIsmm]
Measure=Calc
Formula=([NIsm]<10240?10240:[NIsm])
AverageSize=40
DynamicVariables=1
[NIt]
Measure=NetIn
Cumulative=1

[NOs]
Measure=NetOut
MaxValue=([NOsmm])
AverageSize=20
DynamicVariables=1
[NOsC]
Measure=Calc
Formula=([NOs])
MaxValue=([NOsmm])
DynamicVariables=1
[NOsm]
Measure=Calc
Formula=([NOs])
AverageSize=40
DynamicVariables=1
[NOsmm]
Measure=Calc
Formula=([NOsm]<10240?10240:[NOsm])
AverageSize=40
DynamicVariables=1
[NOt]
Measure=NetOut
Cumulative=1

[GPU1t]
Measure=Plugin
Plugin=ATIPlugin.dll
MeasureID=Temperature
AdapterID=1
AverageSize=20
MinValue=50
MaxValue=80
[GPU1a]
Measure=Plugin
Plugin=ATIPlugin.dll
MeasureID=Activity
AdapterID=1
AverageSize=20
MinValue=0
MaxValue=100
measures.lua

Code: Select all

function Initialize()
	meta()
	AvgTiny=4
	AvgShort=10
	AvgLong=AvgShort*4
	HWDetect()
end

function HWDetect()
	logicalcores=0
	physicalcores=0
	diskcount=0
	physicalnetwork=0
	measures['IsLogical'].RegHKey='HKEY_LOCAL_MACHINE'
	measures['IsLogical'].RegValue='FeatureSet'
	measures['IsPhysical'].CoreTempType='Temperature'
	measures['IsDisk'].Total=1
	measures['IsNetwork'].RegHKey='HKEY_LOCAL_MACHINE'
	measures['IsNetwork'].RegValue='Description'
	for i=26,1,-1 do
		measures['IsLogical'].RegKey='HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\'..(i-1)
		measures['IsPhysical'].CoreTempIndex=i-1
		measures['IsDisk'].Drive=string.char(91-i) ..':\\'
		measures['IsNetwork'].RegKey='SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards\\'..(i)
		measures['IsPhysical'].UpdateMeasure()
		measures['IsLogical'].UpdateMeasure()
		measures['IsDisk'].UpdateMeasure()
		measures['IsNetwork'].UpdateMeasure()
		if measures['IsPhysical'].Value > 0 then physicalcores=math.max(physicalcores,i) end
		if measures['IsLogical'].Value > 0 then 
			logicalcores=math.max(logicalcores,i) 
			measures['CPU' .. i].Processor=i
			measures['CPU' .. i].AverageSize=AvgShort
			measures['CPUp' .. i].PerfMonObject='Processor Information'
			measures['CPUp' .. i].PerfMonCounter='Parking Status'
			measures['CPUp' .. i].PerfMonInstance='0,'..(i-1)
			measures['CPUp' .. i].PerfMonDifference=0
			measures['CPUt' .. i].CoreTempType='Temperature'
			if physicalcores<logicalcores then
				measures['CPUt' .. i].CoreTempIndex=math.ceil(i/2.0)-1
			else
				measures['CPUt' .. i].CoreTempIndex=i-1
			end
			measures['CPUt' .. i].AverageSize=AvgShort
		else
			measures['CPU' .. i].Disabled=1
			measures['CPUp' .. i].Disabled=1
			measures['CPUt' .. i].Disabled=1
		end
		if measures['IsDisk'].Value > 0 then
			diskcount = diskcount + 1
			measures['Disk'..diskcount..'s'].Drive=string.char(91-i) ..':\\'
			measures['Disk'..diskcount..'s'].InvertMeasure=1
			measures['Disk'..diskcount..'s'].UpdateDivider=300
			measures['Disk'..diskcount..'a'].PerfMonObject='LogicalDisk'
			measures['Disk'..diskcount..'a'].PerfMonCounter='% Disk Time'
			measures['Disk'..diskcount..'a'].PerfMonInstance=string.char(91-i) ..':'
			measures['Disk'..diskcount..'a'].AverageSize=AvgTiny
		end
		if string.len(measures['IsNetwork'].String) > 1 then
			physicalnetwork = math.max(i,physicalnetwork)
		end
	end
	for i=diskcount,12 do
		measures['Disk'..i..'s'].Disabled=1
		measures['Disk'..i..'a'].Disabled=1
	end
	measures['IsLogical'].Disabled=1
	measures['IsPhysical'].Disabled=1
	measures['IsDisk'].Disabled=1
	measures['IsNetwork'].Disabled=1
	measures['NIs'].Interface=physicalnetwork-1
	measures['NIt'].Interface=physicalnetwork-1
	measures['NOs'].Interface=physicalnetwork-1
	measures['NOt'].Interface=physicalnetwork-1
	LC = math.ceil(logicalcores/2)+4
	variables.diskcount = diskcount
	variables.logicalcores = logicalcores
	variables.physicalcores = physicalcores
	variables.physicalnetwork = physicalnetwork
end

function Update()
	return 0
end

function meta()
	local metameters = {}
	local metameter = {}
	metameter.__newindex = function(tb,key,value)
		SKIN:Bang('!SetOption',tb.__metername,key,value)
	end
	metameter.__index = function(tb,key)
		return tb.__meter:GetOption(key)
	end
	metameters.__index = function(tb,key)
		meters[key]={}
		meters[key].__meter = SKIN:GetMeter(key)
		meters[key].__metername = key
		setmetatable(meters[key],metameter)
		return meters[key]
	end
	meters = {}
	setmetatable(meters,metameters)

	local metameasures = {}
	local metameasure = {}
	metameasure.__newindex = function(tb,key,value)
		SKIN:Bang('!SetOption',tb.__measurename,key,value)
	end
	metameasure.__index = function(tb,key)
		if key == 'String' then
			return tb.__measure:GetStringValue()
		elseif key == 'Value' then
			return tonumber(tb.__measure:GetValue())
		elseif key == 'MinValue' then
			return tonumber(tb.__measure:GetMinValue())
		elseif key == 'MaxValue' then
			return tonumber(tb.__measure:GetMaxValue())
		elseif key == 'UpdateMeasure' then
			return function() SKIN:Bang('!UpdateMeasure',tb.__measurename) end
		else
			local t = tb.__measure:GetNumberOption(key,nil)
			return t or tb.__measure:GetOption(key)
		end
	end
	metameasures.__index = function(tb,key)
		measures[key]={}
		measures[key].__measure = SKIN:GetMeasure(key)
		measures[key].__measurename = key
		setmetatable(measures[key],metameasure)
		return measures[key]
	end
	measures = {}
	setmetatable(measures,metameasures)

	local metavariables = {}
	metavariables.__index = function(tb,key)
		return SKIN:GetVariable(key)
	end
	metavariables.__newindex = function(tb,key,value)
		SKIN:Bang('!SetVariable',key,value)
	end
	variables = {}
	setmetatable(variables,metavariables)
end
Example Skin
As Running on my i7 3930k (intel 6 core hyperthreaded)
Idle
Image
Medium Load
Image
100% Load Torture Test
Image

hud.ini

Code: Select all

[Rainmeter]
Author=Ailia
AppVersion=2001000
Update=50
MouseActionCursor=0
@Include=measures.inc

[Metadata]
Name=LuaCore
Version=1
Description=A Lua Driven CPU/Ram/Drive/Temp meter
Instructions=1. Enable      2. ???      3. Profit
License=MIT License

[Layout]
Measure=Script
DynamicVariables=1
ScriptFile=layout.lua
UpdateDivider=10

[C1]
Measure=CALC
[Ca1]
Measure=CALC
[C2]
Measure=CALC
[Ca2]
Measure=CALC
[C3]
Measure=CALC
[Ca3]
Measure=CALC
[C4]
Measure=CALC
[Ca4]
Measure=CALC
[C5]
Measure=CALC
[Ca5]
Measure=CALC
[C6]
Measure=CALC
[Ca6]
Measure=CALC
[C7]
Measure=CALC
[Ca7]
Measure=CALC
[C8]
Measure=CALC
[Ca8]
Measure=CALC

[Me1]
Measure=CALC
[Ms1]
Meter=ROUNDLINE
[M1]
Meter=ROUNDLINE
[Me2]
Measure=CALC
[Ms2]
Meter=ROUNDLINE
[M2]
Meter=ROUNDLINE
[Me3]
Measure=CALC
[Ms3]
Meter=ROUNDLINE
[M3]
Meter=ROUNDLINE
[Me4]
Measure=CALC
[Ms4]
Meter=ROUNDLINE
[M4]
Meter=ROUNDLINE
[Me5]
Measure=CALC
[Ms5]
Meter=ROUNDLINE
[M5]
Meter=ROUNDLINE
[Me6]
Measure=CALC
[Ms6]
Meter=ROUNDLINE
[M6]
Meter=ROUNDLINE
[Me7]
Measure=CALC
[Ms7]
Meter=ROUNDLINE
[M7]
Meter=ROUNDLINE
[Me8]
Measure=CALC
[Ms8]
Meter=ROUNDLINE
[M8]
Meter=ROUNDLINE
[Me9]
Measure=CALC
[Ms9]
Meter=ROUNDLINE
[M9]
Meter=ROUNDLINE
[Me10]
Measure=CALC
[Ms10]
Meter=ROUNDLINE
[M10]
Meter=ROUNDLINE
[Me11]
Measure=CALC
[Ms11]
Meter=ROUNDLINE
[M11]
Meter=ROUNDLINE
[Me12]
Measure=CALC
[Ms12]
Meter=ROUNDLINE
[M12]
Meter=ROUNDLINE
[Me13]
Measure=CALC
[Ms13]
Meter=ROUNDLINE
[M13]
Meter=ROUNDLINE
[Me14]
Measure=CALC
[Ms14]
Meter=ROUNDLINE
[M14]
Meter=ROUNDLINE
[Me15]
Measure=CALC
[Ms15]
Meter=ROUNDLINE
[M15]
Meter=ROUNDLINE
[Me16]
Measure=CALC
[Ms16]
Meter=ROUNDLINE
[M16]
Meter=ROUNDLINE

[RAA]
Measure=CALC

[Rs0]
Meter=ROUNDLINE
[R0]
Meter=ROUNDLINE

[Re1]
Measure=CALC
[Rs1]
Meter=ROUNDLINE
[R1]
Meter=ROUNDLINE

[Re2]
Measure=CALC
[Rs2]
Meter=ROUNDLINE
[R2]
Meter=ROUNDLINE

[DAA]
Measure=CALC

[Ds0]
Meter=ROUNDLINE
[D0]
Meter=ROUNDLINE

[De1]
Measure=CALC
[Ds1]
Meter=ROUNDLINE
[D1]
Meter=ROUNDLINE

[De2]
Measure=CALC
[Ds2]
Meter=ROUNDLINE
[D2]
Meter=ROUNDLINE

[NIs1]
Meter=ROUNDLINE
[NI1]
Meter=ROUNDLINE

[NOs1]
Meter=ROUNDLINE
[NO1]
Meter=ROUNDLINE

[GPUs1]
Meter=ROUNDLINE
[GPUs2]
Meter=ROUNDLINE
[GPU1]
Meter=ROUNDLINE
[GPU2]
Meter=ROUNDLINE
layout.lua

Code: Select all

function Initialize()
	meta()
	Color='0, 0, 0, 160'
	ColorShadow='128, 128, 128, 100'
	ShadowOffset=2
	ArcStart=13
	ArcLength=9
	ArcLineLength=ArcStart-ArcLength
	ArcOffset=2
	RingOffset=ShadowOffset+ArcOffset+ArcLength
	TempLow=50
	TempHigh=80
	AvgTiny=4
	AvgShort=10
	AvgLong=AvgShort*4
end

function Update()
	logicalcores = tonumber(variables.logicalcores)
	if logicalcores > 0 then
		LC = math.ceil(logicalcores/2)+4
		for i=1,16 do
			if i <= logicalcores then
				initcpu(i)
			else
				disable(i)
			end
		end
		initdisk()
		initram()
		initnet()
		initgpu()
		measures.Layout.Disabled=1
	end
	return 0
end

function initcpu(meternumber)
	local ring = math.ceil(meternumber/2)
	if meternumber % 2 == 1 then
		measures['C' .. ring].Formula='(([CPU' .. ring .. ']+[CPU' .. ring+1 .. '])/2)'
		measures['C' .. ring].AverageSize=AvgShort
		measures['C' .. ring].DynamicVariables=1
		if meternumber % 4 < 3 then
			measures['Ca' .. ring].Formula='(Ca' .. ring .. ' + 0.01 + (C' .. ring .. ' * 0.01) ** 2) % 6.283'
		else
			measures['Ca' .. ring].Formula='(Ca' .. ring .. ' - 0.01 - (C' .. ring .. ' * 0.01) ** 2) % 6.283'
		end
	end
	measures['CPUp' .. meternumber].IfEqualValue=0
	measures['CPUp' .. meternumber].IfEqualAction='[!ShowMeter M' .. meternumber .. ']'
	measures['CPUp' .. meternumber].IfAboveValue=0
	measures['CPUp' .. meternumber].IfAboveAction='[!HideMeter M' .. meternumber .. ']'
	measures['Me' .. meternumber].Formula='(CPU' .. meternumber .. ' * 0.007) ** 2 + 0.08'
	measures['Me' .. meternumber].AverageSize=AvgLong
	basestyle(meters['M' .. meternumber],ring+3,false)
	basestyle(meters['Ms' .. meternumber],ring+3,true)
	meters['M' .. meternumber].LineColor='([CPUt' .. meternumber .. ']>' .. TempLow .. '?([CPUt' .. meternumber .. ']>' .. TempHigh .. '?255:([CPUt' .. meternumber .. ']-' .. TempLow .. ')*(255/(' .. TempHigh .. '-' .. TempLow .. '))):0),0,0,160'
	meters['M' .. meternumber].MeasureName='Me'..meternumber
	meters['Ms' .. meternumber].MeasureName='Me'..meternumber
	if meternumber % 2 == 1 then
		meters['M' .. meternumber].StartAngle='[Ca' .. ring .. ']'
		meters['Ms' .. meternumber].StartAngle='[Ca' .. ring .. ']'
	else
		meters['M' .. meternumber].StartAngle='([Ca' .. ring .. '] + 3.14)'
		meters['Ms' .. meternumber].StartAngle='([Ca' .. ring .. '] + 3.14)'
	end
end

function disable(meternumber)
	measures['CPU' .. meternumber].Disabled=1
	measures['CPUp' .. meternumber].Disabled=1
	measures['CPUt' .. meternumber].Disabled=1
	meters['M' .. meternumber].Hidden=1
	meters['Ms' .. meternumber].Hidden=1
	measures['Me' .. meternumber].Disabled=1
end

function basestyle(meter,ring,shadow)
	if shadow == true then
		meter.X=ShadowOffset
		meter.Y=ShadowOffset
		meter.LineColor=ColorShadow
	else
		meter.X=0
		meter.Y=0
		meter.LineColor=Color
	end
	if ring % 2 == 0 and ring>3 then
		meter.RotationAngle=math.pi*-2
	end
	meter.W=(ArcStart+RingOffset*LC+ShadowOffset)*2
	meter.H=(ArcStart+RingOffset*LC+ShadowOffset)*2
	meter.AntiAlias=1
	meter.Solid=1
	meter.StartAngle=math.pi/-2
	meter.DynamicVariables=1
	meter.LineStart=ArcStart+RingOffset*(ring)
	meter.LineLength=ArcLineLength+RingOffset*(ring)
	meter.MeasureName='Full'
end

function initdisk()
	measures.DAA.Formula='(DAA + 0.01 + (Disk1a * 0.0000006) ** 0.5) % 6.283'
	for i=1,2 do
		measures['De' .. i].Formula='(Disk1a * 0.00000004) ** 0.5'
		basestyle(meters['D' .. i],1,false)
		basestyle(meters['Ds' .. i],1,true)
		meters['D' .. i].MeasureName='De'..i
		meters['Ds' .. i].MeasureName='De'..i
		if i % 2 == 1 then
			meters['D' .. i].StartAngle='([DAA] + 3.14)'
			meters['Ds' .. i].StartAngle='([DAA] + 3.14)'
		else
			meters['D' .. i].StartAngle='[DAA]'
			meters['Ds' .. i].StartAngle='[DAA]'
		end
	end
	basestyle(meters.D0,0,false)
	basestyle(meters.Ds0,0,true)
	meters.D0.MeasureName='Disk1s'
end

function initram()
	measures.RAA.Formula='(RAA + 0.01 + (RA * 0.001) ** 0.5) % 6.283'
	for i=1,2 do
		measures['Re' .. i].Formula='(RA * 0.001) ** 0.5'
		basestyle(meters['R' .. i],3,false)
		basestyle(meters['Rs' .. i],3,true)
		meters['R' .. i].MeasureName='Re'..i
		meters['Rs' .. i].MeasureName='Re'..i
		if i % 2 == 1 then
			meters['R' .. i].StartAngle='([RAA] + 3.14)'
			meters['Rs' .. i].StartAngle='([RAA] + 3.14)'
		else
			meters['R' .. i].StartAngle='[RAA]'
			meters['Rs' .. i].StartAngle='[RAA]'
		end
	end
	basestyle(meters.R0,2,false)
	basestyle(meters.Rs0,2,true)
	meters.R0.MeasureName='RS'
end

function initnet()
	basestyle(meters.NI1,logicalcores/2+4,false)
	basestyle(meters.NIs1,logicalcores/2+4,true)
	basestyle(meters.NO1,logicalcores/2+4,false)
	basestyle(meters.NOs1,logicalcores/2+4,true)
	meters.NI1.MeasureName='NIsC'
	meters.NIs1.MeasureName='NIsC'
	meters.NO1.MeasureName='NOsC'
	meters.NOs1.MeasureName='NOsC'
	
	meters.NI1.RotationAngle=math.pi/-2
	meters.NIs1.RotationAngle=math.pi/-2
	meters.NI1.StartAngle=math.pi/4
	meters.NIs1.StartAngle=math.pi/4
	
	meters.NO1.RotationAngle=math.pi/2
	meters.NOs1.RotationAngle=math.pi/2
	meters.NO1.StartAngle=math.pi + math.pi/-4
	meters.NOs1.StartAngle=math.pi + math.pi/-4
end

function initgpu()
	basestyle(meters.GPU1,logicalcores/2+4,false)
	basestyle(meters.GPUs1,logicalcores/2+4,true)
	basestyle(meters.GPU2,logicalcores/2+4,false)
	basestyle(meters.GPUs2,logicalcores/2+4,true)
	meters.GPU1.MeasureName='GPU1a'
	meters.GPUs1.MeasureName='GPU1a'
	meters.GPU2.MeasureName='GPU1a'
	meters.GPUs2.MeasureName='GPU1a'
	
	meters.GPU1.LineColor='([GPU1t]>' .. TempLow .. '?([GPU1t]>' .. TempHigh .. '?255:([GPU1t]-' .. TempLow .. ')*(255/(' .. TempHigh .. '-' .. TempLow .. '))):0),0,0,160'
	meters.GPU2.LineColor='([GPU1t]>' .. TempLow .. '?([GPU1t]>' .. TempHigh .. '?255:([GPU1t]-' .. TempLow .. ')*(255/(' .. TempHigh .. '-' .. TempLow .. '))):0),0,0,160'
	
	meters.GPU1.StartAngle=(math.pi+math.pi/2)
	meters.GPUs1.StartAngle=(math.pi+math.pi/2)
	meters.GPU2.StartAngle=(math.pi+math.pi/2)
	meters.GPUs2.StartAngle=(math.pi+math.pi/2)
	
	meters.GPU1.RotationAngle=math.pi/4
	meters.GPUs1.RotationAngle=math.pi/4
	meters.GPU2.RotationAngle=math.pi/-4
	meters.GPUs2.RotationAngle=math.pi/-4
end

function meta()
	local metameters = {}
	local metameter = {}
	metameter.__newindex = function(tb,key,value)
		SKIN:Bang('!SetOption',tb.__metername,key,value)
	end
	metameter.__index = function(tb,key)
		return tb.__meter:GetOption(key)
	end
	metameters.__index = function(tb,key)
		meters[key]={}
		meters[key].__meter = SKIN:GetMeter(key)
		meters[key].__metername = key
		setmetatable(meters[key],metameter)
		return meters[key]
	end
	meters = {}
	setmetatable(meters,metameters)

	local metameasures = {}
	local metameasure = {}
	metameasure.__newindex = function(tb,key,value)
		SKIN:Bang('!SetOption',tb.__measurename,key,value)
	end
	metameasure.__index = function(tb,key)
		if key == 'String' then
			return tb.__measure:GetStringValue()
		elseif key == 'Value' then
			return tonumber(tb.__measure:GetValue())
		elseif key == 'MinValue' then
			return tonumber(tb.__measure:GetMinValue())
		elseif key == 'MaxValue' then
			return tonumber(tb.__measure:GetMaxValue())
		elseif key == 'UpdateMeasure' then
			return function() SKIN:Bang('!UpdateMeasure',tb.__measurename) end
		else
			local t = tb.__measure:GetNumberOption(key,nil)
			return t or tb.__measure:GetOption(key)
		end
	end
	metameasures.__index = function(tb,key)
		measures[key]={}
		measures[key].__measure = SKIN:GetMeasure(key)
		measures[key].__measurename = key
		setmetatable(measures[key],metameasure)
		return measures[key]
	end
	measures = {}
	setmetatable(measures,metameasures)

	local metavariables = {}
	metavariables.__index = function(tb,key)
		return SKIN:GetVariable(key)
	end
	metavariables.__newindex = function(tb,key,value)
		SKIN:Bang('!SetVariable',key,value)
	end
	variables = {}
	setmetatable(variables,metavariables)
end