aseprite/tests/scripts/test_utils.lua
Guilherme Belchior ffc3684b1b Compose groups separately from all other layers
Maintain hierarchical structure of sprite groups instead of flattening.
Allows opacity and blend mode to be applied correctly to groups.
Sets the foundation for future features like mask layers.

Note:
Requires full image rendering and impacts performance in some scenarios.
Avoids complex code changes for minor performance gains.

Co-authored-by: Guilherme Marcondes <guilherme.marcondes@tecnico.ulisboa.pt>
2024-06-24 18:16:42 -03:00

291 lines
8.8 KiB
Lua

-- Copyright (C) 2019-2020 Igara Studio S.A.
--
-- This file is released under the terms of the MIT license.
-- Read LICENSE.txt for more information.
function expect_eq(a, b)
if a ~= b then
print(debug.traceback())
print('Expected A == B but:')
print(' - Value A = ' .. tostring(a))
print(' - Value B = ' .. tostring(b))
assert(a == b)
end
end
local function dump_img(image)
local w = image.width
local h = image.height
print('Image(' .. tostring(w) .. 'x' .. tostring(h) .. ') = {')
for v=0,h-1 do
local lineStr = ' '
for u=0,w-1 do
local pix = image:getPixel(u, v)
local pixStr
if image.colorMode == ColorMode.RGB then
pixStr = string.format('rgba(%d,%d,%d,%d)',
app.pixelColor.rgbaR(pix),
app.pixelColor.rgbaG(pix),
app.pixelColor.rgbaB(pix),
app.pixelColor.rgbaA(pix))
elseif image.colorMode == ColorMode.GRAY then
pixStr = string.format('gray(%d,%d)',
app.pixelColor.grayaV(pix),
app.pixelColor.grayaA(pix))
else
pixStr = tostring(pix)
end
lineStr = lineStr .. pixStr .. ','
end
print(lineStr)
end
print('}')
end
function expect_clr(color, expectedColor)
if color ~= expectedColor then
print(debug.traceback())
print('Expected A == B but:')
print(string.format(' - Value A = rgba(%d,%d,%d,%d)',
app.pixelColor.rgbaR(color),
app.pixelColor.rgbaG(color),
app.pixelColor.rgbaB(color),
app.pixelColor.rgbaA(color)))
print(string.format(' - Value B = rgba(%d,%d,%d,%d)',
app.pixelColor.rgbaR(expectedColor),
app.pixelColor.rgbaG(expectedColor),
app.pixelColor.rgbaB(expectedColor),
app.pixelColor.rgbaA(expectedColor)))
assert(color == expectedColor)
end
end
function expect_img(image, expectedPixels)
local w = image.width
local h = image.height
if w*h ~= #expectedPixels then
print(debug.traceback())
print('Expected pixels: #=' .. #expectedPixels)
print('Image size: w=' .. w .. ' h=' .. h .. ' #=' .. w*h)
dump_img(image)
assert(w*h == #expectedPixels)
end
for y=0,h-1 do
for x=0,w-1 do
local value = image:getPixel(x, y)
local expected = expectedPixels[1+y*w+x]
if value ~= expected then
dump_img(image)
print('In pixel (' .. x .. ', ' .. y .. '):')
local a = value
local b = expected
print(debug.traceback())
print('Expected A == B but:')
if image.colorMode == ColorMode.RGB then
print(string.format(' - Value A = rgba(%d,%d,%d,%d)',
app.pixelColor.rgbaR(a),
app.pixelColor.rgbaG(a),
app.pixelColor.rgbaB(a),
app.pixelColor.rgbaA(a)))
print(string.format(' - Value B = rgba(%d,%d,%d,%d)',
app.pixelColor.rgbaR(b),
app.pixelColor.rgbaG(b),
app.pixelColor.rgbaB(b),
app.pixelColor.rgbaA(b)))
elseif image.colorMode == ColorMode.GRAY then
print(string.format(' - Value A = gray(%d,%d)',
app.pixelColor.grayaV(a),
app.pixelColor.grayaA(a)))
print(string.format(' - Value B = gray(%d,%d)',
app.pixelColor.grayaV(b),
app.pixelColor.grayaA(b)))
else
print(' - Value A = ' .. tostring(a))
print(' - Value B = ' .. tostring(b))
end
assert(a == b)
end
end
end
end
function expect_img_msg(image, expectedPixels, msg)
local status, err = pcall(expect_img, image, expectedPixels)
if not status then
print(msg)
error(err)
end
end
function array_to_pixels(array, image)
local w = image.width
local h = image.height
assert(w*h == #array)
local i = 1
for y=0,h-1 do
for x=0,w-1 do
image:drawPixel(x, y, array[i])
i = i+1
end
end
end
-- Returns true if the given array (layers) of layers
function expect_rendered_layers(expectedImage, sprite, layerNames, frame)
function contains_layer(name)
for _,n in ipairs(layerNames) do
if name == n then return true end
end
return false
end
if frame == nil then frame = 1 end
local render = Image(sprite.spec)
function render_layers(prefix, layers)
for _,layer in ipairs(layers) do
if layer.isGroup then
render_layers(layer.name.."/", layer.layers)
end
if contains_layer(prefix..layer.name) then
local cel = layer:cel(frame)
if cel then
render:drawImage(cel.image, cel.position)
end
end
end
end
render_layers("", sprite.layers)
if not expectedImage:isEqual(render) then
print("Rendering:")
for _,n in ipairs(layerNames) do
print(" - " .. n)
end
error("render doesn't match to the expected image")
end
end
-- Asserts that the passed sprites are equals without taking
-- into account:
-- * User data custom properties.
-- * Filename.
-- * Pixel ratio.
-- * Grid bounds.
function assert_sprites_eq(expectedSprite, sprite)
assert(expectedSprite.width == sprite.width)
assert(expectedSprite.height == sprite.height)
assert(expectedSprite.colorMode == sprite.colorMode)
assert(expectedSprite.transparentColor == sprite.transparentColor)
assert_layers_eq(expectedSprite.layers, sprite.layers)
assert_frames_eq(expectedSprite.frames, sprite.frames)
assert_tags_eq(expectedSprite.tags, sprite.tags)
assert_slices_eq(expectedSprite.slices, sprite.slices)
end
function assert_layers_eq(expectedLayers, layers)
assert(#expectedLayers == #layers)
for i = 1,#layers do
assert_layer_eq(expectedLayers[i], layers[i])
end
end
function assert_layer_eq(expectedLayer, layer)
assert(expectedLayer.name == layer.name)
assert(expectedLayer.opacity == layer.opacity)
assert(expectedLayer.blendMode == layer.blendMode)
assert(expectedLayer.stackIndex == layer.stackIndex)
assert(expectedLayer.isGroup == layer.isGroup)
assert(expectedLayer.isImage == layer.isImage)
assert(expectedLayer.isTransparent == layer.isTransparent)
assert(expectedLayer.isGroup == layer.isGroup)
assert(expectedLayer.isBackground == layer.isBackground)
assert(expectedLayer.isContinuous == layer.isContinuous)
assert(expectedLayer.isReference == layer.isReference)
assert(expectedLayer.color == layer.color)
assert(expectedLayer.data == layer.data)
if expectedLayer.isGroup then
assert_layers_eq(expectedLayer.layers, layer.layers)
else
assert_cels_eq(expectedLayer.cels, layer.cels)
end
end
function assert_frames_eq(expectedFrames, frames)
assert(#expectedFrames == #frames)
for i = 1,#frames do
assert(expectedFrames[i].frameNumber == frames[i].frameNumber)
assert(expectedFrames[i].duration == frames[i].duration)
end
end
function assert_cels_eq(expectedCels, cels)
assert(#expectedCels == #cels)
for i = 1,#cels do
local expCel = expectedCels[i]
local cel = cels[i]
assert(expCel.frameNumber == cel.frameNumber)
assert(expCel.bounds.x == cel.bounds.x)
assert(expCel.bounds.y == cel.bounds.y)
assert(expCel.bounds.width == cel.bounds.width)
assert(expCel.bounds.height == cel.bounds.height)
assert(expCel.position.x == cel.position.x)
assert(expCel.position.y == cel.position.y)
assert(expCel.opacity == cel.opacity)
assert(expCel.color == cel.color)
assert(expCel.data == cel.data)
assert(expCel.image:isEqual(cel.image))
end
end
function assert_tags_eq(expectedTags, tags)
assert(#expectedTags == #tags)
for i = 1,#tags do
local expTag = expectedTags[i]
local tag = tags[i]
local a = expTag.fromFrame
local b = tag.fromFrame
assert(expTag.fromFrame.frameNumber == tag.fromFrame.frameNumber)
assert(expTag.toFrame.frameNumber == tag.toFrame.frameNumber)
assert(expTag.name == tag.name)
assert(expTag.aniDir == tag.aniDir)
assert(expTag.color == tag.color)
assert(expTag.data == tag.data)
end
end
function assert_slices_eq(expectedSlices, slices)
assert(#expectedSlices == #slices)
for i = 1,#slices do
local expSlice = expectedSlices[i]
local slice = slices[i]
assert(expSlice.bounds.x == slice.bounds.x)
assert(expSlice.bounds.y == slice.bounds.y)
assert(expSlice.bounds.width == slice.bounds.width)
assert(expSlice.bounds.height == slice.bounds.height)
assert(expSlice.color == slice.color)
assert(expSlice.data == slice.data)
assert(expSlice.name == slice.name)
if expSlice.center == nil or slice.center == nil then
assert(expSlice.center == slice.center)
else
assert(expSlice.center.x == slice.center.x)
assert(expSlice.center.y == slice.center.y)
assert(expSlice.center.width == slice.center.width)
assert(expSlice.center.height == slice.center.height)
end
if expSlice.pivot == nil or slice.pivot == nil then
assert(expSlice.pivot == slice.pivot)
else
assert(expSlice.pivot.x == slice.pivot.x)
assert(expSlice.pivot.y == slice.pivot.y)
end
end
end