diff --git a/garrysmod/lua/includes/util/color.lua b/garrysmod/lua/includes/util/color.lua index e1d49d19bb..b6afedbe5f 100644 --- a/garrysmod/lua/includes/util/color.lua +++ b/garrysmod/lua/includes/util/color.lua @@ -12,8 +12,12 @@ RegisterMetaTable( "Color", COLOR ) -----------------------------------------------------------]] function Color( r, g, b, a ) - a = a or 255 - return setmetatable( { r = math.min( tonumber(r), 255 ), g = math.min( tonumber(g), 255 ), b = math.min( tonumber(b), 255 ), a = math.min( tonumber(a), 255 ) }, COLOR ) + return setmetatable( { + r = math.min( tonumber( r ), 255 ), + g = math.min( tonumber( g ), 255 ), + b = math.min( tonumber( b ), 255 ), + a = math.min( tonumber( a or 255 ), 255 ) + }, COLOR ) end @@ -31,10 +35,86 @@ end -----------------------------------------------------------]] function IsColor( obj ) - return getmetatable(obj) == COLOR + return getmetatable( obj ) == COLOR end +--[[--------------------------------------------------------- + Different color represntations +-----------------------------------------------------------]] +function HSVToColor( h, s, v ) + + h = h % 360 + + local c = v * s + local x = c * ( 1 - math.abs( ( h / 60 ) % 2 - 1 ) ) + local m = v - c + + local r, g, b + if ( h < 60 ) then + r, g, b = c, x, 0 + elseif ( h < 120 ) then + r, g, b = x, c, 0 + elseif ( h < 180 ) then + r, g, b = 0, c, x + elseif ( h < 240 ) then + r, g, b = 0, x, c + elseif ( h < 300 ) then + r, g, b = x, 0, c + else + r, g, b = c, 0, x + end + + return Color( + math.floor( ( r + m ) * 255 ) % 255, + math.floor( ( g + m ) * 255 ) % 255, + math.floor( ( b + m ) * 255 ) % 255 + ) + +end + +function HSLToColor( h, s, l ) + + h = h % 360 + + local c = ( 1 - math.abs( 2 * l - 1 ) ) * s + local x = c * ( 1 - math.abs( ( h / 60 ) % 2 - 1 ) ) + local m = l - c / 2 + + local r, g, b + if ( h < 60 ) then + r, g, b = c, x, 0 + elseif ( h < 120 ) then + r, g, b = x, c, 0 + elseif ( h < 180 ) then + r, g, b = 0, c, x + elseif ( h < 240 ) then + r, g, b = 0, x, c + elseif ( h < 300 ) then + r, g, b = x, 0, c + else + r, g, b = c, 0, x + end + + return Color( + math.floor( ( r + m ) * 255 ) % 255, + math.floor( ( g + m ) * 255 ) % 255, + math.floor( ( b + m ) * 255 ) % 255 + ) + +end + +function HWBToColor( h, w, b ) + + local v = 1 - b + local s = 0 + if ( v > 0 ) then + s = 1 - w / v + end + + return HSVToColor( h, s, v ) + +end --[[--------------------------------------------------------- Returns color as a string @@ -64,7 +144,7 @@ function COLOR:ToHSL() end --[[--------------------------------------------------------- - Converts a color to HSV + Converts a color to HSV color space -----------------------------------------------------------]] function COLOR:ToHSV() @@ -72,6 +152,16 @@ function COLOR:ToHSV() end +--[[--------------------------------------------------------- + Converts a color to HWB color space +-----------------------------------------------------------]] +function COLOR:ToHWB() + + local h, s, v = self:ToHSV() + return h, ( 1 - s ) * v, 1 - v + +end + --[[--------------------------------------------------------- Converts color to vector - loss of precision / alpha lost -----------------------------------------------------------]] @@ -92,7 +182,12 @@ end function COLOR:Lerp( target_clr, frac ) - return Color( Lerp( frac, self.r, target_clr.r ), Lerp( frac, self.g, target_clr.g ), Lerp( frac, self.b, target_clr.b ), Lerp( frac, self.a, target_clr.a ) ) + return Color( + Lerp( frac, self.r, target_clr.r ), + Lerp( frac, self.g, target_clr.g ), + Lerp( frac, self.b, target_clr.b ), + Lerp( frac, self.a, target_clr.a ) + ) end @@ -116,6 +211,158 @@ function COLOR:ToTable() end +local function ColorCopy( dest, origin ) + + dest.r = origin.r + dest.g = origin.g + dest.b = origin.b + +end + +-- HSV hue +function COLOR:GetHue() + + local hue = self:ToHSV() + return hue + +end + +function COLOR:SetHue( hue ) + + local _, saturation, brightness = self:ToHSV() + hue = hue % 360 + ColorCopy( self, HSVToColor( hue, saturation, brightness ) ) + +end + +function COLOR:AddHue( hueAdd ) + + local hue, saturation, brightness = self:ToHSV() + hue = ( hue + hueAdd ) % 360 + ColorCopy( self, HSVToColor( hue, saturation, brightness ) ) + +end + +-- HSV saturation +function COLOR:GetSaturation() + + local _, saturation = self:ToHSV() + return saturation + +end + +function COLOR:SetSaturation( saturation ) + + local hue, _, brightness = self:ToHSV() + saturation = math.Clamp( saturation, 0, 1 ) + ColorCopy( self, HSVToColor( hue, saturation, brightness ) ) + +end + +function COLOR:AddSaturation( saturationAdd ) + + local hue, saturation, brightness = self:ToHSV() + saturation = math.Clamp( saturation + saturationAdd, 0, 1 ) + ColorCopy( self, HSVToColor( hue, saturation, brightness ) ) + +end + +-- HSV brightness +function COLOR:GetBrightness() + + local _, _, brightness = self:ToHSV() + return brightness + +end + +function COLOR:SetBrightness( brightness ) + + local hue, saturation = self:ToHSV() + brightness = math.Clamp( brightness, 0, 1 ) + ColorCopy( self, HSVToColor( hue, saturation, brightness ) ) + +end + +function COLOR:AddBrightness( brightnessAdd ) + + local hue, saturation, brightness = self:ToHSV() + brightness = math.Clamp( brightness + brightnessAdd, 0, 1 ) + ColorCopy( self, HSVToColor( hue, saturation, brightness ) ) + +end + +-- HSL lightness +function COLOR:GetLightness() + + local _, _, lightness = self:ToHSL() + return lightness + +end + +function COLOR:SetLightness( lightness ) + + local hue, saturation = self:ToHSL() + lightness = math.Clamp( lightness, 0, 1 ) + ColorCopy( self, HSLToColor( hue, saturation, lightness ) ) + +end + +function COLOR:AddLightness( lightnessAdd ) + + local hue, saturation, lightness = self:ToHSL() + lightness = math.Clamp( lightness + lightnessAdd, 0, 1 ) + ColorCopy( self, HSLToColor( hue, saturation, lightness ) ) + +end + +-- HWB whiteness +function COLOR:GetWhiteness() + + local _, whiteness = self:ToHWB() + return whiteness + +end + +function COLOR:SetWhiteness( whiteness ) + + local hue, _, blackness = self:ToHWB() + whiteness = math.Clamp( whiteness, 0, 1 ) + ColorCopy( self, HWBToColor( hue, whiteness, blackness ) ) + +end + +function COLOR:AddWhiteness( whitenessAdd ) + + local hue, whiteness, blackness = self:ToHWB() + whiteness = math.Clamp( whiteness + whitenessAdd, 0, 1 ) + ColorCopy( self, HWBToColor( hue, whiteness, blackness ) ) + +end + +-- HWB blackness +function COLOR:GetBlackness() + + local _, _, blackness = self:ToHWB() + return blackness + +end + +function COLOR:SetBlackness( blackness ) + + local hue, whiteness = self:ToHWB() + blackness = math.Clamp( blackness, 0, 1 ) + ColorCopy( self, HWBToColor( hue, whiteness, blackness ) ) + +end + +function COLOR:AddBlackness( blacknessAdd ) + + local hue, whiteness, blackness = self:ToHWB() + blackness = math.Clamp( blackness + blacknessAdd, 0, 1 ) + ColorCopy( self, HWBToColor( hue, whiteness, blackness ) ) + +end + local imat = FindMetaTable( "IMaterial" ) -- This is so that the return value has the color meta table