Run it
Copy the script and paste it into your executor.
FPS =
FRAME_FOLDER =
WHITE_AS_TRANSPARENT =
WHITE_THRESHOLD =
ALPHA_THRESHOLD =
PIXEL_BLOCK =
STABLE_FRAMES =
MAX_FRAMES =
WIDTH =
HEIGHT =
MAX_ENCODED_BYTES =
AssetService = :()
Players = :()
ReplicatedStorage = :()
allowedFps = {
[] = ,
[] = ,
[] = ,
[] = ,
[] = ,
[] = ,
}
(allowedFps[FPS], )
(FRAME_FOLDER)
(FRAME_FOLDER)
(():(FRAME_FOLDER))
framePaths = {}
highestFrame =
hasFramesAboveLimit =
_, path ((FRAME_FOLDER))
fileName = path:()
digits = fileName fileName:():()
index = digits (digits)
index index >=
index <= MAX_FRAMES
framePaths[index]
(():(index, framePaths[index], path))
framePaths[index] = path
highestFrame = .(highestFrame, index)
hasFramesAboveLimit =
(highestFrame > , ():(FRAME_FOLDER))
index = , highestFrame
(framePaths[index], ():(index))
frameCount = highestFrame
hasFramesAboveLimit
(():(MAX_FRAMES))
palette = {}
stableOutput = {}
pendingOutput = {}
pendingCounts = {}
processedFrameCount =
(red, green, blue)
quantizedRed = .(.(red / + ) * , , )
quantizedGreen = .(.(green / + ) * , , )
quantizedBlue = .(.(blue / + ) * , , )
quantizedBlue = .(quantizedBlue + )
key = quantizedRed * + quantizedGreen * + quantizedBlue
color = palette[key]
color
color = .(quantizedRed, quantizedGreen, quantizedBlue)
palette[key] = color
color
(path)
assetId = (path, )
ok, imageOrError = (
AssetService.CreateEditableImageAsync,
AssetService,
Content.(assetId)
)
(ok, ():(path, (imageOrError)))
image = imageOrError
imageWidth = .(image.Size.X + )
imageHeight = .(image.Size.Y + )
imageWidth ~= WIDTH imageHeight ~= HEIGHT
image:()
(():(
path,
imageWidth,
imageHeight,
WIDTH,
HEIGHT
))
pixelBuffer = image:(.zero, image.Size)
grid = {}
processedFrameCount +=
blockY = , HEIGHT - , PIXEL_BLOCK
blockX = , WIDTH - , PIXEL_BLOCK
redTotal =
greenTotal =
blueTotal =
alphaTotal =
sampleCount =
sampleY = blockY, .(blockY + PIXEL_BLOCK - , HEIGHT - )
sampleX = blockX, .(blockX + PIXEL_BLOCK - , WIDTH - )
offset = (sampleY * WIDTH + sampleX) *
redTotal += buffer.(pixelBuffer, offset)
greenTotal += buffer.(pixelBuffer, offset + )
blueTotal += buffer.(pixelBuffer, offset + )
alphaTotal += buffer.(pixelBuffer, offset + )
sampleCount +=
red = .(redTotal / sampleCount + )
green = .(greenTotal / sampleCount + )
blue = .(blueTotal / sampleCount + )
alpha = .(alphaTotal / sampleCount + )
transparent = alpha < ALPHA_THRESHOLD
WHITE_AS_TRANSPARENT red >= WHITE_THRESHOLD green >= WHITE_THRESHOLD blue >= WHITE_THRESHOLD
transparent =
desired = transparent (red, green, blue)
outputY = blockY, .(blockY + PIXEL_BLOCK - , HEIGHT - )
outputX = blockX, .(blockX + PIXEL_BLOCK - , WIDTH - )
outputIndex = outputY * WIDTH + outputX +
output = desired
processedFrameCount >
output = stableOutput[outputIndex]
desired == output
pendingOutput[outputIndex] =
pendingCounts[outputIndex] =
desired == pendingOutput[outputIndex]
count = (pendingCounts[outputIndex] ) +
pendingCounts[outputIndex] = count
count >= STABLE_FRAMES
output = desired
pendingOutput[outputIndex] =
pendingCounts[outputIndex] =
pendingOutput[outputIndex] = desired
pendingCounts[outputIndex] =
stableOutput[outputIndex] = output
output
grid[outputIndex] = output
image:()
grid
(():(frameCount, WIDTH, HEIGHT))
importedFrames = .(frameCount)
index = , frameCount
importedFrames[index] = (framePaths[index])
index % == index == frameCount
(():(index, frameCount))
.()
AnimData = ( :: any)(ReplicatedStorage:():())
encoded = AnimData.(importedFrames, FPS, )
(encoded, )
(#encoded <= MAX_ENCODED_BYTES, ():(
.(#encoded / ),
.(MAX_ENCODED_BYTES / )
))
playerGui = Players.LocalPlayer:()
webTown = playerGui:()
blocker = webTown webTown:()
studio = blocker blocker:()
(studio, )
plusButton
speedButton
_, child (studio:())
child:()
label = child:()
text = label label:() label.Text child.Text
text ==
plusButton = child
text:(, , )
speedButton = child
(plusButton, )
plusConnections = (plusButton.MouseButton1Click)
(#plusConnections > (plusConnections[].Function) == , )
plusUpvalues = debug.(plusConnections[].Function)
currentFrames = plusUpvalues[]
undoStack = plusUpvalues[]
rebuildTimeline = plusUpvalues[]
showFrame = plusUpvalues[]
((currentFrames) == , )
((rebuildTimeline) == (showFrame) == , )
.(currentFrames)
index, grid (importedFrames)
currentFrames[index] = grid
(undoStack) ==
.(undoStack)
speedButton
speedConnections = (speedButton.MouseButton1Click)
#speedConnections > (speedConnections[].Function) ==
debug.(speedConnections[].Function, , FPS)
label = speedButton:()
label label:()
label.Text = ():(FPS)
()
()
(():(
frameCount,
.(#encoded / ),
FPS
))