Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 53 additions & 19 deletions plugin/src/App/Components/ClassIcon.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
local StudioService = game:GetService("StudioService")
local AssetService = game:GetService("AssetService")

type CachedImageInfo = {
pixels: buffer,
size: Vector2,
}

local Rojo = script:FindFirstAncestor("Rojo")
local Plugin = Rojo.Plugin
local Packages = Rojo.Packages
Expand All @@ -11,55 +16,84 @@ 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)
local imageCache: { [string]: CachedImageInfo } = {}

local function cloneBuffer(b: buffer): buffer
local newBuffer = buffer.create(buffer.len(b))
buffer.copy(newBuffer, 0, b)
return newBuffer
end

local function getImageSizeAndPixels(image: string): (Vector2, buffer)
local cachedImage = imageCache[image]

if not cachedImage then
local editableImage = AssetService:CreateEditableImageAsync(Content.fromUri(image))
local size = editableImage.Size
local pixels = editableImage:ReadPixelsBuffer(Vector2.zero, size)
imageCache[image] = {
Size = editableImage.Size,
Pixels = editableImage:ReadPixels(Vector2.zero, editableImage.Size),
pixels = pixels,
size = size,
}

return size, cloneBuffer(pixels)
end

return imageCache[image].Size, table.clone(imageCache[image].Pixels)
return cachedImage.size, cloneBuffer(cachedImage.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)
--stylua: ignore
local success, editableImageSize, editableImagePixels = pcall(function(_iconProps: { [any]: any }, _color: Color3): (Vector2, buffer)
local size, pixels = getImageSizeAndPixels(_iconProps.Image)
local pixelsLen = buffer.len(pixels)

local minVal, maxVal = math.huge, -math.huge
for i = 1, #pixels, 4 do
if pixels[i + 3] == 0 then

for i = 0, pixelsLen, 4 do
if buffer.readu8(pixels, i + 3) == 0 then
continue
end
local pixelVal = math.max(pixels[i], pixels[i + 1], pixels[i + 2])
local pixelVal = math.max(
buffer.readu8(pixels, i),
buffer.readu8(pixels, i + 1),
buffer.readu8(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
local hue, sat, val = _color:ToHSV()

for i = 0, pixelsLen, 4 do
if buffer.readu8(pixels, i + 3) == 0 then
continue
end

local pixelVal = math.max(pixels[i], pixels[i + 1], pixels[i + 2])
local gIndex = i + 1
local bIndex = i + 2

local pixelVal = math.max(
buffer.readu8(pixels, i),
buffer.readu8(pixels, gIndex),
buffer.readu8(pixels, bIndex)
)
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
buffer.writeu8(pixels, i, newPixelColor.R)
buffer.writeu8(pixels, gIndex, newPixelColor.G)
buffer.writeu8(pixels, bIndex, newPixelColor.B)
end
return size, pixels
end)
end, iconProps, color)
if success then
iconProps.EditableImagePixels = editableImagePixels
iconProps.EditableImageSize = editableImageSize
Expand Down
5 changes: 3 additions & 2 deletions plugin/src/App/Components/EditableImage.lua
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,16 @@ function EditableImage:init()
end

function EditableImage:writePixels()
local image = self.ref.current
local image = self.ref.current :: EditableImage

if not image then
return
end
if not self.props.pixels then
return
end

image:WritePixels(Vector2.zero, self.props.size, self.props.pixels)
image:WritePixelsBuffer(Vector2.zero, self.props.size, self.props.pixels)
end

function EditableImage:render()
Expand Down
Loading