forked from rojo-rbx/rojo
127 lines
3.1 KiB
Lua
127 lines
3.1 KiB
Lua
local StudioService = game:GetService("StudioService")
|
|
local AssetService = game:GetService("AssetService")
|
|
|
|
local Rojo = script:FindFirstAncestor("Rojo")
|
|
local Plugin = Rojo.Plugin
|
|
local Packages = Rojo.Packages
|
|
|
|
local Roact = require(Packages.Roact)
|
|
|
|
local e = Roact.createElement
|
|
|
|
local EditableImage = require(Plugin.App.Components.EditableImage)
|
|
|
|
local imageCache = {}
|
|
local function getImageSizeAndPixels(image)
|
|
if not imageCache[image] then
|
|
local editableImage = AssetService:CreateEditableImageAsync(image)
|
|
imageCache[image] = {
|
|
Size = editableImage.Size,
|
|
Pixels = editableImage:ReadPixels(Vector2.zero, editableImage.Size),
|
|
}
|
|
end
|
|
|
|
return imageCache[image].Size, table.clone(imageCache[image].Pixels)
|
|
end
|
|
|
|
local function getRecoloredClassIcon(className, color)
|
|
local iconProps = StudioService:GetClassIcon(className)
|
|
|
|
if iconProps and color then
|
|
local success, editableImageSize, editableImagePixels = pcall(function()
|
|
local size, pixels = getImageSizeAndPixels(iconProps.Image)
|
|
|
|
local minVal, maxVal = math.huge, -math.huge
|
|
for i = 1, #pixels, 4 do
|
|
if pixels[i + 3] == 0 then
|
|
continue
|
|
end
|
|
local pixelVal = math.max(pixels[i], pixels[i + 1], pixels[i + 2])
|
|
|
|
minVal = math.min(minVal, pixelVal)
|
|
maxVal = math.max(maxVal, pixelVal)
|
|
end
|
|
|
|
local hue, sat, val = color:ToHSV()
|
|
for i = 1, #pixels, 4 do
|
|
if pixels[i + 3] == 0 then
|
|
continue
|
|
end
|
|
|
|
local pixelVal = math.max(pixels[i], pixels[i + 1], pixels[i + 2])
|
|
local newVal = val
|
|
if minVal < maxVal then
|
|
-- Remap minVal - maxVal to val*0.9 - val
|
|
newVal = val * (0.9 + 0.1 * (pixelVal - minVal) / (maxVal - minVal))
|
|
end
|
|
|
|
local newPixelColor = Color3.fromHSV(hue, sat, newVal)
|
|
pixels[i], pixels[i + 1], pixels[i + 2] = newPixelColor.R, newPixelColor.G, newPixelColor.B
|
|
end
|
|
return size, pixels
|
|
end)
|
|
if success then
|
|
iconProps.EditableImagePixels = editableImagePixels
|
|
iconProps.EditableImageSize = editableImageSize
|
|
end
|
|
end
|
|
|
|
return iconProps
|
|
end
|
|
|
|
local ClassIcon = Roact.PureComponent:extend("ClassIcon")
|
|
|
|
function ClassIcon:init()
|
|
self.state = {
|
|
iconProps = nil,
|
|
}
|
|
end
|
|
|
|
function ClassIcon:updateIcon()
|
|
local props = self.props
|
|
local iconProps = getRecoloredClassIcon(props.className, props.color)
|
|
self:setState({
|
|
iconProps = iconProps,
|
|
})
|
|
end
|
|
|
|
function ClassIcon:didMount()
|
|
self:updateIcon()
|
|
end
|
|
|
|
function ClassIcon:didUpdate(lastProps)
|
|
if lastProps.className ~= self.props.className or lastProps.color ~= self.props.color then
|
|
self:updateIcon()
|
|
end
|
|
end
|
|
|
|
function ClassIcon:render()
|
|
local iconProps = self.state.iconProps
|
|
if not iconProps then
|
|
return nil
|
|
end
|
|
|
|
return e(
|
|
"ImageLabel",
|
|
{
|
|
Size = self.props.size,
|
|
Position = self.props.position,
|
|
LayoutOrder = self.props.layoutOrder,
|
|
AnchorPoint = self.props.anchorPoint,
|
|
ImageTransparency = self.props.transparency,
|
|
Image = iconProps.Image,
|
|
ImageRectOffset = iconProps.ImageRectOffset,
|
|
ImageRectSize = iconProps.ImageRectSize,
|
|
BackgroundTransparency = 1,
|
|
},
|
|
if iconProps.EditableImagePixels
|
|
then e(EditableImage, {
|
|
size = iconProps.EditableImageSize,
|
|
pixels = iconProps.EditableImagePixels,
|
|
})
|
|
else nil
|
|
)
|
|
end
|
|
|
|
return ClassIcon
|