SyntaxGameServer/RCCService2021/internalscripts/thumbnails/AnimationSilhouette.lua

177 lines
6.1 KiB
Lua

-- AnimationSilhouette.lua
-- Generates a Silhouette of a character doing the animation in the color requested
local assetUrl, baseUrl, x, y, silhouetteColor = ...
local ThumbnailGenerator = game:GetService("ThumbnailGenerator")
ThumbnailGenerator:AddProfilingCheckpoint("ThumbnailScriptStarted")
local BundleLoader = require(ThumbnailGenerator:GetThumbnailModule("BundleLoader"))
pcall(function() game:GetService("ContentProvider"):SetBaseUrl(baseUrl) end)
game:GetService("ScriptContext").ScriptsDisabled = true
local emoteAnim = game:GetObjects(assetUrl)[1]
local bundleId = 401 -- Default is Alexandra Ninniflip
local bundleIdValue = emoteAnim:FindFirstChild("ThumbnailBundleId")
if bundleIdValue and bundleIdValue:IsA("NumberValue") then
bundleId = bundleIdValue.Value
end
-- Default keyframe to use in thumbnail is middle keyframe
local thumbnailKeyframeNumber
local thumbnailKeyframeValue = emoteAnim:FindFirstChild("ThumbnailKeyframe")
if thumbnailKeyframeValue and thumbnailKeyframeValue:IsA("NumberValue") then
thumbnailKeyframeNumber = thumbnailKeyframeValue.Value
end
local thumbnailZoom = 1
local thumbnailZoomValue = emoteAnim:FindFirstChild("ThumbnailZoom")
if thumbnailZoomValue and thumbnailZoomValue:IsA("NumberValue") then
thumbnailZoom = thumbnailZoomValue.Value
end
local fieldOfView = 20
local fieldOfViewValue = emoteAnim:FindFirstChild("ThumbnailFieldOfView")
if fieldOfViewValue and fieldOfViewValue:IsA("NumberValue") then
fieldOfView = fieldOfViewValue.Value
end
local verticalOffset = 0
local verticalOffsetValue = emoteAnim:FindFirstChild("ThumbnailVerticalOffset")
if verticalOffsetValue and verticalOffsetValue:IsA("NumberValue") then
verticalOffset = verticalOffsetValue.Value
end
local horizontalOffset = 0
local horizontalOffsetValue = emoteAnim:FindFirstChild("ThumbnailHorizontalOffset")
if horizontalOffsetValue and horizontalOffsetValue:IsA("NumberValue") then
horizontalOffset = horizontalOffsetValue.Value
end
local rotationDegrees = 0
local thumbnailRotationValue = emoteAnim:FindFirstChild("ThumbnailCharacterRotation")
if thumbnailRotationValue and thumbnailRotationValue:IsA("NumberValue") then
rotationDegrees = thumbnailRotationValue.Value
end
local bundleCharacter = BundleLoader.LoadBundleCharacter(baseUrl, bundleId)
ThumbnailGenerator:AddProfilingCheckpoint("BundleCharacterLoaded")
local r, g, b = unpack(silhouetteColor:split("/"))
local silhouetteColor3 = Color3.fromRGB(tonumber(r), tonumber(g), tonumber(b))
local overrideColor3Value = emoteAnim:FindFirstChild("ThumbnailSilhouetteColor")
if overrideColor3Value and overrideColor3Value:IsA("Color3Value") then
silhouetteColor3 = overrideColor3Value.Value
end
local KeyframeSequenceProvider = game:GetService("KeyframeSequenceProvider")
local kfs = KeyframeSequenceProvider:GetKeyframeSequence(emoteAnim.AnimationId)
local emoteKeyframes = kfs:GetKeyframes()
ThumbnailGenerator:AddProfilingCheckpoint("KeyframesLoaded")
local function getJointBetween(part0, part1)
for _, obj in pairs(part1:GetChildren()) do
if obj:IsA("Motor6D") and obj.Part0 == part0 then
return obj
end
end
end
local function applyPose(character, poseKeyframe)
local function recurApplyPoses(parentPose, poseObject)
if parentPose then
local joint = getJointBetween(character[parentPose.Name], character[poseObject.Name])
joint.C1 = joint.C1 * poseObject.CFrame:inverse()
end
for _, subPose in pairs(poseObject:GetSubPoses()) do
recurApplyPoses(poseObject, subPose)
end
end
for _, poseObj in pairs(poseKeyframe:GetPoses()) do
recurApplyPoses(nil, poseObj)
end
end
local thumbnailKeyframe
if thumbnailKeyframeNumber then
-- Check that the index provided as the keyframe number is valid
if thumbnailKeyframeNumber > 0 and thumbnailKeyframeNumber <= #emoteKeyframes then
thumbnailKeyframe = emoteKeyframes[thumbnailKeyframeNumber]
else
thumbnailKeyframe = emoteKeyframes[math.ceil(#emoteKeyframes/2)]
end
else
thumbnailKeyframe = emoteKeyframes[math.ceil(#emoteKeyframes/2)]
end
if rotationDegrees ~= 0 then
local rootPose = thumbnailKeyframe:GetPoses()[1]
if rootPose then
local upperTorsoPose = rootPose:GetSubPoses()[1]
if upperTorsoPose then
upperTorsoPose.CFrame = upperTorsoPose.CFrame * CFrame.Angles(0, math.rad(rotationDegrees), 0)
end
end
end
applyPose(bundleCharacter, thumbnailKeyframe)
local function getCameraOffset(fov, extentsSize)
local xSize, ySize, zSize = extentsSize.X, extentsSize.Y, extentsSize.Z
local maxSize = math.sqrt(xSize^2 + ySize^2 + zSize^2)
local fovMultiplier = 1 / math.tan(math.rad(fov) / 2)
local halfSize = maxSize / 2
return halfSize * fovMultiplier
end
local function zoomExtents(model, lookVector, thumbnailCamera)
local modelCFrame = model:GetModelCFrame()
local position = modelCFrame.p
position = position + Vector3.new(horizontalOffset, -verticalOffset, 0)
local extentsSize = model:GetExtentsSize()
local cameraOffset = getCameraOffset(thumbnailCamera.FieldOfView, extentsSize)
local zoomFactor = 1 / thumbnailZoom
cameraOffset = cameraOffset * zoomFactor
local cameraRotation = thumbnailCamera.CFrame - thumbnailCamera.CFrame.p
thumbnailCamera.CFrame = cameraRotation + position + (lookVector * cameraOffset)
end
local function createThumbnailCamera(model)
local modelCFrame = model:GetModelCFrame()
local lookVector = modelCFrame.lookVector
local humanoidRootPart = model:FindFirstChild("HumanoidRootPart")
if humanoidRootPart then
lookVector = humanoidRootPart.CFrame.lookVector
end
local thumbnailCamera = Instance.new("Camera")
thumbnailCamera.Name = "ThumbnailCamera"
thumbnailCamera.Parent = model
thumbnailCamera.FieldOfView = fieldOfView
thumbnailCamera.CFrame = CFrame.new(modelCFrame.p + (lookVector * 5), modelCFrame.p)
thumbnailCamera.Focus = modelCFrame
zoomExtents(model, lookVector, thumbnailCamera)
end
createThumbnailCamera(bundleCharacter)
local result, requestedUrls = game:GetService("ThumbnailGenerator"):ClickSilhouette(x, y, silhouetteColor3)
ThumbnailGenerator:AddProfilingCheckpoint("ThumbnailGenerated")
return result, requestedUrls