mirror of
https://github.com/aseprite/aseprite.git
synced 2025-02-04 15:40:10 +00:00
Merge remote-tracking branch 'tests/main'
This commit is contained in:
commit
c7cafca69a
9
.github/workflows/build.yml
vendored
9
.github/workflows/build.yml
vendored
@ -64,13 +64,6 @@ jobs:
|
||||
if [[ "${{ runner.os }}" == "Linux" ]] ; then
|
||||
export XVFB=xvfb-run
|
||||
fi
|
||||
if [[ "${{ github.base_ref }}" == "beta" ]] || [[ "${{ github.ref }}" == "refs/heads/beta" ]] ; then
|
||||
export TESTS_BRANCH=beta
|
||||
else
|
||||
export TESTS_BRANCH=main
|
||||
fi
|
||||
cd build
|
||||
export ASEPRITE=$PWD/bin/aseprite
|
||||
git clone --branch $TESTS_BRANCH --recursive https://github.com/aseprite/tests.git
|
||||
export ASEPRITE=$PWD/build/bin/aseprite
|
||||
cd tests
|
||||
$XVFB bash run-tests.sh
|
||||
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -1,3 +1,6 @@
|
||||
[submodule "tests/third_party/json"]
|
||||
path = tests/third_party/json
|
||||
url = https://github.com/aseprite/json.lua
|
||||
[submodule "third_party/pixman"]
|
||||
path = third_party/pixman
|
||||
url = https://github.com/aseprite/pixman.git
|
||||
|
21
tests/LICENSE.txt
Normal file
21
tests/LICENSE.txt
Normal file
@ -0,0 +1,21 @@
|
||||
Copyright (c) 2018-2022 Igara Studio S.A.
|
||||
Copyright (c) 2018 David Capello
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
31
tests/README.md
Normal file
31
tests/README.md
Normal file
@ -0,0 +1,31 @@
|
||||
# Aseprite Tests
|
||||
|
||||
Test suite for [Aseprite](https://github.com/aseprite/aseprite)
|
||||
to avoid breaking backward compatibility.
|
||||
|
||||
This project is cloned by the
|
||||
[build.yml](https://github.com/aseprite/aseprite/blob/main/.github/workflows/build.yml) file
|
||||
on Aseprite project to do several automated tests:
|
||||
|
||||
* Save/load file formats correctly. For this we have `.aseprite`, `.png`,
|
||||
`.gif`, etc. files [sprites](https://github.com/aseprite/tests/tree/main/sprites)
|
||||
folder.
|
||||
* Test backward compatibility with [Aseprite CLI](https://www.aseprite.org/docs/cli/) options
|
||||
* Future [scripting API](https://github.com/aseprite/api) using [scripts](https://github.com/aseprite/tests/tree/main/scripts)
|
||||
|
||||
## How to run tests?
|
||||
|
||||
You have to set the `ASEPRITE` environment variable pointing to the
|
||||
Aseprite executable and then run `run-tests.sh` from Bash:
|
||||
|
||||
export ASEPRITE=$HOME/your-aseprite-build/bin/aseprite
|
||||
git clone https://github.com/aseprite/tests.git
|
||||
cd tests
|
||||
bash run-tests.sh
|
||||
|
||||
You can filter some tests with a regex giving a parameter to
|
||||
`run-tests.sh`, for example:
|
||||
|
||||
run-tests.sh color
|
||||
|
||||
Should run all tests which have the `color` word in their name.
|
61
tests/cli/file-formats.sh
Normal file
61
tests/cli/file-formats.sh
Normal file
@ -0,0 +1,61 @@
|
||||
#! /bin/bash
|
||||
# Copyright (C) 2019 Igara Studio S.A.
|
||||
|
||||
# Create a simple image and save it in all formats using scripts
|
||||
d=$t/file-formats
|
||||
mkdir $d
|
||||
cat >$d/gen.lua <<EOF
|
||||
local a = Sprite(32, 32)
|
||||
app.useTool{ points={{0,0},{31,31}}, tool='filled_ellipse', color=Color(255,255,255) }
|
||||
a:saveAs('$d/test.aseprite')
|
||||
a:saveAs('$d/test.gif')
|
||||
a:saveAs('$d/test.ico')
|
||||
a:saveAs('$d/test.jpg')
|
||||
a:saveAs('$d/test.pcx')
|
||||
a:saveAs('$d/test.svg')
|
||||
a:saveAs('$d/test.tga')
|
||||
a:saveAs('$d/test.webp')
|
||||
EOF
|
||||
$ASEPRITE -b -script "$d/gen.lua" || exit 1
|
||||
|
||||
# Load image and save in all formats using CLI
|
||||
$ASEPRITE -b "$d/test.aseprite" \
|
||||
-save-as "$d/test2.gif" \
|
||||
-save-as "$d/test2.ico" \
|
||||
-save-as "$d/test2.jpg" \
|
||||
-save-as "$d/test2.pcx" \
|
||||
-save-as "$d/test2.svg" \
|
||||
-save-as "$d/test2.tga" \
|
||||
-save-as "$d/test2.webp" \
|
||||
|| exit 1
|
||||
|
||||
# Compare that all images are the same/equivalent
|
||||
# Note: app.open() and Sprite{fromFile:} are the same
|
||||
cat >$d/compare.lua <<EOF
|
||||
local a = Sprite{ fromFile="$d/test.aseprite" }
|
||||
local b = {
|
||||
app.open("$d/test.gif"), app.open("$d/test2.gif"),
|
||||
app.open("$d/test.ico"), app.open("$d/test2.ico"),
|
||||
app.open("$d/test.jpg"), app.open("$d/test2.jpg"),
|
||||
app.open("$d/test.pcx"), app.open("$d/test2.pcx"),
|
||||
--app.open("$d/test.svg"), -- we don't support loading SVG files
|
||||
app.open("$d/test.tga"), app.open("$d/test2.tga"),
|
||||
app.open("$d/test.webp"), app.open("$d/test2.webp")
|
||||
}
|
||||
for i,c in ipairs(b) do
|
||||
if c.colorMode == ColorMode.INDEXED then
|
||||
app.activeSprite = c
|
||||
app.command.ChangePixelFormat{ format="rgb" }
|
||||
end
|
||||
assert(c.colorMode == ColorMode.RGB)
|
||||
if c.layers[1].isBackground then -- jpg and pcx
|
||||
app.activeSprite = c
|
||||
app.command.LayerFromBackground()
|
||||
-- tolerance is 1 to remove jpg noise
|
||||
app.command.ReplaceColor{ from=Color(0, 0, 0, 255), to=Color(0, 0, 0, 0), tolerance=1 }
|
||||
app.command.ReplaceColor{ from=Color(255, 255, 255, 255), to=Color(255, 255, 255, 255), tolerance=1 }
|
||||
end
|
||||
assert(a.cels[1].image:isEqual(c.cels[1].image))
|
||||
end
|
||||
EOF
|
||||
$ASEPRITE -b -script "$d/compare.lua" || exit 1
|
7
tests/cli/help.sh
Normal file
7
tests/cli/help.sh
Normal file
@ -0,0 +1,7 @@
|
||||
#! /bin/bash
|
||||
# Copyright (C) 2018 Igara Studio S.A.
|
||||
|
||||
if ! $ASEPRITE --help | grep "\\-\\-help" > /dev/null ; then
|
||||
echo "FAILED: --help doesn't include usage information"
|
||||
exit 1
|
||||
fi
|
10
tests/cli/list-layers.sh
Normal file
10
tests/cli/list-layers.sh
Normal file
@ -0,0 +1,10 @@
|
||||
#! /bin/bash
|
||||
# Copyright (C) 2018 Igara Studio S.A.
|
||||
|
||||
expect "bg
|
||||
fg" "$ASEPRITE -b --list-layers sprites/1empty3.aseprite"
|
||||
|
||||
expect "a
|
||||
b
|
||||
c
|
||||
d" "$ASEPRITE -b --list-layers sprites/abcd.aseprite"
|
5
tests/cli/list-tags.sh
Normal file
5
tests/cli/list-tags.sh
Normal file
@ -0,0 +1,5 @@
|
||||
#! /bin/bash
|
||||
# Copyright (C) 2018 Igara Studio S.A.
|
||||
|
||||
expect "a
|
||||
b" "$ASEPRITE -b --list-tags sprites/1empty3.aseprite"
|
256
tests/cli/save-as.sh
Normal file
256
tests/cli/save-as.sh
Normal file
@ -0,0 +1,256 @@
|
||||
#! /bin/bash
|
||||
# Copyright (C) 2018-2021 Igara Studio S.A.
|
||||
|
||||
function list_files() {
|
||||
oldwd=$(pwd $PWDARG)
|
||||
cd $1 && ls -1 *.*
|
||||
cd $oldwd
|
||||
}
|
||||
|
||||
# --save-as
|
||||
|
||||
d=$t/save-as
|
||||
$ASEPRITE -b sprites/1empty3.aseprite --save-as "$d/image00.png" || exit 1
|
||||
expect "image00.png
|
||||
image01.png
|
||||
image02.png" "list_files $d"
|
||||
|
||||
# --ignore-empty --save-as
|
||||
|
||||
d=$t/save-as-ignore-empty
|
||||
$ASEPRITE -b sprites/1empty3.aseprite --ignore-empty --save-as $d/image00.png || exit 1
|
||||
expect "image00.png
|
||||
image02.png" "list_files $d"
|
||||
|
||||
# --split-layers --save-as
|
||||
|
||||
d=$t/save-as-split-layers
|
||||
$ASEPRITE -b sprites/1empty3.aseprite --split-layers --save-as $d/layer.png || exit 1
|
||||
expect "layer (bg) 0.png
|
||||
layer (bg) 1.png
|
||||
layer (bg) 2.png
|
||||
layer (fg) 0.png
|
||||
layer (fg) 1.png
|
||||
layer (fg) 2.png" "list_files $d"
|
||||
|
||||
# --save-as {layer}
|
||||
|
||||
d=$t/save-as-layer
|
||||
mkdir $d # TODO why do we need this?
|
||||
$ASEPRITE -b sprites/1empty3.aseprite --save-as $d/layer-{layer}.gif || exit 1
|
||||
expect "layer-bg.gif
|
||||
layer-fg.gif" "list_files $d"
|
||||
|
||||
# --save-as frame8-test.png
|
||||
|
||||
d=$t/save-as-frame8-test
|
||||
$ASEPRITE -b sprites/1empty3.aseprite --save-as "$d/frame8-test.png" || exit 1
|
||||
expect "frame8-test1.png
|
||||
frame8-test2.png
|
||||
frame8-test3.png" "list_files $d"
|
||||
|
||||
# --save-as frame-0.png
|
||||
|
||||
d=$t/save-as-frame-0
|
||||
$ASEPRITE -b sprites/1empty3.aseprite --save-as "$d/frame-0.png" || exit 1
|
||||
expect "frame-0.png
|
||||
frame-1.png
|
||||
frame-2.png" "list_files $d"
|
||||
|
||||
# --save-as frame-00.png
|
||||
|
||||
d=$t/save-as-frame-00
|
||||
$ASEPRITE -b sprites/1empty3.aseprite --save-as "$d/frame-00.png" || exit 1
|
||||
expect "frame-00.png
|
||||
frame-01.png
|
||||
frame-02.png" "list_files $d"
|
||||
|
||||
# --save-as frame-001.png
|
||||
|
||||
d=$t/save-as-frame-001
|
||||
$ASEPRITE -b sprites/1empty3.aseprite --save-as "$d/frame-001.png" || exit 1
|
||||
expect "frame-001.png
|
||||
frame-002.png
|
||||
frame-003.png" "list_files $d"
|
||||
|
||||
# --save-as frame-0032.png
|
||||
|
||||
d=$t/save-as-frame-0032
|
||||
$ASEPRITE -b sprites/1empty3.aseprite --save-as "$d/frame-0032.png" || exit 1
|
||||
expect "frame-0032.png
|
||||
frame-0033.png
|
||||
frame-0034.png" "list_files $d"
|
||||
|
||||
# --trim --save-as
|
||||
|
||||
d=$t/save-as-trim
|
||||
$ASEPRITE -b --trim sprites/1empty3.aseprite --save-as "$d/trim-000.png" || exit 1
|
||||
expect "trim-000.png
|
||||
trim-001.png
|
||||
trim-002.png" "list_files $d"
|
||||
cat >$d/compare.lua <<EOF
|
||||
local a = app.open("sprites/1empty3.aseprite")
|
||||
assert(a.width == 32)
|
||||
assert(a.height == 32)
|
||||
app.command.FlattenLayers()
|
||||
app.command.AutocropSprite()
|
||||
assert(a.width == 22)
|
||||
assert(a.height == 26)
|
||||
local b = app.open("$d/trim-000.png")
|
||||
assert(b.width == 22)
|
||||
assert(b.height == 26)
|
||||
local cleanImage = Image(b.spec)
|
||||
cleanImage:clear()
|
||||
for f = 1,3 do
|
||||
local celA = a.layers[1]:cel(f)
|
||||
local celB = b.layers[1]:cel(f)
|
||||
if celA and celB then
|
||||
assert(celA.image:isEqual(celB.image))
|
||||
else
|
||||
assert(not celA)
|
||||
assert(not celB or celB.image:isEqual(cleanImage))
|
||||
end
|
||||
end
|
||||
EOF
|
||||
$ASEPRITE -b --script "$d/compare.lua" || exit 1
|
||||
|
||||
# -split-layers -trim -save-as
|
||||
|
||||
d=$t/save-as-split-layers-trim
|
||||
$ASEPRITE -batch -split-layers -trim sprites/1empty3.aseprite -save-as "$d/{layer}{frame}.png" || exit 1
|
||||
expect "bg0.png
|
||||
bg1.png
|
||||
bg2.png
|
||||
fg0.png
|
||||
fg1.png
|
||||
fg2.png" "list_files $d"
|
||||
cat >$d/compare.lua <<EOF
|
||||
local orig = app.open("sprites/1empty3.aseprite")
|
||||
local bg = app.open("$d/bg0.png")
|
||||
local fg = app.open("$d/fg0.png")
|
||||
assert(bg.width == 22)
|
||||
assert(bg.height == 11)
|
||||
assert(fg.width == 19)
|
||||
assert(fg.height == 11)
|
||||
for f = 1,3 do
|
||||
local origCelBG = orig.layers[1]:cel(f)
|
||||
local origCelFG = orig.layers[2]:cel(f)
|
||||
local celBG = bg.layers[1]:cel(f)
|
||||
local celFG = fg.layers[1]:cel(f)
|
||||
if origCelBG and celBG then
|
||||
assert(origCelBG.image:isEqual(celBG.image))
|
||||
else
|
||||
local cleanImage = Image(celBG.image.spec)
|
||||
cleanImage:clear()
|
||||
assert(not origCelBG)
|
||||
assert(celBG.image:isEqual(cleanImage))
|
||||
end
|
||||
if origCelFG and celFG then
|
||||
assert(origCelFG.image:isEqual(celFG.image))
|
||||
else
|
||||
local cleanImage = Image(celFG.image.spec)
|
||||
cleanImage:clear()
|
||||
assert(not origCelFG)
|
||||
assert(celFG.image:isEqual(cleanImage))
|
||||
end
|
||||
end
|
||||
EOF
|
||||
$ASEPRITE -b -script "$d/compare.lua" || exit 1
|
||||
|
||||
# --save-as without path
|
||||
# https://github.com/aseprite/aseprite/issues/591
|
||||
|
||||
d=$t/save-as-without-path
|
||||
mkdir $d
|
||||
oldwd=$(pwd $PWDARG)
|
||||
cd $d
|
||||
$ASEPRITE -b -split-layers $oldwd/sprites/abcd.aseprite -save-as issue591.png || exit 1
|
||||
if [[ ! -f "issue591 (a).png" ||
|
||||
! -f "issue591 (b).png" ||
|
||||
! -f "issue591 (c).png" ||
|
||||
! -f "issue591 (d).png" ]]; then
|
||||
echo "FAIL: Regression detected (issue 591)"
|
||||
exit 1
|
||||
fi
|
||||
cd $oldwd
|
||||
|
||||
# --save-as group without showing hidden children
|
||||
# https://github.com/aseprite/aseprite/issues/2084#issuecomment-525835889
|
||||
|
||||
if [[ "$(uname)" =~ "MINGW" ]] || [[ "$(uname)" =~ "MSYS" ]] ; then
|
||||
# Ignore this test on Windows because we cannot give * as a parameter (?)
|
||||
echo Do nothing
|
||||
else
|
||||
d=$t/save-as-groups-and-hidden
|
||||
mkdir $d
|
||||
$ASEPRITE -b sprites/groups2.aseprite -layer \* -save-as "$d/g2-all.png" || exit 1
|
||||
$ASEPRITE -b sprites/groups2.aseprite -layer \* -ignore-layer items -save-as "$d/g2-all-without-items.png" || exit 1
|
||||
$ASEPRITE -b sprites/groups2.aseprite -layer \* -ignore-layer gun -save-as "$d/g2-all-without-gun1.png" || exit 1
|
||||
$ASEPRITE -b sprites/groups2.aseprite -layer \* -ignore-layer sword -save-as "$d/g2-all-without-sword1.png" || exit 1
|
||||
$ASEPRITE -b sprites/groups2.aseprite -layer \* -ignore-layer items/gun -save-as "$d/g2-all-without-gun2.png" || exit 1
|
||||
$ASEPRITE -b sprites/groups2.aseprite -layer \* -ignore-layer items/sword -save-as "$d/g2-all-without-sword2.png" || exit 1
|
||||
$ASEPRITE -b sprites/groups2.aseprite -layer \* -ignore-layer player -save-as "$d/g2-all-without-player.png" || exit 1
|
||||
$ASEPRITE -b sprites/groups2.aseprite -layer player -save-as "$d/g2-player.png" || exit 1
|
||||
$ASEPRITE -b sprites/groups2.aseprite -layer items -save-as "$d/g2-items.png" || exit 1
|
||||
$ASEPRITE -b sprites/groups2.aseprite -layer items/\* -save-as "$d/g2-items-all.png" || exit 1
|
||||
$ASEPRITE -b sprites/groups2.aseprite -layer sword -save-as "$d/g2-sword.png" || exit 1
|
||||
$ASEPRITE -b sprites/groups2.aseprite -layer gun -save-as "$d/g2-gun.png" || exit 1
|
||||
|
||||
$ASEPRITE -b sprites/groups3abc.aseprite -layer a -save-as "$d/g3-a.png" || exit 1
|
||||
$ASEPRITE -b sprites/groups3abc.aseprite -layer b -save-as "$d/g3-b.png" || exit 1
|
||||
$ASEPRITE -b sprites/groups3abc.aseprite -layer c -save-as "$d/g3-c.png" || exit 1
|
||||
$ASEPRITE -b sprites/groups3abc.aseprite -layer a/\* -save-as "$d/g3-a-all.png" || exit 1
|
||||
$ASEPRITE -b sprites/groups3abc.aseprite -layer b/\* -save-as "$d/g3-b-all.png" || exit 1
|
||||
$ASEPRITE -b sprites/groups3abc.aseprite -layer c/\* -save-as "$d/g3-c-all.png" || exit 1
|
||||
$ASEPRITE -b sprites/groups3abc.aseprite -layer a/a -save-as "$d/g3-aa.png" || exit 1
|
||||
$ASEPRITE -b sprites/groups3abc.aseprite -layer b/a -save-as "$d/g3-ba.png" || exit 1
|
||||
$ASEPRITE -b sprites/groups3abc.aseprite -layer c/a -save-as "$d/g3-ca.png" || exit 1
|
||||
$ASEPRITE -b sprites/groups3abc.aseprite -layer a/b -save-as "$d/g3-ab.png" || exit 1
|
||||
$ASEPRITE -b sprites/groups3abc.aseprite -layer b/b -save-as "$d/g3-bb.png" || exit 1
|
||||
$ASEPRITE -b sprites/groups3abc.aseprite -layer c/b -save-as "$d/g3-cb.png" || exit 1
|
||||
$ASEPRITE -b sprites/groups3abc.aseprite -layer a/c -save-as "$d/g3-ac.png" || exit 1
|
||||
$ASEPRITE -b sprites/groups3abc.aseprite -layer b/c -save-as "$d/g3-bc.png" || exit 1
|
||||
$ASEPRITE -b sprites/groups3abc.aseprite -layer c/c -save-as "$d/g3-cc.png" || exit 1
|
||||
|
||||
cat >$d/compare.lua <<EOF
|
||||
dofile('scripts/test_utils.lua')
|
||||
|
||||
local g2 = app.open("sprites/groups2.aseprite")
|
||||
local g3 = app.open("sprites/groups3abc.aseprite")
|
||||
|
||||
function img(name)
|
||||
local i = Image{ fromFile="$d/" .. name .. ".png" }
|
||||
if not i then error('file ' .. name .. '.png does not exist') end
|
||||
return i
|
||||
end
|
||||
|
||||
expect_rendered_layers(img("g2-all"), g2, { "items/gun", "items/sword", "player/head", "player/body" })
|
||||
expect_rendered_layers(img("g2-all-without-items"), g2, { "player/head", "player/body" })
|
||||
expect_rendered_layers(img("g2-all-without-gun1"), g2, { "items/sword", "player/head", "player/body" })
|
||||
expect_rendered_layers(img("g2-all-without-gun2"), g2, { "items/sword", "player/head", "player/body" })
|
||||
expect_rendered_layers(img("g2-all-without-sword1"), g2, { "items/gun", "player/head", "player/body" })
|
||||
expect_rendered_layers(img("g2-all-without-sword2"), g2, { "items/gun", "player/head", "player/body" })
|
||||
expect_rendered_layers(img("g2-player"), g2, { "player/head", "player/body" })
|
||||
expect_rendered_layers(img("g2-items"), g2, { "items/sword" })
|
||||
expect_rendered_layers(img("g2-items-all"), g2, { "items/gun", "items/sword" })
|
||||
expect_rendered_layers(img("g2-sword"), g2, { "items/sword" })
|
||||
expect_rendered_layers(img("g2-gun"), g2, { "items/gun" })
|
||||
|
||||
expect_rendered_layers(img("g3-a"), g3, { "a/a", "a/b", "a/c" })
|
||||
expect_rendered_layers(img("g3-b"), g3, { "b/a", "b/c" })
|
||||
expect_rendered_layers(img("g3-c"), g3, { "c/c" })
|
||||
expect_rendered_layers(img("g3-a-all"), g3, { "a/a", "a/b", "a/c" })
|
||||
expect_rendered_layers(img("g3-b-all"), g3, { "b/a", "b/b", "b/c" })
|
||||
expect_rendered_layers(img("g3-c-all"), g3, { "c/a", "c/b", "c/c" })
|
||||
expect_rendered_layers(img("g3-aa"), g3, { "a/a" })
|
||||
expect_rendered_layers(img("g3-ab"), g3, { "a/b" })
|
||||
expect_rendered_layers(img("g3-ac"), g3, { "a/c" })
|
||||
expect_rendered_layers(img("g3-ba"), g3, { "b/a" })
|
||||
expect_rendered_layers(img("g3-bb"), g3, { "b/b" })
|
||||
expect_rendered_layers(img("g3-bc"), g3, { "b/c" })
|
||||
expect_rendered_layers(img("g3-ca"), g3, { "c/a" })
|
||||
expect_rendered_layers(img("g3-cb"), g3, { "c/b" })
|
||||
expect_rendered_layers(img("g3-cc"), g3, { "c/c" })
|
||||
EOF
|
||||
$ASEPRITE -b -script "$d/compare.lua" || exit 1
|
||||
fi
|
402
tests/cli/sheet.sh
Normal file
402
tests/cli/sheet.sh
Normal file
@ -0,0 +1,402 @@
|
||||
#! /bin/bash
|
||||
# Copyright (C) 2019-2022 Igara Studio S.A.
|
||||
|
||||
# $1 = first sprite sheet json file
|
||||
# $2 = second sprite sheet json file
|
||||
function compare_sheet_data() {
|
||||
cat $1 | grep -v "\"image\"" > $1-tmp
|
||||
cat $2 | grep -v "\"image\"" > $2-tmp
|
||||
diff -u $1-tmp $2-tmp
|
||||
}
|
||||
|
||||
# --sheet and STDOUT
|
||||
|
||||
d=$t/sheet
|
||||
mkdir $d # we need to create the directory because the >STDOUT redirection
|
||||
if ! $ASEPRITE -b sprites/1empty3.aseprite --sheet "$d/sheet.png" > "$d/stdout.json" ; then
|
||||
exit 1
|
||||
fi
|
||||
cat >$d/compare.lua <<EOF
|
||||
local json = dofile('third_party/json/json.lua')
|
||||
local data = json.decode(io.open('$d/stdout.json'):read('a'))
|
||||
local frames = { data.frames['1empty3 0.aseprite'],
|
||||
data.frames['1empty3 1.aseprite'],
|
||||
data.frames['1empty3 2.aseprite'] }
|
||||
assert(frames[1].frame.x == 0)
|
||||
assert(frames[2].frame.x == 32)
|
||||
assert(frames[3].frame.x == 64)
|
||||
for i,v in ipairs(frames) do
|
||||
assert(v.frame.y == 0)
|
||||
assert(v.frame.w == 32)
|
||||
assert(v.frame.h == 32)
|
||||
end
|
||||
EOF
|
||||
$ASEPRITE -b -script "$d/compare.lua" || exit 1
|
||||
|
||||
# --sheet --data
|
||||
|
||||
d0=$d
|
||||
d=$t/sheet-data
|
||||
$ASEPRITE -b sprites/1empty3.aseprite --sheet "$d/sheet.png" --data "$d/sheet.json" || exit 1
|
||||
compare_sheet_data $d0/stdout.json $d/sheet.json || exit 1
|
||||
cat >$d/compare.lua <<EOF
|
||||
local orig = app.open("sprites/1empty3.aseprite")
|
||||
local sheet = app.open("$d/sheet.png")
|
||||
local expected = Image(orig.width*3, orig.height, orig.colorMode)
|
||||
expected:clear()
|
||||
for f = 1,3 do
|
||||
expected:drawSprite(orig, f, (f-1)*orig.width, 0)
|
||||
end
|
||||
assert(expected:isEqual(sheet.cels[1].image))
|
||||
EOF
|
||||
$ASEPRITE -b -script "$d/compare.lua" || exit 1
|
||||
|
||||
# vertical sprite sheet
|
||||
|
||||
d=$t/vertical-sheet
|
||||
mkdir $d
|
||||
# TODO this should be possible in a future
|
||||
# $ASEPRITE -b sprites/1empty3.aseprite -sheet-type vertical --sheet "$d/sheet.png" --data "$d/sheet.json" || exit 1
|
||||
cat >$d/create.lua <<EOF
|
||||
local sprite = app.open("sprites/1empty3.aseprite")
|
||||
app.command.ExportSpriteSheet {
|
||||
type="vertical",
|
||||
textureFilename="$d/sheet1.png",
|
||||
dataFilename="$d/sheet1.json"
|
||||
}
|
||||
app.command.ExportSpriteSheet {
|
||||
type=SpriteSheetType.VERTICAL,
|
||||
textureFilename="$d/sheet2.png",
|
||||
dataFilename="$d/sheet2.json"
|
||||
}
|
||||
EOF
|
||||
$ASEPRITE -b -script "$d/create.lua" || exit 1
|
||||
compare_sheet_data "$d/sheet1.json" "$d/sheet2.json" || exit 1
|
||||
cmp "$d/sheet1.png" "$d/sheet2.png" || exit 1
|
||||
cat >$d/compare.lua <<EOF
|
||||
local orig = app.open("sprites/1empty3.aseprite")
|
||||
local sheet = app.open("$d/sheet1.png")
|
||||
local expected = Image(orig.width, orig.height*3, orig.colorMode)
|
||||
expected:clear()
|
||||
for f = 1,3 do
|
||||
expected:drawSprite(orig, f, 0, (f-1)*orig.height)
|
||||
end
|
||||
assert(expected:isEqual(sheet.cels[1].image))
|
||||
EOF
|
||||
$ASEPRITE -b -script "$d/compare.lua" || exit 1
|
||||
|
||||
# --split-layers --sheet --data
|
||||
|
||||
d=$t/split-layers-sheet-data
|
||||
$ASEPRITE -b --split-layers sprites/1empty3.aseprite \
|
||||
--filename-format "{layer}-{frame}" \
|
||||
--sheet "$d/sheet.png" \
|
||||
--data "$d/sheet.json" || exit 1
|
||||
cat >$d/compare.lua <<EOF
|
||||
local json = dofile('third_party/json/json.lua')
|
||||
local data = json.decode(io.open('$d/sheet.json'):read('a'))
|
||||
assert(data.meta.size.w == 96)
|
||||
assert(data.meta.size.h == 64)
|
||||
|
||||
local orig = app.open("sprites/1empty3.aseprite")
|
||||
local sheet = app.open("$d/sheet.png")
|
||||
local expected = Image(orig.width*3, orig.height*2, orig.colorMode)
|
||||
expected:clear()
|
||||
for lay = 1,2 do
|
||||
orig.layers[1].isVisible = (lay == 1)
|
||||
orig.layers[2].isVisible = (lay == 2)
|
||||
for frm = 1,3 do
|
||||
local x, y = (frm-1)*orig.width, (lay-1)*orig.height
|
||||
expected:drawSprite(orig, frm, x, y)
|
||||
|
||||
local frmData = data.frames[orig.layers[lay].name .. '-' .. (frm-1)]
|
||||
assert(frmData.frame.x == x)
|
||||
assert(frmData.frame.y == y)
|
||||
assert(frmData.frame.w == 32)
|
||||
assert(frmData.frame.h == 32)
|
||||
end
|
||||
end
|
||||
assert(expected:isEqual(sheet.cels[1].image))
|
||||
EOF
|
||||
$ASEPRITE -b -script "$d/compare.lua" || exit 1
|
||||
|
||||
# Test that the transparent color persists in the output sheet
|
||||
|
||||
d=$t/sheet-custom-transparent-index
|
||||
if ! $ASEPRITE -b sprites/bg-index-3.aseprite -sheet "$d/sheet.aseprite" -data "$d/sheet.json" ; then
|
||||
exit 1
|
||||
fi
|
||||
cat >$d/compare.lua <<EOF
|
||||
local original = Sprite{ fromFile='sprites/bg-index-3.aseprite' }
|
||||
assert(original.transparentColor == 3)
|
||||
local sheet = Sprite{ fromFile='$d/sheet.aseprite' }
|
||||
assert(sheet.transparentColor == 3)
|
||||
EOF
|
||||
$ASEPRITE -b -script "$d/compare.lua" || exit 1
|
||||
|
||||
# Don't discard empty frames if -ignore-empty is not used (even if -trim is used)
|
||||
# https://github.com/aseprite/aseprite/issues/2116
|
||||
# -layer -trim -ignore-empty -list-tags -sheet -data
|
||||
|
||||
d=$t/sheet-trim-without-ignore-empty
|
||||
$ASEPRITE -b \
|
||||
-list-tags \
|
||||
-layer "c" \
|
||||
"sprites/tags3.aseprite" \
|
||||
-trim \
|
||||
-sheet-pack \
|
||||
-sheet "$d/sheet1.png" \
|
||||
-format json-array \
|
||||
-data "$d/sheet1.json" || exit 1
|
||||
$ASEPRITE -b \
|
||||
-list-tags \
|
||||
-layer "c" \
|
||||
"sprites/tags3.aseprite" \
|
||||
-trim -ignore-empty \
|
||||
-sheet-pack \
|
||||
-sheet "$d/sheet2.png" \
|
||||
-format json-array \
|
||||
-data "$d/sheet2.json" || exit 1
|
||||
|
||||
cat >$d/check.lua <<EOF
|
||||
local json = dofile('third_party/json/json.lua')
|
||||
local sheet1 = json.decode(io.open('$d/sheet1.json'):read('a'))
|
||||
local sheet2 = json.decode(io.open('$d/sheet2.json'):read('a'))
|
||||
assert(#sheet1.frames == 12)
|
||||
assert(#sheet2.frames == 4)
|
||||
EOF
|
||||
$ASEPRITE -b -script "$d/check.lua" || exit 1
|
||||
|
||||
# -sheet -sheet-columns vs -sheet-rows
|
||||
|
||||
d=$t/sheet-columns-and-rows
|
||||
$ASEPRITE -b -split-layers sprites/1empty3.aseprite \
|
||||
-filename-format "{layer}{frame}" \
|
||||
-sheet "$d/sheet1.png" \
|
||||
-sheet-type rows \
|
||||
-sheet-columns 3 \
|
||||
-data "$d/sheet1.json" || exit $?
|
||||
$ASEPRITE -b -split-layers sprites/1empty3.aseprite \
|
||||
-filename-format "{layer}{frame}" \
|
||||
-sheet "$d/sheet2.png" \
|
||||
-sheet-type columns \
|
||||
-sheet-rows 3 \
|
||||
-data "$d/sheet2.json" || exit $?
|
||||
$ASEPRITE -b \
|
||||
-script-param file1=$d/sheet1.json \
|
||||
-script-param file2=$d/sheet2.json \
|
||||
-script scripts/compare_sprite_sheets.lua || exit $?
|
||||
|
||||
# -sheet -trim vs -trim-sprite
|
||||
|
||||
d=$t/sheet-columns-and-rows
|
||||
$ASEPRITE -b -split-layers sprites/1empty3.aseprite \
|
||||
-trim \
|
||||
-filename-format "{layer}{frame}" \
|
||||
-sheet "$d/sheet1.png" \
|
||||
-data "$d/sheet1.json" || exit $?
|
||||
|
||||
$ASEPRITE -b -split-layers sprites/1empty3.aseprite \
|
||||
-trim-sprite \
|
||||
-filename-format "{layer}{frame}" \
|
||||
-sheet "$d/sheet2.png" \
|
||||
-data "$d/sheet2.json" || exit $?
|
||||
$ASEPRITE -b \
|
||||
-script-param file1=$d/sheet1.json \
|
||||
-script-param file2=$d/sheet2.json \
|
||||
-script scripts/compare_sprite_sheets.lua || exit $?
|
||||
|
||||
# Test all sprite sheet types
|
||||
# -sheet horizontal/vertical/rows/columns/packed
|
||||
d=$t/sheet-all-types
|
||||
for type in horizontal vertical rows columns packed ; do
|
||||
$ASEPRITE -b "sprites/tags3.aseprite" \
|
||||
-sheet-type $type -sheet "$d/$type.png" \
|
||||
-format json-array -data "$d/$type.json" || exit $?
|
||||
|
||||
$ASEPRITE -b -split-layers "sprites/tags3.aseprite" \
|
||||
-sheet-type $type -sheet "$d/$type-layers.png" \
|
||||
-format json-array -data "$d/$type-layers.json" || exit $?
|
||||
|
||||
$ASEPRITE -b -split-layers -merge-duplicates "sprites/tags3.aseprite" \
|
||||
-sheet-type $type -sheet "$d/$type-layers-merge-duplicates.png" \
|
||||
-format json-array -data "$d/$type-layers-merge-duplicates.json" || exit $?
|
||||
|
||||
$ASEPRITE -b -split-tags "sprites/tags3.aseprite" \
|
||||
-sheet-type $type -sheet "$d/$type-tags.png" \
|
||||
-format json-array -data "$d/$type-tags.json" || exit $?
|
||||
|
||||
$ASEPRITE -b -split-tags -trim "sprites/tags3.aseprite" \
|
||||
-sheet-type $type -sheet "$d/$type-tags-trim.png" \
|
||||
-format json-array -data "$d/$type-tags-trim.json" || exit $?
|
||||
|
||||
$ASEPRITE -b -split-layers -split-tags "sprites/tags3.aseprite" \
|
||||
-sheet-type $type -sheet "$d/$type-layer-tags.png" \
|
||||
-format json-array -data "$d/$type-layer-tags.json" || exit $?
|
||||
done
|
||||
|
||||
for type in horizontal vertical rows columns ; do
|
||||
for subtype in "" "-layers" "-layers-merge-duplicates" "-tags" "-tags-trim" "-layer-tags" ; do
|
||||
$ASEPRITE -b \
|
||||
-script-param file1=$d/packed$subtype.json \
|
||||
-script-param file2=$d/$type$subtype.json \
|
||||
-script scripts/compare_sprite_sheets.lua || exit $?
|
||||
done
|
||||
done
|
||||
|
||||
# "Trim Cels" (-trim) with -merge-duplicates didn't generate the
|
||||
# correct "spriteSourceSize" for each frame.
|
||||
# https://igarastudio.zendesk.com/agent/tickets/407
|
||||
d=$t/ticket-407
|
||||
for layer in a b ; do
|
||||
$ASEPRITE -b -layer "$layer" "sprites/point4frames.aseprite" \
|
||||
-trim \
|
||||
-data "$d/data1-$layer.json" \
|
||||
-format json-array -sheet "$d/sheet1-$layer.png" || exit 1
|
||||
$ASEPRITE -b -layer "$layer" "sprites/point4frames.aseprite" \
|
||||
-trim -merge-duplicates \
|
||||
-data "$d/data2-$layer.json" \
|
||||
-format json-array -sheet "$d/sheet2-$layer.png" || exit 1
|
||||
cat >$d/compare.lua <<EOF
|
||||
local json = dofile('third_party/json/json.lua')
|
||||
local data1 = json.decode(io.open('$d/data1-$layer.json'):read('a'))
|
||||
local data2 = json.decode(io.open('$d/data2-$layer.json'):read('a'))
|
||||
assert(#data1.frames == #data2.frames)
|
||||
for i = 1,#data1.frames do
|
||||
local a = data1.frames[i].spriteSourceSize
|
||||
local b = data2.frames[i].spriteSourceSize
|
||||
assert(a.x == b.x)
|
||||
assert(a.y == b.y)
|
||||
assert(a.w == b.w)
|
||||
assert(a.h == b.h)
|
||||
end
|
||||
EOF
|
||||
$ASEPRITE -b -script "$d/compare.lua" || exit 1
|
||||
done
|
||||
|
||||
# Same problem as in ticket 407 but with "sourceSize" field and
|
||||
# different sprites in the same texture atlas.
|
||||
d=$t/ticket-407-w-atlas
|
||||
$ASEPRITE -b \
|
||||
-layer a "sprites/point4frames.aseprite" \
|
||||
"sprites/point2frames.aseprite" \
|
||||
-data "$d/data1.json" \
|
||||
-format json-array -sheet "$d/sheet1.png" || exit 1
|
||||
$ASEPRITE -b \
|
||||
-layer a "sprites/point4frames.aseprite" \
|
||||
"sprites/point2frames.aseprite" \
|
||||
-trim \
|
||||
-data "$d/data2.json" \
|
||||
-format json-array -sheet-pack -sheet "$d/sheet2.png" || exit 1
|
||||
cat >$d/compare.lua <<EOF
|
||||
local json = dofile('third_party/json/json.lua')
|
||||
local data1 = json.decode(io.open('$d/data1.json'):read('a'))
|
||||
local data2 = json.decode(io.open('$d/data2.json'):read('a'))
|
||||
assert(#data1.frames == #data2.frames)
|
||||
for i = 1,#data1.frames do
|
||||
local a = data1.frames[i].sourceSize
|
||||
local b = data2.frames[i].sourceSize
|
||||
assert(a.w == b.w)
|
||||
assert(a.h == b.h)
|
||||
end
|
||||
EOF
|
||||
$ASEPRITE -b -script "$d/compare.lua" || exit 1
|
||||
|
||||
# https://github.com/aseprite/aseprite/issues/2380
|
||||
# Check that -split-layers and -list-layers include group information
|
||||
d=$t/issue-2380
|
||||
$ASEPRITE -b -trim -all-layers "sprites/groups3abc.aseprite" -data "$d/sheet1.json" -format json-array -sheet "$d/sheet1.png" -list-layers
|
||||
$ASEPRITE -b -trim -all-layers -split-layers "sprites/groups3abc.aseprite" -data "$d/sheet2.json" -format json-array -sheet "$d/sheet2.png" -list-layers
|
||||
cat >$d/check.lua <<EOF
|
||||
local json = dofile('third_party/json/json.lua')
|
||||
local sheet1 = json.decode(io.open('$d/sheet1.json'):read('a'))
|
||||
local sheet2 = json.decode(io.open('$d/sheet2.json'):read('a'))
|
||||
assert(#sheet1.meta.layers == 12)
|
||||
assert(#sheet2.meta.layers == 12)
|
||||
assert(json.encode(sheet1.meta.layers) == json.encode(sheet2.meta.layers))
|
||||
EOF
|
||||
$ASEPRITE -b -script "$d/check.lua" || exit 1
|
||||
|
||||
# https://github.com/aseprite/aseprite/issues/2432
|
||||
# -ignore-layer is ignoring extra layers when -split-layers is used
|
||||
d=$t/issue-2432
|
||||
$ASEPRITE -b -trim -ignore-layer "c" -all-layers "sprites/groups3abc.aseprite" -data "$d/sheet1.json" -format json-array -sheet "$d/sheet1.png" -list-layers
|
||||
$ASEPRITE -b -trim -ignore-layer "c" -all-layers -split-layers "sprites/groups3abc.aseprite" -data "$d/sheet2.json" -format json-array -sheet "$d/sheet2.png" -list-layers
|
||||
cat >$d/check.lua <<EOF
|
||||
local json = dofile('third_party/json/json.lua')
|
||||
local sheet1 = json.decode(io.open('$d/sheet1.json'):read('a'))
|
||||
local sheet2 = json.decode(io.open('$d/sheet2.json'):read('a'))
|
||||
assert(#sheet1.meta.layers == 8)
|
||||
assert(#sheet2.meta.layers == 8)
|
||||
assert(json.encode(sheet1.meta.layers) == json.encode(sheet2.meta.layers))
|
||||
EOF
|
||||
$ASEPRITE -b -script "$d/check.lua" || exit 1
|
||||
|
||||
# https://github.com/aseprite/aseprite/issues/2600
|
||||
# -merge-duplicates -split-layers -trim give incorrect 'frame' coordinates on linked cels
|
||||
d=$t/issue-2600
|
||||
$ASEPRITE -b -list-layers -format json-array -trim -merge-duplicates -split-layers -all-layers "sprites/link.aseprite" -data "$d/sheet.json" -sheet "$d/sheet.png"
|
||||
cat >$d/check.lua <<EOF
|
||||
local json = dofile('third_party/json/json.lua')
|
||||
local sheet = json.decode(io.open('$d/sheet.json'):read('a'))
|
||||
local restoredSprite = Sprite(sheet.frames[1].sourceSize.w, sheet.frames[1].sourceSize.h, ColorMode.RGB)
|
||||
local spriteSheet = Image{ fromFile="$d/sheet.png" }
|
||||
local lay = 1
|
||||
repeat
|
||||
local layerName = sheet.meta.layers[lay].name
|
||||
local layer = restoredSprite.layers[lay]
|
||||
for i=1, #sheet.frames do
|
||||
if string.find(sheet.frames[i].filename, layerName) ~= nil then
|
||||
local sample = sheet.frames[i]
|
||||
local dotAseIndex = string.find(sample.filename, ".ase")
|
||||
local frame = (string.sub(sample.filename, dotAseIndex - 2, dotAseIndex - 1)) + 1
|
||||
for f=#restoredSprite.frames, frame-1 do
|
||||
restoredSprite:newEmptyFrame()
|
||||
end
|
||||
local image = Image(sample.frame.w, sample.frame.h)
|
||||
for y=0,image.height-1 do
|
||||
for x=0,image.width-1 do
|
||||
image:drawPixel(x, y, spriteSheet:getPixel(sample.frame.x + x, sample.frame.y + y))
|
||||
end
|
||||
end
|
||||
restoredSprite:newCel(layer, frame, image, Point(sample.spriteSourceSize.x, sample.spriteSourceSize.y))
|
||||
end
|
||||
end
|
||||
if lay < #sheet.meta.layers then
|
||||
restoredSprite:newLayer()
|
||||
end
|
||||
lay = lay + 1
|
||||
until(lay > #sheet.meta.layers)
|
||||
|
||||
app.activeSprite = restoredSprite
|
||||
app.activeLayer = restoredSprite.layers[#restoredSprite.layers]
|
||||
for i=1,#restoredSprite.layers-1 do
|
||||
app.command.MergeDownLayer()
|
||||
end
|
||||
|
||||
local orig = app.open("sprites/link.aseprite")
|
||||
app.activeSprite = orig
|
||||
app.activeLayer = orig.layers[#orig.layers]
|
||||
for i=1,#orig.layers-1 do
|
||||
app.command.MergeDownLayer()
|
||||
end
|
||||
|
||||
assert(orig.width == restoredSprite.width)
|
||||
assert(orig.height == restoredSprite.height)
|
||||
assert(#orig.frames == #restoredSprite.frames)
|
||||
for fr=1,#restoredSprite.frames do
|
||||
for celIndex1=1,#restoredSprite.cels do
|
||||
if restoredSprite.cels[celIndex1].frameNumber == fr then
|
||||
for celIndex2=1,#orig.cels do
|
||||
if orig.cels[celIndex2].frameNumber == fr then
|
||||
assert(orig.cels[celIndex2].position == restoredSprite.cels[celIndex1].position)
|
||||
if orig.cels[celIndex2].image ~= nil and restoredSprite.cels[celIndex1].image ~= nil then
|
||||
assert(orig.cels[celIndex2].image:isEqual(restoredSprite.cels[celIndex1].image))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
EOF
|
||||
$ASEPRITE -b -script "$d/check.lua" || exit 1
|
7
tests/cli/version.sh
Normal file
7
tests/cli/version.sh
Normal file
@ -0,0 +1,7 @@
|
||||
#! /bin/bash
|
||||
# Copyright (C) 2018 Igara Studio S.A.
|
||||
|
||||
if ! $ASEPRITE --version | grep "Aseprite 1\\." > /dev/null ; then
|
||||
echo "FAILED: --version doesn't include 'Aseprite 1.' string"
|
||||
exit 1
|
||||
fi
|
107
tests/run-tests.sh
Executable file
107
tests/run-tests.sh
Executable file
@ -0,0 +1,107 @@
|
||||
#! /bin/bash
|
||||
# Copyright (C) 2018 Igara Studio S.A.
|
||||
# Copyright (C) 2018 David Capello
|
||||
|
||||
if [[ "$ASEPRITE" == "" ]]; then
|
||||
echo ASEPRITE env var must be pointing to the Aseprite executable
|
||||
exit 1
|
||||
fi
|
||||
|
||||
function fail() {
|
||||
echo FAIL
|
||||
echo $BASH_SOURCE:$BASH_LINENO: error: $*
|
||||
exit 1
|
||||
}
|
||||
|
||||
function expect() {
|
||||
if [[ $1 != "$($2 | tr -d "\r")" ]] ; then
|
||||
echo "FAILED: $2"
|
||||
echo "EXPECTED: $1"
|
||||
echo "RESULT: $($2)"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# General information
|
||||
echo ----------------------------------------------------------------------
|
||||
echo $ASEPRITE --version
|
||||
$ASEPRITE --version
|
||||
|
||||
filter="$*"
|
||||
if [[ "$filter" != "" ]]; then
|
||||
echo Filter: $filter
|
||||
fi
|
||||
|
||||
t=$(mktemp -d)
|
||||
if [[ "$(uname)" =~ "MINGW" ]] || [[ "$(uname)" =~ "MSYS" ]] ; then
|
||||
PWDARG=-W
|
||||
t=$(cd "$t" && pwd $PWDARG)
|
||||
else
|
||||
PWDARG=
|
||||
fi
|
||||
echo Temp dir: $t
|
||||
export ASEPRITE_USER_FOLDER=$t
|
||||
|
||||
if [[ "$filter" == "" ]] || [[ "console" =~ $filter ]]; then
|
||||
echo ----------------------------------------------------------------------
|
||||
echo "Testing console..."
|
||||
echo "uname=$(uname)"
|
||||
|
||||
$ASEPRITE -b --script scripts/console_assert.lua >$t/tmp 2>&1
|
||||
! grep -q "this should be in the output" $t/tmp && fail "print() text not found in output"
|
||||
! grep -q "assertion failed" $t/tmp && fail "assert() text not found in output"
|
||||
grep -q "this should not be in the output" $t/tmp && fail "text that shouldn't be in the output is"
|
||||
|
||||
if [[ "$(uname)" =~ "MINGW" ]] || [[ "$(uname)" =~ "MSYS" ]] ; then
|
||||
echo Ignore console tests on Windows
|
||||
else
|
||||
$ASEPRITE -b --script scripts/console_print.lua >$t/tmp 2>&1
|
||||
cat >$t/tmp_expected <<EOF
|
||||
hello world
|
||||
1 2 3
|
||||
EOF
|
||||
! diff -u $t/tmp $t/tmp_expected && fail
|
||||
fi
|
||||
fi
|
||||
|
||||
first=0
|
||||
result=0
|
||||
for script in scripts/*.lua ; do
|
||||
[[ $script =~ console ]] && continue
|
||||
if [[ "$filter" != "" ]]; then
|
||||
[[ $script =~ $filter ]] || continue
|
||||
fi
|
||||
if [ $first == 0 ]; then
|
||||
echo ----------------------------------------------------------------------
|
||||
echo "Testing scripts..."
|
||||
first=1
|
||||
fi
|
||||
echo "Running $script"
|
||||
if ! $ASEPRITE -b --script $script >$t/tmp 2>&1 ; then
|
||||
echo FAILED && cat $t/tmp
|
||||
result=1
|
||||
fi
|
||||
done
|
||||
|
||||
first=0
|
||||
for script in cli/*.sh ; do
|
||||
if [[ "$filter" == "" ]] || [[ $script =~ $filter ]]; then
|
||||
if [ $first == 0 ]; then
|
||||
echo ----------------------------------------------------------------------
|
||||
echo "Testing CLI..."
|
||||
first=1
|
||||
fi
|
||||
echo "Running $script"
|
||||
source $script
|
||||
fi
|
||||
done
|
||||
|
||||
echo ----------------------------------------------------------------------
|
||||
if [ $result == 0 ] ; then
|
||||
echo Done
|
||||
else
|
||||
echo FAILED
|
||||
fi
|
||||
echo ----------------------------------------------------------------------
|
||||
|
||||
exit $result
|
25
tests/scripts/app_active.lua
Normal file
25
tests/scripts/app_active.lua
Normal file
@ -0,0 +1,25 @@
|
||||
-- Copyright (C) 2018-2019 Igara Studio S.A.
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
local s = Sprite(32, 64)
|
||||
assert(s == app.activeSprite)
|
||||
assert(s == app.site.sprite)
|
||||
assert(s == app.activeFrame.sprite)
|
||||
assert(s == app.site.frame.sprite)
|
||||
assert(1 == app.activeFrame.frameNumber)
|
||||
assert(1 == app.site.frame.frameNumber)
|
||||
assert(1 == app.site.frameNumber)
|
||||
assert(0.100 == app.activeFrame.duration) -- Default frame duration
|
||||
assert(0.100 == app.site.frame.duration)
|
||||
assert(s == app.activeLayer.sprite)
|
||||
assert(s == app.site.layer.sprite)
|
||||
assert(s == app.activeCel.sprite)
|
||||
assert(s == app.site.cel.sprite)
|
||||
|
||||
app.activeFrame.duration = 0.8
|
||||
|
||||
app.command.NewFrame()
|
||||
assert(2 == app.activeFrame.frameNumber)
|
||||
assert(0.8 == app.activeFrame.duration) -- Copy frame duration of previous frame
|
606
tests/scripts/app_command.lua
Normal file
606
tests/scripts/app_command.lua
Normal file
@ -0,0 +1,606 @@
|
||||
-- Copyright (C) 2019-2020 Igara Studio S.A.
|
||||
-- Copyright (C) 2018 David Capello
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
dofile('./test_utils.lua')
|
||||
|
||||
local rgba = app.pixelColor.rgba
|
||||
local rgbaR = app.pixelColor.rgbaR
|
||||
local rgbaG = app.pixelColor.rgbaG
|
||||
local rgbaB = app.pixelColor.rgbaB
|
||||
|
||||
do -- Undo/Redo commands (like app.undo/redo())
|
||||
local s = Sprite(32, 32)
|
||||
assert(s.width == 32)
|
||||
assert(s.height == 32)
|
||||
|
||||
s:resize(50, 40)
|
||||
assert(s.width == 50)
|
||||
assert(s.height == 40)
|
||||
|
||||
app.command.Undo()
|
||||
assert(s.width == 32)
|
||||
assert(s.height == 32)
|
||||
|
||||
app.command.Redo()
|
||||
assert(s.width == 50)
|
||||
assert(s.height == 40)
|
||||
end
|
||||
|
||||
do -- NewSprite
|
||||
local s1 = app.activeSprite
|
||||
app.command.NewFile{ }
|
||||
assert(s1 == app.activeSprite)
|
||||
app.command.NewFile{ width=256, height=128, colorMode=ColorMode.INDEXED }
|
||||
local s2 = app.activeSprite
|
||||
assert(s1 ~= s2)
|
||||
assert(s2.width == 256)
|
||||
assert(s2.height == 128)
|
||||
assert(s2.colorMode == ColorMode.INDEXED)
|
||||
end
|
||||
|
||||
do -- ExportSpriteSheet
|
||||
local s = Sprite{ fromFile="sprites/2f-index-3x3.aseprite" }
|
||||
app.command.ExportSpriteSheet {
|
||||
type="horizontal",
|
||||
textureFilename="_test_export_spritesheet1.png",
|
||||
shapePadding=1
|
||||
}
|
||||
local i = Image{ fromFile="_test_export_spritesheet1.png" }
|
||||
expect_img(i, {
|
||||
11,8,11,21,8,11,11,
|
||||
11,8,11,21,11,8,11,
|
||||
11,8,11,21,11,11,8,
|
||||
})
|
||||
end
|
||||
|
||||
do -- NewLayer/RemoveLayer
|
||||
local s = Sprite(32, 32)
|
||||
assert(#s.layers == 1)
|
||||
local lay = s.layers[1]
|
||||
app.command.NewLayer{top=true}
|
||||
local lay2 = app.activeLayer
|
||||
assert(#s.layers == 2)
|
||||
assert(s.layers[2].isImage)
|
||||
|
||||
app.command.NewLayer{top=true, group=true}
|
||||
local lay3 = app.activeLayer
|
||||
assert(#s.layers == 3)
|
||||
assert(s.layers[3].isGroup)
|
||||
|
||||
assert(app.activeLayer == lay3)
|
||||
app.command.RemoveLayer()
|
||||
assert(app.activeLayer == lay2)
|
||||
assert(#s.layers == 2)
|
||||
|
||||
app.command.RemoveLayer()
|
||||
assert(app.activeLayer == lay)
|
||||
assert(#s.layers == 1)
|
||||
end
|
||||
|
||||
do -- Background/Transparent layers
|
||||
local s = Sprite(32, 32)
|
||||
assert(s.layers[1].isTransparent)
|
||||
assert(s.cels[1].image:getPixel(0, 0) == app.pixelColor.rgba(0, 0, 0, 0))
|
||||
|
||||
app.bgColor = Color(32, 64, 128)
|
||||
app.command.BackgroundFromLayer() -- the layer will be filled with app.bgColor
|
||||
assert(s.layers[1].isBackground)
|
||||
assert(s.layers[1] == s.backgroundLayer)
|
||||
assert(s.cels[1].image:getPixel(0, 0) == app.pixelColor.rgba(32, 64, 128, 255))
|
||||
|
||||
app.command.LayerFromBackground()
|
||||
assert(s.layers[1].isTransparent)
|
||||
assert(s.cels[1].image:getPixel(0, 0) == app.pixelColor.rgba(32, 64, 128, 255))
|
||||
end
|
||||
|
||||
do -- Crop and Trim
|
||||
local s = Sprite(32, 32)
|
||||
s.selection:select(4, 5, 8, 10)
|
||||
assert(s.cels[1].bounds == Rectangle(0, 0, 32, 32))
|
||||
|
||||
-- Crop
|
||||
|
||||
app.command.CropSprite()
|
||||
assert(s.width == 8)
|
||||
assert(s.height == 10)
|
||||
assert(s.cels[1].bounds == Rectangle(-4, -5, 32, 32))
|
||||
|
||||
-- Autocrop (Trim)
|
||||
|
||||
app.command.AutocropSprite() -- Trim does nothing when we should remove all pixels
|
||||
assert(s.width == 8)
|
||||
assert(s.height == 10)
|
||||
|
||||
s.cels[1].image:putPixel(5, 5, Color(255, 0, 0))
|
||||
s.cels[1].image:putPixel(4, 6, Color(255, 0, 0))
|
||||
app.command.AutocropSprite()
|
||||
assert(s.width == 2)
|
||||
assert(s.height == 2)
|
||||
end
|
||||
|
||||
do -- Cel Opacity
|
||||
local s = Sprite(32, 32)
|
||||
local c = s.cels[1]
|
||||
assert(c.opacity == 255)
|
||||
|
||||
app.command.CelOpacity{opacity=128}
|
||||
assert(c.opacity == 128)
|
||||
|
||||
s.cels[1].opacity = 255
|
||||
assert(c.opacity == 255)
|
||||
|
||||
app.undo()
|
||||
assert(c.opacity == 128)
|
||||
app.undo()
|
||||
assert(c.opacity == 255)
|
||||
end
|
||||
|
||||
do -- PaletteSize
|
||||
local s = Sprite(32, 32)
|
||||
assert(#s.palettes[1] == 256)
|
||||
app.command.PaletteSize{ size=32 }
|
||||
assert(#s.palettes[1] == 32)
|
||||
app.command.PaletteSize{ size=8 }
|
||||
assert(#s.palettes[1] == 8)
|
||||
end
|
||||
|
||||
do -- CanvasSize
|
||||
local s = Sprite(32, 32)
|
||||
assert(s.bounds == Rectangle(0, 0, 32, 32))
|
||||
app.command.CanvasSize{ left=2 }
|
||||
assert(s.bounds == Rectangle(0, 0, 34, 32))
|
||||
app.command.CanvasSize{ top=2, right=4, bottom=8 }
|
||||
assert(s.bounds == Rectangle(0, 0, 38, 42))
|
||||
end
|
||||
|
||||
do -- ReplaceColor
|
||||
local s = Sprite(4, 4)
|
||||
local cel = app.activeCel
|
||||
local red = Color(255, 0, 0)
|
||||
local yellow = Color(255, 255, 0)
|
||||
local blue = Color(0, 0, 255)
|
||||
local r = red.rgbaPixel
|
||||
local y = yellow.rgbaPixel
|
||||
local b = blue.rgbaPixel
|
||||
|
||||
expect_eq(cel.bounds, Rectangle(0, 0, 4, 4))
|
||||
expect_img(cel.image,
|
||||
{ 0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0 })
|
||||
|
||||
app.useTool{ brush=Brush(1), color=red, points={Point(1,1)} }
|
||||
app.useTool{ brush=Brush(1), color=yellow, points={Point(2,2)} }
|
||||
expect_eq(cel.bounds, Rectangle(1, 1, 2, 2))
|
||||
expect_img(cel.image,
|
||||
{ r, 0,
|
||||
0, y })
|
||||
|
||||
app.command.ReplaceColor{ from=red, to=blue }
|
||||
expect_eq(cel.bounds, Rectangle(1, 1, 2, 2))
|
||||
expect_img(cel.image,
|
||||
{ b, 0,
|
||||
0, y })
|
||||
end
|
||||
|
||||
do -- Invert
|
||||
local s = Sprite(2, 2)
|
||||
local cel = app.activeCel
|
||||
local aa = Color(255, 128, 128).rgbaPixel
|
||||
local na = Color(0, 127, 127).rgbaPixel
|
||||
local bb = Color(128, 128, 255).rgbaPixel
|
||||
local nb = Color(127, 127, 0).rgbaPixel
|
||||
local i = cel.image
|
||||
|
||||
i:drawPixel(0, 0, aa)
|
||||
i:drawPixel(1, 0, bb)
|
||||
i:drawPixel(0, 1, bb)
|
||||
i:drawPixel(1, 1, aa)
|
||||
expect_img(cel.image,
|
||||
{ aa, bb,
|
||||
bb, aa })
|
||||
|
||||
app.command.InvertColor()
|
||||
expect_img(cel.image,
|
||||
{ na, nb,
|
||||
nb, na })
|
||||
|
||||
local Na = Color(0, 127, 128).rgbaPixel
|
||||
local Ng = Color(127, 127, 255).rgbaPixel
|
||||
app.command.InvertColor{ channels=FilterChannels.BLUE }
|
||||
expect_img(cel.image,
|
||||
{ Na, Ng,
|
||||
Ng, Na })
|
||||
end
|
||||
|
||||
do -- Outline
|
||||
local s = Sprite(4, 4)
|
||||
local cel = app.activeCel
|
||||
local red = Color(255, 0, 0)
|
||||
local yellow = Color(255, 255, 0)
|
||||
local blue = Color(0, 0, 255)
|
||||
local r = red.rgbaPixel
|
||||
local y = yellow.rgbaPixel
|
||||
local b = blue.rgbaPixel
|
||||
|
||||
expect_eq(cel.bounds, Rectangle(0, 0, 4, 4))
|
||||
expect_img(cel.image,
|
||||
{ 0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0 })
|
||||
|
||||
app.useTool{ brush=Brush(1), color=red, points={Point(1,1)} }
|
||||
app.useTool{ brush=Brush(1), color=yellow, points={Point(2,2)} }
|
||||
expect_eq(cel.bounds, Rectangle(1, 1, 2, 2))
|
||||
expect_img(cel.image,
|
||||
{ r, 0,
|
||||
0, y })
|
||||
|
||||
app.command.Outline{ color=blue }
|
||||
expect_eq(cel.bounds, Rectangle(0, 0, 4, 4))
|
||||
expect_img(cel.image,
|
||||
{ 0, b, 0, 0,
|
||||
b, r, b, 0,
|
||||
0, b, y, b,
|
||||
0, 0, b, 0 })
|
||||
|
||||
-- Test "bgColor", "matrix", "place" params
|
||||
|
||||
app.useTool{ tool='filled_rectangle', brush=Brush(1), color=blue, points={Point(0,0), Point(3,3)} }
|
||||
app.useTool{ tool='filled_rectangle', brush=Brush(1), color=yellow, points={Point(1,1), Point(2,2)} }
|
||||
expect_eq(cel.bounds, Rectangle(0, 0, 4, 4))
|
||||
expect_img(cel.image,
|
||||
{ b, b, b, b,
|
||||
b, y, y, b,
|
||||
b, y, y, b,
|
||||
b, b, b, b })
|
||||
|
||||
app.command.Outline{ color=red, bgColor=blue, matrix='circle' }
|
||||
expect_eq(cel.bounds, Rectangle(0, 0, 4, 4))
|
||||
expect_img(cel.image,
|
||||
{ b, r, r, b,
|
||||
r, y, y, r,
|
||||
r, y, y, r,
|
||||
b, r, r, b })
|
||||
app.undo()
|
||||
|
||||
app.command.Outline{ color=red, bgColor=blue, matrix='square' }
|
||||
expect_eq(cel.bounds, Rectangle(0, 0, 4, 4))
|
||||
expect_img(cel.image,
|
||||
{ r, r, r, r,
|
||||
r, y, y, r,
|
||||
r, y, y, r,
|
||||
r, r, r, r })
|
||||
app.undo()
|
||||
|
||||
app.command.Outline{ color=red, bgColor=blue, place='inside' }
|
||||
expect_eq(cel.bounds, Rectangle(0, 0, 4, 4))
|
||||
expect_img(cel.image,
|
||||
{ b, b, b, b,
|
||||
b, r, r, b,
|
||||
b, r, r, b,
|
||||
b, b, b, b })
|
||||
|
||||
end
|
||||
|
||||
do -- BrightnessContrast
|
||||
local s = Sprite(2, 2)
|
||||
local cel = app.activeCel
|
||||
local c = { rgba(255, 128, 64), rgba(250, 225, 110),
|
||||
rgba( 30, 60, 0), rgba(200, 100, 50), }
|
||||
local i = cel.image
|
||||
|
||||
i:drawPixel(0, 0, c[1])
|
||||
i:drawPixel(1, 0, c[2])
|
||||
i:drawPixel(0, 1, c[3])
|
||||
i:drawPixel(1, 1, c[4])
|
||||
expect_img(i,
|
||||
{ c[1], c[2],
|
||||
c[3], c[4] })
|
||||
|
||||
app.command.BrightnessContrast() -- Do nothing by default
|
||||
expect_img(i,
|
||||
{ c[1], c[2],
|
||||
c[3], c[4] })
|
||||
|
||||
local d = {}
|
||||
for k,v in ipairs(c) do
|
||||
d[k] = rgba(math.min(255, rgbaR(v)*1.5),
|
||||
math.min(255, rgbaG(v)*1.5),
|
||||
math.min(255, rgbaB(v)*1.5), 255)
|
||||
end
|
||||
app.command.BrightnessContrast{ brightness=50 } -- Do nothing by default
|
||||
expect_img(i,
|
||||
{ d[1], d[2],
|
||||
d[3], d[4] })
|
||||
end
|
||||
|
||||
do -- Despeckle
|
||||
local s = Sprite(5, 5)
|
||||
local white = Color(255, 255, 255)
|
||||
local red = Color(255, 0, 0)
|
||||
|
||||
app.bgColor = white
|
||||
app.command.BackgroundFromLayer()
|
||||
|
||||
local cel = app.activeCel
|
||||
local i = cel.image
|
||||
local b = white.rgbaPixel
|
||||
local c = red.rgbaPixel
|
||||
expect_img(i,
|
||||
{ b,b,b,b,b,
|
||||
b,b,b,b,b,
|
||||
b,b,b,b,b,
|
||||
b,b,b,b,b,
|
||||
b,b,b,b,b })
|
||||
|
||||
app.useTool{ tool='filled_rectangle', brush=Brush(1), color=red,
|
||||
points={Point(1,1),Point(3,3)} }
|
||||
expect_img(i,
|
||||
{ b,b,b,b,b,
|
||||
b,c,c,c,b,
|
||||
b,c,c,c,b,
|
||||
b,c,c,c,b,
|
||||
b,b,b,b,b })
|
||||
|
||||
app.command.Despeckle()
|
||||
expect_img(i,
|
||||
{ b,b,b,b,b,
|
||||
b,b,c,b,b,
|
||||
b,c,c,c,b,
|
||||
b,b,c,b,b,
|
||||
b,b,b,b,b })
|
||||
|
||||
app.command.Despeckle()
|
||||
expect_img(i,
|
||||
{ b,b,b,b,b,
|
||||
b,b,b,b,b,
|
||||
b,b,c,b,b,
|
||||
b,b,b,b,b,
|
||||
b,b,b,b,b })
|
||||
end
|
||||
|
||||
do -- HueSaturation
|
||||
local s = Sprite(1, 1)
|
||||
local cel = app.activeCel
|
||||
local i = cel.image
|
||||
local b = Color(255, 0, 0).rgbaPixel
|
||||
|
||||
i:drawPixel(0, 0, b)
|
||||
expect_img(i, { b })
|
||||
|
||||
app.command.HueSaturation{ hue=360 } -- Do nothing (change hue to a full 360 circle)
|
||||
expect_img(i, { b })
|
||||
|
||||
app.command.HueSaturation{ hue=60 }
|
||||
b = Color(255, 255, 0).rgbaPixel
|
||||
expect_img(i, { b })
|
||||
|
||||
app.command.HueSaturation{ hue=60 }
|
||||
b = Color(0, 255, 0).rgbaPixel
|
||||
expect_img(i, { b })
|
||||
|
||||
app.command.HueSaturation{ saturation=-50 }
|
||||
b = Color(64, 191, 64).rgbaPixel
|
||||
expect_img(i, { b })
|
||||
|
||||
app.undo()
|
||||
app.command.HueSaturation{ saturation=-100 }
|
||||
b = Color(128, 128, 128).rgbaPixel
|
||||
expect_img(i, { b })
|
||||
|
||||
app.undo()
|
||||
app.command.HueSaturation{ saturation=-50, mode='hsv' }
|
||||
b = Color(128, 255, 128).rgbaPixel
|
||||
expect_img(i, { b })
|
||||
|
||||
app.undo()
|
||||
app.command.HueSaturation{ value=75 }
|
||||
b = Color(191, 255, 191).rgbaPixel
|
||||
expect_img(i, { b })
|
||||
|
||||
app.undo()
|
||||
app.command.HueSaturation{ alpha=-50 }
|
||||
b = Color(0, 255, 0, 127).rgbaPixel
|
||||
expect_img(i, { b })
|
||||
|
||||
end
|
||||
|
||||
do -- ColorCurve
|
||||
local s = Sprite(2, 1)
|
||||
local cel = app.activeCel
|
||||
local i = cel.image
|
||||
|
||||
i:drawPixel(0, 0, rgba(255, 128, 0))
|
||||
i:drawPixel(1, 0, rgba(64, 0, 32))
|
||||
expect_img(i, { rgba(255, 128, 0), rgba(64, 0, 32) })
|
||||
|
||||
app.command.ColorCurve() -- Do nothing
|
||||
expect_img(i, { rgba(255, 128, 0), rgba(64, 0, 32) })
|
||||
|
||||
app.command.ColorCurve{ curve={{0,0},{255,128}} }
|
||||
expect_img(i, { rgba(128, 64, 0), rgba(32, 0, 16) })
|
||||
|
||||
app.command.ColorCurve{ channels=FilterChannels.ALPHA, curve={{0,0},{255,128}} }
|
||||
expect_img(i, { rgba(128, 64, 0, 128), rgba(32, 0, 16, 128) })
|
||||
|
||||
app.command.ColorCurve{ channels=FilterChannels.RGBA, curve={{0,255},{255,255}} }
|
||||
expect_img(i, { rgba(255, 255, 255), rgba(255, 255, 255) })
|
||||
|
||||
app.command.ColorCurve{ channels=FilterChannels.GREEN, curve={{0,0},{255,0}} }
|
||||
expect_img(i, { rgba(255, 0, 255), rgba(255, 0, 255) })
|
||||
|
||||
app.command.ColorCurve{ channels=FilterChannels.BLUE, curve="0,128,255,128" }
|
||||
expect_img(i, { rgba(255, 0, 128), rgba(255, 0, 128) })
|
||||
end
|
||||
|
||||
do -- ConvolutionMatrix
|
||||
local s = Sprite(3, 3)
|
||||
local cel = app.activeCel
|
||||
local i = cel.image
|
||||
local b = rgba(0, 0, 0)
|
||||
local w = rgba(255, 255, 255)
|
||||
|
||||
app.bgColor = Color(255, 255, 255)
|
||||
app.command.BackgroundFromLayer()
|
||||
i:drawPixel(1, 1, b)
|
||||
expect_img(i, { w, w, w,
|
||||
w, b, w,
|
||||
w, w, w })
|
||||
|
||||
local u = rgba(239, 239, 239)
|
||||
local v = rgba(223, 223, 223)
|
||||
local w = rgba(191, 191, 191)
|
||||
app.command.ConvolutionMatrix{ fromResource="blur-3x3" }
|
||||
expect_img(i, { u, v, u,
|
||||
v, w, v,
|
||||
u, v, u })
|
||||
end
|
||||
|
||||
-- MoveColors and CopyColors
|
||||
do
|
||||
local s = Sprite(32, 32, ColorMode.INDEXED)
|
||||
local p = Palette(4)
|
||||
p:setColor(0, Color(0, 0, 0))
|
||||
p:setColor(1, Color(255, 0, 0))
|
||||
p:setColor(2, Color(0, 255, 0))
|
||||
p:setColor(3, Color(0, 0, 255))
|
||||
s:setPalette(p)
|
||||
assert(#app.range.colors == 0)
|
||||
app.range.colors = { 0, 2 }
|
||||
assert(#app.range.colors == 2)
|
||||
assert(app.range.colors[1] == 0)
|
||||
assert(app.range.colors[2] == 2)
|
||||
app.command.MoveColors{ before=0 }
|
||||
p = s.palettes[1]
|
||||
p:setColor(0, Color(0, 0, 0))
|
||||
p:setColor(1, Color(0, 255, 0))
|
||||
p:setColor(2, Color(255, 0, 0))
|
||||
p:setColor(3, Color(0, 0, 255))
|
||||
|
||||
app.range.colors = { 0, 1 }
|
||||
assert(#app.range.colors == 2)
|
||||
assert(app.range.colors[1] == 0)
|
||||
assert(app.range.colors[2] == 1)
|
||||
app.command.CopyColors{ before=4 }
|
||||
p = s.palettes[1]
|
||||
p:setColor(0, Color(0, 0, 0))
|
||||
p:setColor(1, Color(0, 255, 0))
|
||||
p:setColor(2, Color(255, 0, 0))
|
||||
p:setColor(3, Color(0, 0, 255))
|
||||
p:setColor(4, Color(0, 0, 0))
|
||||
p:setColor(5, Color(0, 255, 0))
|
||||
end
|
||||
|
||||
-- AddColor
|
||||
do
|
||||
local s = Sprite(32, 32)
|
||||
local p = s.palettes[1]
|
||||
|
||||
function testAddColor(color)
|
||||
assert(p:getColor(#p-1) ~= color)
|
||||
app.command.AddColor{ color=color }
|
||||
assert(p:getColor(#p-1) == color)
|
||||
end
|
||||
testAddColor(Color(255, 0, 0))
|
||||
testAddColor(Color(0, 255, 0))
|
||||
testAddColor(Color(0, 0, 255))
|
||||
|
||||
local color = Color(128, 0, 0)
|
||||
app.preferences.color_bar.fg_color = color
|
||||
app.command.AddColor{ source="fg" }
|
||||
assert(p:getColor(#p-1) == color)
|
||||
|
||||
local color = Color(0, 0, 128)
|
||||
app.preferences.color_bar.bg_color = color
|
||||
app.command.AddColor{ source="bg" }
|
||||
assert(p:getColor(#p-1) == color)
|
||||
end
|
||||
|
||||
-- Flip
|
||||
do
|
||||
local s = Sprite(4, 2, ColorMode.INDEXED)
|
||||
local i = s.cels[1].image
|
||||
array_to_pixels({ 0, 1, 2, 3,
|
||||
4, 5, 6, 7 }, i)
|
||||
app.command.Flip{ orientation="horizontal" }
|
||||
expect_img(i, { 3, 2, 1, 0,
|
||||
7, 6, 5, 4 })
|
||||
|
||||
app.command.Flip{ orientation="vertical" }
|
||||
expect_img(i, { 7, 6, 5, 4,
|
||||
3, 2, 1, 0 })
|
||||
|
||||
s.selection:select{ 1, 0, 2, 2 }
|
||||
app.command.Flip{ orientation="horizontal", target="mask" }
|
||||
expect_img(i, { 7, 5, 6, 4,
|
||||
3, 1, 2, 0 })
|
||||
|
||||
s:newFrame()
|
||||
|
||||
assert(app.activeCel.frameNumber == 2)
|
||||
local j = app.activeImage
|
||||
app.command.Flip{ orientation="vertical", target="mask" }
|
||||
expect_img(i, { 7, 5, 6, 4,
|
||||
3, 1, 2, 0 })
|
||||
expect_img(j, { 7, 1, 2, 4,
|
||||
3, 5, 6, 0 })
|
||||
|
||||
app.range.frames = { 1, 2 }
|
||||
app.command.Flip{ orientation="horizontal", target="mask" }
|
||||
expect_img(i, { 7, 6, 5, 4,
|
||||
3, 2, 1, 0 })
|
||||
expect_img(j, { 7, 2, 1, 4,
|
||||
3, 6, 5, 0 })
|
||||
end
|
||||
|
||||
-- Fill
|
||||
do
|
||||
local s = Sprite(4, 2, ColorMode.INDEXED)
|
||||
local c = s.cels[1]
|
||||
local i = c.image
|
||||
i:clear(1)
|
||||
array_to_pixels({ 1, 1, 1, 1,
|
||||
1, 1, 1, 1 }, i)
|
||||
app.fgColor = Color{ index=0 }
|
||||
s.selection = Selection(Rectangle(1, 1, 2, 1))
|
||||
app.command.Fill()
|
||||
expect_eq(Rectangle(0, 0, 4, 2), c.bounds)
|
||||
expect_img(i, { 1, 1, 1, 1,
|
||||
1, 0, 0, 1 })
|
||||
|
||||
c.position = { x=0, y=1 }
|
||||
app.fgColor = Color{ index=2 }
|
||||
s.selection = Selection(Rectangle(1, 0, 2, 2))
|
||||
app.command.Fill()
|
||||
expect_eq(Rectangle(0, 0, 4, 3), c.bounds)
|
||||
expect_img(i, { 0, 2, 2, 0,
|
||||
1, 2, 2, 1,
|
||||
1, 0, 0, 1 })
|
||||
|
||||
app.fgColor = Color{ index=0 }
|
||||
s.selection = Selection(Rectangle(0, 0, 3, 3))
|
||||
app.command.Fill()
|
||||
expect_eq(Rectangle(3, 1, 1, 2), c.bounds)
|
||||
expect_img(i, { 1,
|
||||
1 })
|
||||
|
||||
app.undo() -- undo Fill
|
||||
expect_eq(Rectangle(0, 0, 4, 3), c.bounds)
|
||||
expect_img(i, { 0, 2, 2, 0,
|
||||
1, 2, 2, 1,
|
||||
1, 0, 0, 1 })
|
||||
|
||||
expect_eq(Rectangle(0, 0, 3, 3), s.selection.bounds)
|
||||
app.undo() -- undo selection change
|
||||
expect_eq(Rectangle(1, 0, 2, 2), s.selection.bounds)
|
||||
app.undo() -- undo Fill
|
||||
expect_eq(Rectangle(0, 1, 4, 2), c.bounds)
|
||||
expect_img(i, { 1, 1, 1, 1,
|
||||
1, 0, 0, 1 })
|
||||
end
|
77
tests/scripts/app_fs.lua
Normal file
77
tests/scripts/app_fs.lua
Normal file
@ -0,0 +1,77 @@
|
||||
-- Copyright (C) 2019 Igara Studio S.A.
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
local fs = app.fs
|
||||
local sep = fs.pathSeparator
|
||||
|
||||
assert('' == fs.filePath('first.png'))
|
||||
assert('path' == fs.filePath('path/second.png'))
|
||||
assert('C:\\path' == fs.filePath('C:\\path\\third.png'))
|
||||
|
||||
assert('first.png' == fs.fileName('first.png'))
|
||||
assert('second.png' == fs.fileName('path/second.png'))
|
||||
assert('third.png' == fs.fileName('C:\\path\\third.png'))
|
||||
|
||||
assert('png' == fs.fileExtension('path/file.png'))
|
||||
|
||||
assert('first' == fs.fileTitle('first.png'))
|
||||
assert('second' == fs.fileTitle('path/second.png'))
|
||||
assert('third' == fs.fileTitle('C:\\path\\third.png'))
|
||||
|
||||
assert('first' == fs.filePathAndTitle('first.png'))
|
||||
assert('path/second' == fs.filePathAndTitle('path/second.png'))
|
||||
assert('C:\\path\\third' == fs.filePathAndTitle('C:\\path\\third.png'))
|
||||
|
||||
assert('hi/bye' == fs.joinPath('hi/', 'bye'))
|
||||
assert('hi/bye' .. sep .. 'smth.png' == fs.joinPath('hi/', 'bye', 'smth.png'))
|
||||
|
||||
local pwd = fs.currentPath
|
||||
assert(pwd ~= nil)
|
||||
assert(fs.isDirectory(pwd))
|
||||
assert(not fs.isFile(pwd))
|
||||
assert(fs.isFile(fs.joinPath(pwd, 'run-tests.sh')))
|
||||
|
||||
do
|
||||
local runTestsFound = false
|
||||
local readmeFound = false
|
||||
local files = fs.listFiles(pwd)
|
||||
for i in pairs(files) do
|
||||
if files[i] == 'run-tests.sh' then
|
||||
runTestsFound = true
|
||||
elseif files[i] == 'README.md' then
|
||||
readmeFound = true
|
||||
end
|
||||
|
||||
local fullFs = fs.joinPath(pwd, files[i])
|
||||
if fs.isFile(fullFs) then
|
||||
assert(fs.fileSize(fullFs) > 0)
|
||||
end
|
||||
end
|
||||
assert(runTestsFound)
|
||||
assert(readmeFound)
|
||||
end
|
||||
|
||||
-- Create directories
|
||||
do
|
||||
assert(fs.makeDirectory("_tmp"))
|
||||
assert(fs.isDirectory("_tmp"))
|
||||
|
||||
assert(fs.makeAllDirectories("_tmp/a/b"))
|
||||
assert(fs.isDirectory("_tmp/a"))
|
||||
assert(fs.isDirectory("_tmp/a/b"))
|
||||
|
||||
assert(fs.removeDirectory("_tmp/a/b"))
|
||||
assert(not fs.isDirectory("_tmp/a/b"))
|
||||
assert(fs.isDirectory("_tmp/a"))
|
||||
|
||||
assert(not fs.removeDirectory("_tmp")) -- Should fail
|
||||
assert(fs.isDirectory("_tmp/a"))
|
||||
assert(fs.isDirectory("_tmp"))
|
||||
|
||||
assert(fs.removeDirectory("_tmp/a"))
|
||||
assert(fs.removeDirectory("_tmp"))
|
||||
assert(not fs.isDirectory("_tmp/a"))
|
||||
assert(not fs.isDirectory("_tmp"))
|
||||
end
|
12
tests/scripts/app_pixel_color.lua
Normal file
12
tests/scripts/app_pixel_color.lua
Normal file
@ -0,0 +1,12 @@
|
||||
-- Copyright (C) 2018 David Capello
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
local pc = app.pixelColor
|
||||
assert(0 == pc.rgba(0, 0, 0, 0))
|
||||
assert(1 == pc.rgbaR(pc.rgba(1, 2, 3, 4)))
|
||||
assert(2 == pc.rgbaG(pc.rgba(1, 2, 3, 4)))
|
||||
assert(3 == pc.rgbaB(pc.rgba(1, 2, 3, 4)))
|
||||
assert(4 == pc.rgbaA(pc.rgba(1, 2, 3, 4)))
|
||||
assert(0xff104080 == pc.rgba(0x80, 0x40, 0x10, 0xff))
|
140
tests/scripts/app_preferences.lua
Normal file
140
tests/scripts/app_preferences.lua
Normal file
@ -0,0 +1,140 @@
|
||||
-- Copyright (C) 2019-2021 Igara Studio S.A.
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
-- Preferences for tools
|
||||
do
|
||||
-- The first time we get the tool preferences in CLI mode, we get
|
||||
-- the default options for this tool (in GUI, we get the current
|
||||
-- user-defined options).
|
||||
local t = app.preferences.tool('pencil')
|
||||
assert(t.opacity == 255)
|
||||
assert(t.tolerance == 0)
|
||||
assert(t.contiguous == true)
|
||||
assert(t.brush.type == BrushType.CIRCLE)
|
||||
assert(t.brush.size == 1)
|
||||
t.brush.size = 2
|
||||
assert(t.brush.size == 2)
|
||||
|
||||
-- Getting the tool again must give us the configuration that was
|
||||
-- set inside the script
|
||||
t = app.preferences.tool('pencil')
|
||||
assert(t.brush.size == 2)
|
||||
end
|
||||
|
||||
-- Preferences for documents
|
||||
do
|
||||
local defPref = app.preferences.document(nil)
|
||||
defPref.grid.bounds = Rectangle(0, 0, 16, 16)
|
||||
|
||||
local s = Sprite(32, 32)
|
||||
local p = app.preferences.document(s)
|
||||
assert(s.gridBounds == Rectangle(0, 0, 16, 16))
|
||||
assert(p.grid.bounds == Rectangle(0, 0, 16, 16))
|
||||
assert(p.grid.color == Color(0, 0, 255))
|
||||
p.grid.color = Color(255, 0, 0)
|
||||
assert(p.grid.color == Color(255, 0, 0))
|
||||
end
|
||||
|
||||
-- Default & doc preferences combinations (related to https://community.aseprite.org/t/4305)
|
||||
do
|
||||
-- Set default preferences
|
||||
local defPref = app.preferences.document(nil)
|
||||
defPref.grid.bounds = Rectangle(0, 0, 10, 10)
|
||||
defPref.grid.color = Color(255, 255, 0) -- Yellow
|
||||
assert(defPref.grid.bounds == Rectangle(0, 0, 10, 10))
|
||||
assert(defPref.grid.color == Color(255, 255, 0))
|
||||
|
||||
do -- File with default preferences
|
||||
local doc = Sprite(32, 32)
|
||||
local docPref = app.preferences.document(doc)
|
||||
assert(doc.gridBounds == Rectangle(0, 0, 10, 10))
|
||||
assert(docPref.grid.bounds == Rectangle(0, 0, 10, 10))
|
||||
assert(docPref.grid.color == Color(255, 255, 0))
|
||||
doc:saveAs('_test_pref.png')
|
||||
doc:close()
|
||||
end
|
||||
|
||||
do -- File with specific preferences
|
||||
local doc = Sprite(32, 32)
|
||||
local docPref = app.preferences.document(doc)
|
||||
docPref.grid.color = Color(0, 128, 0) -- Green
|
||||
assert(docPref.grid.bounds == Rectangle(0, 0, 10, 10))
|
||||
assert(docPref.grid.color == Color(0, 128, 0))
|
||||
doc:saveAs('_test_pref2.png')
|
||||
doc:close()
|
||||
end
|
||||
|
||||
-- Now we change default preferences
|
||||
defPref.grid.bounds = Rectangle(0, 0, 64, 64)
|
||||
defPref.grid.color = Color(255, 0, 0) -- Red
|
||||
assert(defPref.grid.bounds == Rectangle(0, 0, 64, 64))
|
||||
assert(defPref.grid.color == Color(255, 0, 0))
|
||||
do -- A new document should have the new default preferences
|
||||
local doc = Sprite(32, 32)
|
||||
local docPref = app.preferences.document(doc)
|
||||
assert(docPref.grid.bounds == Rectangle(0, 0, 64, 64))
|
||||
assert(docPref.grid.color == Color(255, 0, 0))
|
||||
doc:close()
|
||||
end
|
||||
do -- The first document should have the new default preferences (because it was saved with the defaults)
|
||||
|
||||
-- TODO maybe related to https://community.aseprite.org/t/grid-for-new-documents/3303
|
||||
-- should we get the new defaults or the values when we saved the document?
|
||||
-- (e.g. even if we didn't change the grid values, it looks
|
||||
-- like if the user changed something about the grid or the
|
||||
-- background colors, the expected behavior would be to
|
||||
-- restore the exact same colors, no the new defaults)
|
||||
|
||||
local doc = Sprite{ fromFile="_test_pref.png" }
|
||||
local docPref = app.preferences.document(doc)
|
||||
assert(docPref.grid.bounds == Rectangle(0, 0, 64, 64))
|
||||
assert(docPref.grid.color == Color(255, 0, 0))
|
||||
doc:close()
|
||||
end
|
||||
do -- The second document should have the new specific preferences for the grid color
|
||||
local doc = Sprite{ fromFile="_test_pref2.png" }
|
||||
local docPref = app.preferences.document(doc)
|
||||
assert(docPref.grid.bounds == Rectangle(0, 0, 64, 64))
|
||||
assert(docPref.grid.color == Color(0, 128, 0))
|
||||
doc:close()
|
||||
end
|
||||
end
|
||||
|
||||
do -- Test that undoing grid bounds, updates the grid in the preferences correctly
|
||||
local doc = Sprite(32, 32)
|
||||
assert(doc.gridBounds == Rectangle(0, 0, 64, 64))
|
||||
assert(app.preferences.document(doc).grid.bounds == Rectangle(0, 0, 64, 64))
|
||||
|
||||
doc.gridBounds = Rectangle(0, 0, 4, 4)
|
||||
assert(doc.gridBounds == Rectangle(0, 0, 4, 4))
|
||||
assert(app.preferences.document(doc).grid.bounds == Rectangle(0, 0, 4, 4))
|
||||
|
||||
app.undo()
|
||||
assert(doc.gridBounds == Rectangle(0, 0, 64, 64))
|
||||
assert(app.preferences.document(doc).grid.bounds == Rectangle(0, 0, 64, 64))
|
||||
|
||||
app.redo()
|
||||
assert(doc.gridBounds == Rectangle(0, 0, 4, 4))
|
||||
assert(app.preferences.document(doc).grid.bounds == Rectangle(0, 0, 4, 4))
|
||||
end
|
||||
|
||||
do -- Test symmetry preferences
|
||||
do -- File with default preferences
|
||||
local doc = Sprite(200, 100)
|
||||
local docPref = app.preferences.document(doc)
|
||||
assert(docPref.symmetry.x_axis == 100)
|
||||
assert(docPref.symmetry.y_axis == 50)
|
||||
docPref.symmetry.x_axis = 25
|
||||
doc:saveAs('_test_symmetry.png')
|
||||
doc:close()
|
||||
end
|
||||
do -- File with default preferences
|
||||
local doc = Sprite{ fromFile='_test_symmetry.png' }
|
||||
local docPref = app.preferences.document(doc)
|
||||
assert(docPref.symmetry.x_axis == 25)
|
||||
assert(docPref.symmetry.y_axis == 50)
|
||||
doc:close()
|
||||
end
|
||||
end
|
40
tests/scripts/app_transaction.lua
Normal file
40
tests/scripts/app_transaction.lua
Normal file
@ -0,0 +1,40 @@
|
||||
-- Copyright (C) 2018 David Capello
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
local s = Sprite(16, 32)
|
||||
assert(s.width == 16)
|
||||
assert(s.height == 32)
|
||||
|
||||
s.width = 20
|
||||
assert(s.width == 20)
|
||||
assert(s.height == 32)
|
||||
|
||||
s.height = 40
|
||||
assert(s.width == 20)
|
||||
assert(s.height == 40)
|
||||
|
||||
app.undo()
|
||||
assert(s.width == 20)
|
||||
assert(s.height == 32)
|
||||
|
||||
app.undo()
|
||||
assert(s.width == 16)
|
||||
assert(s.height == 32)
|
||||
|
||||
app.transaction(
|
||||
function()
|
||||
s.width = 20
|
||||
s.height = 40
|
||||
end)
|
||||
assert(s.width == 20)
|
||||
assert(s.height == 40)
|
||||
|
||||
app.undo()
|
||||
assert(s.width == 16)
|
||||
assert(s.height == 32)
|
||||
|
||||
app.redo()
|
||||
assert(s.width == 20)
|
||||
assert(s.height == 40)
|
74
tests/scripts/brush.lua
Normal file
74
tests/scripts/brush.lua
Normal file
@ -0,0 +1,74 @@
|
||||
-- Copyright (C) 2019 Igara Studio S.A.
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
dofile('./test_utils.lua')
|
||||
|
||||
do
|
||||
local b = Brush()
|
||||
assert(b.type == BrushType.CIRCLE)
|
||||
assert(b.size == 1)
|
||||
assert(b.angle == 0)
|
||||
assert(b.center == Point{ x=0, y=0 })
|
||||
assert(b.pattern == BrushPattern.NONE)
|
||||
assert(b.patternOrigin == Point{ x=0, y=0 })
|
||||
|
||||
local c = Brush(3)
|
||||
assert(c.type == BrushType.CIRCLE)
|
||||
assert(c.size == 3)
|
||||
assert(c.center == Point{ x=1, y=1 })
|
||||
|
||||
local d = Brush(4)
|
||||
assert(d.type == BrushType.CIRCLE)
|
||||
assert(d.size == 4)
|
||||
assert(d.center == Point{ x=2, y=2 })
|
||||
end
|
||||
|
||||
do
|
||||
local b = Brush{ type=BrushType.SQUARE, size=4 }
|
||||
assert(b.type == BrushType.SQUARE)
|
||||
assert(b.size == 4)
|
||||
assert(b.angle == 0)
|
||||
end
|
||||
|
||||
do
|
||||
local b = Brush{ type=BrushType.LINE, size=5, angle=90 }
|
||||
assert(b.type == BrushType.LINE)
|
||||
assert(b.size == 5)
|
||||
assert(b.angle == 90)
|
||||
end
|
||||
|
||||
do
|
||||
local b = Brush{ type=BrushType.IMAGE, image=Image(4, 8) }
|
||||
local c = Brush{ image=Image(4, 8) }
|
||||
assert(b.type == BrushType.IMAGE)
|
||||
assert(c.type == BrushType.IMAGE)
|
||||
assert(b.image.width == 4)
|
||||
assert(b.image.height == 8)
|
||||
assert(b.pattern == BrushPattern.NONE)
|
||||
assert(b.patternOrigin.x == 0)
|
||||
assert(b.patternOrigin.y == 0)
|
||||
end
|
||||
|
||||
do
|
||||
local rgba = app.pixelColor.rgba
|
||||
local r = rgba(255, 0, 0)
|
||||
local g = rgba(0, 128, 0)
|
||||
local b = rgba(0, 0, 255)
|
||||
|
||||
local img = Image(2, 2)
|
||||
img:putPixel(0, 0, r)
|
||||
img:putPixel(1, 0, b)
|
||||
img:putPixel(0, 1, b)
|
||||
img:putPixel(1, 1, r)
|
||||
|
||||
local brush = Brush{ image=img }
|
||||
expect_img(brush.image, { r, b, b, r })
|
||||
|
||||
brush:setFgColor(g)
|
||||
expect_img(brush.image, { r, g, g, r })
|
||||
|
||||
brush:setBgColor(b)
|
||||
expect_img(brush.image, { b, g, g, b })
|
||||
end
|
29
tests/scripts/cel.lua
Normal file
29
tests/scripts/cel.lua
Normal file
@ -0,0 +1,29 @@
|
||||
-- Copyright (C) 2018 David Capello
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
local s = Sprite(32, 64)
|
||||
assert(#s.layers == 1)
|
||||
assert(#s.cels == 1)
|
||||
|
||||
local c = s.cels[1]
|
||||
assert(c.sprite == s)
|
||||
assert(c.layer == s.layers[1])
|
||||
assert(c.frame == s.frames[1])
|
||||
assert(c.frame.frameNumber == 1)
|
||||
assert(c.frameNumber == 1)
|
||||
assert(c.image)
|
||||
assert(c.bounds == Rectangle(0, 0, 32, 64))
|
||||
assert(c.position == Point(0, 0))
|
||||
assert(c.color == Color())
|
||||
assert(c.data == "")
|
||||
|
||||
c.color = Color{ r=255, g=100, b=20 }
|
||||
c.data = "test"
|
||||
assert(c.color == Color{ r=255, g=100, b=20 })
|
||||
assert(c.data == "test")
|
||||
|
||||
c.position = Point(2, 4)
|
||||
assert(c.position == Point(2, 4))
|
||||
assert(c.bounds == Rectangle(2, 4, 32, 64))
|
86
tests/scripts/cels.lua
Normal file
86
tests/scripts/cels.lua
Normal file
@ -0,0 +1,86 @@
|
||||
-- Copyright (C) 2020 Igara Studio S.A.
|
||||
-- Copyright (C) 2018 David Capello
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
dofile('./test_utils.lua')
|
||||
|
||||
do
|
||||
local s = Sprite(32, 32)
|
||||
for i = 1,3 do s:newFrame() end
|
||||
assert(#s.frames == 4)
|
||||
|
||||
-- Layer a and b
|
||||
local a = s.layers[1]
|
||||
local b = s:newLayer()
|
||||
|
||||
local ca = { s.cels[1],
|
||||
s.cels[2],
|
||||
s.cels[3] }
|
||||
|
||||
local cb = { s:newCel(b, 1),
|
||||
s:newCel(b, 2, Image(8, 8), 4, 4),
|
||||
s:newCel(b, 3, Image(32, 10), 16, 10) }
|
||||
|
||||
assert(cb[1].bounds == Rectangle(0, 0, 32, 32))
|
||||
assert(cb[2].bounds == Rectangle(4, 4, 8, 8))
|
||||
assert(cb[3].bounds == Rectangle(16, 10, 32, 10))
|
||||
|
||||
-- Check how layer cels are updated when we delete a cel in the middle
|
||||
|
||||
assert(cb[1] == b.cels[1])
|
||||
assert(cb[2] == b.cels[2])
|
||||
assert(cb[3] == b.cels[3])
|
||||
|
||||
local i = 1
|
||||
for k,v in ipairs(b.cels) do
|
||||
assert(i == k)
|
||||
assert(v == b.cels[k])
|
||||
i = i+1
|
||||
end
|
||||
|
||||
s:deleteCel(cb[2])
|
||||
assert(cb[1] == b.cels[1])
|
||||
assert(cb[3] == b.cels[2])
|
||||
end
|
||||
|
||||
-- Some extra tests of newCel() and deleteCel()
|
||||
do
|
||||
local s = Sprite(4, 4, ColorMode.INDEXED)
|
||||
local layer = app.activeLayer
|
||||
app.bgColor = 0
|
||||
app.command.BackgroundFromLayer()
|
||||
expect_img(s.cels[1].image, { 0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0 })
|
||||
|
||||
-- Crash in old versions undoing newCel() in a background layer
|
||||
s:newCel(layer, 1)
|
||||
app.undo()
|
||||
|
||||
-- Check that newCel clears with bgColor in background layer
|
||||
local img = Image(ImageSpec{ width=2, height=2,
|
||||
colorMode=ColorMode.INDEXED })
|
||||
array_to_pixels({ 0, 1,
|
||||
2, 3 }, img)
|
||||
|
||||
app.bgColor = Color(1) -- bgColor used to clear the background cel
|
||||
s:newCel(layer, 1, img, Point(1, 1))
|
||||
expect_img(s.cels[1].image, { 1, 1, 1, 1,
|
||||
1, 0, 1, 1,
|
||||
1, 2, 3, 1,
|
||||
1, 1, 1, 1 })
|
||||
app.undo()
|
||||
|
||||
-- Check deleteCel()
|
||||
app.bgColor = Color(2)
|
||||
s:deleteCel(layer, 1)
|
||||
expect_img(s.cels[1].image, { 2, 2, 2, 2,
|
||||
2, 2, 2, 2,
|
||||
2, 2, 2, 2,
|
||||
2, 2, 2, 2 })
|
||||
app.undo()
|
||||
|
||||
end
|
45
tests/scripts/color.lua
Normal file
45
tests/scripts/color.lua
Normal file
@ -0,0 +1,45 @@
|
||||
-- Copyright (C) 2022 Igara Studio S.A.
|
||||
-- Copyright (C) 2018 David Capello
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
local a, b
|
||||
|
||||
a = Color()
|
||||
assert(a.red == 0)
|
||||
assert(a.green == 0)
|
||||
assert(a.blue == 0)
|
||||
assert(a.alpha == 0)
|
||||
|
||||
a = Color{ r=100, g=50, b=10 }
|
||||
b = Color(100, 50, 10)
|
||||
assert(a.red == 100)
|
||||
assert(a.green == 50)
|
||||
assert(a.blue == 10)
|
||||
assert(a.alpha == 255)
|
||||
assert(a == b)
|
||||
|
||||
a = Color{ red=200, green=100, blue=20, alpha=200 }
|
||||
b = Color(200, 100, 20, 200)
|
||||
assert(a.red == 200)
|
||||
assert(a.green == 100)
|
||||
assert(a.blue == 20)
|
||||
assert(a.alpha == 200)
|
||||
assert(a == b)
|
||||
print(a.rgbaPixel)
|
||||
print(app.pixelColor.rgba(200, 100, 20, 200))
|
||||
assert(a.rgbaPixel == app.pixelColor.rgba(200, 100, 20, 200))
|
||||
|
||||
a = Color{ h=180, s=0.4, v=0.5, a=200 }
|
||||
b = Color{ hue=180, saturation=0.4, value=0.5, alpha=200 }
|
||||
assert(a.hue == 180)
|
||||
assert(a.saturation == 0.4)
|
||||
assert(a.value == 0.5)
|
||||
assert(a.alpha == 200)
|
||||
assert(b.hue == 180)
|
||||
assert(b.saturation == 0.4)
|
||||
assert(b.value == 0.5)
|
||||
assert(b.alpha == 200)
|
||||
assert(a == b)
|
||||
assert(a ~= 1) -- Comparing with other type fails
|
51
tests/scripts/color_convert.lua
Normal file
51
tests/scripts/color_convert.lua
Normal file
@ -0,0 +1,51 @@
|
||||
-- Copyright (C) 2019-2022 Igara Studio S.A.
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
dofile('./test_utils.lua')
|
||||
|
||||
-- this tests and ensures that the alpha-ness of a background
|
||||
-- layer is maintained when sprite conversion takes place from
|
||||
-- Indexed to RGB
|
||||
|
||||
do
|
||||
local sprite = Sprite(2, 2, ColorMode.INDEXED)
|
||||
local pal = sprite.palettes[1]
|
||||
|
||||
assert(sprite.layers[1].isTransparent)
|
||||
assert(sprite.colorMode == ColorMode.INDEXED)
|
||||
assert(#pal == 256)
|
||||
|
||||
local color = pal:getColor(3)
|
||||
color.alpha = 200
|
||||
pal:setColor(3, color)
|
||||
|
||||
local image = sprite.cels[1].image
|
||||
image:drawPixel(0, 0, pal:getColor(2))
|
||||
image:drawPixel(0, 1, pal:getColor(3))
|
||||
image:drawPixel(1, 0, pal:getColor(4))
|
||||
image:drawPixel(1, 1, pal:getColor(5))
|
||||
|
||||
app.bgColor = Color{ index=0 }
|
||||
app.command.BackgroundFromLayer()
|
||||
|
||||
local layer = sprite.layers[1]
|
||||
assert(layer.isTransparent == false)
|
||||
assert(layer.name == "Background")
|
||||
|
||||
-- change color mode from Indexed to RGB
|
||||
app.command.ChangePixelFormat {
|
||||
format="rgb"
|
||||
}
|
||||
|
||||
assert(sprite.colorMode == ColorMode.RGB)
|
||||
image = sprite.cels[1].image
|
||||
|
||||
for x=0, 1, 1 do
|
||||
for y=0, 1, 1 do
|
||||
local pixel = image:getPixel(x, y)
|
||||
assert(app.pixelColor.rgbaA(pixel) == 255)
|
||||
end
|
||||
end
|
||||
end
|
201
tests/scripts/color_quantization.lua
Normal file
201
tests/scripts/color_quantization.lua
Normal file
@ -0,0 +1,201 @@
|
||||
-- Copyright (C) 2019-2022 Igara Studio S.A.
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
dofile("./test_utils.lua")
|
||||
|
||||
local rgba = app.pixelColor.rgba
|
||||
|
||||
----------------------------------------------------------------------
|
||||
-- app.command.ColorQuantization
|
||||
|
||||
do
|
||||
-- One sprite with a background layer
|
||||
local s = Sprite(2, 2)
|
||||
app.command.BackgroundFromLayer()
|
||||
|
||||
local i = s.cels[1].image
|
||||
local p = s.palettes[1]
|
||||
assert(#p == 256)
|
||||
assert(s.colorMode == ColorMode.RGB)
|
||||
app.command.ColorQuantization{ algorithm="rgb5a3" }
|
||||
assert(#p == 1)
|
||||
|
||||
array_to_pixels({ rgba(255, 255, 0), rgba(255, 255, 0),
|
||||
rgba(255, 255, 0), rgba(255, 255, 0) }, i)
|
||||
app.command.ColorQuantization{ algorithm="rgb5a3" }
|
||||
assert(#p == 1)
|
||||
assert(p:getColor(0) == Color(255, 255, 0))
|
||||
|
||||
array_to_pixels({ rgba(255, 0, 0), rgba(255, 0, 0),
|
||||
rgba(255, 255, 0), rgba(255, 255, 0) }, i)
|
||||
app.command.ColorQuantization{ algorithm="rgb5a3" }
|
||||
assert(#p == 2)
|
||||
assert(p:getColor(0) == Color(255, 0, 0))
|
||||
assert(p:getColor(1) == Color(255, 255, 0))
|
||||
|
||||
array_to_pixels({ rgba(255, 0, 0), rgba(255, 0, 0),
|
||||
rgba(255, 255, 0), rgba(0, 0, 255) }, i)
|
||||
app.command.ColorQuantization{ algorithm="rgb5a3" }
|
||||
assert(#p == 3)
|
||||
assert(p:getColor(0) == Color(255, 0, 0))
|
||||
assert(p:getColor(1) == Color(255, 255, 0))
|
||||
assert(p:getColor(2) == Color(0, 0, 255))
|
||||
|
||||
-- Convert the background layer to a transparent layer
|
||||
|
||||
app.command.LayerFromBackground()
|
||||
app.command.ColorQuantization{ algorithm="rgb5a3", withAlpha=false }
|
||||
assert(#p == 4) -- One extra color for transparent layer
|
||||
assert(p:getColor(0) == Color(0, 0, 0))
|
||||
assert(p:getColor(1) == Color(255, 0, 0))
|
||||
assert(p:getColor(2) == Color(255, 255, 0))
|
||||
assert(p:getColor(3) == Color(0, 0, 255))
|
||||
|
||||
app.command.ColorQuantization()
|
||||
assert(#p == 4)
|
||||
assert(p:getColor(0) == Color(0, 0, 0, 0))
|
||||
assert(p:getColor(1) == Color(255, 0, 0))
|
||||
assert(p:getColor(2) == Color(255, 255, 0))
|
||||
assert(p:getColor(3) == Color(0, 0, 255))
|
||||
|
||||
array_to_pixels({ rgba(0, 0, 0), rgba(255, 0, 0),
|
||||
rgba(255, 0, 0), rgba(0, 0, 255) }, i)
|
||||
app.command.ColorQuantization{ algorithm="rgb5a3", withAlpha=false }
|
||||
assert(#p == 4)
|
||||
assert(p:getColor(0) == Color(0, 0, 0))
|
||||
assert(p:getColor(1) == Color(0, 0, 0))
|
||||
assert(p:getColor(2) == Color(255, 0, 0))
|
||||
assert(p:getColor(3) == Color(0, 0, 255))
|
||||
|
||||
app.command.ColorQuantization{ algorithm="rgb5a3" }
|
||||
assert(#p == 4)
|
||||
assert(p:getColor(0) == Color(0, 0, 0, 0))
|
||||
assert(p:getColor(1) == Color(0, 0, 0))
|
||||
assert(p:getColor(2) == Color(255, 0, 0))
|
||||
assert(p:getColor(3) == Color(0, 0, 255))
|
||||
end
|
||||
|
||||
do
|
||||
-- One sprite with a transparent layer + a background layer
|
||||
local s = Sprite(2, 2)
|
||||
local p = s.palettes[1]
|
||||
app.command.BackgroundFromLayer()
|
||||
local bg = s.cels[1].image
|
||||
local fg = s:newCel(s:newLayer(), 1).image
|
||||
|
||||
assert(#s.frames == 1)
|
||||
assert(#s.layers == 2)
|
||||
assert(#s.cels == 2)
|
||||
|
||||
array_to_pixels({ rgba(0, 0, 0, 0), rgba(0, 255, 0),
|
||||
rgba(255, 0, 0), rgba(0, 0, 0, 0) }, fg)
|
||||
array_to_pixels({ rgba(0, 0, 0), rgba(0, 0, 0),
|
||||
rgba(0, 0, 0), rgba(0, 0, 255) }, bg)
|
||||
|
||||
app.command.ColorQuantization{ algorithm="rgb5a3" }
|
||||
assert(#p == 5)
|
||||
assert(p:getColor(0) == Color(0, 0, 0, 0))
|
||||
assert(p:getColor(1) == Color(0, 0, 0))
|
||||
assert(p:getColor(2) == Color(0, 255, 0))
|
||||
assert(p:getColor(3) == Color(255, 0, 0))
|
||||
assert(p:getColor(4) == Color(0, 0, 255))
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------
|
||||
-- app.command.ChangePixelFormat
|
||||
|
||||
do
|
||||
local s = Sprite(2, 2, ColorMode.RGB)
|
||||
local p = Palette(4)
|
||||
p:setColor(0, Color(0, 0, 0))
|
||||
p:setColor(1, Color(101, 90, 200))
|
||||
p:setColor(2, Color(102, 91, 201))
|
||||
p:setColor(3, Color(103, 92, 203))
|
||||
s:setPalette(p)
|
||||
|
||||
app.command.BackgroundFromLayer()
|
||||
|
||||
local bg = s.cels[1].image
|
||||
array_to_pixels({ rgba(0, 0, 0), rgba(101, 90, 200),
|
||||
rgba(102, 91, 201), rgba(103, 92, 203) }, bg)
|
||||
|
||||
app.command.ChangePixelFormat{ format="indexed", rgbmap="rgb5a3" }
|
||||
-- Using the 5-bit precision of RGB5A3 will match everything with
|
||||
-- the first palette entry.
|
||||
bg = s.cels[1].image
|
||||
expect_img(bg, { 0, 1,
|
||||
1, 1 })
|
||||
app.undo()
|
||||
|
||||
app.command.ChangePixelFormat{ format="indexed", rgbmap="octree" }
|
||||
bg = s.cels[1].image
|
||||
expect_img(bg, { 0, 1,
|
||||
2, 3 })
|
||||
app.undo()
|
||||
|
||||
p:setColor(0, Color(0, 0, 0, 0))
|
||||
bg = s.cels[1].image
|
||||
array_to_pixels({ rgba(101, 90, 200, 0), rgba(101, 90, 200),
|
||||
rgba(102, 91, 201), rgba(103, 92, 203, 0) }, bg)
|
||||
app.command.ChangePixelFormat{ format="indexed", rgbmap="octree" }
|
||||
bg = s.cels[1].image
|
||||
expect_img(bg, { 0, 1,
|
||||
2, 0 })
|
||||
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------
|
||||
-- Tests for issue aseprite/aseprite#3207
|
||||
-- Conversion RGB to INDEXED color mode, in transparent layers, always
|
||||
-- picks index 0 as transparent color, even if the mask color is present
|
||||
-- in the palette.
|
||||
|
||||
do
|
||||
local s = Sprite(2, 3, ColorMode.RGB)
|
||||
local p = Palette(4)
|
||||
p:setColor(0, Color(0, 0, 0))
|
||||
p:setColor(1, Color(255, 0, 0))
|
||||
p:setColor(2, Color(0, 0, 0, 0))
|
||||
p:setColor(3, Color(0, 255, 0))
|
||||
s:setPalette(p)
|
||||
|
||||
local bg = s.cels[1].image
|
||||
array_to_pixels({ rgba(0, 0, 0),rgba(255, 0, 0),
|
||||
rgba(255, 0, 0), rgba(0, 0, 0, 0),
|
||||
rgba(0, 0, 0, 0), rgba(0, 0, 0, 0), }, bg)
|
||||
|
||||
app.command.ChangePixelFormat{ format="indexed", rgbmap="rgb5a3" }
|
||||
-- Using the 5-bit precision of RGB5A3 will match everything with
|
||||
-- the first palette entry.
|
||||
bg = s.cels[1].image
|
||||
expect_img(bg, { 0, 1,
|
||||
1, 2,
|
||||
2, 2 })
|
||||
app.undo()
|
||||
|
||||
app.command.ChangePixelFormat{ format="indexed", rgbmap="octree" }
|
||||
bg = s.cels[1].image
|
||||
expect_img(bg, { 0, 1,
|
||||
1, 2,
|
||||
2, 2 })
|
||||
app.undo()
|
||||
|
||||
p:setColor(2, Color(0, 0, 255))
|
||||
s:setPalette(p)
|
||||
bg = s.cels[1].image
|
||||
|
||||
app.command.ChangePixelFormat{ format="indexed", rgbmap="rgb5a3" }
|
||||
bg = s.cels[1].image
|
||||
expect_img(bg, { 2, 1,
|
||||
1, 0,
|
||||
0, 0 })
|
||||
app.undo()
|
||||
|
||||
app.command.ChangePixelFormat{ format="indexed", rgbmap="octree" }
|
||||
bg = s.cels[1].image
|
||||
expect_img(bg, { 2, 1,
|
||||
1, 0,
|
||||
0, 0 })
|
||||
end
|
21
tests/scripts/color_space.lua
Normal file
21
tests/scripts/color_space.lua
Normal file
@ -0,0 +1,21 @@
|
||||
-- Copyright (C) 2019 Igara Studio S.A.
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
local none = ColorSpace() -- None
|
||||
local srgb = ColorSpace{ sRGB=true }
|
||||
local none2 = ColorSpace{ sRGB=false }
|
||||
assert(none ~= srgb)
|
||||
assert(none == none2)
|
||||
|
||||
local spr = Sprite(32, 32)
|
||||
local cs1 = spr.colorSpace
|
||||
local cs2 = spr.spec.colorSpace
|
||||
assert(cs1 == cs2)
|
||||
assert(cs1 ~= none)
|
||||
assert(cs1 == srgb) -- Default color profile: sRGB
|
||||
|
||||
local spr3 = Sprite(32, 32)
|
||||
local cs3 = spr.spec.colorSpace
|
||||
assert(cs1 == cs3)
|
60
tests/scripts/compare_sprite_sheets.lua
Normal file
60
tests/scripts/compare_sprite_sheets.lua
Normal file
@ -0,0 +1,60 @@
|
||||
-- Copyright (C) 2019 Igara Studio S.A.
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
local file1 = app.params["file1"]
|
||||
local file2 = app.params["file2"]
|
||||
if file1 == nil or file2 == nil then
|
||||
return 0
|
||||
end
|
||||
|
||||
local json = dofile('../third_party/json/json.lua')
|
||||
local data1 = json.decode(io.open(file1):read('a'))
|
||||
local data2 = json.decode(io.open(file2):read('a'))
|
||||
|
||||
if data1 == nil then
|
||||
print('Cannot read file ' .. file1)
|
||||
return 1
|
||||
elseif data2 == nil then
|
||||
print('Cannot read file ' .. file2)
|
||||
return 1
|
||||
end
|
||||
|
||||
local function replace_filename(fn, newfn)
|
||||
return string.gsub(fn, "(.*)[/\\]([^/\\]+)", "%1/"..newfn)
|
||||
end
|
||||
|
||||
local sheet1 = app.open(replace_filename(file1, data1.meta.image))
|
||||
local sheet2 = app.open(replace_filename(file2, data2.meta.image))
|
||||
|
||||
for k,v in pairs(data1.frames) do
|
||||
local fr1 = data1.frames[k]
|
||||
local fr2 = data2.frames[k]
|
||||
if fr1.duration ~= fr2.duration then
|
||||
print('Frame '..k..' doesn\'t match duration')
|
||||
return 1
|
||||
end
|
||||
if fr1.sourceSize.w ~= fr2.sourceSize.w or
|
||||
fr1.sourceSize.h ~= fr2.sourceSize.h then
|
||||
print('Frame '..k..' doesn\'t match sourceSize')
|
||||
return 1
|
||||
end
|
||||
|
||||
local celImage1 = Image(fr1.frame.w, fr1.frame.h, sheet1.colorMode)
|
||||
local celImage2 = Image(fr2.frame.w, fr2.frame.h, sheet2.colorMode)
|
||||
celImage1:drawSprite(sheet1, 1, -fr1.frame.x, -fr1.frame.y)
|
||||
celImage2:drawSprite(sheet2, 1, -fr2.frame.x, -fr2.frame.y)
|
||||
|
||||
local frImage1 = Image(fr1.sourceSize.w, fr1.sourceSize.h, sheet1.colorMode)
|
||||
local frImage2 = Image(fr2.sourceSize.w, fr2.sourceSize.h, sheet2.colorMode)
|
||||
frImage1:drawImage(celImage1, fr1.spriteSourceSize.x, fr1.spriteSourceSize.y)
|
||||
frImage2:drawImage(celImage2, fr2.spriteSourceSize.x, fr2.spriteSourceSize.y)
|
||||
|
||||
-- To debug this function
|
||||
--frImage1:saveAs(replace_filename(file1, k .. "-fr1.png"))
|
||||
--frImage2:saveAs(replace_filename(file2, k .. "-fr2.png"))
|
||||
--print(k, "fr1", fr1.frame.x, fr1.frame.y, "fr2", fr2.frame.x, fr2.frame.y)
|
||||
|
||||
assert(frImage1:isEqual(frImage2))
|
||||
end
|
9
tests/scripts/console_assert.lua
Normal file
9
tests/scripts/console_assert.lua
Normal file
@ -0,0 +1,9 @@
|
||||
-- Copyright (C) 2018 David Capello
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
assert(true)
|
||||
print("this should be in the output")
|
||||
assert(false)
|
||||
print("this should not be in the output")
|
7
tests/scripts/console_print.lua
Normal file
7
tests/scripts/console_print.lua
Normal file
@ -0,0 +1,7 @@
|
||||
-- Copyright (C) 2018 David Capello
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
print("hello world")
|
||||
print(1, 2, 3)
|
8
tests/scripts/constants.lua
Normal file
8
tests/scripts/constants.lua
Normal file
@ -0,0 +1,8 @@
|
||||
-- Copyright (C) 2018 David Capello
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
assert(ColorMode.RGB == 0)
|
||||
assert(ColorMode.GRAYSCALE == 1)
|
||||
assert(ColorMode.INDEXED == 2)
|
83
tests/scripts/drawing.lua
Normal file
83
tests/scripts/drawing.lua
Normal file
@ -0,0 +1,83 @@
|
||||
-- Copyright (C) 2018-2022 Igara Studio S.A.
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
local pc = app.pixelColor
|
||||
|
||||
-- Image:clear
|
||||
local function test_clear(colorMode, transparentColor)
|
||||
local i = Image(ImageSpec{ width=2, height=2, colorMode=colorMode, transparentColor=transparentColor })
|
||||
i:putPixel(0, 0, 1)
|
||||
i:putPixel(1, 0, 2)
|
||||
i:putPixel(0, 1, 3)
|
||||
i:putPixel(1, 1, 4)
|
||||
assert(1 == i:getPixel(0, 0))
|
||||
assert(2 == i:getPixel(1, 0))
|
||||
assert(3 == i:getPixel(0, 1))
|
||||
assert(4 == i:getPixel(1, 1))
|
||||
i:clear(5)
|
||||
assert(5 == i:getPixel(0, 0))
|
||||
assert(5 == i:getPixel(1, 0))
|
||||
assert(5 == i:getPixel(0, 1))
|
||||
assert(5 == i:getPixel(1, 1))
|
||||
|
||||
print("transparentColor = ", transparentColor)
|
||||
assert(transparentColor == i.spec.transparentColor)
|
||||
|
||||
i:clear() -- Image:clear() clears with i.spec.transparentColor by default
|
||||
assert(transparentColor == i:getPixel(0, 0))
|
||||
assert(transparentColor == i:getPixel(1, 0))
|
||||
assert(transparentColor == i:getPixel(0, 1))
|
||||
assert(transparentColor == i:getPixel(1, 1))
|
||||
end
|
||||
test_clear(ColorMode.RGB, 0)
|
||||
test_clear(ColorMode.GRAYSCALE, 0)
|
||||
test_clear(ColorMode.INDEXED, 0)
|
||||
test_clear(ColorMode.INDEXED, 255)
|
||||
|
||||
-- Image:drawSprite
|
||||
do
|
||||
local spr = Sprite(4, 4)
|
||||
local cel = spr.cels[1]
|
||||
cel.image:putPixel(0, 0, pc.rgba(255, 0, 0, 255))
|
||||
cel.image:putPixel(1, 0, pc.rgba(0, 255, 0, 255))
|
||||
cel.image:putPixel(0, 1, pc.rgba(0, 0, 255, 255))
|
||||
cel.image:putPixel(1, 1, pc.rgba(255, 255, 0, 255))
|
||||
|
||||
local r = Image(spr.spec) -- render
|
||||
r:drawSprite(spr, 1, 0, 0)
|
||||
|
||||
assert(r:getPixel(0, 0) == pc.rgba(255, 0, 0, 255))
|
||||
assert(r:getPixel(1, 0) == pc.rgba(0, 255, 0, 255))
|
||||
assert(r:getPixel(0, 1) == pc.rgba(0, 0, 255, 255))
|
||||
assert(r:getPixel(1, 1) == pc.rgba(255, 255, 0, 255))
|
||||
|
||||
r = Image(3, 3, spr.colorMode)
|
||||
r:drawSprite(spr, 1, Point{x=1, y=1})
|
||||
assert(r:getPixel(0, 0) == pc.rgba(0, 0, 0, 0))
|
||||
assert(r:getPixel(1, 0) == pc.rgba(0, 0, 0, 0))
|
||||
assert(r:getPixel(2, 0) == pc.rgba(0, 0, 0, 0))
|
||||
assert(r:getPixel(0, 1) == pc.rgba(0, 0, 0, 0))
|
||||
assert(r:getPixel(1, 1) == pc.rgba(255, 0, 0, 255))
|
||||
assert(r:getPixel(2, 1) == pc.rgba(0, 255, 0, 255))
|
||||
assert(r:getPixel(0, 2) == pc.rgba(0, 0, 0, 0))
|
||||
assert(r:getPixel(1, 2) == pc.rgba(0, 0, 255, 255))
|
||||
assert(r:getPixel(2, 2) == pc.rgba(255, 255, 0, 255))
|
||||
end
|
||||
|
||||
|
||||
-- Image:drawPixel with indexed color
|
||||
do
|
||||
local a = Sprite(32, 32, ColorMode.INDEXED)
|
||||
local i = a.cels[1].image
|
||||
assert(i:getPixel(0, 0) == 0)
|
||||
assert(i:getPixel(1, 0) == 0)
|
||||
assert(i:getPixel(2, 0) == 0)
|
||||
i:drawPixel(0, 0, Color{ index=2 })
|
||||
i:drawPixel(1, 0, Color{ index=3 }.index)
|
||||
i:drawPixel(2, 0, Color(4))
|
||||
assert(i:getPixel(0, 0) == 2)
|
||||
assert(i:getPixel(1, 0) == 3)
|
||||
assert(i:getPixel(2, 0) == 4)
|
||||
end
|
136
tests/scripts/events.lua
Normal file
136
tests/scripts/events.lua
Normal file
@ -0,0 +1,136 @@
|
||||
-- Copyright (C) 2021 Igara Studio S.A.
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
dofile('./test_utils.lua')
|
||||
|
||||
-- Test app.events
|
||||
do
|
||||
local i = 0
|
||||
local listener = app.events:on('sitechange',
|
||||
function() i = i + 1 end)
|
||||
assert(i == 0)
|
||||
local a = Sprite(32, 32)
|
||||
expect_eq(a, app.activeSprite)
|
||||
expect_eq(1, i)
|
||||
local b = Sprite(32, 32)
|
||||
expect_eq(b, app.activeSprite)
|
||||
expect_eq(2, i)
|
||||
app.activeSprite = a
|
||||
expect_eq(3, i)
|
||||
app.events:off(listener)
|
||||
app.activeSprite = b
|
||||
expect_eq(3, i)
|
||||
end
|
||||
|
||||
do
|
||||
local pref = app.preferences
|
||||
pref.color_bar.fg_color = Color(0, 0, 0)
|
||||
pref.color_bar.bg_color = Color(0, 0, 0)
|
||||
|
||||
local fg, bg = 0, 0
|
||||
local a = app.events:on('fgcolorchange', function() fg = fg + 1 end)
|
||||
local b = app.events:on('bgcolorchange', function() bg = bg + 1 end)
|
||||
assert(fg == 0)
|
||||
assert(bg == 0)
|
||||
|
||||
pref.color_bar.fg_color = Color(255, 0, 0)
|
||||
pref.color_bar.bg_color = Color(255, 0, 0)
|
||||
assert(fg == 1)
|
||||
assert(bg == 1)
|
||||
pref.color_bar.fg_color = Color(255, 0, 0) -- No change (same color)
|
||||
assert(fg == 1)
|
||||
pref.color_bar.fg_color = Color(0, 0, 0)
|
||||
assert(fg == 2)
|
||||
app.events:off(a)
|
||||
app.events:off(b)
|
||||
pref.color_bar.fg_color = Color(255, 0, 0)
|
||||
assert(fg == 2)
|
||||
end
|
||||
|
||||
-- Test Sprite.events
|
||||
do
|
||||
local spr = Sprite(32, 64)
|
||||
local changes = 0
|
||||
function incChanges() changes = changes + 1 end
|
||||
spr.events:on('change', incChanges)
|
||||
expect_eq(0, changes)
|
||||
spr.width = 64
|
||||
expect_eq(1, changes)
|
||||
app.undo()
|
||||
expect_eq(2, changes)
|
||||
app.redo()
|
||||
expect_eq(3, changes)
|
||||
spr.events:off(incChanges)
|
||||
app.undo()
|
||||
expect_eq(3, changes)
|
||||
end
|
||||
|
||||
-- Multiple listeners
|
||||
do
|
||||
local spr = Sprite(2, 2)
|
||||
local ai, bi = 0, 0
|
||||
function a() ai = ai + 1 end
|
||||
function b() bi = bi + 1 end
|
||||
|
||||
spr.events:on('change', a)
|
||||
spr.events:on('change', b)
|
||||
spr.width = 4
|
||||
expect_eq(1, ai)
|
||||
expect_eq(1, bi)
|
||||
|
||||
spr.events:off(a)
|
||||
spr.width = 8
|
||||
expect_eq(1, ai)
|
||||
expect_eq(2, bi)
|
||||
|
||||
spr.events:off(b)
|
||||
spr.width = 16
|
||||
expect_eq(1, ai)
|
||||
expect_eq(2, bi)
|
||||
end
|
||||
|
||||
-- Avoid removing invalid listener when we use Events:off(function)
|
||||
do
|
||||
local spr = Sprite(2, 2)
|
||||
|
||||
local i = 0
|
||||
function inc() i = i + 1 end
|
||||
spr.events:on('change', inc)
|
||||
|
||||
spr.width = 4
|
||||
expect_eq(1, i)
|
||||
|
||||
app.events:off(inc)
|
||||
spr.width = 8
|
||||
|
||||
-- If this fails is because app.events:off(inc) removed the sprite
|
||||
-- listener instead of doing nothing.
|
||||
expect_eq(2, i)
|
||||
end
|
||||
|
||||
-- Accessing Sprite.events when closing the same sprite will call
|
||||
-- push_sprite_events() creating a new app::script::SpriteEvents
|
||||
-- instance again even when we've just destroyed the old one (because
|
||||
-- we're just closing the sprite).
|
||||
do
|
||||
local s = Sprite(32, 32)
|
||||
function onSpriteChange()
|
||||
-- Do nothing
|
||||
end
|
||||
-- Here we access s.events for first time, creating the
|
||||
-- app::script::SpriteEvents for this sprite.
|
||||
s.events:on('change', onSpriteChange)
|
||||
function onSiteChange()
|
||||
-- Accessing s.events again on 'sitechange' when we're just
|
||||
-- closing the sprite, re-generating its SpriteEvents instance.
|
||||
-- We've to have special care of this case.
|
||||
s.events:off(onSpriteChange)
|
||||
end
|
||||
app.events:on('sitechange', onSiteChange)
|
||||
-- Closing the sprite will create a 'sitechange' event calling
|
||||
-- onSiteChange() function.
|
||||
s:close()
|
||||
app.events:off(onSiteChange)
|
||||
end
|
95
tests/scripts/frames.lua
Normal file
95
tests/scripts/frames.lua
Normal file
@ -0,0 +1,95 @@
|
||||
-- Copyright (C) 2018 Igara Studio S.A.
|
||||
-- Copyright (C) 2018 David Capello
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
do
|
||||
local a = Sprite(32, 32)
|
||||
assert(#a.frames == 1)
|
||||
assert(a.frames[1].frameNumber == 1)
|
||||
assert(a.frames[1].duration == 0.1)
|
||||
a.frames[1].duration = 0.2
|
||||
assert(a.frames[1].duration == 0.2)
|
||||
assert(a.layers[1]:cel(1) ~= nil)
|
||||
|
||||
-- Sprite:newEmptyFrame()
|
||||
local fr0 = a:newEmptyFrame()
|
||||
assert(fr0.frameNumber == 2) -- returned the second frame
|
||||
assert(#a.frames == 2)
|
||||
assert(a.frames[1].frameNumber == 1)
|
||||
assert(a.frames[2].frameNumber == 2)
|
||||
assert(a.frames[1].duration == 0.2)
|
||||
assert(a.frames[2].duration == 0.2) -- the duration is copied
|
||||
assert(a.layers[1]:cel(1) ~= nil)
|
||||
assert(a.layers[1]:cel(fr0) == nil) -- no cel
|
||||
assert(fr0 == a.frames[2])
|
||||
a:deleteFrame(fr0)
|
||||
assert(#a.frames == 1)
|
||||
|
||||
-- Sprite:newFrame() without arguments
|
||||
local fr = a:newFrame()
|
||||
assert(fr.frameNumber == 2) -- returned the second frame
|
||||
assert(#a.frames == 2)
|
||||
assert(a.frames[1].frameNumber == 1)
|
||||
assert(a.frames[2].frameNumber == 2)
|
||||
assert(a.frames[1].duration == 0.2)
|
||||
assert(a.frames[2].duration == 0.2)
|
||||
assert(fr == a.frames[2])
|
||||
|
||||
fr.duration = 0.3
|
||||
assert(a.frames[1].duration == 0.2)
|
||||
assert(a.frames[2].duration == 0.3)
|
||||
|
||||
local i = 1
|
||||
for k,v in ipairs(a.frames) do
|
||||
assert(i == k)
|
||||
assert(v == a.frames[k])
|
||||
i = i+1
|
||||
end
|
||||
|
||||
a:deleteFrame(1)
|
||||
assert(#a.frames == 1)
|
||||
assert(a.frames[1].duration == 0.3)
|
||||
|
||||
-- TODO This is a big issue, if we add/delete frames, we don't
|
||||
-- update frame objects, they are still pointing to the same frame
|
||||
-- number, which could lead to confusion.
|
||||
assert(fr.frameNumber == 2)
|
||||
fr.duration = 1 -- This is a do nothing operation
|
||||
|
||||
-- Sprite:newEmptyFrame(n)
|
||||
local fr2 = a:newEmptyFrame(1)
|
||||
assert(#a.frames == 2)
|
||||
assert(fr2.frameNumber == 1) -- returned the first frame
|
||||
print(a.frames[1].duration)
|
||||
assert(a.frames[1].duration == 0.3) -- the duration is copied from the frame
|
||||
assert(a.frames[2].duration == 0.3)
|
||||
assert(fr2 == a.frames[1])
|
||||
assert(a.layers[1]:cel(1) == nil)
|
||||
assert(a.layers[1]:cel(2) ~= nil)
|
||||
|
||||
-- Sprite:newFrame(n)
|
||||
local fr3 = a:newFrame(2)
|
||||
assert(#a.frames == 3)
|
||||
assert(fr3.frameNumber == 2) -- returned the second frame
|
||||
assert(a.frames[1].duration == 0.3)
|
||||
assert(a.frames[2].duration == 0.3) -- copied duration from old frame 2
|
||||
assert(a.frames[3].duration == 0.3)
|
||||
local cel1 = a.layers[1]:cel(1)
|
||||
local cel2 = a.layers[1]:cel(2)
|
||||
local cel3 = a.layers[1]:cel(3)
|
||||
assert(cel1 == nil)
|
||||
assert(cel2 ~= nil)
|
||||
assert(cel3 ~= nil)
|
||||
print(cel2.image.spec.colorMode)
|
||||
print(cel2.image.spec.width)
|
||||
print(cel2.image.spec.height)
|
||||
print(cel3.image.spec.colorMode)
|
||||
print(cel3.image.spec.width)
|
||||
print(cel3.image.spec.height)
|
||||
assert(cel2.image.spec == cel3.image.spec)
|
||||
assert(fr3.previous == a.frames[1])
|
||||
assert(fr3 == a.frames[2])
|
||||
assert(fr3.next == a.frames[3])
|
||||
end
|
276
tests/scripts/image.lua
Normal file
276
tests/scripts/image.lua
Normal file
@ -0,0 +1,276 @@
|
||||
-- Copyright (C) 2019-2022 Igara Studio S.A.
|
||||
-- Copyright (C) 2018 David Capello
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
dofile('./test_utils.lua')
|
||||
|
||||
local rgba = app.pixelColor.rgba
|
||||
|
||||
local a = Image(32, 64)
|
||||
assert(a.width == 32)
|
||||
assert(a.height == 64)
|
||||
assert(a.colorMode == ColorMode.RGB) -- RGB by default
|
||||
assert(a.rowStride == 32*4)
|
||||
assert(a:isEmpty())
|
||||
assert(a:isPlain(rgba(0, 0, 0, 0)))
|
||||
assert(a:isPlain(0))
|
||||
|
||||
do
|
||||
local b = Image(32, 64, ColorMode.INDEXED)
|
||||
assert(b.width == 32)
|
||||
assert(b.height == 64)
|
||||
assert(b.colorMode == ColorMode.INDEXED)
|
||||
assert(b.rowStride == 32*1)
|
||||
|
||||
local c = Image{ width=32, height=64, colorMode=ColorMode.INDEXED }
|
||||
assert(c.width == 32)
|
||||
assert(c.height == 64)
|
||||
assert(c.colorMode == ColorMode.INDEXED)
|
||||
end
|
||||
|
||||
-- Get/put RGBA pixels
|
||||
do
|
||||
for y=0,a.height-1 do
|
||||
for x=0,a.width-1 do
|
||||
a:putPixel(x, y, rgba(x, y, x+y, x-y))
|
||||
end
|
||||
end
|
||||
assert(not a:isEmpty())
|
||||
end
|
||||
|
||||
-- Clone
|
||||
do
|
||||
local c = Image(a)
|
||||
local d = a:clone()
|
||||
assert(c.width == 32)
|
||||
assert(c.height == 64)
|
||||
assert(c.colorMode == ColorMode.RGB)
|
||||
assert(c.width == d.width)
|
||||
assert(c.height == d.height)
|
||||
assert(c.colorMode == d.colorMode)
|
||||
|
||||
-- Get RGB pixels
|
||||
for y=0,c.height-1 do
|
||||
for x=0,c.width-1 do
|
||||
local expectedColor = rgba(x, y, x+y, x-y)
|
||||
assert(c:getPixel(x, y) == expectedColor)
|
||||
assert(d:getPixel(x, y) == expectedColor)
|
||||
end
|
||||
end
|
||||
|
||||
-- Clone a rectangle
|
||||
local e = Image(c, Rectangle(1, 1, 4, 5))
|
||||
print(e.width)
|
||||
print(e.height)
|
||||
assert(e.width == 4)
|
||||
assert(e.height == 5)
|
||||
|
||||
-- Empty clone
|
||||
assert(nil == Image(c, Rectangle(1, 1, 0, 0)))
|
||||
end
|
||||
|
||||
-- Patch
|
||||
do
|
||||
local spr = Sprite(256, 256)
|
||||
local image = app.site.image
|
||||
local copy = image:clone()
|
||||
assert(image:getPixel(0, 0) == 0)
|
||||
for y=0,copy.height-1 do
|
||||
for x=0,copy.width-1 do
|
||||
copy:putPixel(x, y, rgba(255-x, 255-y, 0, 255))
|
||||
end
|
||||
end
|
||||
image:putImage(copy)
|
||||
assert(image:getPixel(0, 0) == rgba(255, 255, 0, 255))
|
||||
assert(image:getPixel(255, 255) == rgba(0, 0, 0, 255))
|
||||
app.undo()
|
||||
assert(image:getPixel(0, 0) == rgba(0, 0, 0, 0))
|
||||
assert(image:getPixel(255, 255) == rgba(0, 0, 0, 0))
|
||||
end
|
||||
|
||||
-- Load/Save
|
||||
do
|
||||
local a = Image{ fromFile="sprites/1empty3.aseprite" }
|
||||
assert(a.width == 32)
|
||||
assert(a.height == 32)
|
||||
a:saveAs("_test_oneframe.png")
|
||||
|
||||
local b = Image{ fromFile="_test_oneframe.png" }
|
||||
assert(b.width == 32)
|
||||
assert(b.height == 32)
|
||||
for y=0,a.height-1 do
|
||||
for x=0,a.width-1 do
|
||||
assert(a:getPixel(x, y) == b:getPixel(x, y))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Save indexed image and load and check that the palette is the same
|
||||
do
|
||||
local spr = Sprite{ fromFile="sprites/abcd.aseprite" }
|
||||
local img = Image{ fromFile="sprites/abcd.aseprite" }
|
||||
spr.cels[1].image:saveAs("_test_palette_a.png")
|
||||
img:saveAs("_test_palette_b.png") -- This file will contain a black palette
|
||||
img:saveAs{ filename="_test_palette_c.png", palette=spr.palettes[1] }
|
||||
|
||||
local a = Sprite{ fromFile="_test_palette_a.png" }
|
||||
local b = Sprite{ fromFile="_test_palette_b.png" }
|
||||
local c = Sprite{ fromFile="_test_palette_c.png" }
|
||||
|
||||
assert(a.width == 5)
|
||||
assert(a.height == 7)
|
||||
assert(b.width == 32)
|
||||
assert(b.height == 32)
|
||||
assert(c.width == 32)
|
||||
assert(c.height == 32)
|
||||
local bimg = b.cels[1].image
|
||||
local cimg = c.cels[1].image
|
||||
for y=0,31 do
|
||||
for x=0,31 do
|
||||
assert(bimg:getPixel(x, y) == cimg:getPixel(x, y))
|
||||
end
|
||||
end
|
||||
|
||||
local apal = a.palettes[1]
|
||||
local bpal = b.palettes[1]
|
||||
local cpal = c.palettes[1]
|
||||
-- Same palette in a and c
|
||||
assert(#apal == #cpal)
|
||||
for i=0,#apal-1 do
|
||||
assert(apal:getColor(i) == cpal:getColor(i))
|
||||
end
|
||||
-- b should contain a complete black palette
|
||||
assert(bpal:getColor(0) == Color(0, 0, 0, 0))
|
||||
for i=1,#bpal-1 do
|
||||
assert(bpal:getColor(i) == Color(0, 0, 0, 255))
|
||||
end
|
||||
end
|
||||
|
||||
-- Resize image
|
||||
do
|
||||
local a = Sprite(3, 2)
|
||||
local cel = a.cels[1]
|
||||
assert(cel.bounds == Rectangle(0, 0, 3, 2))
|
||||
local img = cel.image
|
||||
local cols = { rgba(10, 60, 1), rgba(20, 50, 2), rgba(30, 40, 3),
|
||||
rgba(40, 30, 4), rgba(50, 20, 5), rgba(60, 10, 6) }
|
||||
array_to_pixels(cols, img)
|
||||
expect_img(img, cols)
|
||||
|
||||
-- Test resize of a cel with origin=0,0
|
||||
|
||||
img:resize(img.width*2, img.height*2)
|
||||
|
||||
expect_eq(cel.bounds, Rectangle(0, 0, 6, 4))
|
||||
expect_eq(img.width, 6)
|
||||
expect_eq(img.height, 4)
|
||||
local cols2 = { cols[1],cols[1], cols[2],cols[2], cols[3],cols[3],
|
||||
cols[1],cols[1], cols[2],cols[2], cols[3],cols[3],
|
||||
cols[4],cols[4], cols[5],cols[5], cols[6],cols[6],
|
||||
cols[4],cols[4], cols[5],cols[5], cols[6],cols[6] }
|
||||
expect_img(img, cols2)
|
||||
|
||||
-- Undo
|
||||
function undo()
|
||||
app.undo()
|
||||
img = cel.image -- TODO img shouldn't be invalidated, the resize operation should kept the image ID
|
||||
end
|
||||
undo()
|
||||
|
||||
-- Test a resize when cel origin > 0,0
|
||||
cel.position = Point(2, 1)
|
||||
expect_eq(cel.bounds, Rectangle(2, 1, 3, 2))
|
||||
expect_img(img, cols)
|
||||
img:resize{ width=6, height=4 }
|
||||
expect_eq(cel.bounds, Rectangle(2, 1, 6, 4)) -- Position is not modified
|
||||
expect_eq(img.width, 6)
|
||||
expect_eq(img.height, 4)
|
||||
|
||||
undo()
|
||||
img:resize{ size=Size(6, 4), pivot=Point(1, 1) }
|
||||
expect_eq(cel.bounds, Rectangle(1, 0, 6, 4))
|
||||
|
||||
undo()
|
||||
img:resize{ size=Size(6, 4), pivot=Point(3, 2) }
|
||||
expect_eq(cel.bounds, Rectangle(-1, -1, 6, 4))
|
||||
|
||||
-- Test resize without cel
|
||||
|
||||
local img2 = Image(img)
|
||||
expect_img(img2, cols2)
|
||||
img2:resize(3, 2)
|
||||
expect_img(img2, cols)
|
||||
end
|
||||
|
||||
-- Test v1.2.17 crashes
|
||||
do
|
||||
local defSpec = ImageSpec{ width=1, height=1, colorMode=ColorMode.RGB }
|
||||
|
||||
local img = Image() -- we create a 1x1 RGB image
|
||||
assert(img ~= nil)
|
||||
assert(img.spec == defSpec)
|
||||
|
||||
img = Image(nil)
|
||||
assert(img ~= nil)
|
||||
assert(img.spec == defSpec)
|
||||
|
||||
local spr = Sprite(32, 32, ColorMode.INDEXED)
|
||||
spr.cels[1].image:putPixel(15, 15, 129)
|
||||
img = Image(spr) -- we create a sprite render of the first frame
|
||||
assert(img ~= nil)
|
||||
assert(img.spec == spr.spec)
|
||||
assert(img:getPixel(15, 15) == 129)
|
||||
end
|
||||
|
||||
-- Fix drawImage() when drawing in a cel image
|
||||
do
|
||||
local a = Image(3, 2, ColorMode.INDEXED)
|
||||
array_to_pixels({ 0, 1, 2,
|
||||
2, 3, 4 }, a)
|
||||
|
||||
local function test(b)
|
||||
expect_img(b, { 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0 })
|
||||
|
||||
b:drawImage(a, Point(2, 1))
|
||||
expect_img(b, { 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 1, 2,
|
||||
0, 0, 2, 3, 4,
|
||||
0, 0, 0, 0, 0 })
|
||||
|
||||
b:drawImage(a, Point(0, 1))
|
||||
expect_img(b, { 0, 0, 0, 0, 0,
|
||||
0, 1, 2, 1, 2,
|
||||
2, 3, 4, 3, 4,
|
||||
0, 0, 0, 0, 0 })
|
||||
|
||||
b:drawImage(a, Point(-1, 2))
|
||||
expect_img(b, { 0, 0, 0, 0, 0,
|
||||
0, 1, 2, 1, 2,
|
||||
1, 2, 4, 3, 4,
|
||||
3, 4, 0, 0, 0 })
|
||||
|
||||
b:drawImage(a, Point(0, 3))
|
||||
expect_img(b, { 0, 0, 0, 0, 0,
|
||||
0, 1, 2, 1, 2,
|
||||
1, 2, 4, 3, 4,
|
||||
0, 1, 2, 0, 0 })
|
||||
|
||||
b:drawImage(a, Point(0, 3)) -- Do nothing
|
||||
expect_img(b, { 0, 0, 0, 0, 0,
|
||||
0, 1, 2, 1, 2,
|
||||
1, 2, 4, 3, 4,
|
||||
0, 1, 2, 0, 0 })
|
||||
end
|
||||
|
||||
local b = Image(5, 4, ColorMode.INDEXED)
|
||||
test(b)
|
||||
|
||||
local s = Sprite(5, 4, ColorMode.INDEXED)
|
||||
test(app.activeCel.image)
|
||||
|
||||
end
|
72
tests/scripts/image_iterator.lua
Normal file
72
tests/scripts/image_iterator.lua
Normal file
@ -0,0 +1,72 @@
|
||||
-- Copyright (C) 2018 David Capello
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
local pc = app.pixelColor
|
||||
|
||||
-- Iterate pixels
|
||||
do
|
||||
local spr = Sprite(2, 2)
|
||||
local image = app.site.image
|
||||
local colors = { pc.rgba(255, 0, 0, 255),
|
||||
pc.rgba(0, 255, 0, 255),
|
||||
pc.rgba(255, 0, 255, 255),
|
||||
pc.rgba(255, 0, 255, 255) }
|
||||
local xy = {
|
||||
{ x=0, y=0 },
|
||||
{ x=1, y=0 },
|
||||
{ x=0, y=1 },
|
||||
{ x=1, y=1 } }
|
||||
|
||||
local c = 1
|
||||
for y=0,image.height-1 do
|
||||
for x=0,image.width-1 do
|
||||
image:putPixel(x, y, colors[c])
|
||||
c = c+1
|
||||
end
|
||||
end
|
||||
|
||||
c = 1
|
||||
for y=0,image.height-1 do
|
||||
for x=0,image.width-1 do
|
||||
assert(colors[c] == image:getPixel(x, y))
|
||||
c = c+1
|
||||
end
|
||||
end
|
||||
|
||||
c = 1
|
||||
for it in image:pixels() do
|
||||
assert(colors[c] == it())
|
||||
assert(xy[c].x == it.x)
|
||||
assert(xy[c].y == it.y)
|
||||
c = c+1
|
||||
end
|
||||
|
||||
c = 0
|
||||
for it in image:pixels{x=1, y=0, width=1, height=2} do
|
||||
local i = 1 + it.y*2 + it.x
|
||||
assert(colors[i] == it())
|
||||
assert(xy[i].x == it.x)
|
||||
assert(xy[i].y == it.y)
|
||||
c = c + 1
|
||||
end
|
||||
assert(c == 2)
|
||||
|
||||
-- Iterating outside
|
||||
for it in image:pixels{x=2, y=0, width=2, height=2} do
|
||||
assert(false)
|
||||
end
|
||||
|
||||
c = 1
|
||||
for it in image:pixels() do
|
||||
it(pc.rgba(255, 32*c, 0, 255))
|
||||
c = c+1
|
||||
end
|
||||
|
||||
c = 1
|
||||
for it in image:pixels() do
|
||||
assert(pc.rgba(255, 32*c, 0, 255) == it())
|
||||
c = c+1
|
||||
end
|
||||
end
|
47
tests/scripts/image_spec.lua
Normal file
47
tests/scripts/image_spec.lua
Normal file
@ -0,0 +1,47 @@
|
||||
-- Copyright (C) 2018 Igara Studio S.A.
|
||||
-- Copyright (C) 2018 David Capello
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
do
|
||||
local spec = ImageSpec{colorMode=ColorMode.GRAY, width=32, height=64, transparentColor=2}
|
||||
assert(spec.colorMode == ColorMode.GRAY)
|
||||
assert(spec.width == 32)
|
||||
assert(spec.height == 64)
|
||||
assert(spec.transparentColor == 2)
|
||||
end
|
||||
|
||||
do
|
||||
local sprite = Sprite(32, 64, ColorMode.INDEXED)
|
||||
assert(sprite.width == 32)
|
||||
assert(sprite.height == 64)
|
||||
assert(sprite.colorMode == ColorMode.INDEXED)
|
||||
|
||||
local sprite2 = Sprite(sprite.spec)
|
||||
assert(sprite2.width == 32)
|
||||
assert(sprite2.height == 64)
|
||||
assert(sprite2.colorMode == ColorMode.INDEXED)
|
||||
|
||||
local spec = sprite.spec
|
||||
assert(spec.width == 32)
|
||||
assert(spec.height == 64)
|
||||
assert(spec.colorMode == ColorMode.INDEXED)
|
||||
|
||||
spec.width = 30
|
||||
spec.height = 40
|
||||
spec.colorMode = ColorMode.RGB
|
||||
assert(spec.width == 30)
|
||||
assert(spec.height == 40)
|
||||
assert(spec.colorMode == ColorMode.RGB)
|
||||
|
||||
local image = Image(spec)
|
||||
assert(image.width == 30)
|
||||
assert(image.height == 40)
|
||||
assert(image.colorMode == ColorMode.RGB)
|
||||
|
||||
print(image.spec.width, image.spec.height, image.spec.colorMode)
|
||||
assert(image.spec.width == 30)
|
||||
assert(image.spec.height == 40)
|
||||
assert(image.spec.colorMode == ColorMode.RGB)
|
||||
end
|
75
tests/scripts/import_sprite_sheet_command.lua
Normal file
75
tests/scripts/import_sprite_sheet_command.lua
Normal file
@ -0,0 +1,75 @@
|
||||
-- Copyright (C) 2021 Igara Studio S.A.
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
dofile('./test_utils.lua')
|
||||
|
||||
do
|
||||
local s = Sprite(8, 4, ColorMode.INDEXED)
|
||||
assert(#s.cels == 1)
|
||||
|
||||
local i = s.cels[1].image
|
||||
array_to_pixels({ 0, 1, 2, 3, 3, 2, 1, 0,
|
||||
1, 2, 3, 4, 4, 3, 2, 1,
|
||||
1, 2, 3, 4, 4, 3, 2, 1,
|
||||
0, 1, 2, 3, 3, 2, 1, 0 }, i)
|
||||
|
||||
app.command.ImportSpriteSheet{
|
||||
ui=false,
|
||||
type=SpriteSheetType.ROWS,
|
||||
frameBounds=Rectangle(0, 0, 4, 4)
|
||||
}
|
||||
assert(#s.cels == 2)
|
||||
expect_img(s.cels[1].image,
|
||||
{ 0, 1, 2, 3,
|
||||
1, 2, 3, 4,
|
||||
1, 2, 3, 4,
|
||||
0, 1, 2, 3 })
|
||||
expect_img(s.cels[2].image,
|
||||
{ 3, 2, 1, 0,
|
||||
4, 3, 2, 1,
|
||||
4, 3, 2, 1,
|
||||
3, 2, 1, 0 })
|
||||
|
||||
app.undo();
|
||||
app.command.ImportSpriteSheet{
|
||||
ui=false,
|
||||
type=SpriteSheetType.ROWS,
|
||||
frameBounds=Rectangle(0, 0, 2, 3)
|
||||
}
|
||||
assert(#s.cels == 4)
|
||||
expect_img(s.cels[1].image,
|
||||
{ 0, 1,
|
||||
1, 2,
|
||||
1, 2 })
|
||||
expect_img(s.cels[2].image,
|
||||
{ 2, 3,
|
||||
3, 4,
|
||||
3, 4 })
|
||||
expect_img(s.cels[3].image,
|
||||
{ 3, 2,
|
||||
4, 3,
|
||||
4, 3 })
|
||||
expect_img(s.cels[4].image,
|
||||
{ 1, 0,
|
||||
2, 1,
|
||||
2, 1 })
|
||||
|
||||
|
||||
app.undo();
|
||||
app.command.ImportSpriteSheet{
|
||||
ui=false,
|
||||
type=SpriteSheetType.ROWS,
|
||||
frameBounds=Rectangle(1, 1, 2, 2),
|
||||
padding=Size(2, 0)
|
||||
}
|
||||
assert(#s.cels == 2)
|
||||
expect_img(s.cels[1].image,
|
||||
{ 2, 3,
|
||||
2, 3 })
|
||||
expect_img(s.cels[2].image,
|
||||
{ 3, 2,
|
||||
3, 2 })
|
||||
|
||||
end
|
285
tests/scripts/inks.lua
Normal file
285
tests/scripts/inks.lua
Normal file
@ -0,0 +1,285 @@
|
||||
-- Copyright (C) 2020-2022 Igara Studio S.A.
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
dofile('./test_utils.lua')
|
||||
|
||||
local colorModes = { ColorMode.RGB,
|
||||
ColorMode.GRAY,
|
||||
ColorMode.INDEXED }
|
||||
|
||||
local pencil = "pencil"
|
||||
local pc = app.pixelColor
|
||||
|
||||
local function gray(g)
|
||||
return pc.graya(g, 255)
|
||||
end
|
||||
|
||||
function test_inks(colorMode)
|
||||
-- Test ink over a transparent sprite
|
||||
local s = Sprite(3, 3, colorMode)
|
||||
local p, a, b, c, d
|
||||
if colorMode == ColorMode.GRAY then
|
||||
p = s.palettes[1]
|
||||
a, b, c, d = gray(0), gray(64), gray(128), gray(255)
|
||||
else
|
||||
p = Palette()
|
||||
p:resize(4)
|
||||
p:setColor(0, Color(0, 0, 0))
|
||||
p:setColor(1, Color(64, 64, 64))
|
||||
p:setColor(2, Color(128, 128, 128))
|
||||
p:setColor(3, Color(255, 255, 255))
|
||||
s:setPalette(p)
|
||||
|
||||
a, b, c, d = 0, 1, 2, 3
|
||||
if colorMode == ColorMode.RGB then
|
||||
a = p:getColor(a).rgbaPixel
|
||||
b = p:getColor(b).rgbaPixel
|
||||
c = p:getColor(c).rgbaPixel
|
||||
d = p:getColor(d).rgbaPixel
|
||||
end
|
||||
end
|
||||
|
||||
-- With simple ink opacity doesn't have affect (always the color)
|
||||
local opacities = { 0, 128, 255 }
|
||||
for i = 1,#opacities do
|
||||
expect_img(app.activeImage,
|
||||
{ 0, 0, 0,
|
||||
0, 0, 0,
|
||||
0, 0, 0 })
|
||||
app.useTool{ tool=pencil, color=d, points={ Point(0, 0), Point(2, 2) },
|
||||
ink=Ink.SIMPLE, opacity=opacities[i] }
|
||||
expect_img(app.activeImage,
|
||||
{ d, 0, 0,
|
||||
0, d, 0,
|
||||
0, 0, d })
|
||||
if i < #opacities then app.undo() end
|
||||
end
|
||||
|
||||
-- Check that painting with transparent index (color) on a
|
||||
-- transparent layer (using any value of opacity) with alpha
|
||||
-- compositing doesn't modify pixels
|
||||
for i = 1,#opacities do
|
||||
app.useTool{ tool=pencil, color=0, points={ Point(1, 1) },
|
||||
ink=Ink.ALPHA_COMPOSITING, opacity=opacities[i] }
|
||||
expect_img(app.activeImage,
|
||||
{ d, 0, 0,
|
||||
0, d, 0,
|
||||
0, 0, d })
|
||||
end
|
||||
|
||||
-- Convert to background layer
|
||||
app.bgColor = Color{ index=0 }
|
||||
app.command.BackgroundFromLayer()
|
||||
|
||||
app.useTool{ tool=pencil, color=d, points={ Point(0, 1), Point(2, 1) },
|
||||
ink=Ink.ALPHA_COMPOSITING, opacity=64 }
|
||||
expect_img(app.activeImage,
|
||||
{ d, a, a,
|
||||
b, d, b,
|
||||
a, a, d })
|
||||
|
||||
app.useTool{ tool=pencil, color=d, points={ Point(0, 1) },
|
||||
ink=Ink.ALPHA_COMPOSITING, opacity=86 }
|
||||
expect_img(app.activeImage,
|
||||
{ d, a, a,
|
||||
c, d, b,
|
||||
a, a, d })
|
||||
|
||||
----------------------------------------------------------------------
|
||||
-- Inks with custom brushes
|
||||
|
||||
function test_custom_brush_inks(brushColorMode)
|
||||
-- Colors in the brush image (ba, bb, bc, bd)
|
||||
local ba, bb, bc, bd
|
||||
if brushColorMode == ColorMode.RGB then
|
||||
ba = Color(0, 0, 0)
|
||||
bb = Color(64, 64, 64)
|
||||
bc = Color(128, 128, 128)
|
||||
bd = Color(255, 255, 255)
|
||||
elseif brushColorMode == ColorMode.GRAY then
|
||||
ba, bb, bc, bd = gray(0), gray(64), gray(128), gray(255)
|
||||
else
|
||||
ba, bb, bc, bd = 0, 1, 2, 3
|
||||
end
|
||||
|
||||
local brushImage = Image(2, 2, brushColorMode)
|
||||
array_to_pixels({ 0, bd,
|
||||
bc, 0 }, brushImage)
|
||||
local brush = Brush(brushImage)
|
||||
|
||||
-- da, db, dc, dd are the final result after painting the custom
|
||||
-- brush in the sprite
|
||||
local ra, rb, rc, rd
|
||||
if s.colorMode ~= ColorMode.INDEXED and
|
||||
brushColorMode == ColorMode.INDEXED then
|
||||
-- For indexed images we take the index of the brush and use the
|
||||
-- sprite palette, we are not sure if this in the future might
|
||||
-- change, e.g. having the original palette that was used to
|
||||
-- create the brush integrated to the brush itself, in that case
|
||||
-- we should convert the brush index using the same brush
|
||||
-- palette (instead of the sprite palette).
|
||||
--
|
||||
-- TODO check BrushInkProcessingBase comment for more information
|
||||
if s.colorMode == ColorMode.RGB then
|
||||
ra, rb, rc, rd =
|
||||
p:getColor(ba).rgbaPixel,
|
||||
p:getColor(bb).rgbaPixel,
|
||||
p:getColor(bc).rgbaPixel,
|
||||
p:getColor(bd).rgbaPixel
|
||||
else
|
||||
ra, rb, rc, rd =
|
||||
p:getColor(ba).grayPixel,
|
||||
p:getColor(bb).grayPixel,
|
||||
p:getColor(bc).grayPixel,
|
||||
p:getColor(bd).grayPixel
|
||||
end
|
||||
else
|
||||
ra, rb, rc, rd = a, b, c, d
|
||||
end
|
||||
|
||||
array_to_pixels({ a, a, a,
|
||||
a, a, a,
|
||||
a, a, a }, app.activeImage)
|
||||
|
||||
-- Simple
|
||||
expect_img(app.activeImage,
|
||||
{ a, a, a,
|
||||
a, a, a,
|
||||
a, a, a })
|
||||
app.useTool{ tool=pencil, brush=brush, points={ Point(2, 2) },
|
||||
ink=Ink.SIMPLE }
|
||||
expect_img(app.activeImage,
|
||||
{ a, a, a,
|
||||
a, a, rd,
|
||||
a, rc, a })
|
||||
|
||||
-- Alpha Compositing
|
||||
app.useTool{ tool=pencil, brush=brush, points={ Point(1, 1) },
|
||||
ink=Ink.ALPHA_COMPOSITING, opacity=255 }
|
||||
expect_img(app.activeImage,
|
||||
{ a, rd, a,
|
||||
rc, a, rd,
|
||||
a, rc, a })
|
||||
|
||||
local qc, qd
|
||||
if s.colorMode == ColorMode.GRAY and
|
||||
brushColorMode == ColorMode.INDEXED then
|
||||
qc = gray(pc.grayaV(rc)/2)
|
||||
qd = gray(pc.grayaV(rd)/2)
|
||||
else
|
||||
qc, qd = rb, rc
|
||||
end
|
||||
|
||||
app.useTool{ tool=pencil, brush=brush, points={ Point(1, 2) },
|
||||
ink=Ink.ALPHA_COMPOSITING, opacity=128 }
|
||||
expect_img(app.activeImage,
|
||||
{ a, rd, a,
|
||||
rc, qd, rd,
|
||||
qc, rc, a })
|
||||
|
||||
-- TODO test Lock Alpha, Copy Color+Alpha, Shading...
|
||||
end
|
||||
|
||||
for j = 1,#colorModes do
|
||||
test_custom_brush_inks(colorModes[j])
|
||||
end
|
||||
end
|
||||
|
||||
function test_alpha_compositing_on_indexed_with_full_opacity_and_repeated_colors_in_palette()
|
||||
local s = Sprite(1, 1, ColorMode.INDEXED)
|
||||
local p = Palette()
|
||||
p:resize(5)
|
||||
p:setColor(0, Color(0, 0, 0))
|
||||
p:setColor(1, Color(64, 64, 64))
|
||||
p:setColor(2, Color(128, 128, 128))
|
||||
p:setColor(3, Color(128, 128, 128))
|
||||
p:setColor(4, Color(255, 255, 255))
|
||||
s:setPalette(p)
|
||||
|
||||
local inks = { Ink.SIMPLE, Ink.ALPHA_COMPOSITING }
|
||||
|
||||
-- k=1 -> transparent layer
|
||||
-- k=2 -> background layer
|
||||
for k=1,2 do
|
||||
if k == 2 then app.command.BackgroundFromLayer() end
|
||||
-- i=1 -> simple ink
|
||||
-- i=2 -> alpha compositing ink
|
||||
for i = 1,2 do
|
||||
-- j=color index
|
||||
for j = 0,4 do
|
||||
expect_img(app.activeImage, { 0 })
|
||||
app.useTool{ tool="pencil", color=j, points={ Point(0, 0) },
|
||||
ink=inks[i], opacity=255 }
|
||||
expect_img(app.activeImage, { j })
|
||||
app.undo()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for i = 1,#colorModes do
|
||||
test_inks(colorModes[i])
|
||||
end
|
||||
test_alpha_compositing_on_indexed_with_full_opacity_and_repeated_colors_in_palette()
|
||||
|
||||
----------------------------------------------------------------------
|
||||
-- Test painting with transparent color on indexed
|
||||
----------------------------------------------------------------------
|
||||
|
||||
do
|
||||
local s = Sprite(2, 2, ColorMode.INDEXED)
|
||||
s.transparentColor = 0
|
||||
app.bgColor = 0
|
||||
app.command.BackgroundFromLayer()
|
||||
assert(app.activeLayer.isBackground)
|
||||
expect_img(app.activeImage, { 0, 0,
|
||||
0, 0 })
|
||||
|
||||
app.useTool{ tool="pencil", color=Color{r=0,g=0,b=0},
|
||||
points={ Point(0, 0) },
|
||||
ink=Ink.SIMPLE }
|
||||
expect_img(app.activeImage, { 0, 0,
|
||||
0, 0 })
|
||||
|
||||
-- Test that painting in the background layer with transparent color
|
||||
-- with alpha compositing and all opacity=255, will use the transparent
|
||||
-- index anyway. Reported here: https://github.com/aseprite/aseprite/issues/3047
|
||||
app.useTool{ tool="pencil", color=0,
|
||||
points={ Point(0, 0) },
|
||||
ink=Ink.ALPHA_COMPOSITING,
|
||||
opacity=255 }
|
||||
expect_img(app.activeImage, { 0, 0,
|
||||
0, 0 })
|
||||
|
||||
-- Other cases should keep working
|
||||
local p = s.palettes[1]
|
||||
|
||||
-- palette with only 3 colors: white, gray (50%), black
|
||||
p:setColor(0, Color{ r=255, g=255, b=255 })
|
||||
p:setColor(1, Color{ r=128, g=128, b=128 })
|
||||
p:setColor(2, Color{ r=0, g=0, b=0 })
|
||||
app.useTool{ tool="paint_bucket", color=2,
|
||||
points={ Point(0, 0) },
|
||||
ink=Ink.SIMPLE }
|
||||
expect_img(app.activeImage, { 2, 2,
|
||||
2, 2 })
|
||||
|
||||
-- White over black w/opacity=50% => gray
|
||||
app.useTool{ tool="pencil", color=0,
|
||||
points={ Point(0, 0) },
|
||||
ink=Ink.ALPHA_COMPOSITING,
|
||||
opacity=128 }
|
||||
expect_img(app.activeImage, { 1, 2,
|
||||
2, 2 })
|
||||
|
||||
-- White over gray w/opacity=51% => white
|
||||
app.useTool{ tool="pencil", color=0,
|
||||
points={ Point(0, 0) },
|
||||
ink=Ink.ALPHA_COMPOSITING,
|
||||
opacity=129 }
|
||||
expect_img(app.activeImage, { 0, 2,
|
||||
2, 2 })
|
||||
|
||||
end
|
22
tests/scripts/layer.lua
Normal file
22
tests/scripts/layer.lua
Normal file
@ -0,0 +1,22 @@
|
||||
-- Copyright (C) 2019 Igara Studio S.A.
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
do
|
||||
local s = Sprite(32, 64)
|
||||
local l = s.layers[1]
|
||||
assert(l.parent == s)
|
||||
assert(l.opacity == 255)
|
||||
assert(l.blendMode == BlendMode.NORMAL)
|
||||
|
||||
l.name = "My Layer"
|
||||
l.opacity = 128
|
||||
l.blendMode = BlendMode.MULTIPLY
|
||||
assert(l.name == "My Layer")
|
||||
assert(l.opacity == 128)
|
||||
assert(l.blendMode == BlendMode.MULTIPLY)
|
||||
|
||||
l.data = "Data"
|
||||
assert(l.data == "Data")
|
||||
end
|
215
tests/scripts/layers.lua
Normal file
215
tests/scripts/layers.lua
Normal file
@ -0,0 +1,215 @@
|
||||
-- Copyright (C) 2019-2022 Igara Studio S.A.
|
||||
-- Copyright (C) 2018 David Capello
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
do
|
||||
local s = Sprite(32, 32)
|
||||
assert(#s.layers == 1)
|
||||
|
||||
local a = s.layers[1]
|
||||
local b = s:newLayer()
|
||||
local c = s:newLayer()
|
||||
|
||||
assert(#s.layers == 3)
|
||||
assert(s.layers[1] == a)
|
||||
assert(s.layers[2] == b)
|
||||
assert(s.layers[3] == c)
|
||||
|
||||
local i = 1
|
||||
for k,v in ipairs(s.layers) do
|
||||
assert(i == k)
|
||||
assert(v == s.layers[k])
|
||||
i = i+1
|
||||
end
|
||||
|
||||
s:deleteLayer(b)
|
||||
assert(#s.layers == 2)
|
||||
assert(s.layers[1] == a)
|
||||
assert(s.layers[2] == c)
|
||||
end
|
||||
|
||||
-- Test groups
|
||||
|
||||
do
|
||||
local s = Sprite(32, 64)
|
||||
local l = s.layers[1]
|
||||
assert(#s.layers == 1)
|
||||
local g = s:newGroup()
|
||||
assert(#s.layers == 2)
|
||||
assert(l.parent == s)
|
||||
assert(g.parent == s)
|
||||
assert(s.layers[1] == l)
|
||||
assert(s.layers[2] == g)
|
||||
|
||||
l.parent = g
|
||||
assert(g.parent == s)
|
||||
assert(l.parent == g)
|
||||
|
||||
assert(#s.layers == 1)
|
||||
assert(s.layers[1] == g)
|
||||
assert(#s.layers[1].layers == 1)
|
||||
assert(s.layers[1].layers[1] == l)
|
||||
end
|
||||
|
||||
do
|
||||
local s = Sprite(4, 4)
|
||||
-- 4 layers
|
||||
local a = s.layers[1] a.name = "a"
|
||||
local b = s:newLayer() b.name = "b"
|
||||
local c = s:newLayer() c.name = "c"
|
||||
local d = s:newLayer() d.name = "d"
|
||||
-- 3 groups
|
||||
local e = s:newGroup() e.name = "e"
|
||||
local f = s:newGroup() f.name = "f"
|
||||
local g = s:newGroup() g.name = "g"
|
||||
|
||||
e.parent = f
|
||||
a.parent = f
|
||||
b.parent = f
|
||||
c.parent = g
|
||||
d.parent = g
|
||||
|
||||
assert(#s.layers == 2)
|
||||
assert(s.layers[1] == f)
|
||||
assert(s.layers[2] == g)
|
||||
assert(s.layers["f"] == f)
|
||||
assert(s.layers["g"] == g)
|
||||
assert(f.stackIndex == 1)
|
||||
assert(g.stackIndex == 2)
|
||||
|
||||
assert(#f.layers == 3)
|
||||
assert(f.layers[1] == e)
|
||||
assert(f.layers[2] == a)
|
||||
assert(f.layers[3] == b)
|
||||
assert(f.layers["e"] == e)
|
||||
assert(f.layers["a"] == a)
|
||||
assert(f.layers["b"] == b)
|
||||
assert(e.stackIndex == 1)
|
||||
assert(a.stackIndex == 2)
|
||||
assert(b.stackIndex == 3)
|
||||
|
||||
assert(#g.layers == 2)
|
||||
assert(g.layers[1] == c)
|
||||
assert(g.layers[2] == d)
|
||||
assert(g.layers["c"] == c)
|
||||
assert(g.layers["d"] == d)
|
||||
assert(c.stackIndex == 1)
|
||||
assert(d.stackIndex == 2)
|
||||
|
||||
d.stackIndex = 1
|
||||
assert(d.stackIndex == 1)
|
||||
assert(c.stackIndex == 2)
|
||||
|
||||
d.stackIndex = 2
|
||||
assert(c.stackIndex == 1)
|
||||
assert(d.stackIndex == 2)
|
||||
|
||||
c.stackIndex = 2
|
||||
assert(d.stackIndex == 1)
|
||||
assert(c.stackIndex == 2)
|
||||
end
|
||||
|
||||
-- Test possible bugs with stackIndex
|
||||
do
|
||||
local s = Sprite(4, 4)
|
||||
local a = s.layers[1] a.name = "a"
|
||||
local b = s:newLayer() b.name = "b"
|
||||
local c = s:newLayer() c.name = "c"
|
||||
local d = s:newLayer() d.name = "d"
|
||||
assert(d.stackIndex == 4)
|
||||
assert(s.layers[4].name == "d")
|
||||
|
||||
d.stackIndex = d.stackIndex+1
|
||||
assert(d.stackIndex == 4)
|
||||
assert(s.layers[4].name == "d")
|
||||
|
||||
-- Go down in the stack
|
||||
d.stackIndex = d.stackIndex-1
|
||||
assert(s.layers[3].name == "d")
|
||||
|
||||
d.stackIndex = d.stackIndex-1
|
||||
assert(s.layers[2].name == "d")
|
||||
|
||||
-- Without change
|
||||
d.stackIndex = d.stackIndex
|
||||
assert(s.layers[2].name == "d")
|
||||
|
||||
-- Go up
|
||||
d.stackIndex = d.stackIndex+1
|
||||
assert(d.stackIndex == 3)
|
||||
assert(s.layers[3].name == "d")
|
||||
|
||||
d.stackIndex = d.stackIndex+1
|
||||
assert(d.stackIndex == 4)
|
||||
assert(s.layers[4].name == "d")
|
||||
|
||||
-- Go specific stack indexes
|
||||
for i=1,4 do
|
||||
d.stackIndex = i
|
||||
assert(d.stackIndex == i)
|
||||
assert(s.layers[i].name == "d")
|
||||
end
|
||||
end
|
||||
|
||||
-- Test crash because ActiveSiteHandler::onBeforeRemoveLayer() didn't
|
||||
-- update the selected range of layers correctly (i.e. removing
|
||||
-- deleted layer from the selected layers in the active range).
|
||||
do
|
||||
local s = Sprite(4, 4)
|
||||
local a = s:newGroup() a.name = "a"
|
||||
local b = s:newGroup() b.name = "b"
|
||||
local c = s:newGroup() c.name = "c"
|
||||
local ca = s:newGroup() ca.name = "ca"
|
||||
local cb = s:newGroup() cb.name = "cb"
|
||||
local d = s:newGroup() d.name = "d"
|
||||
|
||||
d.parent = ca
|
||||
ca.parent = c
|
||||
cb.parent = c
|
||||
c.parent = b
|
||||
b.parent = a
|
||||
|
||||
assert(#a.layers == 1)
|
||||
assert(#c.layers == 2)
|
||||
|
||||
app.range.layers = { b }
|
||||
app.command.RemoveLayer()
|
||||
assert(#a.layers == 0)
|
||||
app.undo()
|
||||
assert(#a.layers == 1)
|
||||
assert(#c.layers == 2)
|
||||
|
||||
-- Crash selecting a layer that was removed and then brought back to
|
||||
-- life with "undo"
|
||||
app.range.layers = { b }
|
||||
end
|
||||
|
||||
-- Test layer name bug when iterating over layers where names given to
|
||||
-- some layers are integers and also are valid ranges/indexes in the
|
||||
-- list of layers
|
||||
do
|
||||
local layerNames = { "2", "4", "Non-integer", "1" }
|
||||
local s = Sprite(4, 4)
|
||||
local layer1 = s.layers[1] layer1.name = layerNames[1]
|
||||
local layer2 = s:newLayer() layer2.name = layerNames[2]
|
||||
local layer3 = s:newLayer() layer3.name = layerNames[3]
|
||||
local layer4 = s:newLayer() layer4.name = layerNames[4]
|
||||
|
||||
local i = 1
|
||||
for index, layer in ipairs(app.activeSprite.layers) do
|
||||
assert(index == i)
|
||||
assert(layer.name == layerNames[i])
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
|
||||
-- Compare layers vs sprites (just return false)
|
||||
|
||||
do
|
||||
local s = Sprite(2, 2)
|
||||
assert(s.layers[1].parent == s)
|
||||
assert(s.layers[1] ~= s) -- Uses Layer_eq() to compare
|
||||
assert(s ~= s.layers[1]) -- Uses Sprite_eq() to compare
|
||||
end
|
10
tests/scripts/math.lua
Normal file
10
tests/scripts/math.lua
Normal file
@ -0,0 +1,10 @@
|
||||
-- Copyright (C) 2018 David Capello
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
assert(100 == math.abs(-100))
|
||||
assert(100 == math.min(100, 200, 300))
|
||||
assert(300 == math.max(100, 200, 300))
|
||||
assert(50 == math.fmod(250, 100))
|
||||
assert(3141 == math.floor(1000*math.pi))
|
27
tests/scripts/merge_down_bugs.lua
Normal file
27
tests/scripts/merge_down_bugs.lua
Normal file
@ -0,0 +1,27 @@
|
||||
-- Copyright (C) 2019 Igara Studio S.A.
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
local red = Color{ r=255, g=0, b=0 }
|
||||
local blue = Color{ r=0, g=0, b=255 }
|
||||
|
||||
-- Reproduces the bug reported in https://community.aseprite.org/t/2894
|
||||
do
|
||||
local s = Sprite(32, 32)
|
||||
local a = s.layers[1]
|
||||
app.useTool{ color=red, layer=a, points={ Point(2, 2) }}
|
||||
|
||||
local b = s:newLayer()
|
||||
app.useTool{ color=blue, layer=b, points={ Point(1, 1) }}
|
||||
|
||||
a.isContinuous = true
|
||||
b.isContinuous = true
|
||||
|
||||
app.command.NewFrame()
|
||||
app.activeLayer = b
|
||||
app.command.MergeDownLayer()
|
||||
|
||||
assert(#s.cels == 2)
|
||||
assert(s.cels[1].image:isEqual(s.cels[2].image))
|
||||
end
|
14
tests/scripts/os.lua
Normal file
14
tests/scripts/os.lua
Normal file
@ -0,0 +1,14 @@
|
||||
-- Copyright (C) 2018 David Capello
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
assert("" ~= os.getenv("PATH"))
|
||||
print("PATH", os.getenv("PATH"))
|
||||
|
||||
local start_clock = os.clock()
|
||||
print("Start ", start_clock)
|
||||
|
||||
local end_clock = os.clock()
|
||||
print("End ", end_clock, " Elapsed ", end_clock - start_clock)
|
||||
assert(start_clock < end_clock)
|
55
tests/scripts/paint_bucket.lua
Normal file
55
tests/scripts/paint_bucket.lua
Normal file
@ -0,0 +1,55 @@
|
||||
-- Copyright (C) 2020-2021 Igara Studio S.A.
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
dofile('./test_utils.lua')
|
||||
|
||||
app.activeTool = 'paint_bucket'
|
||||
assert(app.activeTool.id == 'paint_bucket')
|
||||
assert(app.activeBrush.type == BrushType.CIRCLE)
|
||||
assert(app.activeBrush.size == 1)
|
||||
assert(app.activeBrush.angle == 0)
|
||||
assert(app.preferences.tool('paint_bucket').floodfill.pixel_connectivity == 0)
|
||||
|
||||
local function test_paint_bucket(colorMode, a, b, c)
|
||||
local spr = Sprite(4, 4, colorMode)
|
||||
local img = app.activeImage
|
||||
|
||||
array_to_pixels({ a, a, a, a,
|
||||
a, b, b, a,
|
||||
a, a, b, a,
|
||||
a, a, a, b, }, img)
|
||||
|
||||
app.useTool{ points={Point(0, 0)}, color=b }
|
||||
expect_img(img, { b, b, b, b,
|
||||
b, b, b, b,
|
||||
b, b, b, b,
|
||||
b, b, b, b, })
|
||||
|
||||
app.undo()
|
||||
-- FOUR_CONNECTED=0
|
||||
app.preferences.tool('paint_bucket').floodfill.pixel_connectivity = 0
|
||||
assert(app.preferences.tool('paint_bucket').floodfill.pixel_connectivity == 0)
|
||||
app.useTool{ points={Point(1, 1)}, color=c }
|
||||
expect_img(img, { a, a, a, a,
|
||||
a, c, c, a,
|
||||
a, a, c, a,
|
||||
a, a, a, b, })
|
||||
|
||||
app.undo()
|
||||
-- EIGHT_CONNECTED=1
|
||||
app.preferences.tool('paint_bucket').floodfill.pixel_connectivity = 1
|
||||
assert(app.preferences.tool('paint_bucket').floodfill.pixel_connectivity == 1)
|
||||
app.useTool{ points={Point(1, 1)}, color=c }
|
||||
expect_img(img, { a, a, a, a,
|
||||
a, c, c, a,
|
||||
a, a, c, a,
|
||||
a, a, a, c, })
|
||||
end
|
||||
|
||||
local rgba = app.pixelColor.rgba
|
||||
local gray = app.pixelColor.graya
|
||||
test_paint_bucket(ColorMode.RGB, rgba(0, 0, 0), rgba(128, 128, 128), rgba(255, 255, 255))
|
||||
test_paint_bucket(ColorMode.GRAYSCALE, gray(0), gray(128), gray(255))
|
||||
test_paint_bucket(ColorMode.INDEXED, 1, 2, 3)
|
87
tests/scripts/palette.lua
Normal file
87
tests/scripts/palette.lua
Normal file
@ -0,0 +1,87 @@
|
||||
-- Copyright (C) 2019 Igara Studio S.A.
|
||||
-- Copyright (C) 2018 David Capello
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
do
|
||||
local p = Palette()
|
||||
assert(#p == 256)
|
||||
for i = 0,#p-1 do
|
||||
assert(p:getColor(i) == Color(0, 0, 0))
|
||||
end
|
||||
end
|
||||
|
||||
do
|
||||
local p = Palette(32)
|
||||
assert(#p == 32)
|
||||
for i = 0,#p-1 do
|
||||
assert(p:getColor(i) == Color(0, 0, 0))
|
||||
end
|
||||
|
||||
p:resize(4)
|
||||
assert(#p == 4)
|
||||
p:setColor(0, Color(255, 8, 32))
|
||||
p:setColor(1, Color(250, 4, 30))
|
||||
p:setColor(2, Color(240, 3, 20))
|
||||
p:setColor(3, Color(210, 2, 10))
|
||||
assert(p:getColor(0) == Color(255, 8, 32))
|
||||
assert(p:getColor(1) == Color(250, 4, 30))
|
||||
assert(p:getColor(2) == Color(240, 3, 20))
|
||||
assert(p:getColor(3) == Color(210, 2, 10))
|
||||
|
||||
-- Check alpha
|
||||
local c = Color{red=100, green=50, blue=10, alpha=128}
|
||||
p:setColor(3, c)
|
||||
assert(p:getColor(3) == c)
|
||||
assert(p:getColor(3).alpha == 128)
|
||||
end
|
||||
|
||||
-- Load/save
|
||||
do
|
||||
local p = Palette{ fromFile="sprites/abcd.aseprite" }
|
||||
assert(#p == 5)
|
||||
assert(p:getColor(0) == Color(0, 0, 0))
|
||||
assert(p:getColor(1) == Color(25, 0, 255))
|
||||
assert(p:getColor(2) == Color(255, 0, 0))
|
||||
assert(p:getColor(3) == Color(255, 255, 0))
|
||||
assert(p:getColor(4) == Color(0, 128, 0))
|
||||
|
||||
p:saveAs("_test_.gpl")
|
||||
|
||||
local q = Palette{ fromFile="_test_.gpl" }
|
||||
assert(#p == #q)
|
||||
for i=0,#q-1 do
|
||||
assert(p:getColor(i) == q:getColor(i))
|
||||
end
|
||||
end
|
||||
|
||||
-- Default palette and resources
|
||||
do
|
||||
local db16 = Palette{ fromResource="DB16" }
|
||||
local db32 = Palette{ fromResource="DB32" }
|
||||
|
||||
assert(#db16 == 16)
|
||||
assert(#db32 == 32)
|
||||
assert(db32:getColor(0) == Color(0, 0, 0))
|
||||
assert(db32:getColor(31) == Color(138, 111, 48))
|
||||
|
||||
assert(app.defaultPalette == db32)
|
||||
|
||||
app.defaultPalette = db16
|
||||
assert(app.defaultPalette == db16)
|
||||
|
||||
-- Default sprite palette is completely black
|
||||
-- TODO should we use the app.defaultPalette as the default palette?
|
||||
local spr = Sprite(32, 32, ColorMode.INDEXED)
|
||||
local sprPal = spr.palettes[1];
|
||||
assert(#sprPal == 256)
|
||||
assert(sprPal ~= db16)
|
||||
assert(sprPal ~= db32)
|
||||
for i=0,255 do
|
||||
assert(sprPal:getColor(i) == Color(0, 0,0))
|
||||
end
|
||||
|
||||
spr:setPalette(db32)
|
||||
assert(sprPal == db32)
|
||||
end
|
361
tests/scripts/pixel_perfect.lua
Normal file
361
tests/scripts/pixel_perfect.lua
Normal file
@ -0,0 +1,361 @@
|
||||
-- Copyright (C) 2019-2021 Igara Studio S.A.
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
dofile('./test_utils.lua')
|
||||
|
||||
local spr = Sprite(6, 6)
|
||||
local cel = spr.cels[1]
|
||||
|
||||
-- Point size 1px, solid color, no symmetry, no tiled mode
|
||||
do
|
||||
local title = '1px, solid, no symmetry, no tiled'
|
||||
local red = Color{ r=255, g=0, b=0 }
|
||||
local r = red.rgbaPixel
|
||||
local pixel=Brush{ size=1, type=BrushType.CIRCLE }
|
||||
local testData = {
|
||||
{
|
||||
id='1 - ' .. title .. ': right then down',
|
||||
points={ Point(2, 2), Point(3, 2), Point(3, 3) },
|
||||
expected={ r, 0,
|
||||
0, r }
|
||||
},
|
||||
{
|
||||
id='2 - ' .. title .. ': down then right',
|
||||
points={ Point(2, 2), Point(2, 3), Point(3, 3) },
|
||||
expected={ r, 0,
|
||||
0, r }
|
||||
},
|
||||
{
|
||||
id='3 - ' .. title .. ': left then up',
|
||||
points={ Point(2, 2), Point(1, 2), Point(1, 1) },
|
||||
expected={ r, 0,
|
||||
0, r }
|
||||
},
|
||||
{
|
||||
id='4 - ' .. title .. ': up then left',
|
||||
points={ Point(2, 2), Point(2, 1), Point(1, 1) },
|
||||
expected={ r, 0,
|
||||
0, r }
|
||||
}
|
||||
}
|
||||
|
||||
for i,v in ipairs(testData) do
|
||||
app.useTool{
|
||||
tool='pencil',
|
||||
freehandAlgorithm=1,
|
||||
brush=pixel,
|
||||
color=red,
|
||||
points=v.points}
|
||||
expect_img_msg(cel.image, v.expected, '\nTest \'' .. v.id .. '\' failed')
|
||||
cel.image:clear(0)
|
||||
end
|
||||
end
|
||||
|
||||
-- Point size 2px, translucent color, no symmetry, no tiled mode
|
||||
do
|
||||
local title = '2px, translucent, no symmetry, no tiled'
|
||||
local red = Color{ r=255, g=0, b=0, a=127 }
|
||||
local r = red.rgbaPixel
|
||||
local square=Brush{ size=2, type=BrushType.SQUARE }
|
||||
local testData = {
|
||||
{
|
||||
id='1 - ' .. title .. ': right then down',
|
||||
points={ Point(2, 2), Point(3, 2), Point(3, 3) },
|
||||
expected={ r, r, 0,
|
||||
r, r, r,
|
||||
0, r, r }
|
||||
},
|
||||
{
|
||||
id='2 - ' .. title .. ': down then right',
|
||||
points={ Point(2, 2), Point(2, 3), Point(3, 3) },
|
||||
expected={ r, r, 0,
|
||||
r, r, r,
|
||||
0, r, r }
|
||||
},
|
||||
{
|
||||
id='3 - ' .. title .. ': left then up',
|
||||
points={ Point(2, 2), Point(1, 2), Point(1, 1) },
|
||||
expected={ r, r, 0,
|
||||
r, r, r,
|
||||
0, r, r }
|
||||
},
|
||||
{
|
||||
id='4 - ' .. title .. ': up then left',
|
||||
points={ Point(2, 2), Point(2, 1), Point(1, 1) },
|
||||
expected={ r, r, 0,
|
||||
r, r, r,
|
||||
0, r, r }
|
||||
}
|
||||
}
|
||||
|
||||
for i,v in ipairs(testData) do
|
||||
app.useTool{
|
||||
tool='pencil',
|
||||
freehandAlgorithm=1,
|
||||
brush=square,
|
||||
color=red,
|
||||
points=v.points}
|
||||
expect_img_msg(cel.image, v.expected, '\nTest \'' .. v.id .. '\' failed')
|
||||
cel.image:clear(0)
|
||||
end
|
||||
end
|
||||
|
||||
-- Point size 2px, translucent color, symmetry, no tiled mode
|
||||
do
|
||||
local pref = app.preferences
|
||||
local docPref = pref.document(spr)
|
||||
pref.symmetry_mode.enabled = true
|
||||
docPref.symmetry.mode = 3
|
||||
docPref.symmetry.x_axis = 3
|
||||
docPref.symmetry.y_axis = 3
|
||||
|
||||
local title = '2px, translucent, symmetry on, no tiled'
|
||||
local red = Color{ r=255, g=0, b=0, a=127 }
|
||||
local r = red.rgbaPixel
|
||||
local square=Brush{ size=2, type=BrushType.SQUARE }
|
||||
local testData = {
|
||||
{
|
||||
id='1 - ' .. title .. ': right then down',
|
||||
points={ Point(1, 1), Point(2, 1), Point(2, 2) },
|
||||
expected={ r, r, 0, 0, r, r,
|
||||
r, r, r, r, r, r,
|
||||
0, r, r, r, r, 0,
|
||||
0, r, r, r, r, 0,
|
||||
r, r, r, r, r, r,
|
||||
r, r, 0, 0, r, r }
|
||||
},
|
||||
{
|
||||
id='2 - ' .. title .. ': down then right',
|
||||
points={ Point(1, 1), Point(1, 2), Point(2, 2) },
|
||||
expected={ r, r, 0, 0, r, r,
|
||||
r, r, r, r, r, r,
|
||||
0, r, r, r, r, 0,
|
||||
0, r, r, r, r, 0,
|
||||
r, r, r, r, r, r,
|
||||
r, r, 0, 0, r, r }
|
||||
},
|
||||
{
|
||||
id='3 - ' .. title .. ': left then up',
|
||||
points={ Point(2, 2), Point(1, 2), Point(1, 1) },
|
||||
expected={ r, r, 0, 0, r, r,
|
||||
r, r, r, r, r, r,
|
||||
0, r, r, r, r, 0,
|
||||
0, r, r, r, r, 0,
|
||||
r, r, r, r, r, r,
|
||||
r, r, 0, 0, r, r }
|
||||
},
|
||||
{
|
||||
id='4 - ' .. title .. ': up then left',
|
||||
points={ Point(2, 2), Point(2, 1), Point(1, 1) },
|
||||
expected={ r, r, 0, 0, r, r,
|
||||
r, r, r, r, r, r,
|
||||
0, r, r, r, r, 0,
|
||||
0, r, r, r, r, 0,
|
||||
r, r, r, r, r, r,
|
||||
r, r, 0, 0, r, r }
|
||||
}
|
||||
}
|
||||
|
||||
for i,v in ipairs(testData) do
|
||||
app.useTool{
|
||||
tool='pencil',
|
||||
freehandAlgorithm=1,
|
||||
brush=square,
|
||||
color=red,
|
||||
points=v.points}
|
||||
expect_img_msg(cel.image, v.expected, '\nTest \'' .. v.id .. '\' failed')
|
||||
cel.image:clear(0)
|
||||
end
|
||||
end
|
||||
|
||||
-- Point size 2px, translucent color, no symmetry, tiled mode on
|
||||
do
|
||||
local pref = app.preferences
|
||||
local docPref = pref.document(spr)
|
||||
pref.symmetry_mode.enabled = false
|
||||
docPref.tiled.mode = 3
|
||||
|
||||
local title = '2px, translucent, no symmetry, tiled'
|
||||
local red = Color{ r=255, g=0, b=0, a=127 }
|
||||
local r = red.rgbaPixel
|
||||
local square=Brush{ size=2, type=BrushType.SQUARE }
|
||||
local testData = {
|
||||
-- Top left corner
|
||||
{
|
||||
id='1 - ' .. title .. ': on top left corner, right then down',
|
||||
points={ Point(0, 0), Point(1, 0), Point(1, 1) },
|
||||
expected={ r, r, 0, 0, 0, r,
|
||||
r, r, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
r, 0, 0, 0, 0, r }
|
||||
},
|
||||
{
|
||||
id='2 - ' .. title .. ': on top left corner, down then right',
|
||||
points={ Point(0, 0), Point(0, 1), Point(1, 1) },
|
||||
expected={ r, r, 0, 0, 0, r,
|
||||
r, r, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
r, 0, 0, 0, 0, r }
|
||||
},
|
||||
{
|
||||
id='3 - ' .. title .. ': on top left corner, left then up',
|
||||
points={ Point(0, 0), Point(-1, 0), Point(-1, -1) },
|
||||
expected={ r, 0, 0, 0, 0, r,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, r, r,
|
||||
r, 0, 0, 0, r, r }
|
||||
},
|
||||
{
|
||||
id='4 - ' .. title .. ': on top left corner, up then left',
|
||||
points={ Point(0, 0), Point(0, -1), Point(-1, -1) },
|
||||
expected={ r, 0, 0, 0, 0, r,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, r, r,
|
||||
r, 0, 0, 0, r, r }
|
||||
},
|
||||
-- Top right corner
|
||||
{
|
||||
id='5 - ' .. title .. ': on top right corner, right then down',
|
||||
points={ Point(6, 0), Point(7, 0), Point(7, 1) },
|
||||
expected={ r, r, 0, 0, 0, r,
|
||||
r, r, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
r, 0, 0, 0, 0, r }
|
||||
},
|
||||
{
|
||||
id='6 - ' .. title .. ': on top right corner, down then right',
|
||||
points={ Point(6, 0), Point(6, 1), Point(7, 1) },
|
||||
expected={ r, r, 0, 0, 0, r,
|
||||
r, r, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
r, 0, 0, 0, 0, r }
|
||||
},
|
||||
{
|
||||
id='7 - ' .. title .. ': on top right corner, left then up',
|
||||
points={ Point(6, 0), Point(5, 0), Point(5, -1) },
|
||||
expected={ r, 0, 0, 0, 0, r,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, r, r,
|
||||
r, 0, 0, 0, r, r }
|
||||
},
|
||||
{
|
||||
id='8 - ' .. title .. ': on top right corner, up then left',
|
||||
points={ Point(6, 0), Point(5, 0), Point(5, -1) },
|
||||
expected={ r, 0, 0, 0, 0, r,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, r, r,
|
||||
r, 0, 0, 0, r, r }
|
||||
},
|
||||
-- Bottom left corner
|
||||
{
|
||||
id='9 - ' .. title .. ': on bottom left corner, right then down',
|
||||
points={ Point(0, 6), Point(1, 6), Point(1, 7) },
|
||||
expected={ r, r, 0, 0, 0, r,
|
||||
r, r, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
r, 0, 0, 0, 0, r }
|
||||
},
|
||||
{
|
||||
id='10 - ' .. title .. ': on bottom left corner, down then right',
|
||||
points={ Point(0, 6), Point(0, 7), Point(1, 7) },
|
||||
expected={ r, r, 0, 0, 0, r,
|
||||
r, r, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
r, 0, 0, 0, 0, r }
|
||||
},
|
||||
{
|
||||
id='11 - ' .. title .. ': on bottom left corner, left then up',
|
||||
points={ Point(0, 6), Point(-1, 6), Point(-1, 5) },
|
||||
expected={ r, 0, 0, 0, 0, r,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, r, r,
|
||||
r, 0, 0, 0, r, r }
|
||||
},
|
||||
{
|
||||
id='12 - ' .. title .. ': on bottom left corner, up then left',
|
||||
points={ Point(0, 6), Point(0, 5), Point(-1, 5) },
|
||||
expected={ r, 0, 0, 0, 0, r,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, r, r,
|
||||
r, 0, 0, 0, r, r }
|
||||
},
|
||||
-- Botomm right corner
|
||||
{
|
||||
id='13 - ' .. title .. ': on bottom right corner, right then down',
|
||||
points={ Point(6, 6), Point(7, 6), Point(7, 7) },
|
||||
expected={ r, r, 0, 0, 0, r,
|
||||
r, r, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
r, 0, 0, 0, 0, r }
|
||||
},
|
||||
{
|
||||
id='14 - ' .. title .. ': on bottom right corner, down then right',
|
||||
points={ Point(6, 6), Point(6, 7), Point(7, 7) },
|
||||
expected={ r, r, 0, 0, 0, r,
|
||||
r, r, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
r, 0, 0, 0, 0, r }
|
||||
},
|
||||
{
|
||||
id='15 - ' .. title .. ': on bottom right corner, left then up',
|
||||
points={ Point(6, 6), Point(5, 6), Point(5, 5) },
|
||||
expected={ r, 0, 0, 0, 0, r,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, r, r,
|
||||
r, 0, 0, 0, r, r }
|
||||
},
|
||||
{
|
||||
id='16 - ' .. title .. ': on bottom right corner, up then left',
|
||||
points={ Point(6, 6), Point(6, 5), Point(5, 5) },
|
||||
expected={ r, 0, 0, 0, 0, r,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, r, r,
|
||||
r, 0, 0, 0, r, r }
|
||||
},
|
||||
}
|
||||
|
||||
for i,v in ipairs(testData) do
|
||||
app.useTool{
|
||||
tool='pencil',
|
||||
freehandAlgorithm=1,
|
||||
brush=square,
|
||||
color=red,
|
||||
points=v.points}
|
||||
expect_img_msg(cel.image, v.expected, '\nTest \'' .. v.id .. '\' failed')
|
||||
cel.image:clear(0)
|
||||
end
|
||||
end
|
75
tests/scripts/point.lua
Normal file
75
tests/scripts/point.lua
Normal file
@ -0,0 +1,75 @@
|
||||
-- Copyright (C) 2019 Igara Studio S.A.
|
||||
-- Copyright (C) 2018 David Capello
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
local pt = Point()
|
||||
assert(pt.x == 0)
|
||||
assert(pt.y == 0)
|
||||
|
||||
pt = Point(1, 2)
|
||||
assert(pt.x == 1)
|
||||
assert(pt.y == 2)
|
||||
assert("Point{ x=1, y=2 }" == tostring(pt))
|
||||
|
||||
local pt2 = Point(pt)
|
||||
assert(pt2.x == 1)
|
||||
assert(pt2.y == 2)
|
||||
|
||||
pt.x = 5
|
||||
pt.y = 6
|
||||
assert(pt.x == 5)
|
||||
assert(pt.y == 6)
|
||||
|
||||
pt = Point{x=10, y=20}
|
||||
assert(pt.x == 10)
|
||||
assert(pt.y == 20)
|
||||
|
||||
pt = Point{45, 25}
|
||||
assert(pt.x == 45)
|
||||
assert(pt.y == 25)
|
||||
|
||||
pt = -pt
|
||||
assert(pt.x == -45)
|
||||
assert(pt.y == -25)
|
||||
|
||||
-- add/sub/mul/div/mod/pow/idiv
|
||||
|
||||
pt = Point(1, 2) + 4
|
||||
pt2 = 4 + Point(1, 2)
|
||||
assert(pt.x == 5)
|
||||
assert(pt.y == 6)
|
||||
assert(pt == pt2)
|
||||
|
||||
pt = Point(1, 2) + Point(3, 4)
|
||||
assert(pt.x == 4)
|
||||
assert(pt.y == 6)
|
||||
|
||||
pt = Point(3, 4) - 1
|
||||
assert(pt.x == 2)
|
||||
assert(pt.y == 3)
|
||||
|
||||
pt = Point(1, 5) - Point(3, 2)
|
||||
assert(pt.x == -2)
|
||||
assert(pt.y == 3)
|
||||
|
||||
pt = Point(6, 10) * 2
|
||||
assert(pt.x == 12)
|
||||
assert(pt.y == 20)
|
||||
|
||||
pt = Point(6, 10) / 2
|
||||
assert(pt.x == 3)
|
||||
assert(pt.y == 5)
|
||||
|
||||
pt = Point(10, 5) % 2
|
||||
assert(pt.x == 0)
|
||||
assert(pt.y == 1)
|
||||
|
||||
pt = Point(2, 5) ^ 2
|
||||
assert(pt.x == 4)
|
||||
assert(pt.y == 25)
|
||||
|
||||
pt = Point(31, 10) // 3
|
||||
assert(pt.x == 10)
|
||||
assert(pt.y == 3)
|
10
tests/scripts/print_on_gc.lua
Normal file
10
tests/scripts/print_on_gc.lua
Normal file
@ -0,0 +1,10 @@
|
||||
-- Copyright (C) 2019 Igara Studio S.A.
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
-- Create global variable which will be GC'd on lua_close()
|
||||
a = { }
|
||||
|
||||
-- Call print() on __gc, in previous version this produced a crash at exit
|
||||
setmetatable(a, { __gc=function() print('gc') end })
|
118
tests/scripts/range.lua
Normal file
118
tests/scripts/range.lua
Normal file
@ -0,0 +1,118 @@
|
||||
-- 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.
|
||||
|
||||
do
|
||||
-- Three layers
|
||||
local s = Sprite(32, 32)
|
||||
assert(#s.layers == 1)
|
||||
|
||||
app.activeCel = s.cels[1]
|
||||
|
||||
local r = app.range
|
||||
assert(#r.layers == 1)
|
||||
assert(#r.frames == 1)
|
||||
assert(#r.cels == 1)
|
||||
assert(r.layers[1] == s.layers[1])
|
||||
assert(r.frames[1] == s.frames[1])
|
||||
assert(r.cels[1] == s.cels[1])
|
||||
|
||||
s:newLayer()
|
||||
assert(#s.layers == 2)
|
||||
|
||||
local r = app.range
|
||||
assert(#r.layers == 1)
|
||||
assert(#r.frames == 1)
|
||||
assert(#r.cels == 0)
|
||||
assert(r.layers[1] == s.layers[2])
|
||||
assert(r.frames[1] == s.frames[1])
|
||||
end
|
||||
|
||||
-- Test app.range.colors
|
||||
do
|
||||
assert(#app.range.colors == 0)
|
||||
app.range.colors = { 2 }
|
||||
assert(#app.range.colors == 1)
|
||||
assert(app.range.colors[1] == 2)
|
||||
app.range.colors = { 1, 4 }
|
||||
assert(#app.range.colors == 2)
|
||||
assert(app.range.colors[1] == 1)
|
||||
assert(app.range.colors[2] == 4)
|
||||
app.range.colors = { 5, 2, 10, 8, 0 }
|
||||
assert(#app.range.colors == 5)
|
||||
-- app.range.colors are always sorted by color index
|
||||
assert(app.range.colors[1] == 0)
|
||||
assert(app.range.colors[2] == 2)
|
||||
assert(app.range.colors[3] == 5)
|
||||
assert(app.range.colors[4] == 8)
|
||||
assert(app.range.colors[5] == 10)
|
||||
assert(app.range:containsColor(0))
|
||||
assert(not app.range:containsColor(1))
|
||||
assert(app.range:containsColor(2))
|
||||
assert(app.range:containsColor(5))
|
||||
assert(app.range:containsColor(8))
|
||||
assert(app.range:containsColor(10))
|
||||
end
|
||||
|
||||
-- Test setters
|
||||
do
|
||||
local spr = Sprite(32, 32)
|
||||
local lay1 = spr.layers[1]
|
||||
local r = app.range
|
||||
assert(r.type == RangeType.EMPTY)
|
||||
assert(#r.layers == 1)
|
||||
assert(#r.frames == 1)
|
||||
assert(r.layers[1] == lay1)
|
||||
assert(r.frames[1].frameNumber == 1)
|
||||
|
||||
local lay2 = spr:newLayer()
|
||||
r = app.range
|
||||
assert(r.type == RangeType.EMPTY)
|
||||
assert(#r.layers == 1)
|
||||
assert(#r.frames == 1)
|
||||
assert(r.layers[1] == lay2)
|
||||
assert(r.frames[1].frameNumber == 1)
|
||||
|
||||
r.layers = { lay1, lay2 }
|
||||
assert(r.type == RangeType.LAYERS)
|
||||
assert(#r.layers == 2)
|
||||
assert(#r.frames == 1)
|
||||
assert(r.layers[1] == lay1)
|
||||
assert(r.layers[2] == lay2)
|
||||
assert(r.frames[1].frameNumber == 1)
|
||||
|
||||
spr:newFrame()
|
||||
spr:newFrame()
|
||||
r.frames = { 1, 3 }
|
||||
assert(r.type == RangeType.FRAMES)
|
||||
assert(#r.layers == 2)
|
||||
assert(#r.frames == 2)
|
||||
assert(r.layers[1] == lay1)
|
||||
assert(r.layers[2] == lay2)
|
||||
assert(r.frames[1].frameNumber == 1)
|
||||
assert(r.frames[2].frameNumber == 3)
|
||||
|
||||
r.layers = { lay2 }
|
||||
assert(r.type == RangeType.LAYERS)
|
||||
assert(#r.layers == 1)
|
||||
assert(#r.frames == 2)
|
||||
assert(r.layers[1] == lay2)
|
||||
assert(r.frames[1].frameNumber == 1)
|
||||
assert(r.frames[2].frameNumber == 3)
|
||||
|
||||
-- Clear range
|
||||
r:clear()
|
||||
assert(r.type == RangeType.EMPTY)
|
||||
assert(#r.layers == 1)
|
||||
assert(#r.frames == 1)
|
||||
assert(r.layers[1] == app.activeLayer)
|
||||
assert(r.frames[1] == app.activeFrame)
|
||||
|
||||
-- Check that Range:clear() reset the selected colors
|
||||
r.colors = { 2 }
|
||||
assert(#r.colors == 1)
|
||||
assert(r.colors[1] == 2)
|
||||
r:clear()
|
||||
assert(#r.colors == 0)
|
||||
end
|
72
tests/scripts/rectangle.lua
Normal file
72
tests/scripts/rectangle.lua
Normal file
@ -0,0 +1,72 @@
|
||||
-- Copyright (C) 2019 Igara Studio S.A.
|
||||
-- Copyright (C) 2018 David Capello
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
local rc = Rectangle()
|
||||
assert(rc.x == 0)
|
||||
assert(rc.y == 0)
|
||||
assert(rc.width == 0)
|
||||
assert(rc.height == 0)
|
||||
assert(rc.isEmpty)
|
||||
|
||||
rc = Rectangle(1, 2, 3, 4)
|
||||
assert(rc.x == 1)
|
||||
assert(rc.y == 2)
|
||||
assert(rc.width == 3)
|
||||
assert(rc.height == 4)
|
||||
assert(not rc.isEmpty)
|
||||
assert("Rectangle{ x=1, y=2, width=3, height=4 }" == tostring(rc))
|
||||
|
||||
local rc2 = Rectangle(rc)
|
||||
assert(rc2.x == 1)
|
||||
assert(rc2.y == 2)
|
||||
assert(rc2.width == 3)
|
||||
assert(rc2.height == 4)
|
||||
|
||||
rc.x = 5;
|
||||
rc.y = 6;
|
||||
rc.width = 7;
|
||||
rc.height = 8;
|
||||
assert(rc.x == 5)
|
||||
assert(rc.y == 6)
|
||||
assert(rc.width == 7)
|
||||
assert(rc.height == 8)
|
||||
|
||||
rc = Rectangle{x=2, y=3, width=4, height=5}
|
||||
assert(rc.x == 2)
|
||||
assert(rc.y == 3)
|
||||
assert(rc.width == 4)
|
||||
assert(rc.height == 5)
|
||||
|
||||
rc = Rectangle{6, 7, 8, 9}
|
||||
assert(rc.x == 6)
|
||||
assert(rc.y == 7)
|
||||
assert(rc.width == 8)
|
||||
assert(rc.height == 9)
|
||||
|
||||
-- Rectangle:contains
|
||||
|
||||
local a = Rectangle{x=2, y=3, width=4, height=5}
|
||||
local b = Rectangle{x=3, y=4, width=1, height=1}
|
||||
assert(a:contains(b))
|
||||
assert(not b:contains(a))
|
||||
|
||||
-- Rectangle:intersect
|
||||
|
||||
assert(a:intersects(b))
|
||||
assert(b == a:intersect(b))
|
||||
|
||||
a = Rectangle{x=2, y=3, width=4, height=5}
|
||||
b = Rectangle{x=3, y=4, width=4, height=5}
|
||||
c = Rectangle{x=3, y=4, width=3, height=4}
|
||||
assert(c == a:intersect(b))
|
||||
assert(c == b:intersect(a))
|
||||
assert((a & b) == c)
|
||||
|
||||
-- Rectangle:union
|
||||
|
||||
c = Rectangle{x=2, y=3, width=5, height=6}
|
||||
assert(c == a:union(b))
|
||||
assert(c == (a | b))
|
142
tests/scripts/save_file_command.lua
Normal file
142
tests/scripts/save_file_command.lua
Normal file
@ -0,0 +1,142 @@
|
||||
-- Copyright (C) 2022 Igara Studio S.A.
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
function fix_test_img(testImg, scale, fileExt, cm, c1)
|
||||
-- With file formats that don't support alpha channel, we
|
||||
-- compare totally transparent pixels (alpha=0) with black.
|
||||
if fileExt == "tga" and cm == ColorMode.GRAYSCALE then
|
||||
local pixel
|
||||
if cm == ColorMode.RGB then
|
||||
pixel = c1.rgbaPixel
|
||||
elseif cm == ColorMode.GRAYSCALE then
|
||||
pixel = c1.grayPixel
|
||||
else
|
||||
pixel = 0 -- Do nothing in indexed
|
||||
end
|
||||
for p in testImg:pixels() do
|
||||
if p() == 0 then p(pixel) end
|
||||
end
|
||||
end
|
||||
testImg:resize(testImg.width*scale, testImg.height*scale)
|
||||
end
|
||||
|
||||
for _,cm in ipairs{ ColorMode.RGB,
|
||||
ColorMode.GRAYSCALE,
|
||||
ColorMode.INDEXED } do
|
||||
local spr = Sprite(32, 32, cm)
|
||||
spr.palettes[1]:resize(3)
|
||||
spr.palettes[1]:setColor(0, Color(0, 0, 0, 0))
|
||||
spr.palettes[1]:setColor(1, Color(0, 0, 0, 255))
|
||||
spr.palettes[1]:setColor(2, Color(255, 0, 0, 255))
|
||||
|
||||
local c1, c2
|
||||
if cm == ColorMode.RGB then
|
||||
c1 = Color(0, 0, 0)
|
||||
c2 = Color(255, 0, 0)
|
||||
elseif cm == ColorMode.GRAYSCALE then
|
||||
c1 = Color{ gray=0 }
|
||||
c2 = Color{ gray=255 }
|
||||
elseif cm == ColorMode.INDEXED then
|
||||
c1 = 1
|
||||
c2 = 2
|
||||
end
|
||||
|
||||
app.useTool{ color=c1, brush=Brush(1),
|
||||
tool="filled_ellipse", points={{0,0},{31,31}} }
|
||||
app.useTool{ color=c2, brush=Brush(1),
|
||||
tool="filled_ellipse", points={{4,4},{27,27}} }
|
||||
spr.filename = "_test_a.aseprite"
|
||||
|
||||
app.command.SaveFile()
|
||||
assert(spr.filename == "_test_a.aseprite")
|
||||
|
||||
app.command.SaveFileAs{ filename="_test_b.png" }
|
||||
assert(spr.filename == "_test_b.png")
|
||||
|
||||
app.command.SaveFileCopyAs{ filename="_test_c.png" }
|
||||
assert(spr.filename == "_test_b.png")
|
||||
|
||||
-- Scale
|
||||
for _,fn in ipairs{ "_test_c_scaled.png",
|
||||
"_test_c_scaled.gif",
|
||||
"_test_c_scaled.fli",
|
||||
"_test_c_scaled.tga",
|
||||
"_test_c_scaled.bmp" } do
|
||||
local fileExt = app.fs.fileExtension(fn)
|
||||
|
||||
-- TODO support saving any color mode to FLI files on the fly
|
||||
if (fileExt ~= "fli" or cm == ColorMode.INDEXED) and
|
||||
-- TODO Review grayscale support in bmp files
|
||||
(fileExt ~= "bmp" or cm ~= ColorMode.GRAYSCALE) then
|
||||
for _,scale in ipairs({ 1, 2, 3, 4 }) do
|
||||
print(fn, scale, cm)
|
||||
|
||||
app.activeSprite = spr
|
||||
app.command.SaveFileCopyAs{ filename=fn, scale=scale }
|
||||
local c = app.open(fn)
|
||||
assert(c.width == spr.width*scale)
|
||||
assert(c.height == spr.height*scale)
|
||||
|
||||
-- GIF file is loaded as indexed, so we have to convert from
|
||||
-- indexed to the ColorMode
|
||||
if c.colorMode ~= cm then
|
||||
assert(fileExt == "gif" or fileExt == "bmp")
|
||||
|
||||
if cm == ColorMode.RGB then
|
||||
app.activeSprite = c
|
||||
app.command.ChangePixelFormat{ format="rgb" }
|
||||
elseif cm == ColorMode.GRAYSCALE then
|
||||
app.activeSprite = c
|
||||
app.command.ChangePixelFormat{ format="grayscale" }
|
||||
else
|
||||
assert(false)
|
||||
end
|
||||
end
|
||||
|
||||
local testImg = Image(spr.cels[1].image)
|
||||
fix_test_img(testImg, scale, fileExt, cm, c1)
|
||||
if not c.cels[1].image:isEqual(testImg) then
|
||||
c.cels[1].image:saveAs("_testA.png")
|
||||
testImg:saveAs("_testB.png")
|
||||
end
|
||||
assert(c.cels[1].image.colorMode == testImg.colorMode)
|
||||
assert(c.cels[1].image:isEqual(testImg))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Scale + Slices
|
||||
local slice = spr:newSlice(Rectangle(1, 2, 8, 15))
|
||||
slice.name = "small_slice"
|
||||
for _,fn in ipairs({ "_test_c_small_slice.png",
|
||||
-- TODO slices aren't supported in gif/fli yet
|
||||
--"_test_c_small_slice.gif",
|
||||
--"_test_c_small_slice.fli",
|
||||
"_test_c_small_slice.tga",
|
||||
"_test_c_small_slice.bmp" }) do
|
||||
local fileExt = app.fs.fileExtension(fn)
|
||||
|
||||
if (fileExt ~= "bmp" or cm ~= ColorMode.GRAYSCALE) then
|
||||
for _,scale in ipairs({ 1, 2, 3, 4 }) do
|
||||
print(fn, scale, cm)
|
||||
|
||||
app.activeSprite = spr
|
||||
app.command.SaveFileCopyAs{ filename=fn, slice="small_slice", scale=scale }
|
||||
local c = app.open(fn)
|
||||
assert(c.width == slice.bounds.width*scale)
|
||||
assert(c.height == slice.bounds.height*scale)
|
||||
|
||||
local testImg = Image(spr.cels[1].image, spr.slices[1].bounds)
|
||||
fix_test_img(testImg, scale, fileExt, cm, c1)
|
||||
if not c.cels[1].image:isEqual(testImg) then
|
||||
c.cels[1].image:saveAs("_testA.png")
|
||||
testImg:saveAs("_testB.png")
|
||||
end
|
||||
assert(c.cels[1].image:isEqual(testImg))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
121
tests/scripts/selection.lua
Normal file
121
tests/scripts/selection.lua
Normal file
@ -0,0 +1,121 @@
|
||||
-- Copyright (C) 2018 David Capello
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
-- Isolated selection
|
||||
do
|
||||
local a = Selection()
|
||||
assert(a.bounds.x == 0)
|
||||
assert(a.bounds.y == 0)
|
||||
assert(a.bounds.width == 0)
|
||||
assert(a.bounds.height == 0)
|
||||
assert(a.isEmpty)
|
||||
|
||||
a:select(1, 2, 3, 4)
|
||||
assert(a.bounds.x == 1)
|
||||
assert(a.bounds.y == 2)
|
||||
assert(a.bounds.width == 3)
|
||||
assert(a.bounds.height == 4)
|
||||
assert(not a.isEmpty)
|
||||
assert(a:contains(1, 2))
|
||||
assert(a:contains(1+3-1, 2+4-1))
|
||||
assert(not a:contains(0, 1))
|
||||
assert(not a:contains(1+3, 2+4))
|
||||
|
||||
a:select{x=5, y=6, width=7, height=8}
|
||||
assert(a.bounds.x == 5)
|
||||
assert(a.bounds.y == 6)
|
||||
assert(a.bounds.width == 7)
|
||||
assert(a.bounds.height == 8)
|
||||
|
||||
a:deselect()
|
||||
assert(a.bounds.x == 0)
|
||||
assert(a.bounds.y == 0)
|
||||
assert(a.bounds.width == 0)
|
||||
assert(a.bounds.height == 0)
|
||||
assert(a.isEmpty)
|
||||
assert(not a:contains(0, 0))
|
||||
|
||||
-- Constructor with rectangles
|
||||
local b = Selection(1, 2, 3, 4)
|
||||
assert(b.bounds == Rectangle(1, 2, 3, 4))
|
||||
assert(b.origin == Point(1, 2))
|
||||
|
||||
-- Move
|
||||
b.origin = Point(5, 6)
|
||||
assert(b.bounds == Rectangle(5, 6, 3, 4))
|
||||
assert(b.origin == Point(5, 6))
|
||||
end
|
||||
|
||||
-- Sprite Selection
|
||||
do
|
||||
local spr = Sprite(32, 32)
|
||||
local sel = spr.selection
|
||||
assert(sel.bounds.x == 0)
|
||||
assert(sel.bounds.y == 0)
|
||||
assert(sel.bounds.width == 0)
|
||||
assert(sel.bounds.height == 0)
|
||||
|
||||
sel:selectAll()
|
||||
assert(sel.bounds.x == 0)
|
||||
assert(sel.bounds.y == 0)
|
||||
assert(sel.bounds.width == spr.width)
|
||||
assert(sel.bounds.height == spr.height)
|
||||
|
||||
sel:select(2, 3, 4, 5)
|
||||
assert(sel.bounds.x == 2)
|
||||
assert(sel.bounds.y == 3)
|
||||
assert(sel.bounds.width == 4)
|
||||
assert(sel.bounds.height == 5)
|
||||
|
||||
sel.origin = Point(5, 6)
|
||||
assert(sel.bounds == Rectangle(5, 6, 4, 5))
|
||||
end
|
||||
|
||||
-- Comparison
|
||||
do
|
||||
local a = Selection()
|
||||
local b = Selection()
|
||||
assert(a == b)
|
||||
|
||||
a:select(0, 0, 1, 1)
|
||||
assert(a ~= b)
|
||||
|
||||
b:add(a)
|
||||
assert(a == b)
|
||||
|
||||
a:subtract(b)
|
||||
assert(a ~= b)
|
||||
|
||||
b:subtract(b)
|
||||
assert(a == b)
|
||||
end
|
||||
|
||||
-- Operations
|
||||
do
|
||||
local a = Selection()
|
||||
a:select(2, 3, 4, 5)
|
||||
assert(a.bounds == Rectangle(2, 3, 4, 5))
|
||||
|
||||
a:subtract(2, 3, 4, 1)
|
||||
assert(a.bounds == Rectangle(2, 4, 4, 4))
|
||||
|
||||
assert(a:contains(3, 5))
|
||||
a:subtract(3, 5, 1, 1)
|
||||
assert(not a:contains(3, 5))
|
||||
assert(a.bounds == Rectangle(2, 4, 4, 4))
|
||||
|
||||
local b = Selection()
|
||||
assert(a.bounds == Rectangle(2, 4, 4, 4))
|
||||
assert(b.isEmpty)
|
||||
a:subtract(b) -- This should be a no-op because b is empty
|
||||
assert(a.bounds == Rectangle(2, 4, 4, 4))
|
||||
|
||||
b:select(0, 0, 32, 32)
|
||||
assert(a ~= b)
|
||||
b:intersect(a)
|
||||
assert(a == b)
|
||||
assert(b.bounds == Rectangle(2, 4, 4, 4))
|
||||
assert(b.bounds == Rectangle(2, 4, 4, 4))
|
||||
end
|
28
tests/scripts/selection_tools.lua
Normal file
28
tests/scripts/selection_tools.lua
Normal file
@ -0,0 +1,28 @@
|
||||
-- Copyright (C) 2021 Igara Studio S.A.
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
dofile('./test_utils.lua')
|
||||
|
||||
----------------------------------------------------------------------
|
||||
-- Test magic wand in transparent layer
|
||||
-- Note: A regression in the beta was found in this case.
|
||||
|
||||
do
|
||||
local s = Sprite(4, 4, ColorMode.INDEXED)
|
||||
app.command.LayerFromBackground()
|
||||
|
||||
local i = s.cels[1].image
|
||||
i:clear(0)
|
||||
i:putPixel(0, 0, 1)
|
||||
expect_eq(4, i.width)
|
||||
expect_eq(4, i.height)
|
||||
|
||||
app.useTool{ tool='magic_wand', points={Point(0, 0)} }
|
||||
expect_eq(Rectangle(0, 0, 1, 1), s.selection.bounds)
|
||||
|
||||
app.useTool{ tool='magic_wand', points={Point(1, 0)} }
|
||||
expect_eq(Rectangle(0, 0, 4, 4), s.selection.bounds)
|
||||
assert(not s.selection:contains(0, 0))
|
||||
end
|
75
tests/scripts/size.lua
Normal file
75
tests/scripts/size.lua
Normal file
@ -0,0 +1,75 @@
|
||||
-- Copyright (C) 2019 Igara Studio S.A.
|
||||
-- Copyright (C) 2018 David Capello
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
local sz = Size()
|
||||
assert(sz.width == 0)
|
||||
assert(sz.height == 0)
|
||||
|
||||
sz = Size(3, 4)
|
||||
assert(sz.width == 3)
|
||||
assert(sz.height == 4)
|
||||
assert("Size{ width=3, height=4 }" == tostring(sz))
|
||||
|
||||
local sz2 = Size(sz)
|
||||
assert(sz2.width == 3)
|
||||
assert(sz2.height == 4)
|
||||
|
||||
sz.width = 7
|
||||
sz.height = 8
|
||||
assert(sz.width == 7)
|
||||
assert(sz.height == 8)
|
||||
|
||||
sz = Size{width=10, height=20}
|
||||
assert(sz.width == 10)
|
||||
assert(sz.height == 20)
|
||||
|
||||
sz = Size{45, 25}
|
||||
assert(sz.width == 45)
|
||||
assert(sz.height == 25)
|
||||
|
||||
sz = -sz
|
||||
assert(sz.width == -45)
|
||||
assert(sz.height == -25)
|
||||
|
||||
-- add/sub/mul/div/mod/pow/idiv
|
||||
|
||||
sz = Size(1, 2) + 4
|
||||
sz2 = 4 + Size(1, 2)
|
||||
assert(sz.width == 5)
|
||||
assert(sz.height == 6)
|
||||
assert(sz == sz2)
|
||||
|
||||
sz = Size(1, 2) + Size(3, 4)
|
||||
assert(sz.width == 4)
|
||||
assert(sz.height == 6)
|
||||
|
||||
sz = Size(3, 4) - 1
|
||||
assert(sz.width == 2)
|
||||
assert(sz.height == 3)
|
||||
|
||||
sz = Size(8, 5) - Size(3, 2)
|
||||
assert(sz.width == 5)
|
||||
assert(sz.height == 3)
|
||||
|
||||
sz = Size(6, 10) * 2
|
||||
assert(sz.width == 12)
|
||||
assert(sz.height == 20)
|
||||
|
||||
sz = Size(6, 10) / 2
|
||||
assert(sz.width == 3)
|
||||
assert(sz.height == 5)
|
||||
|
||||
sz = Size(10, 5) % 2
|
||||
assert(sz.width == 0)
|
||||
assert(sz.height == 1)
|
||||
|
||||
sz = Size(2, 5) ^ 2
|
||||
assert(sz.width == 4)
|
||||
assert(sz.height == 25)
|
||||
|
||||
sz = Size(31, 10) // 3
|
||||
assert(sz.width == 10)
|
||||
assert(sz.height == 3)
|
27
tests/scripts/slice.lua
Normal file
27
tests/scripts/slice.lua
Normal file
@ -0,0 +1,27 @@
|
||||
-- Copyright (C) 2018 David Capello
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
do
|
||||
local s = Sprite(32, 32)
|
||||
|
||||
local a = s:newSlice(0, 0, 32, 32)
|
||||
assert(a.bounds == Rectangle(0, 0, 32, 32))
|
||||
assert(a.sprite == s)
|
||||
|
||||
assert(a.name == "Slice")
|
||||
a.name = "Slice A"
|
||||
assert(a.name == "Slice A")
|
||||
|
||||
assert(a.center == nil)
|
||||
a.center = Rectangle(2, 3, 28, 20)
|
||||
assert(a.center == Rectangle(2, 3, 28, 20))
|
||||
|
||||
assert(a.pivot == nil)
|
||||
a.pivot = Point(16, 17)
|
||||
assert(a.pivot == Point(16, 17))
|
||||
|
||||
a.data = "Data"
|
||||
assert(a.data == "Data")
|
||||
end
|
40
tests/scripts/slices.lua
Normal file
40
tests/scripts/slices.lua
Normal file
@ -0,0 +1,40 @@
|
||||
-- Copyright (C) 2022 Igara Studio S.A.
|
||||
-- Copyright (C) 2018 David Capello
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
do
|
||||
local s = Sprite(32, 32)
|
||||
|
||||
local a = s:newSlice()
|
||||
local b = s:newSlice(0, 2, 8, 10)
|
||||
local c = s:newSlice{ x=0, y=0, width=32, height=32 }
|
||||
assert(a.bounds == nil)
|
||||
assert(b.bounds == Rectangle(0, 2, 8, 10))
|
||||
assert(c.bounds == Rectangle(0, 0, 32, 32))
|
||||
|
||||
local bounds = { nil, Rectangle(0, 2, 8, 10), Rectangle(0, 0, 32, 32) }
|
||||
|
||||
local i = 1
|
||||
for k,v in ipairs(s.slices) do
|
||||
assert(i == k)
|
||||
assert(v == s.slices[k])
|
||||
assert(bounds[i] == s.slices[k].bounds)
|
||||
i = i+1
|
||||
end
|
||||
|
||||
s:deleteSlice(b)
|
||||
assert(a == s.slices[1])
|
||||
assert(c == s.slices[2])
|
||||
|
||||
assert(2 == #s.slices)
|
||||
app.undo()
|
||||
assert(3 == #s.slices)
|
||||
app.undo()
|
||||
assert(2 == #s.slices)
|
||||
app.undo()
|
||||
assert(1 == #s.slices)
|
||||
app.undo()
|
||||
assert(0 == #s.slices)
|
||||
end
|
208
tests/scripts/sprite.lua
Normal file
208
tests/scripts/sprite.lua
Normal file
@ -0,0 +1,208 @@
|
||||
-- Copyright (C) 2019-2022 Igara Studio S.A.
|
||||
-- Copyright (C) 2018 David Capello
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
do
|
||||
local a = Sprite(32, 64)
|
||||
assert(a.width == 32)
|
||||
assert(a.height == 64)
|
||||
assert(a.colorMode == ColorMode.RGB) -- RGB by default
|
||||
assert(a.bounds == Rectangle{x=0, y=0, width=32, height=64})
|
||||
|
||||
-- Crop and resize
|
||||
a.selection:select(2, 3, 4, 5)
|
||||
a:crop()
|
||||
assert(a.width == 4)
|
||||
assert(a.height == 5)
|
||||
assert(a.cels[1].image.width == 32)
|
||||
assert(a.cels[1].image.height == 64)
|
||||
a:resize(6, 8)
|
||||
assert(a.width == 6)
|
||||
assert(a.height == 8)
|
||||
assert(a.cels[1].image.width == 32 * 6 / 4) -- Check that the image was resized (not only the canvas)
|
||||
assert(a.cels[1].image.height == 64 * 8 / 5)
|
||||
a:crop{x=-1, y=-1, width=20, height=30}
|
||||
assert(a.width == 20)
|
||||
assert(a.height == 30)
|
||||
|
||||
-- Resize sprite setting width/height (just changing canvas size)
|
||||
a.width = 8
|
||||
a.height = 10
|
||||
assert(a.width == 8)
|
||||
assert(a.height == 10)
|
||||
|
||||
-- Test other Sprite() constructors
|
||||
local b = Sprite(4, 8, ColorMode.INDEXED)
|
||||
assert(b.width == 4)
|
||||
assert(b.height == 8)
|
||||
assert(b.colorMode == ColorMode.INDEXED)
|
||||
|
||||
local c = Sprite{ colorMode=ColorMode.INDEXED, width=10, height=20 }
|
||||
assert(c.width == 10)
|
||||
assert(c.height == 20)
|
||||
assert(c.colorMode == ColorMode.INDEXED)
|
||||
|
||||
local d = Sprite{ fromFile="sprites/abcd.aseprite" }
|
||||
assert(#d.layers == 4)
|
||||
assert(d.width == 32)
|
||||
assert(d.height == 32)
|
||||
assert(d.colorMode == ColorMode.INDEXED)
|
||||
end
|
||||
|
||||
-- Transparent color
|
||||
|
||||
do
|
||||
local a = Sprite(32, 32, ColorMode.INDEXED)
|
||||
assert(a.transparentColor == 0)
|
||||
a.transparentColor = 8
|
||||
assert(a.transparentColor == 8)
|
||||
end
|
||||
|
||||
-- Palette
|
||||
|
||||
do
|
||||
local a = Sprite(32, 32, ColorMode.INDEXED)
|
||||
assert(#a.palettes == 1)
|
||||
assert(#a.palettes[1] == 256)
|
||||
|
||||
local p = Palette(3)
|
||||
p:setColor(0, Color(255, 0, 0))
|
||||
p:setColor(1, Color(0, 255, 0))
|
||||
p:setColor(2, Color(0, 0, 255))
|
||||
a:setPalette(p)
|
||||
|
||||
assert(#a.palettes == 1)
|
||||
assert(#a.palettes[1] == 3)
|
||||
assert(a.palettes[1]:getColor(0) == Color(255, 0, 0))
|
||||
assert(a.palettes[1]:getColor(1) == Color(0, 255, 0))
|
||||
assert(a.palettes[1]:getColor(2) == Color(0, 0, 255))
|
||||
end
|
||||
|
||||
-- Duplicate & Flatten
|
||||
|
||||
do
|
||||
local a = Sprite(32, 32)
|
||||
a:newLayer()
|
||||
a:newLayer()
|
||||
assert(#a.layers == 3)
|
||||
|
||||
local b = Sprite(a) -- Clone a
|
||||
a:flatten() -- Flatten a
|
||||
assert(#a.layers == 1)
|
||||
assert(#b.layers == 3)
|
||||
end
|
||||
|
||||
-- Resize non-active sprite
|
||||
do
|
||||
local a = Sprite(32, 32)
|
||||
local b = Sprite(64, 64)
|
||||
app.activeSprite = a
|
||||
a:resize(10, 10)
|
||||
b:resize(20, 20)
|
||||
assert(a.width == 10)
|
||||
assert(a.height == 10)
|
||||
assert(b.width == 20)
|
||||
assert(b.height == 20)
|
||||
app.undo()
|
||||
assert(a.width == 32)
|
||||
assert(a.height == 32)
|
||||
app.activeSprite = b
|
||||
app.undo()
|
||||
assert(b.width == 64)
|
||||
assert(b.height == 64)
|
||||
end
|
||||
|
||||
-- Grid bounds
|
||||
do
|
||||
local s = Sprite(32, 32)
|
||||
assert(s.gridBounds == Rectangle{0, 0, 16, 16})
|
||||
s.gridBounds = Rectangle{2, 3, 8, 4}
|
||||
assert(s.gridBounds == Rectangle{2, 3, 8, 4})
|
||||
s:saveAs("_test_sprite_gridbounds.aseprite")
|
||||
|
||||
local s2 = Sprite{ fromFile="_test_sprite_gridbounds.aseprite" }
|
||||
assert(s2.gridBounds == Rectangle{2, 3, 8, 4})
|
||||
end
|
||||
|
||||
-- Pixel ratio
|
||||
do
|
||||
local s = Sprite(32, 32)
|
||||
assert(s.pixelRatio == Size{1, 1})
|
||||
s.pixelRatio = Size{3, 2}
|
||||
assert(s.pixelRatio == Size{3, 2})
|
||||
s:saveAs("_test_sprite_pixelratio.aseprite")
|
||||
|
||||
local s2 = Sprite{ fromFile="_test_sprite_pixelratio.aseprite" }
|
||||
assert(s2.pixelRatio == Size{3, 2})
|
||||
end
|
||||
|
||||
-- Sprite{ fromFile, oneFrame }
|
||||
do
|
||||
local s = Sprite(32, 32)
|
||||
s:newFrame()
|
||||
s:saveAs("_test1.png")
|
||||
assert(#s.frames == 2)
|
||||
|
||||
s = Sprite{ fromFile="_test1.png" }
|
||||
assert(#s.frames == 2)
|
||||
|
||||
s = Sprite{ fromFile="_test1.png", oneFrame=true }
|
||||
assert(#s.frames == 1)
|
||||
|
||||
s = Sprite{ fromFile="_test1.png", oneFrame=false }
|
||||
assert(#s.frames == 2)
|
||||
end
|
||||
|
||||
-- Issues with sprites having pixel with indexes out of palette bounds:
|
||||
-- Saving png failed (https://github.com/aseprite/aseprite/issues/2842)
|
||||
do
|
||||
local s = Sprite(2, 2, ColorMode.INDEXED)
|
||||
assert(#s.palettes == 1)
|
||||
|
||||
s.transparentColor = 1
|
||||
s.palettes[1]:resize(8)
|
||||
assert(#s.palettes[1] == 8)
|
||||
s.cels[1].image:clear(2)
|
||||
s.cels[1].image:putPixel(0, 0, 7)
|
||||
s:saveAs("_test1_.png") -- OK
|
||||
|
||||
s.palettes[1]:resize(4)
|
||||
assert(#s.palettes[1] == 4)
|
||||
local result = s:saveAs("_test2_palerr_.png") -- Used to fail
|
||||
|
||||
-- If result=false we got a "libpng: Wrote palette index exceeding num_palette"
|
||||
assert(result)
|
||||
|
||||
local s2 = app.open("_test2_palerr_.png")
|
||||
assert(s2 ~= nil)
|
||||
print(s2.cels[1].image:getPixel(0, 0))
|
||||
assert(s2.cels[1].image:getPixel(0, 0) == 1)
|
||||
end
|
||||
-- Flatten visible layers uses indices outside the palette range as opaque colors instead of transparent color (https://github.com/aseprite/aseprite/issues/2912)
|
||||
do
|
||||
local s = Sprite(2, 2, ColorMode.INDEXED)
|
||||
|
||||
s.transparentColor = 0
|
||||
s.palettes[1]:resize(4)
|
||||
|
||||
s.cels[1].image:clear(1)
|
||||
local l = s:newLayer()
|
||||
s:newCel(l)
|
||||
s.cels[2].image:putPixel(0, 0, 2)
|
||||
s.cels[2].image:putPixel(1, 0, 7)
|
||||
s:flatten()
|
||||
|
||||
assert(s.cels[1].image:getPixel(0, 0) == 2)
|
||||
assert(s.cels[1].image:getPixel(1, 0) == 1) -- Get the color of the first layer
|
||||
end
|
||||
|
||||
-- Compare sprite IDs
|
||||
|
||||
do
|
||||
local a = Sprite(1, 1)
|
||||
local b = Sprite(1, 1)
|
||||
assert(a == a)
|
||||
assert(a ~= b) -- Compares IDs, not sprite size
|
||||
end
|
23
tests/scripts/string.lua
Normal file
23
tests/scripts/string.lua
Normal file
@ -0,0 +1,23 @@
|
||||
-- Copyright (C) 2018 David Capello
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
assert(72 == string.byte("Hello", 1))
|
||||
assert(101 == string.byte("Hello", 2))
|
||||
assert(111 == string.byte("Hello", 5))
|
||||
assert("Hello" == string.char(72, 101, 108, 108, 111))
|
||||
|
||||
local s = "Hello"
|
||||
assert(111 == s:byte(5))
|
||||
assert(5 == string.len(s))
|
||||
assert("olleH" == string.reverse(s))
|
||||
assert("hello" == string.lower(s))
|
||||
assert("HELLO" == string.upper(s))
|
||||
|
||||
assert("Simple int 32" == string.format("Simple int %d", 32))
|
||||
assert("Simple int 0032" == string.format("Simple int %04d", 32))
|
||||
|
||||
assert(7 == string.find("Hello World!", "W"))
|
||||
|
||||
assert("-- hi 1000 --" == string.format("-- %s %d --", "hi", 1000))
|
45
tests/scripts/tag.lua
Normal file
45
tests/scripts/tag.lua
Normal file
@ -0,0 +1,45 @@
|
||||
-- Copyright (C) 2020 Igara Studio S.A.
|
||||
-- Copyright (C) 2018 David Capello
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
do
|
||||
local s = Sprite(32, 32)
|
||||
for i = 1,7 do s:newFrame() end
|
||||
assert(#s.frames == 8)
|
||||
|
||||
a = s:newTag(1, 8)
|
||||
assert(a.sprite == s)
|
||||
assert(a.fromFrame.frameNumber == 1)
|
||||
assert(a.toFrame.frameNumber == 8)
|
||||
assert(a.frames == 8)
|
||||
|
||||
a.fromFrame = 2
|
||||
a.toFrame = 5
|
||||
assert(a.fromFrame.frameNumber == 2)
|
||||
assert(a.toFrame.frameNumber == 5)
|
||||
|
||||
assert(a.name == "Tag")
|
||||
a.name = "Tag A"
|
||||
assert(a.name == "Tag A")
|
||||
|
||||
assert(a.aniDir == AniDir.FORWARD) -- Default AniDir is FORWARD
|
||||
a.aniDir = AniDir.REVERSE
|
||||
assert(a.aniDir == AniDir.REVERSE)
|
||||
a.aniDir = AniDir.PING_PONG
|
||||
assert(a.aniDir == AniDir.PING_PONG)
|
||||
a.aniDir = AniDir.FORWARD
|
||||
assert(a.aniDir == AniDir.FORWARD)
|
||||
|
||||
assert(a.color == Color(0, 0, 0))
|
||||
a.color = Color(255, 0, 0)
|
||||
assert(a.color == Color(255, 0, 0))
|
||||
|
||||
assert(a.repeats == 0)
|
||||
a.repeats = 1
|
||||
assert(a.repeats == 1)
|
||||
|
||||
a.data = "Data"
|
||||
assert(a.data == "Data")
|
||||
end
|
36
tests/scripts/tags.lua
Normal file
36
tests/scripts/tags.lua
Normal file
@ -0,0 +1,36 @@
|
||||
-- Copyright (C) 2018 David Capello
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
do
|
||||
local s = Sprite(32, 32)
|
||||
for i = 1,7 do s:newFrame() end
|
||||
assert(#s.frames == 8)
|
||||
|
||||
a = s:newTag(1, 2)
|
||||
b = s:newTag(3, 4)
|
||||
c = s:newTag(5, 8)
|
||||
|
||||
assert(a.frames == 2)
|
||||
assert(b.frames == 2)
|
||||
assert(c.frames == 4)
|
||||
|
||||
assert(a == s.tags[1])
|
||||
assert(b == s.tags[2])
|
||||
assert(c == s.tags[3])
|
||||
|
||||
local i = 1
|
||||
for k,v in ipairs(s.tags) do
|
||||
assert(i == k)
|
||||
assert(v == s.tags[k])
|
||||
i = i+1
|
||||
end
|
||||
|
||||
s:deleteTag(b)
|
||||
assert(a == s.tags[1])
|
||||
assert(c == s.tags[2])
|
||||
|
||||
assert(c.fromFrame.frameNumber == 5)
|
||||
assert(c.toFrame.frameNumber == 8)
|
||||
end
|
134
tests/scripts/test_utils.lua
Normal file
134
tests/scripts/test_utils.lua
Normal file
@ -0,0 +1,134 @@
|
||||
-- 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
|
||||
lineStr = lineStr .. image:getPixel(u, v) .. ','
|
||||
end
|
||||
print(lineStr)
|
||||
end
|
||||
print('}')
|
||||
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
|
1119
tests/scripts/tilemap.lua
Normal file
1119
tests/scripts/tilemap.lua
Normal file
File diff suppressed because it is too large
Load Diff
684
tests/scripts/tools.lua
Normal file
684
tests/scripts/tools.lua
Normal file
@ -0,0 +1,684 @@
|
||||
-- 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.
|
||||
|
||||
dofile('./test_utils.lua')
|
||||
|
||||
local rgba = app.pixelColor.rgba
|
||||
local gray = app.pixelColor.graya
|
||||
|
||||
----------------------------------------------------------------------
|
||||
-- activeTool
|
||||
----------------------------------------------------------------------
|
||||
|
||||
local pencil = app.activeTool -- pencil is the default tool
|
||||
assert(pencil ~= nil)
|
||||
assert(pencil.id == 'pencil')
|
||||
app.activeTool = 'line'
|
||||
assert(app.activeTool.id == 'line')
|
||||
app.activeTool = pencil
|
||||
assert(app.activeTool.id == 'pencil')
|
||||
|
||||
-- default brush is a circle of 1x1 when there is no UI
|
||||
assert(app.activeBrush.type == BrushType.CIRCLE)
|
||||
assert(app.activeBrush.size == 1)
|
||||
assert(app.activeBrush.angle == 0)
|
||||
|
||||
----------------------------------------------------------------------
|
||||
-- create sprite for testing
|
||||
----------------------------------------------------------------------
|
||||
|
||||
local spr = Sprite(4, 4)
|
||||
local cel = spr.cels[1]
|
||||
expect_eq(cel.bounds, Rectangle(0, 0, 4, 4))
|
||||
|
||||
----------------------------------------------------------------------
|
||||
-- pencil and eraser
|
||||
----------------------------------------------------------------------
|
||||
|
||||
app.useTool{
|
||||
tool='pencil',
|
||||
color=Color{ r=0, g=0, b=0 },
|
||||
points={ Point(2, 2),
|
||||
Point(3, 2) }}
|
||||
expect_eq(cel.bounds, Rectangle(2, 2, 2, 1))
|
||||
|
||||
app.useTool{
|
||||
tool='eraser',
|
||||
points={ Point(2, 2) }}
|
||||
expect_eq(cel.bounds, Rectangle(3, 2, 1, 1))
|
||||
|
||||
app.useTool{
|
||||
tool='eraser',
|
||||
points={ Point(3, 2) }}
|
||||
-- This must fail because cel is pointing to an invalid cel now.
|
||||
-- TODO: In a future this could change if this issue:
|
||||
-- https://github.com/aseprite/aseprite/issues/1833
|
||||
-- is implemented.
|
||||
assert(not pcall(function() print(cel.bounds) end))
|
||||
|
||||
----------------------------------------------------------------------
|
||||
-- line
|
||||
----------------------------------------------------------------------
|
||||
|
||||
local red = Color{ r=255, g=0, b=0 }
|
||||
app.useTool{
|
||||
tool='line',
|
||||
color=red,
|
||||
points={ Point(0, 0), Point(3, 3) }}
|
||||
local cel = spr.cels[1]
|
||||
expect_eq(cel.bounds, Rectangle(0, 0, 4, 4))
|
||||
do
|
||||
local r = red.rgbaPixel
|
||||
local expected = { r, 0, 0, 0,
|
||||
0, r, 0, 0,
|
||||
0, 0, r, 0,
|
||||
0, 0, 0, r }
|
||||
assert(cel.image.width == 4)
|
||||
assert(cel.image.height == 4)
|
||||
for v=0,3 do
|
||||
for u=0,3 do
|
||||
assert(cel.image:getPixel(u, v) == expected[1+v*4+u])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------
|
||||
-- paint_bucket
|
||||
----------------------------------------------------------------------
|
||||
|
||||
app.useTool{
|
||||
tool='paint_bucket',
|
||||
color=red,
|
||||
points={ Point(3, 0) }}
|
||||
local cel = spr.cels[1]
|
||||
do
|
||||
local r = red.rgbaPixel
|
||||
local expected = { r, r, r, r,
|
||||
0, r, r, r,
|
||||
0, 0, r, r,
|
||||
0, 0, 0, r }
|
||||
assert(cel.image.width == 4)
|
||||
assert(cel.image.height == 4)
|
||||
for v=0,3 do
|
||||
for u=0,3 do
|
||||
assert(cel.image:getPixel(u, v) == expected[1+v*4+u])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------
|
||||
-- rectangle
|
||||
----------------------------------------------------------------------
|
||||
|
||||
local blue = Color{ r=0, g=0, b=255 }
|
||||
app.useTool{
|
||||
tool='rectangle',
|
||||
color=blue,
|
||||
points={ Point(0, 0), Point(3, 3) }}
|
||||
local cel = spr.cels[1]
|
||||
do
|
||||
local r = red.rgbaPixel
|
||||
local b = blue.rgbaPixel
|
||||
local expected = { b, b, b, b,
|
||||
b, r, r, b,
|
||||
b, 0, r, b,
|
||||
b, b, b, b }
|
||||
assert(cel.image.width == 4)
|
||||
assert(cel.image.height == 4)
|
||||
for v=0,3 do
|
||||
for u=0,3 do
|
||||
assert(cel.image:getPixel(u, v) == expected[1+v*4+u])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------
|
||||
-- ellipse
|
||||
----------------------------------------------------------------------
|
||||
|
||||
local yellow = Color{ r=255, g=255, b=0 }
|
||||
app.useTool{
|
||||
tool='ellipse',
|
||||
color=yellow,
|
||||
points={ Point(0, 0), Point(3, 3) }}
|
||||
local cel = spr.cels[1]
|
||||
do
|
||||
local r = red.rgbaPixel
|
||||
local b = blue.rgbaPixel
|
||||
local y = yellow.rgbaPixel
|
||||
local expected = { b, y, y, b,
|
||||
y, r, r, y,
|
||||
y, 0, r, y,
|
||||
b, y, y, b }
|
||||
assert(cel.image.width == 4)
|
||||
assert(cel.image.height == 4)
|
||||
for v=0,3 do
|
||||
for u=0,3 do
|
||||
assert(cel.image:getPixel(u, v) == expected[1+v*4+u])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------
|
||||
-- draw in several cels
|
||||
----------------------------------------------------------------------
|
||||
|
||||
do
|
||||
local spr2 = Sprite(4, 4)
|
||||
spr2:newFrame()
|
||||
|
||||
local bgLay = spr2.layers[1]
|
||||
local fgLay = spr2:newLayer()
|
||||
local bgCel1 = spr2:newCel(fgLay, 1, Image(spr2.spec))
|
||||
local fgCel1 = spr2:newCel(bgLay, 1, Image(spr2.spec))
|
||||
local bgCel2 = spr2:newCel(fgLay, 2, Image(spr2.spec))
|
||||
local fgCel2 = spr2:newCel(bgLay, 2, Image(spr2.spec))
|
||||
expect_eq(fgCel1.bounds, Rectangle(0, 0, 4, 4))
|
||||
expect_eq(bgCel1.bounds, Rectangle(0, 0, 4, 4))
|
||||
expect_eq(fgCel2.bounds, Rectangle(0, 0, 4, 4))
|
||||
expect_eq(bgCel2.bounds, Rectangle(0, 0, 4, 4))
|
||||
|
||||
-- After each useTool(), the cels will be shrunken to the minimum
|
||||
-- required size.
|
||||
app.activeTool = 'pencil'
|
||||
app.useTool{ color=red, cel=bgCel1, points={ Point(0, 0) }}
|
||||
app.useTool{ color=red, layer=bgCel2.layer, frame=bgCel2.frame, points={ Point(1, 0) }}
|
||||
|
||||
-- After using the tool in bgCel2, the activeFrame is the frame
|
||||
-- number 2.
|
||||
assert(bgCel2.frame == app.activeFrame)
|
||||
assert(bgCel2.frame == fgCel2.frame)
|
||||
|
||||
app.activeFrame = fgCel1.frame
|
||||
app.useTool{ color=yellow, layer=fgCel1.layer, points={ Point(1, 1) }}
|
||||
app.useTool{ color=yellow, cel=fgCel2, points={ Point(2, 1) }}
|
||||
|
||||
expect_eq(bgCel1.bounds, Rectangle(0, 0, 1, 1))
|
||||
expect_eq(bgCel2.bounds, Rectangle(1, 0, 1, 1))
|
||||
expect_eq(fgCel1.bounds, Rectangle(1, 1, 1, 1))
|
||||
expect_eq(fgCel2.bounds, Rectangle(2, 1, 1, 1))
|
||||
|
||||
assert(bgCel1.image:getPixel(0, 0) == red.rgbaPixel)
|
||||
assert(bgCel2.image:getPixel(0, 0) == red.rgbaPixel)
|
||||
assert(fgCel1.image:getPixel(0, 0) == yellow.rgbaPixel)
|
||||
assert(fgCel2.image:getPixel(0, 0) == yellow.rgbaPixel)
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------
|
||||
-- draw with brushes
|
||||
----------------------------------------------------------------------
|
||||
|
||||
function drawing_with_simple_brushes(colorMode, a, b, c)
|
||||
print("drawing_with_simple_brushes", colorMode)
|
||||
|
||||
local expectedImages = {
|
||||
{ 0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0 },
|
||||
{ 0, 0, 0, 0,
|
||||
0, a, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0 },
|
||||
{ 0, 0, 0, 0,
|
||||
0, b, b, 0,
|
||||
0, b, b, 0,
|
||||
0, 0, 0, 0 },
|
||||
{ c, c, c, 0,
|
||||
c, c, c, c,
|
||||
c, c, c, c,
|
||||
0, c, c, c }
|
||||
}
|
||||
|
||||
local s = Sprite(4, 4, colorMode)
|
||||
assert(s == app.activeSprite)
|
||||
assert(s.cels[1] == app.activeCel)
|
||||
|
||||
function expect_cel_is_image(imageIndex)
|
||||
local a = Image(s.spec)
|
||||
a:drawSprite(s, 1, Point(0, 0))
|
||||
local b = expectedImages[imageIndex]
|
||||
expect_img(a, b)
|
||||
end
|
||||
|
||||
expect_cel_is_image(1)
|
||||
app.useTool{ tool='pencil', color=a, points={ Point(1, 1) } }
|
||||
assert(#s.cels == 1)
|
||||
expect_cel_is_image(2)
|
||||
app.undo()
|
||||
|
||||
expect_cel_is_image(1)
|
||||
app.useTool{ tool='pencil',
|
||||
brush=Brush{ size=2, type=BrushType.SQUARE },
|
||||
color=b, points={ Point(2, 2) } }
|
||||
expect_cel_is_image(3)
|
||||
app.undo()
|
||||
|
||||
expect_cel_is_image(1)
|
||||
app.useTool{ tool='pencil',
|
||||
brush=Brush{ size=2, type=BrushType.SQUARE, center=Point(0, 0) },
|
||||
color=b, points={ Point(1, 1) } }
|
||||
expect_cel_is_image(3)
|
||||
app.undo()
|
||||
|
||||
expect_cel_is_image(1)
|
||||
app.useTool{ tool='line',
|
||||
brush={ size=3, type=BrushType.SQUARE },
|
||||
color=c, points={ Point(1, 1), Point(2, 2) } }
|
||||
expect_cel_is_image(4)
|
||||
app.undo()
|
||||
|
||||
end
|
||||
|
||||
do
|
||||
drawing_with_simple_brushes(ColorMode.RGB, red.rgbaPixel, blue.rgbaPixel, yellow.rgbaPixel)
|
||||
drawing_with_simple_brushes(ColorMode.GRAY, gray(255), gray(128), gray(32))
|
||||
drawing_with_simple_brushes(ColorMode.INDEXED, 1, 2, 3)
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------
|
||||
-- draw with special image brushes + patterns
|
||||
----------------------------------------------------------------------
|
||||
|
||||
function drawing_with_image_brushes(imageColorMode, colorInImage,
|
||||
brushColorMode, colorInBrush, palette)
|
||||
print("drawing_with_image_brushes", imageColorMode, brushColorMode)
|
||||
local s = Sprite(4, 4, imageColorMode)
|
||||
local c = colorInImage
|
||||
cel = s.cels[1]
|
||||
|
||||
if palette then
|
||||
s:setPalette(palette)
|
||||
end
|
||||
|
||||
-- Brush image with BrushPattern.ORIGIN
|
||||
local bi = Image(2, 2, brushColorMode)
|
||||
bi:clear(0)
|
||||
bi:putPixel(0, 0, colorInBrush)
|
||||
bi:putPixel(1, 1, colorInBrush)
|
||||
local b = Brush { image=bi,
|
||||
center=Point(0, 0),
|
||||
pattern=BrushPattern.ORIGIN,
|
||||
patternOrigin=Point(0, 0) }
|
||||
|
||||
expect_img(app.activeImage,
|
||||
{ 0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0 })
|
||||
|
||||
app.useTool{ tool=pencil, brush=b, points={ Point(0, 0) } }
|
||||
expect_eq(cel.bounds, Rectangle(0, 0, 2, 2))
|
||||
expect_img(app.activeImage,
|
||||
{ c, 0,
|
||||
0, c })
|
||||
app.undo()
|
||||
|
||||
app.useTool{ tool=pencil, brush=b, points={ Point(0, 0), Point(1, 1) } }
|
||||
expect_eq(cel.bounds, Rectangle(0, 0, 3, 3))
|
||||
expect_img(app.activeImage,
|
||||
{ c, 0, 0,
|
||||
0, c, 0,
|
||||
0, 0, c })
|
||||
app.undo()
|
||||
|
||||
app.useTool{ tool=pencil, brush=b, points={ Point(0, 1) } }
|
||||
expect_eq(cel.bounds, Rectangle(0, 1, 2, 2))
|
||||
expect_img(app.activeImage,
|
||||
{ 0, c,
|
||||
c, 0 })
|
||||
app.undo()
|
||||
|
||||
app.useTool{ tool=pencil, brush=b, points={ Point(0, 0), Point(2, 0),
|
||||
Point(0, 0), Point(0, 1) } }
|
||||
expect_eq(cel.bounds, Rectangle(0, 0, 4, 3))
|
||||
expect_img(app.activeImage,
|
||||
{ c, 0, c, 0,
|
||||
0, c, 0, c,
|
||||
c, 0, 0, 0 })
|
||||
app.undo()
|
||||
|
||||
app.useTool{ tool='paint_bucket', brush=b, points={ Point(0, 0) } }
|
||||
expect_eq(cel.bounds, Rectangle(0, 0, 4, 4))
|
||||
expect_img(app.activeImage,
|
||||
{ c, 0, c, 0,
|
||||
0, c, 0, c,
|
||||
c, 0, c, 0,
|
||||
0, c, 0, c })
|
||||
app.undo()
|
||||
|
||||
app.useTool{ tool=pencil, brush=b, points={ Point(1, 0) } }
|
||||
assert(app.activeImage ~= nil)
|
||||
expect_eq(cel.bounds, Rectangle(1, 0, 2, 2))
|
||||
expect_img(app.activeImage,
|
||||
{ 0, c,
|
||||
c, 0 })
|
||||
app.undo()
|
||||
|
||||
app.useTool{ tool=pencil, brush=b, points={ Point(1, 0),
|
||||
Point(1, 0)} }
|
||||
assert(app.activeImage ~= nil)
|
||||
expect_eq(cel.bounds, Rectangle(1, 0, 2, 2))
|
||||
expect_img(app.activeImage,
|
||||
{ 0, c,
|
||||
c, 0 })
|
||||
app.undo()
|
||||
|
||||
-- Change brush pattern to BrushPattern.TARGET
|
||||
|
||||
b = Brush { image=bi,
|
||||
center=Point(0, 0),
|
||||
pattern=BrushPattern.TARGET,
|
||||
patternOrigin=Point(0, 0) }
|
||||
|
||||
app.useTool{ tool=pencil, brush=b, points={ Point(1, 0) } }
|
||||
expect_eq(cel.bounds, Rectangle(1, 0, 2, 2))
|
||||
expect_img(app.activeImage,
|
||||
{ c, 0,
|
||||
0, c })
|
||||
app.undo()
|
||||
|
||||
end
|
||||
|
||||
do
|
||||
drawing_with_image_brushes(ColorMode.RGB, rgba(255, 0, 0),
|
||||
ColorMode.RGB, rgba(255, 0, 0))
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------
|
||||
-- draw with symmetry
|
||||
----------------------------------------------------------------------
|
||||
|
||||
function drawing_with_symmetry(imageColorMode, colorInImage,
|
||||
brushColorMode, colorInBrush, palette)
|
||||
print("drawing_with_symmetry", imageColorMode, brushColorMode)
|
||||
local s = Sprite(8, 3, imageColorMode)
|
||||
local c = colorInImage
|
||||
cel = s.cels[1]
|
||||
|
||||
if palette then
|
||||
s:setPalette(palette)
|
||||
end
|
||||
|
||||
-- Enable symmetry
|
||||
local pref = app.preferences
|
||||
local docPref = pref.document(s)
|
||||
pref.symmetry_mode.enabled = true
|
||||
docPref.symmetry.mode = 1 -- TODO use SymmetryMode.HORIZONTAL when it's available
|
||||
docPref.symmetry.x_axis = 4
|
||||
|
||||
expect_eq(cel.bounds, Rectangle(0, 0, 8, 3))
|
||||
expect_img(cel.image,
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0 })
|
||||
|
||||
local b = Brush { size=1 }
|
||||
app.fgColor = c
|
||||
app.useTool{ tool=pencil, brush=b, points={ Point(0, 0) } }
|
||||
expect_eq(cel.bounds, Rectangle(0, 0, 8, 1))
|
||||
expect_img(cel.image,
|
||||
{ c, 0, 0, 0, 0, 0, 0, c })
|
||||
app.undo()
|
||||
|
||||
app.useTool{ tool=pencil, brush=b, points={ Point(2, 0) } }
|
||||
expect_eq(cel.bounds, Rectangle(2, 0, 4, 1))
|
||||
expect_img(cel.image,
|
||||
{ c, 0, 0, c })
|
||||
app.undo()
|
||||
|
||||
-- Brush size 2x2 center=(1,1)
|
||||
b = Brush { size=2 }
|
||||
assert(b.center.x == 1)
|
||||
assert(b.center.y == 1)
|
||||
app.useTool{ tool=pencil, brush=b, points={ Point(1, 1) } }
|
||||
expect_eq(cel.bounds, Rectangle(0, 0, 8, 2))
|
||||
expect_img(cel.image,
|
||||
{ c, c, 0, 0, 0, 0, c, c,
|
||||
c, c, 0, 0, 0, 0, c, c })
|
||||
app.undo()
|
||||
|
||||
-- Brush size 2x2 center=(0,0)
|
||||
b = Brush { size=2, center=Point(0, 0) }
|
||||
assert(b.center.x == 0)
|
||||
assert(b.center.y == 0)
|
||||
app.useTool{ tool=pencil, brush=b, points={ Point(1, 0) } }
|
||||
expect_eq(cel.bounds, Rectangle(1, 0, 6, 2))
|
||||
expect_img(cel.image,
|
||||
{ c, c, 0, 0, c, c,
|
||||
c, c, 0, 0, c, c })
|
||||
app.undo()
|
||||
|
||||
-- Brush size 3x3
|
||||
b = Brush { size=3 }
|
||||
app.useTool{ tool=pencil, brush=b, points={ Point(1, 1) } }
|
||||
expect_eq(cel.bounds, Rectangle(0, 0, 8, 3))
|
||||
expect_img(cel.image,
|
||||
{ 0, c, 0, 0, 0, 0, c, 0,
|
||||
c, c, c, 0, 0, c, c, c,
|
||||
0, c, 0, 0, 0, 0, c, 0 })
|
||||
app.undo()
|
||||
|
||||
-- Brush size 3x3
|
||||
b = Brush { size=3, center=Point(1, 1) }
|
||||
app.useTool{ tool=pencil, brush=b, points={ Point(2, 1) } }
|
||||
expect_eq(cel.bounds, Rectangle(1, 0, 6, 3))
|
||||
expect_img(cel.image,
|
||||
{ 0, c, 0, 0, c, 0,
|
||||
c, c, c, c, c, c,
|
||||
0, c, 0, 0, c, 0 })
|
||||
app.undo()
|
||||
|
||||
-- Brush size 4x4 center=(2,2)
|
||||
b = Brush { size=4 }
|
||||
assert(b.center.x == 2)
|
||||
assert(b.center.y == 2)
|
||||
app.useTool{ tool=pencil, brush=b, points={ Point(1, 1) } }
|
||||
expect_eq(cel.bounds, Rectangle(0, 0, 8, 3))
|
||||
expect_img(cel.image,
|
||||
{ c, c, c, 0, 0, c, c, c,
|
||||
c, c, c, 0, 0, c, c, c,
|
||||
c, c, 0, 0, 0, 0, c, c })
|
||||
app.undo()
|
||||
|
||||
-- Brush size 4x4 center=(1,1)
|
||||
b = Brush { size=4, center=Point(1, 1) }
|
||||
app.useTool{ tool=pencil, brush=b, points={ Point(1, 0) } }
|
||||
expect_eq(cel.bounds, Rectangle(0, 0, 8, 3))
|
||||
expect_img(cel.image,
|
||||
{ c, c, c, c, c, c, c, c,
|
||||
c, c, c, c, c, c, c, c,
|
||||
0, c, c, 0, 0, c, c, 0 })
|
||||
app.undo()
|
||||
|
||||
-- Odd symmetry
|
||||
docPref.symmetry.x_axis = 4.5
|
||||
|
||||
b = Brush { size=1 }
|
||||
app.useTool{ tool=pencil, brush=b, points={ Point(4, 0) } }
|
||||
expect_eq(cel.bounds, Rectangle(4, 0, 1, 1))
|
||||
expect_img(cel.image,
|
||||
{ c })
|
||||
app.undo()
|
||||
|
||||
b = Brush { size=1 }
|
||||
app.useTool{ tool=pencil, brush=b, points={ Point(3, 0) } }
|
||||
expect_eq(cel.bounds, Rectangle(3, 0, 3, 1))
|
||||
expect_img(cel.image,
|
||||
{ c, 0, c })
|
||||
app.undo()
|
||||
|
||||
b = Brush { size=2 }
|
||||
app.useTool{ tool=pencil, brush=b, points={ Point(2, 0) } }
|
||||
expect_eq(cel.bounds, Rectangle(1, 0, 7, 1))
|
||||
expect_img(cel.image,
|
||||
{ c, c, 0, 0, 0, c, c })
|
||||
app.undo()
|
||||
|
||||
end
|
||||
|
||||
do
|
||||
drawing_with_symmetry(ColorMode.RGB, rgba(255, 0, 0),
|
||||
ColorMode.RGB, rgba(255, 0, 0))
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------
|
||||
-- useTool in a transaction
|
||||
----------------------------------------------------------------------
|
||||
|
||||
do
|
||||
local s = Sprite(2, 2)
|
||||
local r = red.rgbaPixel
|
||||
local y = yellow.rgbaPixel
|
||||
app.fgColor = r
|
||||
|
||||
local cel = s.cels[1]
|
||||
expect_img(cel.image, { 0, 0,
|
||||
0, 0 })
|
||||
app.transaction(
|
||||
function()
|
||||
app.useTool{ tool=pencil,
|
||||
color=r, brush=Brush{ size=1 },
|
||||
points={ Point(0, 0) } }
|
||||
app.useTool{ tool=pencil,
|
||||
color=y, brush=Brush{ size=1 },
|
||||
points={ Point(1, 1) } }
|
||||
end)
|
||||
expect_img(cel.image, { r, 0,
|
||||
0, y })
|
||||
app.undo() -- Undo the whole transaction (two useTool grouped in one transaction)
|
||||
expect_img(cel.image, { 0, 0,
|
||||
0, 0 })
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------
|
||||
-- draw with tiled mode + image brush
|
||||
-- test for: https://community.aseprite.org/t/tile-mode-glitch/1183
|
||||
----------------------------------------------------------------------
|
||||
|
||||
function drawing_with_tiled_mode_and_image_brush()
|
||||
print("drawing_with_tiled_mode_and_image_brush")
|
||||
local spr = Sprite(8, 3, ColorMode.INDEXED)
|
||||
local cel = spr.cels[1]
|
||||
|
||||
-- enable tiled mode
|
||||
local pref = app.preferences
|
||||
local docPref = pref.document(spr)
|
||||
docPref.tiled.mode = 3 -- both
|
||||
|
||||
expect_img(cel.image,
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0 })
|
||||
|
||||
-- Create brush
|
||||
local brushImg = Image(5, 2, ColorMode.INDEXED)
|
||||
array_to_pixels({ 1, 2, 3, 2, 1,
|
||||
0, 1, 2, 1, 0 }, brushImg)
|
||||
local bru = Brush { image=brushImg }
|
||||
|
||||
-- Without overflow
|
||||
app.useTool{ tool=pencil, brush=bru, points={ Point(2, 1) } }
|
||||
expect_img(cel.image,
|
||||
{ 1, 2, 3, 2, 1,
|
||||
0, 1, 2, 1, 0 })
|
||||
app.undo()
|
||||
|
||||
-- Overflow at the left-side
|
||||
app.useTool{ tool=pencil, brush=bru, points={ Point(1, 1) } }
|
||||
expect_img(cel.image,
|
||||
{ 2, 3, 2, 1, 0, 0, 0, 1,
|
||||
1, 2, 1, 0, 0, 0, 0, 0 })
|
||||
app.undo()
|
||||
|
||||
-- Overflow at the right-side
|
||||
app.useTool{ tool=pencil, brush=bru, points={ Point(9, 1) } }
|
||||
expect_img(cel.image,
|
||||
{ 2, 3, 2, 1, 0, 0, 0, 1,
|
||||
1, 2, 1, 0, 0, 0, 0, 0 })
|
||||
app.undo()
|
||||
|
||||
-- Overflow at the top
|
||||
app.useTool{ tool=pencil, brush=bru, points={ Point(0, 0) } }
|
||||
expect_img(cel.image,
|
||||
{ 2, 1, 0, 0, 0, 0, 0, 1,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
3, 2, 1, 0, 0, 0, 1, 2 })
|
||||
app.undo()
|
||||
|
||||
-- Overflow at the bottom
|
||||
app.useTool{ tool=pencil, brush=bru, points={ Point(1, 3) } }
|
||||
expect_img(cel.image,
|
||||
{ 1, 2, 1, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
2, 3, 2, 1, 0, 0, 0, 1 })
|
||||
app.undo()
|
||||
|
||||
docPref.tiled.mode = 0 -- none (disable tiled mode)
|
||||
end
|
||||
drawing_with_tiled_mode_and_image_brush()
|
||||
|
||||
----------------------------------------------------------------------
|
||||
-- countour with pixel perfect
|
||||
----------------------------------------------------------------------
|
||||
|
||||
do
|
||||
local s = Sprite(3, 3, ColorMode.INDEXED)
|
||||
local i = app.activeImage
|
||||
i:clear(1)
|
||||
expect_img(i,
|
||||
{ 1, 1, 1,
|
||||
1, 1, 1,
|
||||
1, 1, 1 })
|
||||
app.useTool{
|
||||
tool='contour',
|
||||
brush=Brush(1),
|
||||
color=2,
|
||||
freehandAlgorithm=1, -- 1=FreehandAlgorithm.PIXEL_PERFECT
|
||||
points={ { 1, 1 }, { 2, 1 }, { 2, 2 }
|
||||
}
|
||||
}
|
||||
expect_img(app.activeImage,
|
||||
{ 1, 1, 1,
|
||||
1, 2, 1,
|
||||
1, 1, 2 })
|
||||
|
||||
app.undo()
|
||||
|
||||
-- Test one pixel when using one point
|
||||
app.useTool{
|
||||
tool='contour',
|
||||
brush=Brush(1),
|
||||
color=2,
|
||||
freehandAlgorithm=1, -- 1=FreehandAlgorithm.PIXEL_PERFECT
|
||||
points={ { 1, 1 } }
|
||||
}
|
||||
expect_img(app.activeImage,
|
||||
{ 1, 1, 1,
|
||||
1, 2, 1,
|
||||
1, 1, 1 })
|
||||
app.undo()
|
||||
|
||||
-- Test bug where one click doesn't draw with the contour tool with
|
||||
-- pixel perfect algorith.
|
||||
-- Report: https://community.aseprite.org/t/13149
|
||||
expect_img(app.activeImage,
|
||||
{ 1, 1, 1,
|
||||
1, 1, 1,
|
||||
1, 1, 1 })
|
||||
app.useTool{
|
||||
tool='contour',
|
||||
brush=Brush(1),
|
||||
color=2,
|
||||
freehandAlgorithm=1, -- 1=FreehandAlgorithm.PIXEL_PERFECT
|
||||
-- Two points in the same spot, this happens in the UI, one
|
||||
-- created in mouse down, other in mouse up.
|
||||
points={ { 1, 1 }, { 1, 1 } }
|
||||
}
|
||||
expect_img(app.activeImage,
|
||||
{ 1, 1, 1,
|
||||
1, 2, 1,
|
||||
1, 1, 1 })
|
||||
end
|
41
tests/scripts/version.lua
Normal file
41
tests/scripts/version.lua
Normal file
@ -0,0 +1,41 @@
|
||||
-- Copyright (C) 2019-2021 Igara Studio S.A.
|
||||
-- Copyright (C) 2018 David Capello
|
||||
--
|
||||
-- This file is released under the terms of the MIT license.
|
||||
-- Read LICENSE.txt for more information.
|
||||
|
||||
assert(string.sub(tostring(app.version), 1, 1) == "1")
|
||||
assert(string.sub(tostring(app.version), 2, 2) == ".")
|
||||
assert(app.version.major == 1)
|
||||
|
||||
-- We cannot test the specific app.version from the "main" branch
|
||||
-- because it's "1.x-dev" (which is converted to "1.0-dev" as Version object)
|
||||
--assert(app.version > Version("1.2.10-beta4"))
|
||||
|
||||
assert(Version("1") == Version("1"))
|
||||
assert(Version("1.1") > Version("1"))
|
||||
assert(Version("0.1") < Version("0.2"))
|
||||
assert(Version("1.0.1") > Version("1"))
|
||||
assert(Version("1.0.1") < Version("1.1"))
|
||||
assert(Version("1.0.1") == Version("1.0.1"))
|
||||
assert(Version("1.0.1") ~= Version("1.0.2"))
|
||||
assert(Version("1.0.1") > Version("1.0.1-beta"))
|
||||
assert(Version("1.0.1") > Version("1.0.1-dev"))
|
||||
assert(Version("1.0.1-beta") > Version("1.0.1-alpha"))
|
||||
assert(Version("1.0.1-beta50") < Version("1.0.1-beta100"))
|
||||
assert(Version("1.0.1-beta50") <= Version("1.0.1-beta100"))
|
||||
assert(Version("1.0.1-beta100") <= Version("1.0.1-beta100"))
|
||||
|
||||
local v = Version()
|
||||
assert(v.major == 0)
|
||||
assert(v.minor == 0)
|
||||
assert(v.patch == 0)
|
||||
assert(v.prereleaseLabel == "")
|
||||
assert(v.prereleaseNumber == 0)
|
||||
|
||||
v = Version("1.2.10-beta4")
|
||||
assert(v.major == 1)
|
||||
assert(v.minor == 2)
|
||||
assert(v.patch == 10)
|
||||
assert(v.prereleaseLabel == "beta")
|
||||
assert(v.prereleaseNumber == 4)
|
BIN
tests/sprites/1empty3.aseprite
Normal file
BIN
tests/sprites/1empty3.aseprite
Normal file
Binary file not shown.
BIN
tests/sprites/2f-index-3x3.aseprite
Normal file
BIN
tests/sprites/2f-index-3x3.aseprite
Normal file
Binary file not shown.
27
tests/sprites/README.md
Normal file
27
tests/sprites/README.md
Normal file
@ -0,0 +1,27 @@
|
||||
# Files
|
||||
|
||||
* `abcd.aseprite`: Indexed, 32x32, four layers ("a", "b", "c", "d")
|
||||
* `1empty3.aseprite`: RGB, 32x32, two layers ("fg", "bg"), 2nd frame
|
||||
completelly empty, two tags ("a", "b")
|
||||
* `groups2.aseprite`: Indexed, 8x8, two groups ("items", "player"),
|
||||
two layers per group ("items/gun", "items/sword", "player/head",
|
||||
"player/body"), with one layer hidden ("items/gun").
|
||||
* `groups3abc.aseprite`: RGB, 9x11, three groups ("a", "b", "c"), with
|
||||
three layers each one (called "a", "b", "c" too). There is a
|
||||
combination of visibilities ("b/b", "c", "c/a", and "c/b" are
|
||||
hidden).
|
||||
* `bg-index-3.aseprite`: Indexed, 4x4, two layers ("fg" and "bg")
|
||||
with a special transparent index color (= palette index 3).
|
||||
* `tags3.aseprite`: 3 tags ("forward", "reverse", "pingpong") and 3
|
||||
layers ("a", "b", "c"), 4x4, several linked cels + layer "c" with
|
||||
empty cels.
|
||||
* `point4frames.aseprite`: Indexed, 4 frames, 2 layers, same cel
|
||||
content but different positions, can be used to test
|
||||
`-merge-duplicates` to check if all cels go to the same sprite sheet
|
||||
position.
|
||||
* `point2frames.aseprite`: Indexed, 2 frames, 1 layer, same cel
|
||||
content as in `point4frames.aseprite`. Useful to test if
|
||||
`"sourceSize"` is different when two cels from different sprites are
|
||||
merged in the same texture atlas.
|
||||
* `2f-index-3x3.aseprite`: Indexed, 2 frames, 1 layer, mask color set
|
||||
to index 21.
|
BIN
tests/sprites/abcd.aseprite
Normal file
BIN
tests/sprites/abcd.aseprite
Normal file
Binary file not shown.
BIN
tests/sprites/bg-index-3.aseprite
Normal file
BIN
tests/sprites/bg-index-3.aseprite
Normal file
Binary file not shown.
BIN
tests/sprites/groups2.aseprite
Normal file
BIN
tests/sprites/groups2.aseprite
Normal file
Binary file not shown.
BIN
tests/sprites/groups3abc.aseprite
Normal file
BIN
tests/sprites/groups3abc.aseprite
Normal file
Binary file not shown.
BIN
tests/sprites/link.aseprite
Normal file
BIN
tests/sprites/link.aseprite
Normal file
Binary file not shown.
BIN
tests/sprites/point2frames.aseprite
Normal file
BIN
tests/sprites/point2frames.aseprite
Normal file
Binary file not shown.
BIN
tests/sprites/point4frames.aseprite
Normal file
BIN
tests/sprites/point4frames.aseprite
Normal file
Binary file not shown.
BIN
tests/sprites/tags3.aseprite
Normal file
BIN
tests/sprites/tags3.aseprite
Normal file
Binary file not shown.
1
tests/third_party/json
vendored
Submodule
1
tests/third_party/json
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit dbf4b2dd2eb7c23be2773c89eb059dadd6436f94
|
Loading…
x
Reference in New Issue
Block a user