mirror of
https://github.com/aseprite/aseprite.git
synced 2025-02-05 18:40:37 +00:00
Merge branch 'main' into beta
This commit is contained in:
commit
801ea7ab6c
81
.github/workflows/build.yml
vendored
81
.github/workflows/build.yml
vendored
@ -8,35 +8,50 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
os: [windows-latest, macos-latest, ubuntu-latest]
|
os: [windows-latest, macos-latest, ubuntu-latest]
|
||||||
build_type: [RelWithDebInfo, Debug]
|
build_type: [RelWithDebInfo, Debug]
|
||||||
enable_ui: [off]
|
ui: [gui, cli]
|
||||||
include:
|
scripting: [lua, noscripts]
|
||||||
- os: ubuntu-latest
|
exclude:
|
||||||
build_type: Debug
|
- build_type: Debug
|
||||||
enable_ui: on
|
ui: gui
|
||||||
|
- build_type: RelWithDebInfo
|
||||||
|
ui: cli
|
||||||
|
- build_type: RelWithDebInfo
|
||||||
|
scripting: noscripts
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: 'recursive'
|
submodules: 'recursive'
|
||||||
|
- name: Install Dependencies
|
||||||
|
if: runner.os == 'Linux'
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
sudo apt-get update -qq
|
||||||
|
sudo apt-get install -y \
|
||||||
|
libpixman-1-dev libfreetype6-dev libharfbuzz-dev zlib1g-dev \
|
||||||
|
libx11-dev libxcursor-dev libxi-dev libgl1-mesa-dev
|
||||||
|
- name: Install Skia
|
||||||
|
if: ${{ matrix.ui == 'gui' }}
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
if [[ "${{ runner.os }}" == "Windows" ]] ; then
|
||||||
|
choco install wget -y --no-progress
|
||||||
|
wget https://github.com/aseprite/skia/releases/download/m124-08a5439a6b/Skia-Windows-Release-x64.zip
|
||||||
|
unzip Skia-Windows-Release-x64.zip -d skia
|
||||||
|
elif [[ "${{ runner.os }}" == "macOS" ]] ; then
|
||||||
|
wget https://github.com/aseprite/skia/releases/download/m124-08a5439a6b/Skia-macOS-Release-arm64.zip
|
||||||
|
unzip Skia-macOS-Release-arm64.zip -d skia
|
||||||
|
else
|
||||||
|
wget https://github.com/aseprite/skia/releases/download/m124-08a5439a6b/Skia-Linux-Release-x64.zip
|
||||||
|
unzip Skia-Linux-Release-x64.zip -d skia
|
||||||
|
fi
|
||||||
- name: ccache
|
- name: ccache
|
||||||
uses: hendrikmuhs/ccache-action@v1
|
uses: hendrikmuhs/ccache-action@v1
|
||||||
if: ${{ runner.os == 'Linux' || runner.os == 'macOS' }}
|
if: ${{ runner.os == 'Linux' || runner.os == 'macOS' }}
|
||||||
with:
|
with:
|
||||||
key: ${{ matrix.os }}-${{ matrix.enable_ui }}-${{ matrix.build_type }}
|
key: ${{ matrix.os }}-${{ matrix.ui }}-${{ matrix.scripting }}-${{ matrix.build_type }}
|
||||||
- uses: aseprite/get-ninja@main
|
- uses: aseprite/get-ninja@main
|
||||||
- uses: ilammy/msvc-dev-cmd@v1
|
- uses: ilammy/msvc-dev-cmd@v1
|
||||||
if: runner.os == 'Windows'
|
if: runner.os == 'Windows'
|
||||||
- name: Workaround for windows-2022 and cmake 3.25.0
|
|
||||||
if: runner.os == 'Windows'
|
|
||||||
shell: bash
|
|
||||||
run: rm -rf C:/Strawberry/
|
|
||||||
- name: Install Dependencies
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
if [[ "${{ runner.os }}" == "Linux" ]] ; then
|
|
||||||
sudo apt-get update -qq
|
|
||||||
sudo apt-get install -y \
|
|
||||||
libx11-dev libxcursor-dev libxi-dev
|
|
||||||
fi
|
|
||||||
- name: Generating Makefiles
|
- name: Generating Makefiles
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
@ -45,12 +60,37 @@ jobs:
|
|||||||
else
|
else
|
||||||
export enable_ccache=on
|
export enable_ccache=on
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ "${{ matrix.ui }}" == "gui" ]] ; then
|
||||||
|
export enable_ui=on
|
||||||
|
export laf_backend=skia
|
||||||
|
else
|
||||||
|
export enable_ui=off
|
||||||
|
export laf_backend=none
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${{ matrix.scripting }}" == "lua" ]] ; then
|
||||||
|
export enable_scripting=on
|
||||||
|
else
|
||||||
|
export enable_scripting=off
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${{ runner.os }}" == "macOS" ]] ; then
|
||||||
|
export skia_arch=arm64
|
||||||
|
else
|
||||||
|
export skia_arch=x64
|
||||||
|
fi
|
||||||
|
|
||||||
cmake -S . -B build -G Ninja \
|
cmake -S . -B build -G Ninja \
|
||||||
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \
|
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \
|
||||||
-DCMAKE_OSX_DEPLOYMENT_TARGET=10.9 \
|
-DCMAKE_OSX_DEPLOYMENT_TARGET=10.9 \
|
||||||
-DENABLE_TESTS=ON \
|
-DENABLE_TESTS=ON \
|
||||||
-DENABLE_UI=${{ matrix.enable_ui }} \
|
-DENABLE_UI=$enable_ui \
|
||||||
-DENABLE_CCACHE=$enable_ccache
|
-DENABLE_SCRIPTING=$enable_scripting \
|
||||||
|
-DENABLE_CCACHE=$enable_ccache \
|
||||||
|
-DLAF_BACKEND=$laf_backend \
|
||||||
|
-DSKIA_DIR=$(realpath skia) \
|
||||||
|
-DSKIA_LIBRARY_DIR=$(realpath skia/out/Release-$skia_arch)
|
||||||
- name: Compiling
|
- name: Compiling
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
@ -63,6 +103,7 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
cd build && $XVFB ctest --output-on-failure
|
cd build && $XVFB ctest --output-on-failure
|
||||||
- name: Running CLI Tests
|
- name: Running CLI Tests
|
||||||
|
if: ${{ matrix.scripting == 'lua' }}
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
if [[ "${{ runner.os }}" == "Linux" ]] ; then
|
if [[ "${{ runner.os }}" == "Linux" ]] ; then
|
||||||
|
72
.github/workflows/lint_commit.yml
vendored
Normal file
72
.github/workflows/lint_commit.yml
vendored
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
# Based on SerenityOS commit linter:
|
||||||
|
# https://github.com/SerenityOS/serenity/blob/master/.github/workflows/lintcommits.yml
|
||||||
|
|
||||||
|
name: Commit linter
|
||||||
|
on: [pull_request_target]
|
||||||
|
jobs:
|
||||||
|
lint_commits:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
if: always() && github.repository == 'aseprite/aseprite'
|
||||||
|
steps:
|
||||||
|
- name: Lint PR commits
|
||||||
|
uses: actions/github-script@v7
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const rules = [
|
||||||
|
{
|
||||||
|
pattern: /^[^\r]*$/,
|
||||||
|
error: "Commit message contains CRLF line breaks (only unix-style LF linebreaks are allowed)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: /^.+(\r?\n(\r?\n.*)*)?$/,
|
||||||
|
error: "Empty line between commit title and body is missing",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: /^.{0,72}(?:\r?\n(?:(.{0,72})|(.*?([a-z]+:\/\/)?(([a-zA-Z0-9_]|-)+\.)+[a-z]{2,}(:\d+)?([a-zA-Z_0-9@:%\+.~\?&/=]|-)+).*?))*$/,
|
||||||
|
error: "Commit message lines are too long (maximum allowed is 72 characters, except for URLs)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: /^.+[^.\n](\r?\n.*)*$/,
|
||||||
|
error: "Commit title ends in a period",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: /^((?!Signed-off-by: )[\s\S])*$/,
|
||||||
|
error: "Commit body contains a Signed-off-by tag",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const { repository, pull_request } = context.payload;
|
||||||
|
|
||||||
|
// NOTE: This maxes out at 250 commits. If this becomes a problem, see:
|
||||||
|
// https://octokit.github.io/rest.js/v18#pulls-list-commits
|
||||||
|
const opts = github.rest.pulls.listCommits.endpoint.merge({
|
||||||
|
owner: repository.owner.login,
|
||||||
|
repo: repository.name,
|
||||||
|
pull_number: pull_request.number,
|
||||||
|
});
|
||||||
|
const commits = await github.paginate(opts);
|
||||||
|
|
||||||
|
const errors = [];
|
||||||
|
for (const { sha, commit: { message } } of commits) {
|
||||||
|
const commitErrors = [];
|
||||||
|
for (const { pattern, error } of rules) {
|
||||||
|
if (!pattern.test(message)) {
|
||||||
|
commitErrors.push(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (commitErrors.length > 0) {
|
||||||
|
const title = message.split("\n")[0];
|
||||||
|
errors.push([`${title} (${sha}):`, ...commitErrors].join("\n "));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errors.length > 0) {
|
||||||
|
core.setFailed(`One or more of the commits in this PR do not match the code submission policy:\n\n${errors.join("\n")}`);
|
||||||
|
}
|
||||||
|
- name: Comment on PR
|
||||||
|
if: ${{ failure() && !github.event.pull_request.draft }}
|
||||||
|
uses: IdanHo/comment-on-pr@63ea2bf352997c66e524b8b5be7a79163fb3a88a
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.LINT_COMMIT_TOKEN }}
|
||||||
|
with:
|
||||||
|
msg: "Hi there!\n\nOne or more of the commit messages in this PR do not match our [code submission policy](https://github.com/aseprite/aseprite/blob/main/CONTRIBUTING.md), please check the `lint_commits` CI job for more details on which commits were flagged and why.\nPlease do not close this PR and open another, instead modify your commit message(s) with [git commit --amend](https://docs.github.com/en/pull-requests/committing-changes-to-your-project/creating-and-editing-commits/changing-a-commit-message) and force push those changes to update this PR."
|
117
CONTRIBUTING.md
117
CONTRIBUTING.md
@ -1,7 +1,7 @@
|
|||||||
# Code of Conduct
|
# Code of Conduct
|
||||||
|
|
||||||
We have a [code of conduct](CODE_OF_CONDUCT.md) that we all must
|
We have a [code of conduct](CODE_OF_CONDUCT.md) that we all must
|
||||||
read. Be polite to everyone. If you are not in your best day, take a
|
follow. Be polite to everyone. If you are not in your best day, take a
|
||||||
deep breath and try again. Smile :smile:
|
deep breath and try again. Smile :smile:
|
||||||
|
|
||||||
# New Issues
|
# New Issues
|
||||||
@ -24,31 +24,33 @@ check the following items:
|
|||||||
* See how to get the source code correctly in the [INSTALL](INSTALL.md) guide.
|
* See how to get the source code correctly in the [INSTALL](INSTALL.md) guide.
|
||||||
* Check if you are using the latest repository clone.
|
* Check if you are using the latest repository clone.
|
||||||
* Remember that we use submodules, so you need to initialize and update them.
|
* Remember that we use submodules, so you need to initialize and update them.
|
||||||
|
* Search in the [GitHub issues about compilation](https://github.com/aseprite/aseprite/issues?q=is%3Aissue+label%3Acompilation)
|
||||||
|
if someone else had the same problem.
|
||||||
* Remember that might be some [pull requests](https://github.com/aseprite/aseprite/pulls)
|
* Remember that might be some [pull requests](https://github.com/aseprite/aseprite/pulls)
|
||||||
being reviewed to fix your same problem.
|
being reviewed to fix your same issue.
|
||||||
|
|
||||||
If you have a compilation problem, you can ask in the
|
If you have a compilation problem, you can ask in the
|
||||||
[Development category](https://community.aseprite.org/c/development)
|
[Development category](https://community.aseprite.org/c/development)
|
||||||
in the [Community site](https://community.aseprite.org/) for help
|
in the [Community site](https://community.aseprite.org/) for help
|
||||||
or creating a [GitHub issue](https://github.com/aseprite/aseprite/issues/new).
|
or create a [new GitHub issue](https://github.com/aseprite/aseprite/issues/new).
|
||||||
|
|
||||||
# Contributing
|
# Contributing
|
||||||
|
|
||||||
One of the easiest ways to contribute is writing articles,
|
One of the easiest ways to contribute is writing articles, [Steam
|
||||||
[Steam reviews](https://steamcommunity.com/app/431730/reviews/),
|
reviews](https://steamcommunity.com/app/431730/reviews/), blog posts,
|
||||||
blog posts, recording video tutorials,
|
recording video tutorials, creating pixel art in social media with
|
||||||
[creating pixel art](https://aseprite.deviantart.com/), or showing your love
|
[#aseprite](https://twitter.com/search?q=%23aseprite), or showing your
|
||||||
to Aseprite e.g. naming Aseprite in your website and linking it to
|
love to Aseprite, e.g. naming Aseprite in your website and linking it
|
||||||
https://www.aseprite.org/, following
|
to https://www.aseprite.org/, following [@aseprite](https://twitter.com/aseprite),
|
||||||
[@aseprite](https://twitter.com/aseprite) twitter account, or
|
or [buying an extra Aseprite copy to your friends](https://www.aseprite.org/download/).
|
||||||
[buying an extra Aseprite copy to your friend](https://www.aseprite.org/download/).
|
|
||||||
|
|
||||||
Other ways to contribute require direct contact with us. For example:
|
Other ways to contribute require direct contact with us. For example:
|
||||||
|
|
||||||
* [Writing documentation](https://github.com/aseprite/docs).
|
* [Writing documentation](https://github.com/aseprite/docs).
|
||||||
* Making art with Aseprite and for Aseprite (logos, skins, mockups).
|
* Making art (and fan art) with Aseprite and for Aseprite (logos, skins, mockups).
|
||||||
* Sending patches for features or bug fixes.
|
* Sending patches for features or bug fixes.
|
||||||
* Reviewing issues in the [issue tracker](https://github.com/aseprite/aseprite/issues) and making comments.
|
* Reviewing issues in the [issue tracker](https://github.com/aseprite/aseprite/issues)
|
||||||
|
and making comments.
|
||||||
* Helping other users in the [Community](https://community.aseprite.org/) site.
|
* Helping other users in the [Community](https://community.aseprite.org/) site.
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
@ -56,15 +58,16 @@ Other ways to contribute require direct contact with us. For example:
|
|||||||
You can start seeing the
|
You can start seeing the
|
||||||
[documentation](https://www.aseprite.org/docs/), and
|
[documentation](https://www.aseprite.org/docs/), and
|
||||||
[contact us](mailto:support@aseprite.org) if you want to help
|
[contact us](mailto:support@aseprite.org) if you want to help
|
||||||
writting documentation
|
writing documentation or recording [tutorials](https://www.aseprite.org/docs/tutorial/).
|
||||||
or recording [tutorials](https://www.aseprite.org/docs/tutorial/).
|
|
||||||
|
|
||||||
If you are going to write documentation, we recommend you to take
|
If you are going to write some docs, we recommend you to take
|
||||||
screenshots or record a GIF animations to show steps:
|
screenshots or record a GIF animations to showcase the feature your
|
||||||
|
are documenting or the steps to follow:
|
||||||
|
|
||||||
* As screen recording software, on Windows you can generate GIF files
|
* As screen recording software, on Windows you can generate GIF files
|
||||||
using [LICEcap](http://www.cockos.com/licecap/).
|
using [LICEcap](http://www.cockos.com/licecap/).
|
||||||
* You can upload the PNG/GIF images to [Imgur](http://imgur.com/).
|
* PNG/GIF images can be uploaded in the same docs repository
|
||||||
|
[with a pull request](https://github.com/aseprite/docs/pulls)
|
||||||
|
|
||||||
## Reviewing Issues
|
## Reviewing Issues
|
||||||
|
|
||||||
@ -74,54 +77,54 @@ new [features](https://community.aseprite.org/c/features),
|
|||||||
[bug reports](https://community.aseprite.org/c/bugs), etc. You are
|
[bug reports](https://community.aseprite.org/c/bugs), etc. You are
|
||||||
encouraged to create mockups for any issue you see and attach them.
|
encouraged to create mockups for any issue you see and attach them.
|
||||||
|
|
||||||
## Hacking
|
## Code submission policy
|
||||||
|
|
||||||
The first thing to keep in mind if you want to modify the source code:
|
We have some rules for the changes and commits that are contributed:
|
||||||
checkout the **main** branch. It is the branch that we use to
|
|
||||||
develop new features and fix issues that are planned for the next big
|
|
||||||
release. See the [INSTALL](INSTALL.md) guide to know how to compile.
|
|
||||||
|
|
||||||
To start looking the source code, see how it is organized in
|
* First of all you will need to sign our
|
||||||
[src/README.md](https://github.com/aseprite/aseprite/tree/main/src/#aseprite-source-code)
|
[Contributor License Agreement](https://github.com/igarastudio/cla) (CLA)
|
||||||
file.
|
to submit your code.
|
||||||
|
* Split your changes in the most atomic commits possible: one commit
|
||||||
|
for feature, or fix.
|
||||||
|
* Rebase your commits to the `main` branch (or `beta` if you are
|
||||||
|
targeting the beta version).
|
||||||
|
* Wrap your commit messages at 72 characters.
|
||||||
|
* The first line of the commit message is the subject line.
|
||||||
|
* Write the subject line in the imperative mood, e.g. "Fix something",
|
||||||
|
not "Fixed something".
|
||||||
|
* For platform-specific commits start the subject line using
|
||||||
|
`[win]`, `[osx]`, or `[x11]` prefixes.
|
||||||
|
* For CLI related commits you can use the `[cli]` prefix in the
|
||||||
|
subject line.
|
||||||
|
* For Lua scripting related commits can use the `[lua]` prefix in
|
||||||
|
the subject line.
|
||||||
|
* Check the spelling of your code, comments and commit messages.
|
||||||
|
* Follow our [coding style guide](docs/CODING_STYLE.md). We're using
|
||||||
|
some C++17 features, targeting macOS 10.9 mainly as the oldest
|
||||||
|
platform (and the one limiting us to newer C++ standards),
|
||||||
|
|
||||||
## Forking & Pull Requests
|
You can also take a look at the [src/README.md](https://github.com/aseprite/aseprite/tree/main/src/#aseprite-source-code)
|
||||||
|
guide which contains some information about how the code is structured.
|
||||||
|
|
||||||
You can fork the GitHub repository using the Fork button at
|
# Community
|
||||||
[https://github.com/aseprite/aseprite](https://github.com/aseprite/aseprite).
|
|
||||||
|
|
||||||
The Pull Requests (PR) systems works in this way:
|
|
||||||
|
|
||||||
1. First of all you will need to sign our
|
|
||||||
[Contributor License Agreement](https://github.com/igarastudio/cla) (CLA).
|
|
||||||
1. Then you can start working on Aseprite. Create a new branch from `main`, e.g. `fix-8` to fix the issue 8.
|
|
||||||
Check this guide about [how to name your branch](https://github.com/agis/git-style-guide#branches).
|
|
||||||
1. Start working on that new branch, and push your commits to your fork.
|
|
||||||
1. Create a new PR to merge your `fix-8` branch to the official `main`.
|
|
||||||
1. If the PR is accepted (does not require review/comments/modifications),
|
|
||||||
your branch is merged into `main`.
|
|
||||||
1. You will need to pull changes from the official `main` branch, and
|
|
||||||
merge them in your own `main` branch. Finally you can discard your
|
|
||||||
own `fix-8` branch (because those changes should be already merged
|
|
||||||
into `main` if the PR was accepted).
|
|
||||||
1. Continue working from the new `main` head.
|
|
||||||
|
|
||||||
To keep in mind: **always** start working from the `main` head, if you
|
|
||||||
want to fix three different issues, create three different branches
|
|
||||||
from `main` and then send three different PR. Do not chain all the
|
|
||||||
fixes in one single branch. E.g. `fix-issues-3-and-8-and-25`.
|
|
||||||
|
|
||||||
## Community
|
|
||||||
|
|
||||||
You can use the [Development category](https://community.aseprite.org/c/development)
|
You can use the [Development category](https://community.aseprite.org/c/development)
|
||||||
to ask question about the code, how to compile, etc.
|
to ask questions about the code, how to compile, etc.
|
||||||
If you want to start working in something
|
If you want to start working on something
|
||||||
([issue](https://github.com/aseprite/aseprite/issues),
|
([issue](https://github.com/aseprite/aseprite/issues),
|
||||||
[bug](https://community.aseprite.org/c/bugs),
|
[bug](https://community.aseprite.org/c/bugs),
|
||||||
or [feature](https://community.aseprite.org/c/features)),
|
or [feature](https://community.aseprite.org/c/features)),
|
||||||
post a comment asking if somebody is already working on that,
|
post a comment asking if somebody is already working on that,
|
||||||
in that way you can avoid start programming in something that is already
|
in that way you can avoid starting programming in something that is already
|
||||||
done for the next release or which someone else is working on.
|
done for the next release or which someone else is working on.
|
||||||
|
|
||||||
And always remember to take a look at our
|
# Future
|
||||||
[roadmap](http://www.aseprite.org/roadmap/).
|
|
||||||
|
If you want to contribute a new feature, I highly recommend trying to
|
||||||
|
contribute a couple of pull requests to fix some bugs first. After
|
||||||
|
that you can check what are the features we're planning for the
|
||||||
|
future:
|
||||||
|
|
||||||
|
* Our [roadmap](http://www.aseprite.org/roadmap/) and our [planning](https://github.com/orgs/aseprite/projects/10).
|
||||||
|
* The most liked [issues on GitHub](https://github.com/aseprite/aseprite/issues?q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc).
|
||||||
|
* [Features on the forum](https://community.aseprite.org/c/features/7/l/latest?order=votes) with the most votes.
|
||||||
|
2
laf
2
laf
@ -1 +1 @@
|
|||||||
Subproject commit c90b81aec001293bdf7d19eb7feb22509716705e
|
Subproject commit 10caee2455d07676d79a69a102399080f5eba4a9
|
@ -74,6 +74,7 @@ AppOptions::AppOptions(int argc, const char* argv[])
|
|||||||
, m_scriptParam(m_po.add("script-param").requiresValue("name=value").description("Parameter for a script executed from the\nCLI that you can access with app.params"))
|
, m_scriptParam(m_po.add("script-param").requiresValue("name=value").description("Parameter for a script executed from the\nCLI that you can access with app.params"))
|
||||||
#endif
|
#endif
|
||||||
, m_listLayers(m_po.add("list-layers").description("List layers of the next given sprite\nor include layers in JSON data"))
|
, m_listLayers(m_po.add("list-layers").description("List layers of the next given sprite\nor include layers in JSON data"))
|
||||||
|
, m_listLayerHierarchy(m_po.add("list-layer-hierarchy").description("List layers with groups of the next given sprite\nor include layers hierarchy in JSON data"))
|
||||||
, m_listTags(m_po.add("list-tags").description("List tags of the next given sprite\nor include frame tags in JSON data"))
|
, m_listTags(m_po.add("list-tags").description("List tags of the next given sprite\nor include frame tags in JSON data"))
|
||||||
, m_listSlices(m_po.add("list-slices").description("List slices of the next given sprite\nor include slices in JSON data"))
|
, m_listSlices(m_po.add("list-slices").description("List slices of the next given sprite\nor include slices in JSON data"))
|
||||||
, m_oneFrame(m_po.add("oneframe").description("Load just the first frame"))
|
, m_oneFrame(m_po.add("oneframe").description("Load just the first frame"))
|
||||||
|
@ -90,6 +90,7 @@ public:
|
|||||||
const Option& scriptParam() const { return m_scriptParam; }
|
const Option& scriptParam() const { return m_scriptParam; }
|
||||||
#endif
|
#endif
|
||||||
const Option& listLayers() const { return m_listLayers; }
|
const Option& listLayers() const { return m_listLayers; }
|
||||||
|
const Option& listLayerHierarchy() const { return m_listLayerHierarchy; }
|
||||||
const Option& listTags() const { return m_listTags; }
|
const Option& listTags() const { return m_listTags; }
|
||||||
const Option& listSlices() const { return m_listSlices; }
|
const Option& listSlices() const { return m_listSlices; }
|
||||||
const Option& oneFrame() const { return m_oneFrame; }
|
const Option& oneFrame() const { return m_oneFrame; }
|
||||||
@ -164,6 +165,7 @@ private:
|
|||||||
Option& m_scriptParam;
|
Option& m_scriptParam;
|
||||||
#endif
|
#endif
|
||||||
Option& m_listLayers;
|
Option& m_listLayers;
|
||||||
|
Option& m_listLayerHierarchy;
|
||||||
Option& m_listTags;
|
Option& m_listTags;
|
||||||
Option& m_listSlices;
|
Option& m_listSlices;
|
||||||
Option& m_oneFrame;
|
Option& m_oneFrame;
|
||||||
|
@ -37,6 +37,7 @@ namespace app {
|
|||||||
bool splitGrid = false;
|
bool splitGrid = false;
|
||||||
bool allLayers = false;
|
bool allLayers = false;
|
||||||
bool listLayers = false;
|
bool listLayers = false;
|
||||||
|
bool listLayerHierarchy = false;
|
||||||
bool listTags = false;
|
bool listTags = false;
|
||||||
bool listSlices = false;
|
bool listSlices = false;
|
||||||
bool ignoreEmpty = false;
|
bool ignoreEmpty = false;
|
||||||
|
@ -587,6 +587,13 @@ int CliProcessor::process(Context* ctx)
|
|||||||
else
|
else
|
||||||
cof.listLayers = true;
|
cof.listLayers = true;
|
||||||
}
|
}
|
||||||
|
// --list-layer-hierarchy
|
||||||
|
else if (opt == &m_options.listLayerHierarchy()) {
|
||||||
|
if (m_exporter)
|
||||||
|
m_exporter->setListLayerHierarchy(true);
|
||||||
|
else
|
||||||
|
cof.listLayerHierarchy = true;
|
||||||
|
}
|
||||||
// --list-tags
|
// --list-tags
|
||||||
else if (opt == &m_options.listTags()) {
|
else if (opt == &m_options.listTags()) {
|
||||||
if (m_exporter)
|
if (m_exporter)
|
||||||
|
@ -67,6 +67,10 @@ void DefaultCliDelegate::afterOpenFile(const CliOpenFile& cof)
|
|||||||
std::cout << layer->name() << "\n";
|
std::cout << layer->name() << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cof.listLayerHierarchy) {
|
||||||
|
std::cout << cof.document->sprite()->visibleLayerHierarchyAsString() << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
if (cof.listTags) {
|
if (cof.listTags) {
|
||||||
for (doc::Tag* tag : cof.document->sprite()->tags())
|
for (doc::Tag* tag : cof.document->sprite()->tags())
|
||||||
std::cout << tag->name() << "\n";
|
std::cout << tag->name() << "\n";
|
||||||
|
@ -67,6 +67,9 @@ void PreviewCliDelegate::afterOpenFile(const CliOpenFile& cof)
|
|||||||
if (cof.listLayers)
|
if (cof.listLayers)
|
||||||
std::cout << " - List layers\n";
|
std::cout << " - List layers\n";
|
||||||
|
|
||||||
|
if (cof.listLayerHierarchy)
|
||||||
|
std::cout << " - List layer hierarchy\n";
|
||||||
|
|
||||||
if (cof.listTags)
|
if (cof.listTags)
|
||||||
std::cout << " - List tags\n";
|
std::cout << " - List tags\n";
|
||||||
|
|
||||||
|
@ -623,6 +623,7 @@ void DocExporter::reset()
|
|||||||
m_splitTags = false;
|
m_splitTags = false;
|
||||||
m_listTags = false;
|
m_listTags = false;
|
||||||
m_listLayers = false;
|
m_listLayers = false;
|
||||||
|
m_listLayerHierarchy = false;
|
||||||
m_listSlices = false;
|
m_listSlices = false;
|
||||||
m_documents.clear();
|
m_documents.clear();
|
||||||
}
|
}
|
||||||
@ -1487,7 +1488,7 @@ void DocExporter::createDataFile(const Samples& samples,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// meta.layers
|
// meta.layers
|
||||||
if (m_listLayers) {
|
if (m_listLayers || m_listLayerHierarchy) {
|
||||||
LayerList metaLayers;
|
LayerList metaLayers;
|
||||||
for (auto& item : m_documents) {
|
for (auto& item : m_documents) {
|
||||||
if (item.isOneImageOnly())
|
if (item.isOneImageOnly())
|
||||||
|
@ -77,6 +77,7 @@ namespace app {
|
|||||||
void setSplitTags(bool splitTags) { m_splitTags = splitTags; }
|
void setSplitTags(bool splitTags) { m_splitTags = splitTags; }
|
||||||
void setListTags(bool value) { m_listTags = value; }
|
void setListTags(bool value) { m_listTags = value; }
|
||||||
void setListLayers(bool value) { m_listLayers = value; }
|
void setListLayers(bool value) { m_listLayers = value; }
|
||||||
|
void setListLayerHierarchy(bool value) { m_listLayerHierarchy = value; }
|
||||||
void setListSlices(bool value) { m_listSlices = value; }
|
void setListSlices(bool value) { m_listSlices = value; }
|
||||||
|
|
||||||
void addImage(
|
void addImage(
|
||||||
@ -180,6 +181,7 @@ namespace app {
|
|||||||
bool m_splitTags;
|
bool m_splitTags;
|
||||||
bool m_listTags;
|
bool m_listTags;
|
||||||
bool m_listLayers;
|
bool m_listLayers;
|
||||||
|
bool m_listLayerHierarchy;
|
||||||
bool m_listSlices;
|
bool m_listSlices;
|
||||||
Items m_documents;
|
Items m_documents;
|
||||||
|
|
||||||
|
@ -50,6 +50,13 @@ FILE* lua_user_fopen(const char* fname,
|
|||||||
return base::open_file_raw(fname, mode);
|
return base::open_file_raw(fname, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FILE* lua_user_freopen(const char* fname,
|
||||||
|
const char* mode,
|
||||||
|
FILE* stream)
|
||||||
|
{
|
||||||
|
return base::reopen_file_raw(fname, mode, stream);
|
||||||
|
}
|
||||||
|
|
||||||
namespace app {
|
namespace app {
|
||||||
namespace script {
|
namespace script {
|
||||||
|
|
||||||
|
@ -540,6 +540,20 @@ void LayerGroup::allTilemaps(LayerList& list) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string LayerGroup::visibleLayerHierarchyAsString(const std::string& indent) const
|
||||||
|
{
|
||||||
|
std::string str;
|
||||||
|
for (Layer* child : m_layers) {
|
||||||
|
if (!child->isVisible())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
str += indent + child->name() + (child->isGroup() ? "/" : "") + "\n";
|
||||||
|
if (child->isGroup())
|
||||||
|
str += static_cast<LayerGroup*>(child)->visibleLayerHierarchyAsString(indent+" ");
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
void LayerGroup::getCels(CelList& cels) const
|
void LayerGroup::getCels(CelList& cels) const
|
||||||
{
|
{
|
||||||
for (const Layer* layer : m_layers)
|
for (const Layer* layer : m_layers)
|
||||||
|
@ -215,6 +215,7 @@ namespace doc {
|
|||||||
void allVisibleReferenceLayers(LayerList& list) const;
|
void allVisibleReferenceLayers(LayerList& list) const;
|
||||||
void allBrowsableLayers(LayerList& list) const;
|
void allBrowsableLayers(LayerList& list) const;
|
||||||
void allTilemaps(LayerList& list) const;
|
void allTilemaps(LayerList& list) const;
|
||||||
|
std::string visibleLayerHierarchyAsString(const std::string& indent) const;
|
||||||
|
|
||||||
void getCels(CelList& cels) const override;
|
void getCels(CelList& cels) const override;
|
||||||
void displaceFrames(frame_t fromThis, frame_t delta) override;
|
void displaceFrames(frame_t fromThis, frame_t delta) override;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite Document Library
|
// Aseprite Document Library
|
||||||
// Copyright (c) 2020-2022 Igara Studio S.A.
|
// Copyright (c) 2020-2024 Igara Studio S.A.
|
||||||
// Copyright (c) 2001-2016 David Capello
|
// Copyright (c) 2001-2016 David Capello
|
||||||
//
|
//
|
||||||
// This file is released under the terms of the MIT license.
|
// This file is released under the terms of the MIT license.
|
||||||
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include "base/debug.h"
|
#include "base/debug.h"
|
||||||
#include "base/disable_copying.h"
|
#include "base/disable_copying.h"
|
||||||
|
#include "base/ints.h"
|
||||||
#include "doc/object.h"
|
#include "doc/object.h"
|
||||||
#include "doc/rgbmap.h"
|
#include "doc/rgbmap.h"
|
||||||
|
|
||||||
@ -23,7 +24,7 @@ namespace doc {
|
|||||||
// It acts like a cache for Palette:findBestfit() calls.
|
// It acts like a cache for Palette:findBestfit() calls.
|
||||||
class RgbMapRGB5A3 : public RgbMap {
|
class RgbMapRGB5A3 : public RgbMap {
|
||||||
// Bit activated on m_map entries that aren't yet calculated.
|
// Bit activated on m_map entries that aren't yet calculated.
|
||||||
const int INVALID = 256;
|
const uint16_t INVALID = 256;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RgbMapRGB5A3();
|
RgbMapRGB5A3();
|
||||||
@ -31,13 +32,13 @@ namespace doc {
|
|||||||
// RgbMap impl
|
// RgbMap impl
|
||||||
void regenerateMap(const Palette* palette, int maskIndex) override;
|
void regenerateMap(const Palette* palette, int maskIndex) override;
|
||||||
int mapColor(const color_t rgba) const override {
|
int mapColor(const color_t rgba) const override {
|
||||||
const int r = rgba_getr(rgba);
|
const uint8_t r = rgba_getr(rgba);
|
||||||
const int g = rgba_getg(rgba);
|
const uint8_t g = rgba_getg(rgba);
|
||||||
const int b = rgba_getb(rgba);
|
const uint8_t b = rgba_getb(rgba);
|
||||||
const int a = rgba_geta(rgba);
|
const uint8_t a = rgba_geta(rgba);
|
||||||
// bits -> bbbbbgggggrrrrraaa
|
// bits -> bbbbbgggggrrrrraaa
|
||||||
const int i = (a>>5) | ((b>>3) << 3) | ((g>>3) << 8) | ((r>>3) << 13);
|
const uint32_t i = (a>>5) | ((b>>3) << 3) | ((g>>3) << 8) | ((r>>3) << 13);
|
||||||
const int v = m_map[i];
|
const uint16_t v = m_map[i];
|
||||||
return (v & INVALID) ? generateEntry(i, r, g, b, a): v;
|
return (v & INVALID) ? generateEntry(i, r, g, b, a): v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -773,6 +773,11 @@ LayerList Sprite::allTilemaps() const
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Sprite::visibleLayerHierarchyAsString() const
|
||||||
|
{
|
||||||
|
return m_root->visibleLayerHierarchyAsString("");
|
||||||
|
}
|
||||||
|
|
||||||
CelsRange Sprite::cels() const
|
CelsRange Sprite::cels() const
|
||||||
{
|
{
|
||||||
SelectedFrames selFrames;
|
SelectedFrames selFrames;
|
||||||
|
@ -219,6 +219,7 @@ namespace doc {
|
|||||||
LayerList allVisibleReferenceLayers() const;
|
LayerList allVisibleReferenceLayers() const;
|
||||||
LayerList allBrowsableLayers() const;
|
LayerList allBrowsableLayers() const;
|
||||||
LayerList allTilemaps() const;
|
LayerList allTilemaps() const;
|
||||||
|
std::string visibleLayerHierarchyAsString() const;
|
||||||
|
|
||||||
CelsRange cels() const;
|
CelsRange cels() const;
|
||||||
CelsRange cels(frame_t frame) const;
|
CelsRange cels(frame_t frame) const;
|
||||||
|
@ -8,3 +8,9 @@ assert(100 == math.min(100, 200, 300))
|
|||||||
assert(300 == math.max(100, 200, 300))
|
assert(300 == math.max(100, 200, 300))
|
||||||
assert(50 == math.fmod(250, 100))
|
assert(50 == math.fmod(250, 100))
|
||||||
assert(3141 == math.floor(1000*math.pi))
|
assert(3141 == math.floor(1000*math.pi))
|
||||||
|
|
||||||
|
-- Add tests for integer <-> number comparisons
|
||||||
|
assert(math.floor(0.5) == 0)
|
||||||
|
assert(math.floor(0.5) == 0.0)
|
||||||
|
assert(math.floor(0.5) ~= 0.5)
|
||||||
|
assert(math.floor(0.5)+0.1-0.1 ~= 0.5)
|
||||||
|
@ -133,8 +133,8 @@ for _,cm in ipairs{ ColorMode.RGB,
|
|||||||
app.sprite = spr
|
app.sprite = spr
|
||||||
app.command.SaveFileCopyAs{ filename=fn, slice="small_slice", scale=scale }
|
app.command.SaveFileCopyAs{ filename=fn, slice="small_slice", scale=scale }
|
||||||
local c = app.open(fn)
|
local c = app.open(fn)
|
||||||
assert(c.width == slice.bounds.width*scale)
|
assert(c.width == math.floor(slice.bounds.width*scale))
|
||||||
assert(c.height == slice.bounds.height*scale)
|
assert(c.height == math.floor(slice.bounds.height*scale))
|
||||||
|
|
||||||
local testImg = Image(spr.cels[1].image, spr.slices[1].bounds)
|
local testImg = Image(spr.cels[1].image, spr.slices[1].bounds)
|
||||||
fix_images(testImg, scale, fileExt, c, cm, c1)
|
fix_images(testImg, scale, fileExt, c, cm, c1)
|
||||||
|
@ -21,8 +21,8 @@ do
|
|||||||
a:resize(6, 8)
|
a:resize(6, 8)
|
||||||
assert(a.width == 6)
|
assert(a.width == 6)
|
||||||
assert(a.height == 8)
|
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.width == math.floor(32 * 6 / 4)) -- Check that the image was resized (not only the canvas)
|
||||||
assert(a.cels[1].image.height == 64 * 8 / 5)
|
assert(a.cels[1].image.height == math.floor(64 * 8 / 5))
|
||||||
a:crop{x=-1, y=-1, width=20, height=30}
|
a:crop{x=-1, y=-1, width=20, height=30}
|
||||||
assert(a.width == 20)
|
assert(a.width == 20)
|
||||||
assert(a.height == 30)
|
assert(a.height == 30)
|
||||||
|
2
third_party/lua
vendored
2
third_party/lua
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 04abf20c9e8c973c62b30d0b98f6884ff665b1ba
|
Subproject commit 2a00e6b0013f54ce80b6e3cefe6514e13229987a
|
Loading…
x
Reference in New Issue
Block a user