mirror of https://github.com/aseprite/aseprite.git
Compare commits
71 Commits
b1da5f814a
...
1e34821897
| Author | SHA1 | Date |
|---|---|---|
|
|
1e34821897 | |
|
|
6c7544a132 | |
|
|
577caa4793 | |
|
|
f3a372e78e | |
|
|
11df0bc877 | |
|
|
41e5097c33 | |
|
|
cf290b7679 | |
|
|
d7b2faca6d | |
|
|
fa0b25fe87 | |
|
|
f26ce64208 | |
|
|
e39dc90001 | |
|
|
8f0dea0988 | |
|
|
6f1870cff3 | |
|
|
e8f18087e5 | |
|
|
d8ac1a7a9e | |
|
|
5cfa75ab3f | |
|
|
94174509a4 | |
|
|
c444b566e1 | |
|
|
5d5f3ec234 | |
|
|
71e680e05a | |
|
|
df5dcdc1d9 | |
|
|
85793a9e5f | |
|
|
d7b07a5173 | |
|
|
fae42dbe12 | |
|
|
689e1ff524 | |
|
|
f549d476f1 | |
|
|
f494b8f343 | |
|
|
907138d5dd | |
|
|
7e4f9ad078 | |
|
|
af349ce7ee | |
|
|
3bc4ac0838 | |
|
|
1774d86939 | |
|
|
dce1dfd06b | |
|
|
6283d69707 | |
|
|
27da1b03d0 | |
|
|
834a94855f | |
|
|
21ad78cdbb | |
|
|
20b11a0fd3 | |
|
|
8d4c4857ee | |
|
|
70c8924719 | |
|
|
286dd1c755 | |
|
|
3a14ac72a4 | |
|
|
2db193b8e3 | |
|
|
002356ce19 | |
|
|
9a1e92da35 | |
|
|
07803ff361 | |
|
|
8e07617a9d | |
|
|
9c5ca6bcc6 | |
|
|
e193891df3 | |
|
|
bb8547d004 | |
|
|
85997a08cf | |
|
|
0995e72a6f | |
|
|
f61c2c3950 | |
|
|
0c49f2d7ad | |
|
|
5f7cc42333 | |
|
|
8e75cfc4c7 | |
|
|
983b07383f | |
|
|
c57554646b | |
|
|
74953174d6 | |
|
|
49fa35237a | |
|
|
0ccf9dcc4f | |
|
|
194f8424a8 | |
|
|
debab653fa | |
|
|
6e9024d54d | |
|
|
1fa7fd0831 | |
|
|
ab6b040e83 | |
|
|
bc312a37b3 | |
|
|
3129fda977 | |
|
|
6cb61fb41e | |
|
|
aa817a8d2a | |
|
|
40031f83d8 |
|
|
@ -1,9 +0,0 @@
|
||||||
Describe your bug report or feature request here
|
|
||||||
...
|
|
||||||
...
|
|
||||||
...
|
|
||||||
|
|
||||||
### Aseprite and System version
|
|
||||||
|
|
||||||
* Aseprite version: version number, installer/portable/Steam/beta/dev/commit-hash
|
|
||||||
* System: Windows/macOS/Linux, version, distribution
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to help us improve
|
||||||
|
title: ''
|
||||||
|
labels: bug, triage
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
**To Reproduce**
|
||||||
|
Steps to reproduce the behavior:
|
||||||
|
1. Go to '...'
|
||||||
|
2. Click on '....'
|
||||||
|
3. Scroll down to '....'
|
||||||
|
4. See error
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**Screenshots**
|
||||||
|
If applicable, add screenshots or a screen recording to help explain your problem.
|
||||||
|
|
||||||
|
**Aseprite & System (please complete the following information):**
|
||||||
|
- Aseprite: [version number, installer/portable/Steam/beta/dev/commit-hash]
|
||||||
|
- System: [Windows/macOS/Linux, version, distribution]
|
||||||
|
- Extensions: [List the extensions you have installed]
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context about the problem here.
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for Aseprite
|
||||||
|
title: ''
|
||||||
|
labels: feature, triage
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Did other user suggested a similar idea?**
|
||||||
|
- [ ] No
|
||||||
|
- [ ] Yes/Links to similar ideas
|
||||||
|
> You can try to find a similar feature requests before in:
|
||||||
|
> - GitHub issues: https://github.com/aseprite/aseprite/issues?q=label%3Afeature
|
||||||
|
> - Community site: https://community.aseprite.org/c/features/7
|
||||||
|
> - Steam community: https://steamcommunity.com/app/431730/discussions/1/
|
||||||
|
> In case you find a similar feature request, making a comment there will be useful to give some traction and show interest in the feature.
|
||||||
|
|
||||||
|
**Is your feature request related to a problem? Please describe.**
|
||||||
|
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||||
|
|
||||||
|
**Describe the solution you'd like**
|
||||||
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
|
**Describe alternatives you've considered**
|
||||||
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context or screenshots about the feature request here.
|
||||||
|
|
@ -24,7 +24,8 @@ jobs:
|
||||||
sudo apt-get update -qq
|
sudo apt-get update -qq
|
||||||
sudo apt-get install -y \
|
sudo apt-get install -y \
|
||||||
libpixman-1-dev libfreetype6-dev libharfbuzz-dev zlib1g-dev \
|
libpixman-1-dev libfreetype6-dev libharfbuzz-dev zlib1g-dev \
|
||||||
libx11-dev libxcursor-dev libxi-dev libgl1-mesa-dev libfontconfig1-dev
|
libx11-dev libxcursor-dev libxi-dev libxrandr-dev libgl1-mesa-dev \
|
||||||
|
libfontconfig1-dev
|
||||||
- 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'
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,8 @@ jobs:
|
||||||
sudo apt-get update -qq
|
sudo apt-get update -qq
|
||||||
sudo apt-get install -y \
|
sudo apt-get install -y \
|
||||||
libpixman-1-dev libfreetype6-dev libharfbuzz-dev zlib1g-dev \
|
libpixman-1-dev libfreetype6-dev libharfbuzz-dev zlib1g-dev \
|
||||||
libx11-dev libxcursor-dev libxi-dev libgl1-mesa-dev libfontconfig1-dev
|
libx11-dev libxcursor-dev libxi-dev libxrandr-dev libgl1-mesa-dev \
|
||||||
|
libfontconfig1-dev
|
||||||
- name: Install Skia
|
- name: Install Skia
|
||||||
if: ${{ matrix.ui == 'gui' }}
|
if: ${{ matrix.ui == 'gui' }}
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ jobs:
|
||||||
apt_packages: |
|
apt_packages: |
|
||||||
libc++-dev, libc++abi-dev, libpixman-1-dev,
|
libc++-dev, libc++abi-dev, libpixman-1-dev,
|
||||||
libfreetype6-dev, libharfbuzz-dev, zlib1g-dev, libx11-dev,
|
libfreetype6-dev, libharfbuzz-dev, zlib1g-dev, libx11-dev,
|
||||||
libxcursor-dev, libxi-dev, libgl1-mesa-dev
|
libxcursor-dev, libxi-dev, libxrandr-dev, libgl1-mesa-dev
|
||||||
cmake_command: |
|
cmake_command: |
|
||||||
cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -DLAF_BACKEND=none -DCMAKE_EXPORT_COMPILE_COMMANDS=on
|
cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -DLAF_BACKEND=none -DCMAKE_EXPORT_COMPILE_COMMANDS=on
|
||||||
- uses: ZedThree/clang-tidy-review/upload@v0.20.1
|
- uses: ZedThree/clang-tidy-review/upload@v0.20.1
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ On macOS you will need macOS 15.4 SDK and Xcode 16.3 (older versions might work)
|
||||||
|
|
||||||
You will need the following dependencies on Ubuntu/Debian:
|
You will need the following dependencies on Ubuntu/Debian:
|
||||||
|
|
||||||
sudo apt-get install -y g++ clang cmake ninja-build libx11-dev libxcursor-dev libxi-dev libgl1-mesa-dev libfontconfig1-dev
|
sudo apt-get install -y g++ clang cmake ninja-build libx11-dev libxcursor-dev libxi-dev libxrandr-dev libgl1-mesa-dev libfontconfig1-dev
|
||||||
|
|
||||||
Or use clang-12 packages (or newer) in case that clang in your distribution is older than clang 12.0:
|
Or use clang-12 packages (or newer) in case that clang in your distribution is older than clang 12.0:
|
||||||
|
|
||||||
|
|
@ -82,15 +82,15 @@ Or use clang-12 packages (or newer) in case that clang in your distribution is o
|
||||||
|
|
||||||
On Fedora:
|
On Fedora:
|
||||||
|
|
||||||
sudo dnf install -y gcc-c++ clang libcxx-devel cmake ninja-build libX11-devel libXcursor-devel libXi-devel mesa-libGL-devel fontconfig-devel
|
sudo dnf install -y gcc-c++ clang libcxx-devel cmake ninja-build libX11-devel libXcursor-devel libXi-devel libXrandr-devel mesa-libGL-devel fontconfig-devel
|
||||||
|
|
||||||
On Arch:
|
On Arch:
|
||||||
|
|
||||||
sudo pacman -S gcc clang cmake ninja libx11 libxcursor mesa-libgl fontconfig libwebp
|
sudo pacman -S gcc clang cmake ninja libx11 libxcursor libxi libxrandr mesa-libgl fontconfig libwebp
|
||||||
|
|
||||||
On SUSE:
|
On SUSE:
|
||||||
|
|
||||||
sudo zypper install gcc-c++ clang cmake ninja libX11-devel libXcursor-devel libXi-devel Mesa-libGL-devel fontconfig-devel
|
sudo zypper install gcc-c++ clang cmake ninja libX11-devel libXcursor-devel libXi-devel libXrandr-devel Mesa-libGL-devel fontconfig-devel
|
||||||
|
|
||||||
# Automatic Building
|
# Automatic Building
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@
|
||||||
# HARFBUZZ_INCLUDE_DIRS - containg the HarfBuzz headers
|
# HARFBUZZ_INCLUDE_DIRS - containg the HarfBuzz headers
|
||||||
# HARFBUZZ_LIBRARIES - containg the HarfBuzz library
|
# HARFBUZZ_LIBRARIES - containg the HarfBuzz library
|
||||||
|
|
||||||
include(FindPkgConfig)
|
find_package(PkgConfig QUIET)
|
||||||
|
|
||||||
pkg_check_modules(PC_HARFBUZZ harfbuzz>=0.9.7)
|
pkg_check_modules(PC_HARFBUZZ harfbuzz>=0.9.7)
|
||||||
|
|
||||||
|
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
File diff suppressed because it is too large
Load Diff
11
data/gui.xml
11
data/gui.xml
|
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!-- Aseprite -->
|
<!-- Aseprite -->
|
||||||
<!-- Copyright (C) 2018-2024 Igara Studio S.A. -->
|
<!-- Copyright (C) 2018-2025 Igara Studio S.A. -->
|
||||||
<!-- Copyright (C) 2001-2018 David Capello -->
|
<!-- Copyright (C) 2001-2018 David Capello -->
|
||||||
<gui>
|
<gui>
|
||||||
<!-- Keyboard shortcuts -->
|
<!-- Keyboard shortcuts -->
|
||||||
|
|
@ -119,6 +119,7 @@
|
||||||
<param name="frame" value="current" />
|
<param name="frame" value="current" />
|
||||||
</key>
|
</key>
|
||||||
<key command="ReverseFrames" shortcut="Alt+I" />
|
<key command="ReverseFrames" shortcut="Alt+I" />
|
||||||
|
<key command="RunCommand" shortcut="Ctrl+Space" />
|
||||||
<key command="GotoFirstFrame" shortcut="Home" />
|
<key command="GotoFirstFrame" shortcut="Home" />
|
||||||
<key command="GotoPreviousFrame" shortcut="Left" context="Normal" />
|
<key command="GotoPreviousFrame" shortcut="Left" context="Normal" />
|
||||||
<key command="GotoNextFrame" shortcut="Right" context="Normal" />
|
<key command="GotoNextFrame" shortcut="Right" context="Normal" />
|
||||||
|
|
@ -372,6 +373,12 @@
|
||||||
<param name="quantity" value="1" />
|
<param name="quantity" value="1" />
|
||||||
</key>
|
</key>
|
||||||
|
|
||||||
|
<!-- Main selection actions (apply transformation / undo) -->
|
||||||
|
<key command="DeselectMask" shortcut="Esc" context="Transformation" />
|
||||||
|
<key command="Apply" shortcut="Enter" context="Transformation" />
|
||||||
|
<key command="Apply" shortcut="Enter Pad" context="Transformation" />
|
||||||
|
<key command="Undo" shortcut="Ctrl+Z" mac="Cmd+Z" context="Transformation" />
|
||||||
|
|
||||||
<!-- Move selection with arrows -->
|
<!-- Move selection with arrows -->
|
||||||
<key command="MoveMask" shortcut="Left" context="Selection">
|
<key command="MoveMask" shortcut="Left" context="Selection">
|
||||||
<param name="target" value="content" />
|
<param name="target" value="content" />
|
||||||
|
|
@ -1004,6 +1011,7 @@
|
||||||
<menu text="@.view" id="view_menu">
|
<menu text="@.view" id="view_menu">
|
||||||
<item command="DuplicateView" text="@.view_duplicate_view" group="view_new" />
|
<item command="DuplicateView" text="@.view_duplicate_view" group="view_new" />
|
||||||
<item command="ToggleWorkspaceLayout" text="@.view_workspace_layout" />
|
<item command="ToggleWorkspaceLayout" text="@.view_workspace_layout" />
|
||||||
|
<item command="RunCommand" text="@.view_run_command" />
|
||||||
<separator />
|
<separator />
|
||||||
<item command="ShowExtras" text="@.view_show_extras" />
|
<item command="ShowExtras" text="@.view_show_extras" />
|
||||||
<menu text="@.view_show" group="view_extras">
|
<menu text="@.view_show" group="view_extras">
|
||||||
|
|
@ -1205,6 +1213,7 @@
|
||||||
|
|
||||||
<menu id="slice_popup_menu">
|
<menu id="slice_popup_menu">
|
||||||
<item command="SliceProperties" text="@.properties" group="slice_popup_properties" />
|
<item command="SliceProperties" text="@.properties" group="slice_popup_properties" />
|
||||||
|
<item command="DuplicateSlice" text="@.duplicate" group="slice_popup_duplicate" />
|
||||||
<item command="RemoveSlice" text="@.delete" group="slice_popup_delete" />
|
<item command="RemoveSlice" text="@.delete" group="slice_popup_delete" />
|
||||||
</menu>
|
</menu>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -206,6 +206,7 @@ AddColor_Background = Background
|
||||||
AddColor_Foreground = Foreground
|
AddColor_Foreground = Foreground
|
||||||
AddColor_Specific = Specific
|
AddColor_Specific = Specific
|
||||||
AdvancedMode = Advanced Mode
|
AdvancedMode = Advanced Mode
|
||||||
|
Apply = Apply
|
||||||
AutocropSprite = Trim Sprite
|
AutocropSprite = Trim Sprite
|
||||||
AutocropSprite_ByGrid = Trim Sprite by Grid
|
AutocropSprite_ByGrid = Trim Sprite by Grid
|
||||||
BackgroundFromLayer = Background from Layer
|
BackgroundFromLayer = Background from Layer
|
||||||
|
|
@ -265,6 +266,7 @@ Despeckle = Despeckle
|
||||||
DeveloperConsole = Developer Console
|
DeveloperConsole = Developer Console
|
||||||
DiscardBrush = Discard Brush
|
DiscardBrush = Discard Brush
|
||||||
DuplicateLayer = Duplicate Layer
|
DuplicateLayer = Duplicate Layer
|
||||||
|
DuplicateSlice = Duplicate Slice
|
||||||
DuplicateSprite = Duplicate Sprite
|
DuplicateSprite = Duplicate Sprite
|
||||||
DuplicateView = Duplicate View
|
DuplicateView = Duplicate View
|
||||||
Exit = Exit
|
Exit = Exit
|
||||||
|
|
@ -401,6 +403,7 @@ ReverseFrames = Reverse Frames
|
||||||
Rotate = Rotate {0} {1}
|
Rotate = Rotate {0} {1}
|
||||||
Rotate_Selection = Selection
|
Rotate_Selection = Selection
|
||||||
Rotate_Sprite = Sprite
|
Rotate_Sprite = Sprite
|
||||||
|
RunCommand = Run Command
|
||||||
RunScript = Run Script
|
RunScript = Run Script
|
||||||
SaveFile = Save File
|
SaveFile = Save File
|
||||||
SaveFileAs = Save File As
|
SaveFileAs = Save File As
|
||||||
|
|
@ -582,8 +585,9 @@ rotsprite = RotSprite
|
||||||
pixel_perfect = Pixel-perfect
|
pixel_perfect = Pixel-perfect
|
||||||
linear_gradient = Linear Gradient
|
linear_gradient = Linear Gradient
|
||||||
radial_gradient = Radial Gradient
|
radial_gradient = Radial Gradient
|
||||||
drop_pixel = Drop pixels here (Enter)
|
drop_pixel_and_deselect = Apply transformation and deselect
|
||||||
cancel_drag = Cancel drag and drop (Esc)
|
drop_pixel = Apply transformation and keep selection
|
||||||
|
cancel_drag = Cancel transformation and undo/discard changes
|
||||||
auto_select_layer = Auto Select Layer
|
auto_select_layer = Auto Select Layer
|
||||||
all = All
|
all = All
|
||||||
none = None
|
none = None
|
||||||
|
|
@ -798,7 +802,22 @@ empty_fonts = No system fonts were found
|
||||||
[font_style]
|
[font_style]
|
||||||
antialias = Antialias
|
antialias = Antialias
|
||||||
hinting = Hinting
|
hinting = Hinting
|
||||||
|
hinting_none = No Hinting
|
||||||
|
hinting_slight = Slight Hinting
|
||||||
|
hinting_full = Full Hinting
|
||||||
ligatures = Ligatures
|
ligatures = Ligatures
|
||||||
|
font_weight = Font Weight
|
||||||
|
italic = Italic
|
||||||
|
font_weight_100 = Thin
|
||||||
|
font_weight_200 = Extra Light
|
||||||
|
font_weight_300 = Light
|
||||||
|
font_weight_400 = Normal
|
||||||
|
font_weight_500 = Medium
|
||||||
|
font_weight_600 = Semi Bold
|
||||||
|
font_weight_700 = Bold
|
||||||
|
font_weight_800 = Extra Bold
|
||||||
|
font_weight_900 = Black
|
||||||
|
font_weight_1000 = Extra Black
|
||||||
|
|
||||||
[frame_combo]
|
[frame_combo]
|
||||||
all_frames = All frames
|
all_frames = All frames
|
||||||
|
|
@ -826,6 +845,8 @@ same_in_all_tools = Same in all Tools
|
||||||
opacity = Opacity:
|
opacity = Opacity:
|
||||||
tolerance = Tolerance:
|
tolerance = Tolerance:
|
||||||
show_more = Show more...
|
show_more = Show more...
|
||||||
|
search = Search
|
||||||
|
copy_of = {} Copy
|
||||||
|
|
||||||
[general_text]
|
[general_text]
|
||||||
copy = &Copy
|
copy = &Copy
|
||||||
|
|
@ -966,6 +987,7 @@ key_context_move_tool = Move Tool
|
||||||
key_context_freehand_tool = Freehand Tool
|
key_context_freehand_tool = Freehand Tool
|
||||||
key_context_shape_tool = Shape Tool
|
key_context_shape_tool = Shape Tool
|
||||||
key_context_frames_selection = Frames Selection
|
key_context_frames_selection = Frames Selection
|
||||||
|
key_context_transformation = Transformation
|
||||||
copy_selection = Copy Selection
|
copy_selection = Copy Selection
|
||||||
snap_to_grid = Snap To Grid
|
snap_to_grid = Snap To Grid
|
||||||
lock_axis = Lock Axis
|
lock_axis = Lock Axis
|
||||||
|
|
@ -1174,6 +1196,7 @@ select_save_to_file = &Save to MSK file
|
||||||
view = &View
|
view = &View
|
||||||
view_duplicate_view = Duplicate &View
|
view_duplicate_view = Duplicate &View
|
||||||
view_workspace_layout = Workspace &Layout
|
view_workspace_layout = Workspace &Layout
|
||||||
|
view_run_command = Run Command
|
||||||
view_show_extras = &Extras
|
view_show_extras = &Extras
|
||||||
view_show = &Show
|
view_show = &Show
|
||||||
view_show_layer_edges = &Layer Edges
|
view_show_layer_edges = &Layer Edges
|
||||||
|
|
@ -1697,6 +1720,10 @@ from = From:
|
||||||
to = To:
|
to = To:
|
||||||
tolerance = Tolerance:
|
tolerance = Tolerance:
|
||||||
|
|
||||||
|
[duplicate_slice]
|
||||||
|
x_duplicated = Slice "{}" duplicated
|
||||||
|
n_slices_duplicated = {} slice(s) duplicated
|
||||||
|
|
||||||
[remove_slice]
|
[remove_slice]
|
||||||
x_removed = Slice "{}" removed
|
x_removed = Slice "{}" removed
|
||||||
n_slices_removed = {} slice(s) removed
|
n_slices_removed = {} slice(s) removed
|
||||||
|
|
@ -1781,6 +1808,7 @@ delete_file = Delete file, I've already sent it
|
||||||
|
|
||||||
[slice_popup_menu]
|
[slice_popup_menu]
|
||||||
properties = Slice &Properties...
|
properties = Slice &Properties...
|
||||||
|
duplicate = D&uplicate Slice
|
||||||
delete = &Delete Slice
|
delete = &Delete Slice
|
||||||
|
|
||||||
[slice_properties]
|
[slice_properties]
|
||||||
|
|
@ -1977,3 +2005,17 @@ toggle_left_diagonal = Toggle -45° Symmetry
|
||||||
show_options = Symmetry Options
|
show_options = Symmetry Options
|
||||||
reset_position = Reset Symmetry to Center
|
reset_position = Reset Symmetry to Center
|
||||||
reset_position_to_view_center = Reset Symmetry to View Center
|
reset_position_to_view_center = Reset Symmetry to View Center
|
||||||
|
|
||||||
|
[run_command]
|
||||||
|
title = Run Command
|
||||||
|
title_help = Run Command: Help
|
||||||
|
title_expression = Run Command: Math Expressions
|
||||||
|
title_script = Run Command: Lua Script Runner
|
||||||
|
command_placeholder = Search for commands, ? for help.
|
||||||
|
more_result_count = ... ({} more results)
|
||||||
|
tip_executed_command = Executed: '{0}'
|
||||||
|
tip_code_executed = Code executed successfully.
|
||||||
|
help_search = Type to search through Aseprite's functionality.
|
||||||
|
help_expressions = You can also start with "=" to do math expressions
|
||||||
|
help_lua = or "@" to execute Lua script code.
|
||||||
|
extension_tag = Extension
|
||||||
|
|
|
||||||
|
|
@ -4,27 +4,27 @@
|
||||||
<vbox id="brush_slot_params">
|
<vbox id="brush_slot_params">
|
||||||
<grid columns="2">
|
<grid columns="2">
|
||||||
|
|
||||||
<label text="@.brush" />
|
<label text="@.brush" for="brush_params" />
|
||||||
<buttonset id="brush_params" columns="3" multiple="true">
|
<buttonset id="brush_params" columns="3" multiple="true">
|
||||||
<item id="brush_type" text="@.brush_type" />
|
<item id="brush_type" text="@.brush_type" />
|
||||||
<item id="brush_size" text="@.brush_size" />
|
<item id="brush_size" text="@.brush_size" />
|
||||||
<item id="brush_angle" text="@.brush_angle" />
|
<item id="brush_angle" text="@.brush_angle" />
|
||||||
</buttonset>
|
</buttonset>
|
||||||
|
|
||||||
<label text="@.color" />
|
<label text="@.color" for="color_params" />
|
||||||
<buttonset id="color_params" columns="2" multiple="true">
|
<buttonset id="color_params" columns="2" multiple="true">
|
||||||
<item id="fg_color" text="@.foreground" />
|
<item id="fg_color" text="@.foreground" />
|
||||||
<item id="bg_color" text="@.background" />
|
<item id="bg_color" text="@.background" />
|
||||||
<item id="image_color" text="@.image_color" hspan="2" />
|
<item id="image_color" text="@.image_color" hspan="2" />
|
||||||
</buttonset>
|
</buttonset>
|
||||||
|
|
||||||
<label text="@.ink" />
|
<label text="@.ink" for="ink_params" />
|
||||||
<buttonset id="ink_params" columns="2" multiple="true">
|
<buttonset id="ink_params" columns="2" multiple="true">
|
||||||
<item id="ink_type" text="@.ink_type" />
|
<item id="ink_type" text="@.ink_type" />
|
||||||
<item id="ink_opacity" text="@.ink_opacity" />
|
<item id="ink_opacity" text="@.ink_opacity" />
|
||||||
</buttonset>
|
</buttonset>
|
||||||
|
|
||||||
<label text="@.extras" />
|
<label text="@.extras" for="extra_params" />
|
||||||
<buttonset id="extra_params" columns="2" multiple="true">
|
<buttonset id="extra_params" columns="2" multiple="true">
|
||||||
<item id="shade" text="@.shade" />
|
<item id="shade" text="@.shade" />
|
||||||
<item id="pixel_perfect" text="@.pixel_perfect" />
|
<item id="pixel_perfect" text="@.pixel_perfect" />
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,9 @@
|
||||||
<separator text="@.size" left="true" horizontal="true" />
|
<separator text="@.size" left="true" horizontal="true" />
|
||||||
<hbox>
|
<hbox>
|
||||||
<grid columns="2">
|
<grid columns="2">
|
||||||
<label text="@.width" />
|
<label text="@.width" for="width" />
|
||||||
<expr text="0" id="width" suffix="px" magnet="true" />
|
<expr text="0" id="width" suffix="px" magnet="true" />
|
||||||
<label text="@.height" />
|
<label text="@.height" for="height" />
|
||||||
<expr text="0" id="height" suffix="px" />
|
<expr text="0" id="height" suffix="px" />
|
||||||
<hbox filler="true" cell_hspan="2" />
|
<hbox filler="true" cell_hspan="2" />
|
||||||
</grid>
|
</grid>
|
||||||
|
|
@ -28,16 +28,16 @@
|
||||||
|
|
||||||
<separator text="@.borders" left="true" horizontal="true" />
|
<separator text="@.borders" left="true" horizontal="true" />
|
||||||
<grid columns="4">
|
<grid columns="4">
|
||||||
<label text="@.left" />
|
<label text="@.left" for="left" />
|
||||||
<expr text="0" id="left" suffix="px" tooltip="@.left_tooltip" />
|
<expr text="0" id="left" suffix="px" tooltip="@.left_tooltip" />
|
||||||
|
|
||||||
<label text="@.top" />
|
<label text="@.top" for="top" />
|
||||||
<expr text="0" id="top" suffix="px" tooltip="@.top_tooltip" />
|
<expr text="0" id="top" suffix="px" tooltip="@.top_tooltip" />
|
||||||
|
|
||||||
<label text="@.right" />
|
<label text="@.right" for="right" />
|
||||||
<expr text="0" id="right" suffix="px" tooltip="@.right_tooltip" />
|
<expr text="0" id="right" suffix="px" tooltip="@.right_tooltip" />
|
||||||
|
|
||||||
<label text="@.bottom" />
|
<label text="@.bottom" for="bottom" />
|
||||||
<expr text="0" id="bottom" suffix="px" tooltip="@.bottom_tooltip" />
|
<expr text="0" id="bottom" suffix="px" tooltip="@.bottom_tooltip" />
|
||||||
</grid>
|
</grid>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,11 @@
|
||||||
<gui>
|
<gui>
|
||||||
<window id="cel_properties" text="@.title">
|
<window id="cel_properties" text="@.title">
|
||||||
<grid id="properties_grid" columns="4">
|
<grid id="properties_grid" columns="4">
|
||||||
<label text="@.opacity" />
|
<label text="@.opacity" for="opacity" />
|
||||||
<opacityslider id="opacity" cell_align="horizontal" width="128" cell_hspan="2" />
|
<opacityslider id="opacity" cell_align="horizontal" width="128" cell_hspan="2" />
|
||||||
<button id="user_data" icon="icon_user_data" tooltip="@.user_data_tooltip" />
|
<button id="user_data" icon="icon_user_data" tooltip="@.user_data_tooltip" />
|
||||||
|
|
||||||
<label text="@.zindex" />
|
<label text="@.zindex" for="zindex" />
|
||||||
<expr id="zindex" cell_align="horizontal" width="128" />
|
<expr id="zindex" cell_align="horizontal" width="128" />
|
||||||
<buttonset id="zindex_spin" columns="1">
|
<buttonset id="zindex_spin" columns="1">
|
||||||
<item icon="spin_up" />
|
<item icon="spin_up" />
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,10 @@
|
||||||
<vbox>
|
<vbox>
|
||||||
<hbox expansive="true">
|
<hbox expansive="true">
|
||||||
<grid columns="2">
|
<grid columns="2">
|
||||||
<label text="@.x" />
|
<label text="@.x" for="x" />
|
||||||
<expr id="x" magnet="true" />
|
<expr id="x" magnet="true" />
|
||||||
|
|
||||||
<label text="@.y" />
|
<label text="@.y" for="y" />
|
||||||
<expr id="y" />
|
<expr id="y" />
|
||||||
</grid>
|
</grid>
|
||||||
</hbox>
|
</hbox>
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,9 @@
|
||||||
</view>
|
</view>
|
||||||
<hbox id="dithering_placeholder" />
|
<hbox id="dithering_placeholder" />
|
||||||
<hbox id="amount">
|
<hbox id="amount">
|
||||||
<label text="@.amount" />
|
<label text="@.amount" for="factor" />
|
||||||
<slider min="0" max="100" id="factor" minwidth="100" />
|
<slider min="0" max="100" id="factor" minwidth="100" />
|
||||||
<label text="%" />
|
<label text="%" for="factor" />
|
||||||
</hbox>
|
</hbox>
|
||||||
|
|
||||||
<combobox id="to_gray_combobox">
|
<combobox id="to_gray_combobox">
|
||||||
|
|
@ -24,10 +24,10 @@
|
||||||
|
|
||||||
<check id="advanced_check" text="@general.advanced_options" />
|
<check id="advanced_check" text="@general.advanced_options" />
|
||||||
<grid id="advanced" columns="2">
|
<grid id="advanced" columns="2">
|
||||||
<label text="@rgbmap_algorithm_selector.label" />
|
<label text="@rgbmap_algorithm_selector.label" for="rgbmap_algorithm_selector" />
|
||||||
<hbox id="rgbmap_algorithm_placeholder" cell_align="horizontal" />
|
<hbox id="rgbmap_algorithm_placeholder" cell_align="horizontal" />
|
||||||
|
|
||||||
<label text="@best_fit_criteria_selector.label" />
|
<label text="@best_fit_criteria_selector.label" for="best_fit_criteria_selector" />
|
||||||
<hbox id="best_fit_criteria_placeholder" cell_align="horizontal" />
|
<hbox id="best_fit_criteria_placeholder" cell_align="horizontal" />
|
||||||
</grid>
|
</grid>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<gui>
|
<gui>
|
||||||
<window id="css_options" text="@.title">
|
<window id="css_options" text="@.title">
|
||||||
<grid columns="2">
|
<grid columns="2">
|
||||||
<label text="@.pixel_scale" />
|
<label text="@.pixel_scale" for="pixel_scale" />
|
||||||
<expr id="pixel_scale" magnet="true" cell_align="horizontal"/>
|
<expr id="pixel_scale" magnet="true" cell_align="horizontal"/>
|
||||||
|
|
||||||
<check text="@.with_vars" id="with_vars" cell_hspan="2" />
|
<check text="@.with_vars" id="with_vars" cell_hspan="2" />
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,9 @@
|
||||||
<gui>
|
<gui>
|
||||||
<hbox id="despeckle">
|
<hbox id="despeckle">
|
||||||
<grid columns="2">
|
<grid columns="2">
|
||||||
<label text="@.width" />
|
<label text="@.width" for="width" />
|
||||||
<expr id="width" cell_align="horizontal" />
|
<expr id="width" cell_align="horizontal" />
|
||||||
<label text="@.height" />
|
<label text="@.height" for="height" />
|
||||||
<expr id="height" cell_align="horizontal" />
|
<expr id="height" cell_align="horizontal" />
|
||||||
</grid>
|
</grid>
|
||||||
</hbox>
|
</hbox>
|
||||||
|
|
|
||||||
|
|
@ -3,16 +3,13 @@
|
||||||
<gui>
|
<gui>
|
||||||
<window id="duplicate_sprite" text="@.title">
|
<window id="duplicate_sprite" text="@.title">
|
||||||
<box vertical="true">
|
<box vertical="true">
|
||||||
<box horizontal="true" expansive="true">
|
<grid columns="2">
|
||||||
<box vertical="true" homogeneous="true">
|
|
||||||
<label text="@.duplicate" />
|
<label text="@.duplicate" />
|
||||||
<label text="@.as" />
|
<label text="" id="src_name" cell_align="horizontal" />
|
||||||
</box>
|
|
||||||
<box vertical="true" homogeneous="true" expansive="true">
|
<label text="@.as" for="dst_name" />
|
||||||
<label text="" id="src_name" />
|
<entry maxsize="256" id="dst_name" magnet="true" cell_align="horizontal" />
|
||||||
<entry maxsize="256" id="dst_name" magnet="true" />
|
</grid>
|
||||||
</box>
|
|
||||||
</box>
|
|
||||||
<check text="@.merged_layers" id="flatten" />
|
<check text="@.merged_layers" id="flatten" />
|
||||||
<box horizontal="true" homogeneous="true">
|
<box horizontal="true" homogeneous="true">
|
||||||
<button text="@general.ok" closewindow="true" id="ok" magnet="true" />
|
<button text="@general.ok" closewindow="true" id="ok" magnet="true" />
|
||||||
|
|
|
||||||
|
|
@ -32,29 +32,29 @@
|
||||||
<grid id="options" columns="2" childspacing="0" expansive="true">
|
<grid id="options" columns="2" childspacing="0" expansive="true">
|
||||||
<separator id="separator" text="@.max_point_value" horizontal="true" cell_hspan="2" />
|
<separator id="separator" text="@.max_point_value" horizontal="true" cell_hspan="2" />
|
||||||
|
|
||||||
<label id="size_label" text="@.size" style="mini_label" />
|
<label id="size_label" text="@.size" style="mini_label" for="min_size" />
|
||||||
<slider id="min_size" value="1" min="1" max="64" cell_align="horizontal" style="mini_slider"
|
<slider id="min_size" value="1" min="1" max="64" cell_align="horizontal" style="mini_slider"
|
||||||
tooltip="@.min_size_tooltip" tooltip_dir="left" />
|
tooltip="@.min_size_tooltip" tooltip_dir="left" />
|
||||||
<boxfiller />
|
<boxfiller />
|
||||||
<slider id="max_size" value="64" min="1" max="64" cell_align="horizontal" style="mini_slider"
|
<slider id="max_size" value="64" min="1" max="64" cell_align="horizontal" style="mini_slider"
|
||||||
tooltip="@.max_size_tooltip" tooltip_dir="left" />
|
tooltip="@.max_size_tooltip" tooltip_dir="left" />
|
||||||
|
|
||||||
<label id="angle_label" text="@.angle" style="mini_label" />
|
<label id="angle_label" text="@.angle" style="mini_label" for="min_angle" />
|
||||||
<slider id="min_angle" value="0" min="-180" max="+180" cell_align="horizontal" style="mini_slider"
|
<slider id="min_angle" value="0" min="-180" max="+180" cell_align="horizontal" style="mini_slider"
|
||||||
tooltip="@.min_angle_tooltip" tooltip_dir="left" />
|
tooltip="@.min_angle_tooltip" tooltip_dir="left" />
|
||||||
<boxfiller />
|
<boxfiller />
|
||||||
<slider id="max_angle" value="0" min="-180" max="+180" cell_align="horizontal" style="mini_slider"
|
<slider id="max_angle" value="0" min="-180" max="+180" cell_align="horizontal" style="mini_slider"
|
||||||
tooltip="@.max_angle_tooltip" tooltip_dir="left" />
|
tooltip="@.max_angle_tooltip" tooltip_dir="left" />
|
||||||
|
|
||||||
<label id="gradient_label" text="@.gradient" style="mini_label" />
|
<label id="gradient_label" text="@.gradient" style="mini_label" for="dithering_selector" />
|
||||||
<hbox id="gradient_placeholder" cell_vspan="2" />
|
<hbox id="gradient_placeholder" cell_vspan="2" />
|
||||||
<link id="gradient_from_to" style="mini_label" />
|
<link id="gradient_from_to" style="mini_label" />
|
||||||
|
|
||||||
<separator id="separator2" text="@.sensors_tweaks" horizontal="true" cell_hspan="2" />
|
<separator id="separator2" text="@.sensors_tweaks" horizontal="true" cell_hspan="2" />
|
||||||
|
|
||||||
<label id="pressure_label" text="@.pressure" style="mini_label" />
|
<label id="pressure_label" text="@.pressure" style="mini_label" for="pressure_slider" />
|
||||||
<hbox id="pressure_placeholder" cell_align="horizontal" />
|
<hbox id="pressure_placeholder" cell_align="horizontal" />
|
||||||
<label id="velocity_label" text="@.velocity" style="mini_label" />
|
<label id="velocity_label" text="@.velocity" style="mini_label" for="velocity_slider" />
|
||||||
<hbox id="velocity_placeholder" cell_align="horizontal" />
|
<hbox id="velocity_placeholder" cell_align="horizontal" />
|
||||||
</grid>
|
</grid>
|
||||||
<separator horizontal="true" cell_hspan="2" />
|
<separator horizontal="true" cell_hspan="2" />
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,9 @@
|
||||||
<gui>
|
<gui>
|
||||||
<window id="export_file" text="@.title" help="exporting">
|
<window id="export_file" text="@.title" help="exporting">
|
||||||
<grid columns="3">
|
<grid columns="3">
|
||||||
<label text="@.output_file" />
|
<label text="@.output_file" for="output_field" />
|
||||||
<filename id="output_field" cell_align="horizontal" cell_hspan="2" />
|
<filename id="output_field" cell_align="horizontal" cell_hspan="2" />
|
||||||
<label id="resize_label" text="@.resize" />
|
<label id="resize_label" text="@.resize" for="resize" />
|
||||||
<hbox cell_hspan="2" cell_align="horizontal">
|
<hbox cell_hspan="2" cell_align="horizontal">
|
||||||
<combobox id="resize" editable="true" suffix="%" expansive="true">
|
<combobox id="resize" editable="true" suffix="%" expansive="true">
|
||||||
<listitem text="25" />
|
<listitem text="25" />
|
||||||
|
|
@ -22,17 +22,17 @@
|
||||||
<listitem text="900" />
|
<listitem text="900" />
|
||||||
<listitem text="1000" />
|
<listitem text="1000" />
|
||||||
</combobox>
|
</combobox>
|
||||||
<label id="area_label" text="@.area" />
|
<label id="area_label" text="@.area" for="area" />
|
||||||
<combobox id="area" text="" cell_align="horizontal" cell_hspan="2" expansive="true" />
|
<combobox id="area" text="" cell_align="horizontal" cell_hspan="2" expansive="true" />
|
||||||
</hbox>
|
</hbox>
|
||||||
|
|
||||||
<label id="layers_label" text="@.layers" />
|
<label id="layers_label" text="@.layers" for="layers" />
|
||||||
<combobox id="layers" text="" cell_align="horizontal" cell_hspan="2" />
|
<combobox id="layers" text="" cell_align="horizontal" cell_hspan="2" />
|
||||||
|
|
||||||
<label id="frames_label" text="@.frames" />
|
<label id="frames_label" text="@.frames" for="frames" />
|
||||||
<combobox id="frames" text="" cell_align="horizontal" cell_hspan="2" />
|
<combobox id="frames" text="" cell_align="horizontal" cell_hspan="2" />
|
||||||
|
|
||||||
<label id="anidir_label" text="@.anidir" />
|
<label id="anidir_label" text="@.anidir" for="anidir" />
|
||||||
<combobox id="anidir" text="" cell_align="horizontal" cell_hspan="2" />
|
<combobox id="anidir" text="" cell_align="horizontal" cell_hspan="2" />
|
||||||
|
|
||||||
<check id="play_subtags" text="@.play_subtags" cell_hspan="3" />
|
<check id="play_subtags" text="@.play_subtags" cell_hspan="3" />
|
||||||
|
|
|
||||||
|
|
@ -25,11 +25,11 @@
|
||||||
<!-- Layout -->
|
<!-- Layout -->
|
||||||
|
|
||||||
<grid id="section_layout" columns="4" expansive="true">
|
<grid id="section_layout" columns="4" expansive="true">
|
||||||
<label text="@.sheet_type" />
|
<label text="@.sheet_type" for="sheet_type" />
|
||||||
<combobox id="sheet_type" expansive="true" cell_hspan="3" cell_align="horizontal"
|
<combobox id="sheet_type" expansive="true" cell_hspan="3" cell_align="horizontal"
|
||||||
tooltip="@.sheet_type_tooltip" tooltip_dir="bottom" />
|
tooltip="@.sheet_type_tooltip" tooltip_dir="bottom" />
|
||||||
|
|
||||||
<label text="@.constraints" />
|
<label text="@.constraints" for="constraint_type" />
|
||||||
<hbox cell_hspan="3">
|
<hbox cell_hspan="3">
|
||||||
<combobox id="constraint_type" tooltip="@.constraints_tooltip" />
|
<combobox id="constraint_type" tooltip="@.constraints_tooltip" />
|
||||||
<expr id="width_constraint" />
|
<expr id="width_constraint" />
|
||||||
|
|
@ -50,15 +50,15 @@
|
||||||
<button id="close_sprite_section" icon="window_close_icon" />
|
<button id="close_sprite_section" icon="window_close_icon" />
|
||||||
</hbox>
|
</hbox>
|
||||||
<grid id="section_sprite" columns="4" expansive="true">
|
<grid id="section_sprite" columns="4" expansive="true">
|
||||||
<label text="@.source" />
|
<label text="@.source" for="source" />
|
||||||
<combobox id="source" text="" cell_hspan="2" cell_align="horizontal" />
|
<combobox id="source" text="" cell_hspan="2" cell_align="horizontal" />
|
||||||
<boxfiller />
|
<boxfiller />
|
||||||
|
|
||||||
<label text="@.layers" />
|
<label text="@.layers" for="layers" />
|
||||||
<combobox id="layers" text="" cell_hspan="2" cell_align="horizontal" />
|
<combobox id="layers" text="" cell_hspan="2" cell_align="horizontal" />
|
||||||
<check id="split_layers" text="@.split_layers" tooltip="@.split_layers_tooltip" tooltip_dir="bottom" />
|
<check id="split_layers" text="@.split_layers" tooltip="@.split_layers_tooltip" tooltip_dir="bottom" />
|
||||||
|
|
||||||
<label text="@.frames" />
|
<label text="@.frames" for="frames" />
|
||||||
<combobox id="frames" text="" cell_hspan="2" cell_align="horizontal" />
|
<combobox id="frames" text="" cell_hspan="2" cell_align="horizontal" />
|
||||||
<check id="split_tags" text="@.split_tags" tooltip="@.split_tags_tooltip" tooltip_dir="top" />
|
<check id="split_tags" text="@.split_tags" tooltip="@.split_tags_tooltip" tooltip_dir="top" />
|
||||||
</grid>
|
</grid>
|
||||||
|
|
@ -75,11 +75,11 @@
|
||||||
<hbox cell_hspan="3">
|
<hbox cell_hspan="3">
|
||||||
<vbox>
|
<vbox>
|
||||||
<grid columns="2">
|
<grid columns="2">
|
||||||
<label text="@.border" />
|
<label text="@.border" for="border_padding" />
|
||||||
<expr id="border_padding" text="0" tooltip="@.border_tooltip" />
|
<expr id="border_padding" text="0" tooltip="@.border_tooltip" />
|
||||||
<label text="@.shape" />
|
<label text="@.shape" for="shape_padding" />
|
||||||
<expr id="shape_padding" text="0" tooltip="@.shape_tooltip" />
|
<expr id="shape_padding" text="0" tooltip="@.shape_tooltip" />
|
||||||
<label text="@.inner" />
|
<label text="@.inner" for="inner_padding" />
|
||||||
<expr id="inner_padding" text="0" tooltip="@.inner_tooltip" />
|
<expr id="inner_padding" text="0" tooltip="@.inner_tooltip" />
|
||||||
</grid>
|
</grid>
|
||||||
</vbox>
|
</vbox>
|
||||||
|
|
@ -130,12 +130,12 @@
|
||||||
|
|
||||||
<hbox />
|
<hbox />
|
||||||
<grid id="data_formats_placeholder" columns="3" cell_hspan="3" cell_align="horizontal">
|
<grid id="data_formats_placeholder" columns="3" cell_hspan="3" cell_align="horizontal">
|
||||||
<label text="@.data_filename_format" />
|
<label text="@.data_filename_format" for="data_filename_format" />
|
||||||
<entry id="data_filename_format" maxsize="1024" maxwidth="256" cell_align="horizontal"
|
<entry id="data_filename_format" maxsize="1024" maxwidth="256" cell_align="horizontal"
|
||||||
tooltip="@.data_filename_format_tooltip" />
|
tooltip="@.data_filename_format_tooltip" />
|
||||||
<link text="(?)" url="https://www.aseprite.org/docs/cli/#filename-format" />
|
<link text="(?)" url="https://www.aseprite.org/docs/cli/#filename-format" />
|
||||||
|
|
||||||
<label text="@.data_tagname_format" />
|
<label text="@.data_tagname_format" for="data_tagname_format" />
|
||||||
<entry id="data_tagname_format" maxsize="1024" maxwidth="256" cell_align="horizontal"
|
<entry id="data_tagname_format" maxsize="1024" maxwidth="256" cell_align="horizontal"
|
||||||
tooltip="@.data_tagname_format_tooltip" />
|
tooltip="@.data_tagname_format_tooltip" />
|
||||||
<link text="(?)" url="https://www.aseprite.org/docs/cli/#tagname-format" />
|
<link text="(?)" url="https://www.aseprite.org/docs/cli/#tagname-format" />
|
||||||
|
|
|
||||||
|
|
@ -27,10 +27,10 @@
|
||||||
</box>
|
</box>
|
||||||
<vbox id="file_view_placeholder" expansive="true" />
|
<vbox id="file_view_placeholder" expansive="true" />
|
||||||
<grid columns="2">
|
<grid columns="2">
|
||||||
<label text="@.file_name" />
|
<label text="@.file_name" for="file_name" />
|
||||||
<box id="file_name_placeholder" cell_align="horizontal" />
|
<box id="file_name_placeholder" cell_align="horizontal" />
|
||||||
|
|
||||||
<label text="@.file_type" />
|
<label text="@.file_type" for="file_type" />
|
||||||
<hbox cell_align="horizontal">
|
<hbox cell_align="horizontal">
|
||||||
<combobox id="file_type" minwidth="70" />
|
<combobox id="file_type" minwidth="70" />
|
||||||
<boxfiller />
|
<boxfiller />
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
<label text="" id="frame" />
|
<label text="" id="frame" />
|
||||||
<box cell_align="horizontal" />
|
<box cell_align="horizontal" />
|
||||||
|
|
||||||
<label text="@.duration" />
|
<label text="@.duration" for="frlen" />
|
||||||
<expr id="frlen" magnet="true" />
|
<expr id="frlen" magnet="true" />
|
||||||
<box cell_align="horizontal" />
|
<box cell_align="horizontal" />
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<gui>
|
<gui>
|
||||||
<window id="goto_frame" text="@.title">
|
<window id="goto_frame" text="@.title">
|
||||||
<vbox>
|
<vbox>
|
||||||
<label text="@.frame_or_tags" />
|
<label text="@.frame_or_tags" for="frame" />
|
||||||
<vbox id="frame_placeholder" />
|
<vbox id="frame_placeholder" />
|
||||||
|
|
||||||
<separator horizontal="true" />
|
<separator horizontal="true" />
|
||||||
|
|
|
||||||
|
|
@ -4,16 +4,16 @@
|
||||||
<window id="grid_settings" text="@.title">
|
<window id="grid_settings" text="@.title">
|
||||||
<grid columns="4">
|
<grid columns="4">
|
||||||
|
|
||||||
<label text="@.x" />
|
<label text="@.x" for="grid_x" />
|
||||||
<expr id="grid_x" text="" magnet="true" />
|
<expr id="grid_x" text="" magnet="true" />
|
||||||
|
|
||||||
<label text="@.y" />
|
<label text="@.y" for="grid_y" />
|
||||||
<expr id="grid_y" text="" />
|
<expr id="grid_y" text="" />
|
||||||
|
|
||||||
<label text="@.width" />
|
<label text="@.width" for="grid_w" />
|
||||||
<expr id="grid_w" text="" />
|
<expr id="grid_w" text="" />
|
||||||
|
|
||||||
<label text="@.height" />
|
<label text="@.height" for="grid_h" />
|
||||||
<expr id="grid_h" text="" />
|
<expr id="grid_h" text="" />
|
||||||
|
|
||||||
<separator horizontal="true" cell_hspan="4" />
|
<separator horizontal="true" cell_hspan="4" />
|
||||||
|
|
|
||||||
|
|
@ -7,36 +7,36 @@
|
||||||
<grid columns="4">
|
<grid columns="4">
|
||||||
<button id="select_file" text="@select_file.text" cell_hspan="4" />
|
<button id="select_file" text="@select_file.text" cell_hspan="4" />
|
||||||
|
|
||||||
<label text="@.type" />
|
<label text="@.type" for="sheet_type" />
|
||||||
<combobox id="sheet_type" cell_hspan="3" />
|
<combobox id="sheet_type" cell_hspan="3" />
|
||||||
|
|
||||||
<separator text="@.tiles" horizontal="true" cell_hspan="4" />
|
<separator text="@.tiles" horizontal="true" cell_hspan="4" />
|
||||||
|
|
||||||
<label text="@.x" />
|
<label text="@.x" for="x" />
|
||||||
<expr id="x" text="0" />
|
<expr id="x" text="0" />
|
||||||
|
|
||||||
<label text="@.y" />
|
<label text="@.y" for="y" />
|
||||||
<expr id="y" text="0" />
|
<expr id="y" text="0" />
|
||||||
|
|
||||||
<label text="@.width" />
|
<label text="@.width" for="width" />
|
||||||
<expr id="width" text="16" />
|
<expr id="width" text="16" />
|
||||||
|
|
||||||
<label text="@.height" />
|
<label text="@.height" for="height" />
|
||||||
<expr id="height" text="16" />
|
<expr id="height" text="16" />
|
||||||
|
|
||||||
<separator horizontal="true" cell_hspan="4" />
|
<separator horizontal="true" cell_hspan="4" />
|
||||||
|
|
||||||
<label text="@.columns" />
|
<label text="@.columns" for="columns" />
|
||||||
<expr id="columns" />
|
<expr id="columns" />
|
||||||
|
|
||||||
<label text="@.rows" />
|
<label text="@.rows" for="rows" />
|
||||||
<expr id="rows" />
|
<expr id="rows" />
|
||||||
|
|
||||||
<check id="padding_enabled" text="@.padding" cell_hspan="4" />
|
<check id="padding_enabled" text="@.padding" cell_hspan="4" />
|
||||||
|
|
||||||
<label text="@.horizontal_padding" id="horizontal_padding_label" />
|
<label text="@.horizontal_padding" id="horizontal_padding_label" for="horizontal_padding" />
|
||||||
<expr id="horizontal_padding" text="0" />
|
<expr id="horizontal_padding" text="0" />
|
||||||
<label text="@.vertical_padding" id="vertical_padding_label" />
|
<label text="@.vertical_padding" id="vertical_padding_label" for="vertical_padding" />
|
||||||
<expr id="vertical_padding" text="0" />
|
<expr id="vertical_padding" text="0" />
|
||||||
|
|
||||||
<check id="partial_tiles" text="@.partial_tiles" cell_hspan="4" />
|
<check id="partial_tiles" text="@.partial_tiles" cell_hspan="4" />
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<gui>
|
<gui>
|
||||||
<window id="jpeg_options" text="@.title">
|
<window id="jpeg_options" text="@.title">
|
||||||
<grid columns="2">
|
<grid columns="2">
|
||||||
<label text="@.quality" />
|
<label text="@.quality" for="quality" />
|
||||||
<slider min="0" max="10" id="quality" cell_align="horizontal" width="128" />
|
<slider min="0" max="10" id="quality" cell_align="horizontal" width="128" />
|
||||||
|
|
||||||
<separator horizontal="true" cell_hspan="2" />
|
<separator horizontal="true" cell_hspan="2" />
|
||||||
|
|
|
||||||
|
|
@ -61,10 +61,8 @@
|
||||||
<listbox id="drag_actions" />
|
<listbox id="drag_actions" />
|
||||||
</view>
|
</view>
|
||||||
<separator horizontal="true" />
|
<separator horizontal="true" />
|
||||||
<hbox>
|
<grid columns="4">
|
||||||
<vbox>
|
<label text="@.drag_angle" for="drag_angle" cell_align="top" />
|
||||||
<label text="@.drag_angle" />
|
|
||||||
</vbox>
|
|
||||||
<buttonset columns="3" id="drag_angle">
|
<buttonset columns="3" id="drag_angle">
|
||||||
<item icon="canvas_nw"
|
<item icon="canvas_nw"
|
||||||
style="dir_item"
|
style="dir_item"
|
||||||
|
|
@ -100,15 +98,11 @@
|
||||||
tooltip="@.drag_angle_tooltip"
|
tooltip="@.drag_angle_tooltip"
|
||||||
tooltip_dir="top" />
|
tooltip_dir="top" />
|
||||||
</buttonset>
|
</buttonset>
|
||||||
<vbox>
|
<label text="@.drag_distance" for="drag_distance" cell_align="top" />
|
||||||
<label text="@.drag_distance" />
|
<box>
|
||||||
</vbox>
|
<slider min="1" max="100" id="drag_distance" width="128" tooltip="@.drag_distance_tooltip" tooltip_dir="bottom" />
|
||||||
<vbox>
|
</box>
|
||||||
<slider min="1" max="100" id="drag_distance" cell_align="horizontal" width="128"
|
</grid>
|
||||||
tooltip="@.drag_distance_tooltip"
|
|
||||||
tooltip_dir="bottom" />
|
|
||||||
</vbox>
|
|
||||||
</hbox>
|
|
||||||
</vbox>
|
</vbox>
|
||||||
</vbox>
|
</vbox>
|
||||||
</splitter>
|
</splitter>
|
||||||
|
|
|
||||||
|
|
@ -5,18 +5,18 @@
|
||||||
<window id="layer_properties" text="@.title">
|
<window id="layer_properties" text="@.title">
|
||||||
<vbox>
|
<vbox>
|
||||||
<grid id="properties_grid" columns="3">
|
<grid id="properties_grid" columns="3">
|
||||||
<label text="@.name" />
|
<label text="@.name" for="name" />
|
||||||
<entry text="" id="name" magnet="true" maxsize="256" minwidth="64" cell_align="horizontal" />
|
<entry text="" id="name" magnet="true" maxsize="256" minwidth="64" cell_align="horizontal" />
|
||||||
<button id="user_data" icon="icon_user_data" tooltip="@general.user_data" />
|
<button id="user_data" icon="icon_user_data" tooltip="@general.user_data" />
|
||||||
|
|
||||||
<label text="@.mode" />
|
<label text="@.mode" for="mode" />
|
||||||
<combobox id="mode" />
|
<combobox id="mode" />
|
||||||
<button id="tileset" icon="tiles" tooltip="@.tileset_tooltip" />
|
<button id="tileset" icon="tiles" tooltip="@.tileset_tooltip" />
|
||||||
|
|
||||||
<label text="@.opacity" />
|
<label text="@.opacity" for="opacity" />
|
||||||
<opacityslider id="opacity" width="128" cell_align="horizontal" cell_hspan="2" />
|
<opacityslider id="opacity" width="128" cell_align="horizontal" cell_hspan="2" />
|
||||||
|
|
||||||
<label id="uuid_label" text="@.uuid" visible="false" />
|
<label id="uuid_label" text="@.uuid" visible="false" for="uuid" />
|
||||||
<entry id="uuid" readonly="true" maxsize="36" cell_hspan="2" visible="false"/>
|
<entry id="uuid" readonly="true" maxsize="36" cell_hspan="2" visible="false"/>
|
||||||
</grid>
|
</grid>
|
||||||
</vbox>
|
</vbox>
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
<vbox>
|
<vbox>
|
||||||
<grid columns="2">
|
<grid columns="2">
|
||||||
|
|
||||||
<label id="by_label" text="" />
|
<label id="by_label" text="" for="quantity" />
|
||||||
<expr id="quantity" expansive="true" magnet="true" suffix="px" />
|
<expr id="quantity" expansive="true" magnet="true" suffix="px" />
|
||||||
|
|
||||||
<hbox />
|
<hbox />
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
<window id="new_folder_window" text="@new_folder.title">
|
<window id="new_folder_window" text="@new_folder.title">
|
||||||
<vbox>
|
<vbox>
|
||||||
<hbox>
|
<hbox>
|
||||||
<label text="@new_folder.folder_name" />
|
<label text="@new_folder.folder_name" for="name" />
|
||||||
<entry text="@new_folder.default_new_folder_name" id="name" maxsize="256" magnet="true" expansive="true" minwidth="128" />
|
<entry text="@new_folder.default_new_folder_name" id="name" maxsize="256" magnet="true" expansive="true" minwidth="128" />
|
||||||
</hbox>
|
</hbox>
|
||||||
<hbox>
|
<hbox>
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
<window id="new_layer" text="@.title" help="new-layer">
|
<window id="new_layer" text="@.title" help="new-layer">
|
||||||
<vbox>
|
<vbox>
|
||||||
<grid columns="2">
|
<grid columns="2">
|
||||||
<label text="@.name" />
|
<label text="@.name" for="name" />
|
||||||
<entry maxsize="256" text="@.default_new_layer_name" id="name" magnet="true" />
|
<entry maxsize="256" text="@.default_new_layer_name" id="name" magnet="true" />
|
||||||
|
|
||||||
<vbox>
|
<vbox>
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
<window id="new_layout" text="@.title">
|
<window id="new_layout" text="@.title">
|
||||||
<vbox>
|
<vbox>
|
||||||
<hbox>
|
<hbox>
|
||||||
<label text="@.name" />
|
<label text="@.name" for="name" />
|
||||||
<entry maxsize="128" id="name" magnet="true" expansive="true" />
|
<entry maxsize="128" id="name" magnet="true" expansive="true" />
|
||||||
</hbox>
|
</hbox>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,9 @@
|
||||||
|
|
||||||
<separator text="@.size" left="true" horizontal="true" />
|
<separator text="@.size" left="true" horizontal="true" />
|
||||||
<grid columns="2">
|
<grid columns="2">
|
||||||
<label text="@.width" />
|
<label text="@.width" for="width" />
|
||||||
<expr id="width" magnet="true" cell_align="horizontal" suffix="px" />
|
<expr id="width" magnet="true" cell_align="horizontal" suffix="px" />
|
||||||
<label text="@.height" />
|
<label text="@.height" for="height" />
|
||||||
<expr id="height" cell_align="horizontal" suffix="px" />
|
<expr id="height" cell_align="horizontal" suffix="px" />
|
||||||
</grid>
|
</grid>
|
||||||
|
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
|
|
||||||
<check id="advanced_check" text="@general.advanced_options" />
|
<check id="advanced_check" text="@general.advanced_options" />
|
||||||
<vbox id="advanced">
|
<vbox id="advanced">
|
||||||
<label text="@.pixel_ratio" />
|
<label text="@.pixel_ratio" for="pixel_ratio" />
|
||||||
<combobox id="pixel_ratio" cell_align="horizontal">
|
<combobox id="pixel_ratio" cell_align="horizontal">
|
||||||
<listitem text="@.square_pixels" value="1:1" />
|
<listitem text="@.square_pixels" value="1:1" />
|
||||||
<listitem text="@.double_wide" value="2:1" />
|
<listitem text="@.double_wide" value="2:1" />
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,12 @@
|
||||||
<gui>
|
<gui>
|
||||||
<window id="open_sequence" text="@.title">
|
<window id="open_sequence" text="@.title">
|
||||||
<vbox>
|
<vbox>
|
||||||
<label text="@.description" />
|
<label text="@.description" for="files" />
|
||||||
<view expansive="true" id="view" minwidth="128" minheight="64">
|
<view expansive="true" id="view" minwidth="128" minheight="64">
|
||||||
<listbox id="files" multiselect="true" />
|
<listbox id="files" multiselect="true" />
|
||||||
</view>
|
</view>
|
||||||
<hbox>
|
<hbox>
|
||||||
<label text="@.duration" />
|
<label text="@.duration" for="duration" />
|
||||||
<expr text="0" id="duration" suffix="ms" />
|
<expr text="0" id="duration" suffix="ms" />
|
||||||
</hbox>
|
</hbox>
|
||||||
<separator horizontal="true" />
|
<separator horizontal="true" />
|
||||||
|
|
|
||||||
|
|
@ -36,18 +36,18 @@
|
||||||
<vbox id="section_general">
|
<vbox id="section_general">
|
||||||
<separator text="@.section_general" horizontal="true" />
|
<separator text="@.section_general" horizontal="true" />
|
||||||
<grid columns="2">
|
<grid columns="2">
|
||||||
<label text="@.ui_windows" />
|
<label text="@.ui_windows" for="ui_windows" />
|
||||||
<hbox>
|
<hbox>
|
||||||
<buttonset columns="2" id="ui_windows">
|
<buttonset columns="2" id="ui_windows">
|
||||||
<item icon="one_win_icon" tooltip="@.one_win" tooltip_dir="bottom" style="multi_window_item" />
|
<item icon="one_win_icon" tooltip="@.one_win" tooltip_dir="bottom" style="multi_window_item" />
|
||||||
<item icon="multi_win_icon" tooltip="@.multi_win" tooltip_dir="bottom" style="multi_window_item" />
|
<item icon="multi_win_icon" tooltip="@.multi_win" tooltip_dir="bottom" style="multi_window_item" />
|
||||||
</buttonset>
|
</buttonset>
|
||||||
<hbox id="theme_variants">
|
<hbox id="theme_variants">
|
||||||
<label text="@.theme_mode" />
|
<label id="theme_mode_label" text="@.theme_mode" /> <!-- TODO: Get future dynamic ID, if any -->
|
||||||
</hbox>
|
</hbox>
|
||||||
</hbox>
|
</hbox>
|
||||||
|
|
||||||
<label text="@.screen_scaling" />
|
<label text="@.screen_scaling" for="screen_scale" />
|
||||||
<combobox id="screen_scale">
|
<combobox id="screen_scale">
|
||||||
<listitem text="100%" value="1" />
|
<listitem text="100%" value="1" />
|
||||||
<listitem text="200%" value="2" />
|
<listitem text="200%" value="2" />
|
||||||
|
|
@ -55,7 +55,7 @@
|
||||||
<listitem text="400%" value="4" />
|
<listitem text="400%" value="4" />
|
||||||
</combobox>
|
</combobox>
|
||||||
|
|
||||||
<label text="@.ui_scaling" />
|
<label text="@.ui_scaling" for="ui_scale" />
|
||||||
<combobox id="ui_scale">
|
<combobox id="ui_scale">
|
||||||
<listitem text="100%" value="1" />
|
<listitem text="100%" value="1" />
|
||||||
<listitem text="200%" value="2" />
|
<listitem text="200%" value="2" />
|
||||||
|
|
@ -125,21 +125,21 @@
|
||||||
<separator text="@.section_files" horizontal="true" />
|
<separator text="@.section_files" horizontal="true" />
|
||||||
<label text="@.default_extension_for" />
|
<label text="@.default_extension_for" />
|
||||||
<grid columns="2">
|
<grid columns="2">
|
||||||
<label text="@.save_default_extension" />
|
<label text="@.save_default_extension" for="default_extension" />
|
||||||
<combobox id="default_extension" />
|
<combobox id="default_extension" />
|
||||||
|
|
||||||
<label text="@.export_image_default_extension" />
|
<label text="@.export_image_default_extension" for="export_image_default_extension" />
|
||||||
<combobox id="export_image_default_extension" />
|
<combobox id="export_image_default_extension" />
|
||||||
|
|
||||||
<label text="@.export_animation_default_extension" />
|
<label text="@.export_animation_default_extension" for="export_animation_default_extension" />
|
||||||
<combobox id="export_animation_default_extension" />
|
<combobox id="export_animation_default_extension" />
|
||||||
|
|
||||||
<label text="@.export_sprite_sheet_default_extension" />
|
<label text="@.export_sprite_sheet_default_extension" for="export_sprite_sheet_default_extension" />
|
||||||
<combobox id="export_sprite_sheet_default_extension" />
|
<combobox id="export_sprite_sheet_default_extension" />
|
||||||
</grid>
|
</grid>
|
||||||
|
|
||||||
<grid columns="2">
|
<grid columns="2">
|
||||||
<label text="@.recent_files" />
|
<label text="@.recent_files" for="recent_files" />
|
||||||
<hbox>
|
<hbox>
|
||||||
<slider min="0" max="100" id="recent_files" width="128" tooltip="@.recent_files_tooltip" />
|
<slider min="0" max="100" id="recent_files" width="128" tooltip="@.recent_files_tooltip" />
|
||||||
<button id="clear_recent_files" text="@.clear_recent_files" tooltip="@.clear_recent_files_tooltip" minwidth="60" />
|
<button id="clear_recent_files" text="@.clear_recent_files" tooltip="@.clear_recent_files_tooltip" minwidth="60" />
|
||||||
|
|
@ -203,7 +203,7 @@
|
||||||
<check text="@.color_management" id="color_management" pref="color.manage" />
|
<check text="@.color_management" id="color_management" pref="color.manage" />
|
||||||
|
|
||||||
<grid columns="2">
|
<grid columns="2">
|
||||||
<label text="@.window_cs" id="window_cs_label" />
|
<label text="@.window_cs" id="window_cs_label" for="window_cs" />
|
||||||
<combobox id="window_cs">
|
<combobox id="window_cs">
|
||||||
<listitem text="@.use_monitor_cs" />
|
<listitem text="@.use_monitor_cs" />
|
||||||
<listitem text="@.use_srgb_cs" />
|
<listitem text="@.use_srgb_cs" />
|
||||||
|
|
@ -213,10 +213,10 @@
|
||||||
<boxfiller />
|
<boxfiller />
|
||||||
<separator horizontal="true" />
|
<separator horizontal="true" />
|
||||||
|
|
||||||
<label text="@.working_rgb_cs" id="working_rgb_cs_label" />
|
<label text="@.working_rgb_cs" id="working_rgb_cs_label" for="working_rgb_cs" />
|
||||||
<combobox id="working_rgb_cs" />
|
<combobox id="working_rgb_cs" />
|
||||||
|
|
||||||
<label text="@.files_with_cs" id="files_with_cs_label" />
|
<label text="@.files_with_cs" id="files_with_cs_label" for="files_with_cs" />
|
||||||
<combobox id="files_with_cs">
|
<combobox id="files_with_cs">
|
||||||
<listitem text="@.disable_cs" />
|
<listitem text="@.disable_cs" />
|
||||||
<listitem text="@.use_embedded_cs" />
|
<listitem text="@.use_embedded_cs" />
|
||||||
|
|
@ -225,7 +225,7 @@
|
||||||
<listitem text="@.ask_cs" />
|
<listitem text="@.ask_cs" />
|
||||||
</combobox>
|
</combobox>
|
||||||
|
|
||||||
<label text="@.missing_cs" id="missing_cs_label" />
|
<label text="@.missing_cs" id="missing_cs_label" for="missing_cs" />
|
||||||
<combobox id="missing_cs">
|
<combobox id="missing_cs">
|
||||||
<listitem text="@.disable_cs" />
|
<listitem text="@.disable_cs" />
|
||||||
<listitem text="@.assign_cs" />
|
<listitem text="@.assign_cs" />
|
||||||
|
|
@ -240,12 +240,12 @@
|
||||||
|
|
||||||
<separator text="@.alpha_and_opacity" horizontal="true" />
|
<separator text="@.alpha_and_opacity" horizontal="true" />
|
||||||
<grid columns="2">
|
<grid columns="2">
|
||||||
<label text="@.alpha_range" id="alpha_range_label" />
|
<label text="@.alpha_range" id="alpha_range_label" for="alpha" />
|
||||||
<combobox id="alpha">
|
<combobox id="alpha">
|
||||||
<listitem text="@.8bit_value" />
|
<listitem text="@.8bit_value" />
|
||||||
<listitem text="@.percentage" />
|
<listitem text="@.percentage" />
|
||||||
</combobox>
|
</combobox>
|
||||||
<label text="@.opacity_range" id="opacity_range_label" />
|
<label text="@.opacity_range" id="opacity_range_label" for="opacity" />
|
||||||
<combobox id="opacity">
|
<combobox id="opacity">
|
||||||
<listitem text="@.8bit_value" />
|
<listitem text="@.8bit_value" />
|
||||||
<listitem text="@.percentage" />
|
<listitem text="@.percentage" />
|
||||||
|
|
@ -270,7 +270,7 @@
|
||||||
<check text="@.discard_brush" id="discard_brush" />
|
<check text="@.discard_brush" id="discard_brush" />
|
||||||
<hbox id="sampling_placeholder" />
|
<hbox id="sampling_placeholder" />
|
||||||
<hbox>
|
<hbox>
|
||||||
<label text="@.right_click" />
|
<label text="@.right_click" for="right_click_behavior" />
|
||||||
<combobox id="right_click_behavior" expansive="true" />
|
<combobox id="right_click_behavior" expansive="true" />
|
||||||
</hbox>
|
</hbox>
|
||||||
</vbox>
|
</vbox>
|
||||||
|
|
@ -303,7 +303,7 @@
|
||||||
<check text="@.rewind_on_stop" id="rewind_on_stop" tooltip="@.rewind_on_stop_tooltip"
|
<check text="@.rewind_on_stop" id="rewind_on_stop" tooltip="@.rewind_on_stop_tooltip"
|
||||||
pref="general.rewind_on_stop" />
|
pref="general.rewind_on_stop" />
|
||||||
<hbox>
|
<hbox>
|
||||||
<label text="@.default_first_frame" />
|
<label text="@.default_first_frame" for="first_frame" />
|
||||||
<expr id="first_frame" />
|
<expr id="first_frame" />
|
||||||
</hbox>
|
</hbox>
|
||||||
<separator text="@.timeline_selection" horizontal="true" />
|
<separator text="@.timeline_selection" horizontal="true" />
|
||||||
|
|
@ -337,7 +337,7 @@
|
||||||
<separator text="@.ui_mouse_cursor" horizontal="true" />
|
<separator text="@.ui_mouse_cursor" horizontal="true" />
|
||||||
<check id="native_cursor" text="@.native_cursor" />
|
<check id="native_cursor" text="@.native_cursor" />
|
||||||
<hbox>
|
<hbox>
|
||||||
<label id="cursor_scale_label" text="@.cursor_scale_label" />
|
<label id="cursor_scale_label" text="@.cursor_scale_label" for="cursor_scale" />
|
||||||
<combobox id="cursor_scale">
|
<combobox id="cursor_scale">
|
||||||
<listitem text="100%" value="1" />
|
<listitem text="100%" value="1" />
|
||||||
<listitem text="200%" value="2" />
|
<listitem text="200%" value="2" />
|
||||||
|
|
@ -349,13 +349,13 @@
|
||||||
<separator text="@.painting_cursors" horizontal="true" />
|
<separator text="@.painting_cursors" horizontal="true" />
|
||||||
|
|
||||||
<grid columns="2">
|
<grid columns="2">
|
||||||
<label text="@.crosshair_type" />
|
<label text="@.crosshair_type" for="painting_cursor_type" />
|
||||||
<combobox id="painting_cursor_type">
|
<combobox id="painting_cursor_type">
|
||||||
<listitem text="@.simple_crosshair" value="0" />
|
<listitem text="@.simple_crosshair" value="0" />
|
||||||
<listitem text="@.crosshair_on_sprite" value="1" />
|
<listitem text="@.crosshair_on_sprite" value="1" />
|
||||||
</combobox>
|
</combobox>
|
||||||
|
|
||||||
<label text="@.brush_preview" />
|
<label text="@.brush_preview" for="brush_preview" />
|
||||||
<combobox id="brush_preview">
|
<combobox id="brush_preview">
|
||||||
<listitem text="@.brush_preview_none" value="0" />
|
<listitem text="@.brush_preview_none" value="0" />
|
||||||
<listitem text="@.brush_preview_edges" value="1" />
|
<listitem text="@.brush_preview_edges" value="1" />
|
||||||
|
|
@ -364,7 +364,7 @@
|
||||||
<listitem text="@.brush_preview_fullnedges" value="4" />
|
<listitem text="@.brush_preview_fullnedges" value="4" />
|
||||||
</combobox>
|
</combobox>
|
||||||
|
|
||||||
<label text="@.cursor_color_type" />
|
<label text="@.cursor_color_type" for="cursor_color_type" />
|
||||||
<combobox id="cursor_color_type">
|
<combobox id="cursor_color_type">
|
||||||
<listitem text="@.cursor_neg_bw" value="0" />
|
<listitem text="@.cursor_neg_bw" value="0" />
|
||||||
<listitem text="@.cursor_specific_color" value="1" />
|
<listitem text="@.cursor_specific_color" value="1" />
|
||||||
|
|
@ -384,7 +384,7 @@
|
||||||
|
|
||||||
<separator text="@.bg_checkered" horizontal="true" />
|
<separator text="@.bg_checkered" horizontal="true" />
|
||||||
<grid columns="2">
|
<grid columns="2">
|
||||||
<label text="@.bg_size" />
|
<label text="@.bg_size" for="checkered_bg_size" />
|
||||||
<hbox>
|
<hbox>
|
||||||
<combobox id="checkered_bg_size" />
|
<combobox id="checkered_bg_size" />
|
||||||
<expr id="checkered_bg_custom_w" />
|
<expr id="checkered_bg_custom_w" />
|
||||||
|
|
@ -414,23 +414,23 @@
|
||||||
</hbox>
|
</hbox>
|
||||||
|
|
||||||
<grid columns="5">
|
<grid columns="5">
|
||||||
<label text="@.grid_x" />
|
<label text="@.grid_x" for="grid_x" />
|
||||||
<expr id="grid_x" text="" />
|
<expr id="grid_x" text="" />
|
||||||
<label text="@.grid_y" />
|
<label text="@.grid_y" for="grid_y" />
|
||||||
<expr id="grid_y" text="" />
|
<expr id="grid_y" text="" />
|
||||||
<hbox />
|
<hbox />
|
||||||
|
|
||||||
<label text="@.grid_width" />
|
<label text="@.grid_width" for="grid_w" />
|
||||||
<expr id="grid_w" text="" />
|
<expr id="grid_w" text="" />
|
||||||
<label text="@.grid_height" />
|
<label text="@.grid_height" for="grid_h" />
|
||||||
<expr id="grid_h" text="" />
|
<expr id="grid_h" text="" />
|
||||||
<hbox />
|
<hbox />
|
||||||
|
|
||||||
<label text="@.grid_color" />
|
<label text="@.grid_color" for="grid_color" />
|
||||||
<colorpicker id="grid_color" rgba="true" cell_hspan="3" />
|
<colorpicker id="grid_color" rgba="true" cell_hspan="3" />
|
||||||
<hbox />
|
<hbox />
|
||||||
|
|
||||||
<label text="@.grid_opacity" />
|
<label text="@.grid_opacity" for="grid_opacity" />
|
||||||
<slider id="grid_opacity" cell_hspan="3" min="1" max="255" width="128" />
|
<slider id="grid_opacity" cell_hspan="3" min="1" max="255" width="128" />
|
||||||
<check id="grid_auto_opacity" text="@.grid_auto" />
|
<check id="grid_auto_opacity" text="@.grid_auto" />
|
||||||
</grid>
|
</grid>
|
||||||
|
|
@ -440,11 +440,11 @@
|
||||||
<separator horizontal="true" expansive="true" />
|
<separator horizontal="true" expansive="true" />
|
||||||
</hbox>
|
</hbox>
|
||||||
<grid columns="3">
|
<grid columns="3">
|
||||||
<label text="@.grid_color" />
|
<label text="@.grid_color" for="pixel_grid_color" />
|
||||||
<colorpicker id="pixel_grid_color" rgba="true" />
|
<colorpicker id="pixel_grid_color" rgba="true" />
|
||||||
<hbox />
|
<hbox />
|
||||||
|
|
||||||
<label text="@.grid_opacity" />
|
<label text="@.grid_opacity" for="pixel_grid_opacity" />
|
||||||
<slider id="pixel_grid_opacity" min="1" max="255" width="128" />
|
<slider id="pixel_grid_opacity" min="1" max="255" width="128" />
|
||||||
<check id="pixel_grid_auto_opacity" text="@.grid_auto" />
|
<check id="pixel_grid_auto_opacity" text="@.grid_auto" />
|
||||||
</grid>
|
</grid>
|
||||||
|
|
@ -459,15 +459,15 @@
|
||||||
<vbox id="section_guides_and_slices">
|
<vbox id="section_guides_and_slices">
|
||||||
<separator text="@.guides" horizontal="true" />
|
<separator text="@.guides" horizontal="true" />
|
||||||
<grid columns="2">
|
<grid columns="2">
|
||||||
<label text="@.layer_edges_color" />
|
<label text="@.layer_edges_color" for="layer_edges_color" />
|
||||||
<colorpicker id="layer_edges_color" rgba="true" />
|
<colorpicker id="layer_edges_color" rgba="true" />
|
||||||
<label text="@.auto_guides_color" />
|
<label text="@.auto_guides_color" for="auto_guides_color" />
|
||||||
<colorpicker id="auto_guides_color" rgba="true" />
|
<colorpicker id="auto_guides_color" rgba="true" />
|
||||||
</grid>
|
</grid>
|
||||||
|
|
||||||
<separator text="@.slices" horizontal="true" />
|
<separator text="@.slices" horizontal="true" />
|
||||||
<hbox>
|
<hbox>
|
||||||
<label text="@.default_slice_color" />
|
<label text="@.default_slice_color" for="default_slice_color" />
|
||||||
<colorpicker id="default_slice_color" rgba="true" />
|
<colorpicker id="default_slice_color" rgba="true" />
|
||||||
</hbox>
|
</hbox>
|
||||||
</vbox>
|
</vbox>
|
||||||
|
|
@ -478,7 +478,7 @@
|
||||||
<hbox>
|
<hbox>
|
||||||
<check id="limit_undo" text="@.undo_size_limit" />
|
<check id="limit_undo" text="@.undo_size_limit" />
|
||||||
<expr id="undo_size_limit" tooltip="@.undo_size_limit_tooltip" />
|
<expr id="undo_size_limit" tooltip="@.undo_size_limit_tooltip" />
|
||||||
<label text="@.undo_mb" />
|
<label text="@.undo_mb" for="undo_size_limit" />
|
||||||
</hbox>
|
</hbox>
|
||||||
|
|
||||||
<vbox>
|
<vbox>
|
||||||
|
|
@ -496,7 +496,7 @@
|
||||||
<vbox id="section_alerts">
|
<vbox id="section_alerts">
|
||||||
<separator text="@.section_alerts" horizontal="true" />
|
<separator text="@.section_alerts" horizontal="true" />
|
||||||
<hbox>
|
<hbox>
|
||||||
<label text="@.open_sequence_alert" />
|
<label text="@.open_sequence_alert" for="open_sequence" />
|
||||||
<combobox id="open_sequence">
|
<combobox id="open_sequence">
|
||||||
<listitem text="@.open_sequence_alert_ask" value="0" />
|
<listitem text="@.open_sequence_alert_ask" value="0" />
|
||||||
<listitem text="@.open_sequence_alert_yes" value="1" />
|
<listitem text="@.open_sequence_alert_yes" value="1" />
|
||||||
|
|
@ -582,7 +582,7 @@
|
||||||
<vbox id="section_aseprite_format">
|
<vbox id="section_aseprite_format">
|
||||||
<separator text="@.section_aseprite_format" horizontal="true" />
|
<separator text="@.section_aseprite_format" horizontal="true" />
|
||||||
<grid columns="2">
|
<grid columns="2">
|
||||||
<label text="@.cel_content_format" />
|
<label text="@.cel_content_format" for="cel_format" />
|
||||||
<combobox id="cel_format">
|
<combobox id="cel_format">
|
||||||
<listitem text="@.cel_format_compressed" />
|
<listitem text="@.cel_format_compressed" />
|
||||||
<listitem text="@.cel_format_keep" />
|
<listitem text="@.cel_format_keep" />
|
||||||
|
|
@ -626,14 +626,14 @@
|
||||||
<check id="flash_layer" text="@.flash_selected_layer" />
|
<check id="flash_layer" text="@.flash_selected_layer" />
|
||||||
<check id="use_selection_tool_loop" text="@.use_selection_tool_loop" />
|
<check id="use_selection_tool_loop" text="@.use_selection_tool_loop" />
|
||||||
<hbox>
|
<hbox>
|
||||||
<label text="@.non_active_layer_opacity" />
|
<label text="@.non_active_layer_opacity" for="nonactive_layers_opacity" />
|
||||||
<slider id="nonactive_layers_opacity" min="0" max="255" width="128" />
|
<slider id="nonactive_layers_opacity" min="0" max="255" width="128" />
|
||||||
</hbox>
|
</hbox>
|
||||||
<separator text="@.color_quantization" horizontal="true" />
|
<separator text="@.color_quantization" horizontal="true" />
|
||||||
<grid columns="2">
|
<grid columns="2">
|
||||||
<label text="@rgbmap_algorithm_selector.label" />
|
<label text="@rgbmap_algorithm_selector.label" for="rgbmap_algorithm_selector" />
|
||||||
<hbox id="rgbmap_algorithm_placeholder" />
|
<hbox id="rgbmap_algorithm_placeholder" />
|
||||||
<label text="@best_fit_criteria_selector.label" />
|
<label text="@best_fit_criteria_selector.label" for="best_fit_criteria_selector" />
|
||||||
<hbox id="best_fit_criteria_placeholder" />
|
<hbox id="best_fit_criteria_placeholder" />
|
||||||
</grid>
|
</grid>
|
||||||
<separator text="@.performance" horizontal="true" />
|
<separator text="@.performance" horizontal="true" />
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,9 @@
|
||||||
<gui>
|
<gui>
|
||||||
<vbox id="outline" expansive="true">
|
<vbox id="outline" expansive="true">
|
||||||
<grid columns="2">
|
<grid columns="2">
|
||||||
<label text="@.color" />
|
<label text="@.color" for="color" />
|
||||||
<colorpicker id="color" cell_align="horizontal" />
|
<colorpicker id="color" cell_align="horizontal" />
|
||||||
<label text="@.bg_color" />
|
<label text="@.bg_color" for="bg_color" />
|
||||||
<colorpicker id="bg_color" cell_align="horizontal" />
|
<colorpicker id="bg_color" cell_align="horizontal" />
|
||||||
</grid>
|
</grid>
|
||||||
<hbox>
|
<hbox>
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
<check id="alpha_channel" text="@.alpha_channel" cell_hspan="2" />
|
<check id="alpha_channel" text="@.alpha_channel" cell_hspan="2" />
|
||||||
<check id="advanced_check" text="@general.advanced_options" cell_hspan="2" />
|
<check id="advanced_check" text="@general.advanced_options" cell_hspan="2" />
|
||||||
<hbox id="advanced" cell_hspan="2">
|
<hbox id="advanced" cell_hspan="2">
|
||||||
<label text="@rgbmap_algorithm_selector.label" />
|
<label text="@rgbmap_algorithm_selector.label" for="rgbmap_algorithm_selector" />
|
||||||
<hbox id="rgbmap_algorithm_placeholder" />
|
<hbox id="rgbmap_algorithm_placeholder" />
|
||||||
</hbox>
|
</hbox>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<gui>
|
<gui>
|
||||||
<window id="palette_size" text="@.title">
|
<window id="palette_size" text="@.title">
|
||||||
<grid columns="3">
|
<grid columns="3">
|
||||||
<label text="@.number_of_colors" />
|
<label text="@.number_of_colors" for="colors" />
|
||||||
<expr expansive="true" id="colors" magnet="true" />
|
<expr expansive="true" id="colors" magnet="true" />
|
||||||
<box cell_align="horizontal" />
|
<box cell_align="horizontal" />
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,13 @@
|
||||||
<gui>
|
<gui>
|
||||||
<window id="paste_text" text="@.title">
|
<window id="paste_text" text="@.title">
|
||||||
<grid columns="2">
|
<grid columns="2">
|
||||||
<label text="@.text" />
|
<label text="@.text" for="user_text" />
|
||||||
<entry expansive="true" maxsize="256" minwidth="256" id="user_text" magnet="true" cell_align="horizontal" />
|
<entry expansive="true" maxsize="256" minwidth="256" id="user_text" magnet="true" cell_align="horizontal" />
|
||||||
|
|
||||||
<label text="@.font" />
|
<label text="@.font" for="font_face" />
|
||||||
<font id="font_face" cell_align="horizontal" />
|
<font id="font_face" cell_align="horizontal" />
|
||||||
|
|
||||||
<label text="@.color" />
|
<label text="@.color" for="font_color" />
|
||||||
<hbox>
|
<hbox>
|
||||||
<colorpicker id="font_color" />
|
<colorpicker id="font_color" />
|
||||||
</hbox>
|
</hbox>
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,13 @@
|
||||||
<vbox expansive="true" id="controls">
|
<vbox expansive="true" id="controls">
|
||||||
<hbox expansive="true">
|
<hbox expansive="true">
|
||||||
<grid columns="2" id="controls">
|
<grid columns="2" id="controls">
|
||||||
<label text="@replace_color.from" />
|
<label text="@replace_color.from" for="from" />
|
||||||
<colorpicker id="from" cell_align="horizontal" />
|
<colorpicker id="from" cell_align="horizontal" />
|
||||||
<label text="@replace_color.to" />
|
<label text="@replace_color.to" for="to" />
|
||||||
<colorpicker id="to" cell_align="horizontal" />
|
<colorpicker id="to" cell_align="horizontal" />
|
||||||
</grid>
|
</grid>
|
||||||
</hbox>
|
</hbox>
|
||||||
<label text="@replace_color.tolerance" />
|
<label text="@replace_color.tolerance" for="tolerance" />
|
||||||
<slider min="0" max="255" id="tolerance" />
|
<slider min="0" max="255" id="tolerance" />
|
||||||
</vbox>
|
</vbox>
|
||||||
</gui>
|
</gui>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
<!-- Aseprite -->
|
||||||
|
<!-- Copyright (C) 2025 Igara Studio S.A. -->
|
||||||
|
<gui>
|
||||||
|
<window id="run_command" minwidth="256" maxwidth="256" text="@.title" help="run-command">
|
||||||
|
<vbox>
|
||||||
|
<search id="search" placeholder="@.command_placeholder" />
|
||||||
|
|
||||||
|
<label id="expression_result" visible="false" />
|
||||||
|
|
||||||
|
<vbox id="help" visible="false">
|
||||||
|
<label text="@.help_search" />
|
||||||
|
<label text="@.help_expressions" />
|
||||||
|
<label id="help_lua" text="@.help_lua" />
|
||||||
|
</vbox>
|
||||||
|
|
||||||
|
<vbox id="command_list" visible="false" />
|
||||||
|
<vbox id="more_results" visible="false">
|
||||||
|
<separator horizontal="true" />
|
||||||
|
<label id="more_count" />
|
||||||
|
</vbox>
|
||||||
|
</vbox>
|
||||||
|
</window>
|
||||||
|
</gui>
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
<window id="select_shortcut" text="@.title">
|
<window id="select_shortcut" text="@.title">
|
||||||
<vbox expansive="true">
|
<vbox expansive="true">
|
||||||
<grid columns="3">
|
<grid columns="3">
|
||||||
<label text="@.key" />
|
<label text="@.key" for="key_field" />
|
||||||
<hbox id="key_placeholder" cell_align="horizontal" />
|
<hbox id="key_placeholder" cell_align="horizontal" />
|
||||||
<button text="@.clear" id="clear_button" minwidth="60" />
|
<button text="@.clear" id="clear_button" minwidth="60" />
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,17 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!-- Aseprite -->
|
<!-- Aseprite -->
|
||||||
<!-- Copyright (C) 2019-2024 Igara Studio S.A. -->
|
<!-- Copyright (C) 2019-2025 Igara Studio S.A. -->
|
||||||
<!-- Copyright (C) 2017-2018 David Capello -->
|
<!-- Copyright (C) 2017-2018 David Capello -->
|
||||||
<gui>
|
<gui>
|
||||||
<window id="slice_properties" text="@.title" help="slices#slice-properties">
|
<window id="slice_properties" text="@.title" help="slices#slice-properties">
|
||||||
<vbox>
|
<vbox expansive="true">
|
||||||
<grid id="properties_grid" columns="3">
|
<grid id="properties_grid" columns="3">
|
||||||
<label id="label1" text="@.name" />
|
<label text="@.name" for="name" />
|
||||||
<entry id="name" maxsize="256" magnet="true" cell_align="horizontal" expansive="true" />
|
<entry id="name" maxsize="256" magnet="true" cell_align="horizontal" expansive="true" />
|
||||||
<button id="user_data" icon="icon_user_data" maxsize="32" tooltip="@.user_data_tooltip" />
|
<button id="user_data" icon="icon_user_data" maxsize="32" tooltip="@.user_data_tooltip" />
|
||||||
</grid>
|
</grid>
|
||||||
<grid columns="2">
|
<grid columns="3" expansive="true">
|
||||||
<separator horizontal="true" cell_hspan="2" />
|
<separator horizontal="true" cell_hspan="3" />
|
||||||
|
|
||||||
<box />
|
<box />
|
||||||
<hbox homogeneous="true">
|
<hbox homogeneous="true">
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
<label text="@.width" />
|
<label text="@.width" />
|
||||||
<label text="@.height" />
|
<label text="@.height" />
|
||||||
</hbox>
|
</hbox>
|
||||||
|
<boxfiller cell_align="horizontal" />
|
||||||
|
|
||||||
<label text="@.bounds" />
|
<label text="@.bounds" />
|
||||||
<hbox homogeneous="true">
|
<hbox homogeneous="true">
|
||||||
|
|
@ -28,6 +29,7 @@
|
||||||
<expr id="bounds_w" />
|
<expr id="bounds_w" />
|
||||||
<expr id="bounds_h" />
|
<expr id="bounds_h" />
|
||||||
</hbox>
|
</hbox>
|
||||||
|
<boxfiller />
|
||||||
|
|
||||||
<check text="@.center" id="center" />
|
<check text="@.center" id="center" />
|
||||||
<hbox homogeneous="true">
|
<hbox homogeneous="true">
|
||||||
|
|
@ -36,16 +38,18 @@
|
||||||
<expr id="center_w" />
|
<expr id="center_w" />
|
||||||
<expr id="center_h" />
|
<expr id="center_h" />
|
||||||
</hbox>
|
</hbox>
|
||||||
|
<boxfiller />
|
||||||
|
|
||||||
<check text="@.pivot" id="pivot" />
|
<check text="@.pivot" id="pivot" />
|
||||||
<hbox>
|
<hbox>
|
||||||
<expr id="pivot_x" />
|
<expr id="pivot_x" />
|
||||||
<expr id="pivot_y" />
|
<expr id="pivot_y" />
|
||||||
</hbox>
|
</hbox>
|
||||||
|
<boxfiller />
|
||||||
|
|
||||||
<separator horizontal="true" cell_hspan="2" />
|
<boxfiller cell_align="vertical" cell_hspan="3" />
|
||||||
|
<separator horizontal="true" cell_hspan="3" cell_align="horizontal" />
|
||||||
<hbox cell_hspan="2">
|
<hbox cell_hspan="3">
|
||||||
<boxfiller />
|
<boxfiller />
|
||||||
<hbox homogeneous="true">
|
<hbox homogeneous="true">
|
||||||
<button text="@general.ok" closewindow="true" id="ok" magnet="true" minwidth="60" />
|
<button text="@general.ok" closewindow="true" id="ok" magnet="true" minwidth="60" />
|
||||||
|
|
|
||||||
|
|
@ -22,19 +22,19 @@
|
||||||
<grid columns="2">
|
<grid columns="2">
|
||||||
<separator text="@.advanced" horizontal="true" cell_hspan="2" />
|
<separator text="@.advanced" horizontal="true" cell_hspan="2" />
|
||||||
|
|
||||||
<label text="@.transparent_color" />
|
<label text="@.transparent_color" for="transparent_color" />
|
||||||
<hbox>
|
<hbox>
|
||||||
<hbox id="transparent_color_placeholder" />
|
<hbox id="transparent_color_placeholder" />
|
||||||
</hbox>
|
</hbox>
|
||||||
|
|
||||||
<label text="@.pixel_ratio" />
|
<label text="@.pixel_ratio" for="pixel_ratio" />
|
||||||
<combobox id="pixel_ratio" cell_align="horizontal">
|
<combobox id="pixel_ratio" cell_align="horizontal">
|
||||||
<listitem text="@.square_pixels" value="1:1" />
|
<listitem text="@.square_pixels" value="1:1" />
|
||||||
<listitem text="@.double_wide" value="2:1" />
|
<listitem text="@.double_wide" value="2:1" />
|
||||||
<listitem text="@.double_high" value="1:2" />
|
<listitem text="@.double_high" value="1:2" />
|
||||||
</combobox>
|
</combobox>
|
||||||
|
|
||||||
<label text="@.color_profile" />
|
<label text="@.color_profile" for="color_profile" />
|
||||||
<hbox>
|
<hbox>
|
||||||
<combobox id="color_profile" cell_align="horizontal" expansive="true" />
|
<combobox id="color_profile" cell_align="horizontal" expansive="true" />
|
||||||
<hbox homogeneous="true">
|
<hbox homogeneous="true">
|
||||||
|
|
|
||||||
|
|
@ -1,45 +1,36 @@
|
||||||
<!-- Aseprite -->
|
<!-- Aseprite -->
|
||||||
<!-- Copyright (C) 2024 by Igara Studio S.A. -->
|
<!-- Copyright (C) 2025 by Igara Studio S.A. -->
|
||||||
<!-- Copyright (C) 2001-2018 by David Capello -->
|
<!-- Copyright (C) 2001-2018 by David Capello -->
|
||||||
<gui>
|
<gui>
|
||||||
<window id="sprite_size" text="@.title" help="resize">
|
<window id="sprite_size" text="@.title" help="resize">
|
||||||
<box vertical="true">
|
<box vertical="true">
|
||||||
<box vertical="true">
|
<box vertical="true">
|
||||||
<separator text="@.pixels" left="true" horizontal="true" />
|
<separator text="@.pixels" left="true" horizontal="true" />
|
||||||
<box vertical="true" expansive="true">
|
<grid columns="3">
|
||||||
<box horizontal="true">
|
<label text="@.width" for="width_px" />
|
||||||
<box vertical="true" homogeneous="true">
|
|
||||||
<label text="@.width" />
|
|
||||||
<label text="@.height" />
|
|
||||||
</box>
|
|
||||||
<box vertical="true" homogeneous="true" expansive="true">
|
|
||||||
<expr expansive="true" id="width_px" suffix="px" magnet="true" tooltip="@.width_px_tooltip" />
|
<expr expansive="true" id="width_px" suffix="px" magnet="true" tooltip="@.width_px_tooltip" />
|
||||||
|
|
||||||
|
<check text="@.lock_ratio" id="lock_ratio" selected="true" expansive="false" cell_vspan="2" />
|
||||||
|
|
||||||
|
<label text="@.height" for="height_px" />
|
||||||
<expr expansive="true" id="height_px" suffix="px" tooltip="@.height_px_tooltip" />
|
<expr expansive="true" id="height_px" suffix="px" tooltip="@.height_px_tooltip" />
|
||||||
</box>
|
</grid>
|
||||||
<check text="@.lock_ratio" id="lock_ratio" selected="true" />
|
|
||||||
</box>
|
|
||||||
</box>
|
|
||||||
<separator text="@.percentage" left="true" horizontal="true" />
|
<separator text="@.percentage" left="true" horizontal="true" />
|
||||||
<box vertical="true" expansive="true">
|
<grid columns="3">
|
||||||
<box horizontal="true">
|
<label text="@.width" for="width_perc" />
|
||||||
<box vertical="true" homogeneous="true">
|
<expr expansive="true" text="100" suffix="%" id="width_perc" magnet="true" tooltip="@.width_perc_tooltip" decimals="4" />
|
||||||
<label text="@.width" />
|
|
||||||
<label text="@.height" />
|
<boxfiller cell_vspan="2" />
|
||||||
</box>
|
|
||||||
<box vertical="true" homogeneous="true" expansive="true">
|
<label text="@.height" for="height_perc" />
|
||||||
<expr expansive="true" text="100" suffix="%" id="width_perc" magnet="true" tooltip="@.width_perc_tooltip"
|
<expr expansive="true" text="100" suffix="%" id="height_perc" tooltip="@.height_perc_tooltip" decimals="4" />
|
||||||
decimals="4" />
|
</grid>
|
||||||
<expr expansive="true" text="100" suffix="%" id="height_perc" tooltip="@.height_perc_tooltip"
|
|
||||||
decimals="4" />
|
|
||||||
</box>
|
|
||||||
<box horizontal="true" width="64" />
|
|
||||||
</box>
|
|
||||||
</box>
|
|
||||||
</box>
|
</box>
|
||||||
<separator text="@.interpolation" left="true" horizontal="true" />
|
<separator text="@.interpolation" left="true" horizontal="true" />
|
||||||
<box vertical="true" expansive="true">
|
<box vertical="true" expansive="true">
|
||||||
<box horizontal="true">
|
<box horizontal="true">
|
||||||
<label text="@.method" />
|
<label text="@.method" for="method" />
|
||||||
<combobox id="method" expansive="true" />
|
<combobox id="method" expansive="true" />
|
||||||
</box>
|
</box>
|
||||||
</box>
|
</box>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<gui>
|
<gui>
|
||||||
<window id="svg_options" text="@.title">
|
<window id="svg_options" text="@.title">
|
||||||
<grid columns="2">
|
<grid columns="2">
|
||||||
<label text="@.pixel_scale" />
|
<label text="@.pixel_scale" for="pxsc" />
|
||||||
<expr id="pxsc" magnet="true" cell_align="horizontal"/>
|
<expr id="pxsc" magnet="true" cell_align="horizontal"/>
|
||||||
|
|
||||||
<separator horizontal="true" cell_hspan="2" />
|
<separator horizontal="true" cell_hspan="2" />
|
||||||
|
|
|
||||||
|
|
@ -1,35 +1,36 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!-- Aseprite -->
|
<!-- Aseprite -->
|
||||||
<!-- Copyright (C) 2019-2021 Igara Studio S.A. -->
|
<!-- Copyright (C) 2019-2025 Igara Studio S.A. -->
|
||||||
<!-- Copyright (C) 2015-2018 David Capello -->
|
<!-- Copyright (C) 2015-2018 David Capello -->
|
||||||
<gui>
|
<gui>
|
||||||
<window id="tag_properties" text="@.title">
|
<window id="tag_properties" text="@.title">
|
||||||
<vbox>
|
<vbox>
|
||||||
<grid id="properties_grid" columns="3">
|
<grid id="properties_grid" columns="3">
|
||||||
|
|
||||||
<label text="@.name" />
|
<label text="@.name" for="name" />
|
||||||
<entry maxsize="256" id="name" magnet="true" cell_align="horizontal" expansive="true" />
|
<entry maxsize="256" id="name" magnet="true" cell_align="horizontal" expansive="true" />
|
||||||
<button id="user_data" icon="icon_user_data" maxsize="32" tooltip="@general.user_data" />
|
<button id="user_data" icon="icon_user_data" maxsize="32" tooltip="@general.user_data" />
|
||||||
|
|
||||||
<label text="@.from" />
|
<label text="@.from" for="from" />
|
||||||
<expr id="from" cell_hspan="2" />
|
<expr id="from" cell_hspan="2" />
|
||||||
|
|
||||||
<label text="@.to" />
|
<label text="@.to" for="to" />
|
||||||
<expr id="to" cell_hspan="2" />
|
<expr id="to" cell_hspan="2" />
|
||||||
|
|
||||||
<label text="@.ani_dir" />
|
<label text="@.ani_dir" for="anidir" />
|
||||||
<combobox id="anidir" cell_hspan="2" />
|
<combobox id="anidir" cell_hspan="2" />
|
||||||
|
|
||||||
<check text="@.repeat" id="limit_repeat" />
|
<check text="@.repeat" id="limit_repeat" />
|
||||||
<vbox id="repeat_placeholder" cell_hspan="2" />
|
<vbox id="repeat_placeholder" cell_hspan="2" />
|
||||||
</grid>
|
</grid>
|
||||||
|
<boxfiller />
|
||||||
<grid columns="2">
|
<grid columns="2">
|
||||||
<separator horizontal="true" cell_hspan="2" minwidth="180" />
|
<separator horizontal="true" cell_align="horizontal" cell_hspan="2" minwidth="180" />
|
||||||
|
|
||||||
<box horizontal="true" homogeneous="true" cell_hspan="2" cell_align="right">
|
<hbox homogeneous="true" cell_hspan="2" cell_align="right">
|
||||||
<button text="@general.ok" closewindow="true" id="ok" magnet="true" minwidth="60" />
|
<button text="@general.ok" closewindow="true" id="ok" magnet="true" minwidth="60" />
|
||||||
<button text="@general.cancel" closewindow="true" />
|
<button text="@general.cancel" closewindow="true" />
|
||||||
</box>
|
</hbox>
|
||||||
</grid>
|
</grid>
|
||||||
</vbox>
|
</vbox>
|
||||||
</window>
|
</window>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<gui>
|
<gui>
|
||||||
<window id="tga_options" text="@.title">
|
<window id="tga_options" text="@.title">
|
||||||
<grid columns="2">
|
<grid columns="2">
|
||||||
<label text="@.bits_per_pixel" id="bits_per_pixel_label" />
|
<label text="@.bits_per_pixel" id="bits_per_pixel_label" for="bits_per_pixel" />
|
||||||
<combobox id="bits_per_pixel" cell_align="horizontal" />
|
<combobox id="bits_per_pixel" cell_align="horizontal" />
|
||||||
|
|
||||||
<check text="@.compress" id="compress" cell_hspan="2" />
|
<check text="@.compress" id="compress" cell_hspan="2" />
|
||||||
|
|
|
||||||
|
|
@ -7,19 +7,19 @@
|
||||||
</combobox>
|
</combobox>
|
||||||
|
|
||||||
<grid columns="4" expansive="true">
|
<grid columns="4" expansive="true">
|
||||||
<label text="@.name" />
|
<label text="@.name" for="name" />
|
||||||
<entry maxsize="256" id="name" text="" cell_hspan="3" />
|
<entry maxsize="256" id="name" text="" cell_hspan="3" />
|
||||||
|
|
||||||
<label text="@.grid_width" />
|
<label text="@.grid_width" for="grid_width" />
|
||||||
<expr id="grid_width" text="" />
|
<expr id="grid_width" text="" />
|
||||||
<label text="@.grid_height" />
|
<label text="@.grid_height" for="grid_height" />
|
||||||
<expr id="grid_height" text="" />
|
<expr id="grid_height" text="" />
|
||||||
|
|
||||||
<label id="base_index_label" text="@.base_index" />
|
<label id="base_index_label" text="@.base_index" for="base_index" />
|
||||||
<expr id="base_index" text="1" tooltip="@.base_tooltip" />
|
<expr id="base_index" text="1" tooltip="@.base_tooltip" />
|
||||||
<boxfiller id="base_index_filler" cell_hspan="2" />
|
<boxfiller id="base_index_filler" cell_hspan="2" />
|
||||||
|
|
||||||
<label id="flips_label" text="@.allowed_flips" />
|
<label id="flips_label" text="@.allowed_flips" for="flips" />
|
||||||
<buttonset id="flips" columns="3" multiple="true">
|
<buttonset id="flips" columns="3" multiple="true">
|
||||||
<item id="xflip" text="X" minwidth="20" tooltip="@.allowed_flips_tooltip" tooltip_dir="bottom" />
|
<item id="xflip" text="X" minwidth="20" tooltip="@.allowed_flips_tooltip" tooltip_dir="bottom" />
|
||||||
<item id="yflip" text="Y" minwidth="20" tooltip="@.allowed_flips_tooltip" tooltip_dir="bottom" />
|
<item id="yflip" text="Y" minwidth="20" tooltip="@.allowed_flips_tooltip" tooltip_dir="bottom" />
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
<vbox>
|
<vbox>
|
||||||
<separator text="@.frame_header" left="true" horizontal="true" />
|
<separator text="@.frame_header" left="true" horizontal="true" />
|
||||||
<hbox>
|
<hbox>
|
||||||
<label text="@.first_frame" />
|
<label text="@.first_frame" for="first_frame" />
|
||||||
<expr id="first_frame" />
|
<expr id="first_frame" />
|
||||||
</hbox>
|
</hbox>
|
||||||
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
<separator id="thumb_h_separator" horizontal="true" expansive="true" />
|
<separator id="thumb_h_separator" horizontal="true" expansive="true" />
|
||||||
</hbox>
|
</hbox>
|
||||||
<grid columns="2" id="thumb_box">
|
<grid columns="2" id="thumb_box">
|
||||||
<label text="@.thumbnail_size" />
|
<label text="@.thumbnail_size" for="zoom" />
|
||||||
<slider min="1" max="10" id="zoom" cell_align="horizontal" width="128" />
|
<slider min="1" max="10" id="zoom" cell_align="horizontal" width="128" />
|
||||||
|
|
||||||
<check id="thumb_overlay_enabled" text="@.overlay_size"/>
|
<check id="thumb_overlay_enabled" text="@.overlay_size"/>
|
||||||
|
|
@ -38,10 +38,10 @@
|
||||||
<button id="reset_onionskin" text="@.reset" minwidth="60" />
|
<button id="reset_onionskin" text="@.reset" minwidth="60" />
|
||||||
</hbox>
|
</hbox>
|
||||||
|
|
||||||
<label text="@.opacity" />
|
<label text="@.opacity" for="opacity" />
|
||||||
<opacityslider id="opacity" cell_align="horizontal" width="128" />
|
<opacityslider id="opacity" cell_align="horizontal" width="128" />
|
||||||
|
|
||||||
<label text="@.opacity_step" />
|
<label text="@.opacity_step" for="opacity_step" />
|
||||||
<opacityslider id="opacity_step" cell_align="horizontal" width="128" />
|
<opacityslider id="opacity_step" cell_align="horizontal" width="128" />
|
||||||
|
|
||||||
<check id="loop_tag" text="@.loop_tags" cell_hspan="2" />
|
<check id="loop_tag" text="@.loop_tags" cell_hspan="2" />
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@
|
||||||
<!-- Copyright (C) 2001-2017 by David Capello -->
|
<!-- Copyright (C) 2001-2017 by David Capello -->
|
||||||
<gui>
|
<gui>
|
||||||
<hbox id="user_data">
|
<hbox id="user_data">
|
||||||
<label id="color_label" text="@.color" />
|
<label id="color_label" text="@.color" for="color" />
|
||||||
<label id="entry_label" text="@.user_data" />
|
<label id="entry_label" text="@.user_data" for="entry" />
|
||||||
<colorpicker id="color" simple="true" expansive="true" />
|
<colorpicker id="color" simple="true" expansive="true" />
|
||||||
<entry id="entry" maxsize="65535" minwidth="128" expansive="true" />
|
<entry id="entry" maxsize="65535" minwidth="128" expansive="true" />
|
||||||
</hbox>
|
</hbox>
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
<label text="@.save_as" />
|
<label text="@.save_as" />
|
||||||
<check text="@.animation_loop" id="loop" />
|
<check text="@.animation_loop" id="loop" />
|
||||||
<hbox>
|
<hbox>
|
||||||
<label text="@.type" />
|
<label text="@.type" for="type" />
|
||||||
<combobox id="type" cell_align="horizontal" cell_hspan="2">
|
<combobox id="type" cell_align="horizontal" cell_hspan="2">
|
||||||
<listitem text="@.simple_webp" value="0" />
|
<listitem text="@.simple_webp" value="0" />
|
||||||
<listitem text="@.lossless_webp" value="1" />
|
<listitem text="@.lossless_webp" value="1" />
|
||||||
|
|
@ -16,11 +16,11 @@
|
||||||
</hbox>
|
</hbox>
|
||||||
<vbox id="lossless_options">
|
<vbox id="lossless_options">
|
||||||
<hbox>
|
<hbox>
|
||||||
<label width="55" text="@.compression" />
|
<label width="55" text="@.compression" for="compression" />
|
||||||
<slider min="0" max="9" id="compression" cell_align="horizontal" width="128" />
|
<slider min="0" max="9" id="compression" cell_align="horizontal" width="128" />
|
||||||
</hbox>
|
</hbox>
|
||||||
<hbox>
|
<hbox>
|
||||||
<label width="55" text="@.image_hint" />
|
<label width="55" text="@.image_hint" for="image_hint" />
|
||||||
<combobox width="128" id="image_hint">
|
<combobox width="128" id="image_hint">
|
||||||
<listitem text="@.image_hint_default" value="0" />
|
<listitem text="@.image_hint_default" value="0" />
|
||||||
<listitem text="@.image_hint_picture" value="1" />
|
<listitem text="@.image_hint_picture" value="1" />
|
||||||
|
|
@ -31,11 +31,11 @@
|
||||||
</vbox>
|
</vbox>
|
||||||
<vbox id="lossy_options">
|
<vbox id="lossy_options">
|
||||||
<hbox>
|
<hbox>
|
||||||
<label width="55" text="@.quality" />
|
<label width="55" text="@.quality" for="quality" />
|
||||||
<slider min="0" max="100" id="quality" cell_align="horizontal" width="128" />
|
<slider min="0" max="100" id="quality" cell_align="horizontal" width="128" />
|
||||||
</hbox>
|
</hbox>
|
||||||
<hbox>
|
<hbox>
|
||||||
<label width="55" text="@.image_preset" />
|
<label width="55" text="@.image_preset" for="image_preset" />
|
||||||
<combobox width="128" id="image_preset">
|
<combobox width="128" id="image_preset">
|
||||||
<listitem text="@.image_preset_default" value="0" />
|
<listitem text="@.image_preset_default" value="0" />
|
||||||
<listitem text="@.image_preset_picture" value="1" />
|
<listitem text="@.image_preset_picture" value="1" />
|
||||||
|
|
|
||||||
2
laf
2
laf
|
|
@ -1 +1 @@
|
||||||
Subproject commit 01571537bc6002a2e039a66497837365c394d7fa
|
Subproject commit 39706c11063fb53cf4c8e865102c6f71e2606906
|
||||||
|
|
@ -220,6 +220,7 @@ if(ENABLE_TESTS)
|
||||||
find_tests(ui ui-lib)
|
find_tests(ui ui-lib)
|
||||||
find_tests(app/cli app-lib)
|
find_tests(app/cli app-lib)
|
||||||
find_tests(app/file app-lib)
|
find_tests(app/file app-lib)
|
||||||
|
find_tests(app/ui app-lib)
|
||||||
find_tests(app app-lib)
|
find_tests(app app-lib)
|
||||||
find_tests(. app-lib)
|
find_tests(. app-lib)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ add_custom_command(
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${output_fn}.tmp ${output_fn}
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${output_fn}.tmp ${output_fn}
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
MAIN_DEPENDENCY ${strings_en_ini}
|
MAIN_DEPENDENCY ${strings_en_ini}
|
||||||
DEPENDS ${GEN_DEP})
|
DEPENDS ${GEN_DEP} commands/commands_list.h)
|
||||||
list(APPEND generated_files ${output_fn})
|
list(APPEND generated_files ${output_fn})
|
||||||
|
|
||||||
# Check translations
|
# Check translations
|
||||||
|
|
@ -368,6 +368,7 @@ target_sources(app-lib PRIVATE
|
||||||
color_picker.cpp
|
color_picker.cpp
|
||||||
color_spaces.cpp
|
color_spaces.cpp
|
||||||
color_utils.cpp
|
color_utils.cpp
|
||||||
|
commands/apply.cpp
|
||||||
commands/cmd_about.cpp
|
commands/cmd_about.cpp
|
||||||
commands/cmd_add_color.cpp
|
commands/cmd_add_color.cpp
|
||||||
commands/cmd_advanced_mode.cpp
|
commands/cmd_advanced_mode.cpp
|
||||||
|
|
@ -393,6 +394,7 @@ target_sources(app-lib PRIVATE
|
||||||
commands/cmd_deselect_mask.cpp
|
commands/cmd_deselect_mask.cpp
|
||||||
commands/cmd_discard_brush.cpp
|
commands/cmd_discard_brush.cpp
|
||||||
commands/cmd_duplicate_layer.cpp
|
commands/cmd_duplicate_layer.cpp
|
||||||
|
commands/cmd_duplicate_slice.cpp
|
||||||
commands/cmd_duplicate_sprite.cpp
|
commands/cmd_duplicate_sprite.cpp
|
||||||
commands/cmd_duplicate_view.cpp
|
commands/cmd_duplicate_view.cpp
|
||||||
commands/cmd_enter_license.cpp
|
commands/cmd_enter_license.cpp
|
||||||
|
|
@ -460,6 +462,7 @@ target_sources(app-lib PRIVATE
|
||||||
commands/cmd_reselect_mask.cpp
|
commands/cmd_reselect_mask.cpp
|
||||||
commands/cmd_reverse_frames.cpp
|
commands/cmd_reverse_frames.cpp
|
||||||
commands/cmd_rotate.cpp
|
commands/cmd_rotate.cpp
|
||||||
|
commands/cmd_run_command.cpp
|
||||||
commands/cmd_save_file.cpp
|
commands/cmd_save_file.cpp
|
||||||
commands/cmd_save_mask.cpp
|
commands/cmd_save_mask.cpp
|
||||||
commands/cmd_save_palette.cpp
|
commands/cmd_save_palette.cpp
|
||||||
|
|
@ -653,6 +656,7 @@ target_sources(app-lib PRIVATE
|
||||||
ui/icon_button.cpp
|
ui/icon_button.cpp
|
||||||
ui/incompat_file_window.cpp
|
ui/incompat_file_window.cpp
|
||||||
ui/input_chain.cpp
|
ui/input_chain.cpp
|
||||||
|
ui/key.cpp
|
||||||
ui/keyboard_shortcuts.cpp
|
ui/keyboard_shortcuts.cpp
|
||||||
ui/layer_frame_comboboxes.cpp
|
ui/layer_frame_comboboxes.cpp
|
||||||
ui/layout.cpp
|
ui/layout.cpp
|
||||||
|
|
@ -720,6 +724,7 @@ target_sources(app-lib PRIVATE
|
||||||
util/render_text.cpp
|
util/render_text.cpp
|
||||||
util/resize_image.cpp
|
util/resize_image.cpp
|
||||||
util/shader_helpers.cpp
|
util/shader_helpers.cpp
|
||||||
|
util/slice_utils.cpp
|
||||||
util/tile_flags_utils.cpp
|
util/tile_flags_utils.cpp
|
||||||
util/tileset_utils.cpp
|
util/tileset_utils.cpp
|
||||||
util/wrap_point.cpp
|
util/wrap_point.cpp
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,6 @@
|
||||||
#include "app/ui/keyboard_shortcuts.h"
|
#include "app/ui/keyboard_shortcuts.h"
|
||||||
#include "app/ui/main_window.h"
|
#include "app/ui/main_window.h"
|
||||||
#include "app/ui_context.h"
|
#include "app/ui_context.h"
|
||||||
#include "app/util/filetoks.h"
|
|
||||||
#include "base/fs.h"
|
#include "base/fs.h"
|
||||||
#include "base/string.h"
|
#include "base/string.h"
|
||||||
#include "fmt/format.h"
|
#include "fmt/format.h"
|
||||||
|
|
@ -463,6 +462,8 @@ void AppMenus::reload()
|
||||||
// Create native menus after the default + user defined keyboard
|
// Create native menus after the default + user defined keyboard
|
||||||
// shortcuts are loaded correctly.
|
// shortcuts are loaded correctly.
|
||||||
createNativeMenus();
|
createNativeMenus();
|
||||||
|
|
||||||
|
MenusLoaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_SCRIPTING
|
#ifdef ENABLE_SCRIPTING
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,8 @@ public:
|
||||||
void removeMenuItemFromGroup(Command* cmd);
|
void removeMenuItemFromGroup(Command* cmd);
|
||||||
void removeMenuItemFromGroup(Widget* menuItem);
|
void removeMenuItemFromGroup(Widget* menuItem);
|
||||||
|
|
||||||
|
obs::signal<void()> MenusLoaded;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template<typename Pred>
|
template<typename Pred>
|
||||||
void removeMenuItemFromGroup(Pred pred);
|
void removeMenuItemFromGroup(Pred pred);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2018-2024 Igara Studio S.A.
|
// Copyright (C) 2018-2025 Igara Studio S.A.
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
// the End-User License Agreement for Aseprite.
|
// the End-User License Agreement for Aseprite.
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
#include "app/ui/editor/editor.h"
|
#include "app/ui/editor/editor.h"
|
||||||
#include "os/system.h"
|
#include "os/system.h"
|
||||||
#include "os/window.h"
|
#include "os/window.h"
|
||||||
|
#include "ui/display.h"
|
||||||
|
|
||||||
namespace app {
|
namespace app {
|
||||||
|
|
||||||
|
|
@ -29,17 +30,15 @@ void initialize_color_spaces(Preferences& pref)
|
||||||
pref.color.manage.AfterChange.connect([](bool manage) { g_manage = manage; });
|
pref.color.manage.AfterChange.connect([](bool manage) { g_manage = manage; });
|
||||||
}
|
}
|
||||||
|
|
||||||
os::ColorSpaceRef get_screen_color_space()
|
os::ColorSpaceRef get_current_color_space(ui::Display* display, Doc* doc)
|
||||||
{
|
|
||||||
return os::System::instance()->defaultWindow()->colorSpace();
|
|
||||||
}
|
|
||||||
|
|
||||||
os::ColorSpaceRef get_current_color_space()
|
|
||||||
{
|
{
|
||||||
|
if (!doc) {
|
||||||
if (auto* editor = Editor::activeEditor())
|
if (auto* editor = Editor::activeEditor())
|
||||||
return editor->document()->osColorSpace();
|
doc = editor->document();
|
||||||
else
|
}
|
||||||
return get_screen_color_space();
|
if (doc)
|
||||||
|
return doc->osColorSpace();
|
||||||
|
return display->colorSpace();
|
||||||
}
|
}
|
||||||
|
|
||||||
gfx::ColorSpaceRef get_working_rgb_space_from_preferences()
|
gfx::ColorSpaceRef get_working_rgb_space_from_preferences()
|
||||||
|
|
@ -62,11 +61,11 @@ gfx::ColorSpaceRef get_working_rgb_space_from_preferences()
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// Color conversion
|
// Color conversion
|
||||||
|
|
||||||
ConvertCS::ConvertCS()
|
ConvertCS::ConvertCS(ui::Display* display, Doc* doc)
|
||||||
{
|
{
|
||||||
if (g_manage) {
|
if (g_manage) {
|
||||||
auto srcCS = get_current_color_space();
|
auto srcCS = get_current_color_space(display, doc);
|
||||||
auto dstCS = get_screen_color_space();
|
auto dstCS = display->colorSpace();
|
||||||
if (srcCS && dstCS)
|
if (srcCS && dstCS)
|
||||||
m_conversion = os::System::instance()->convertBetweenColorSpace(srcCS, dstCS);
|
m_conversion = os::System::instance()->convertBetweenColorSpace(srcCS, dstCS);
|
||||||
}
|
}
|
||||||
|
|
@ -95,9 +94,9 @@ gfx::Color ConvertCS::operator()(const gfx::Color c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ConvertCS convert_from_current_to_screen_color_space()
|
ConvertCS convert_from_current_to_display_color_space(ui::Display* display)
|
||||||
{
|
{
|
||||||
return ConvertCS();
|
return ConvertCS(display);
|
||||||
}
|
}
|
||||||
|
|
||||||
ConvertCS convert_from_custom_to_srgb(const os::ColorSpaceRef& from)
|
ConvertCS convert_from_custom_to_srgb(const os::ColorSpaceRef& from)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (c) 2018-2020 Igara Studio S.A.
|
// Copyright (c) 2018-2025 Igara Studio S.A.
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
// the End-User License Agreement for Aseprite.
|
// the End-User License Agreement for Aseprite.
|
||||||
|
|
@ -16,21 +16,25 @@ namespace doc {
|
||||||
class Sprite;
|
class Sprite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace ui {
|
||||||
|
class Display;
|
||||||
|
}
|
||||||
|
|
||||||
namespace app {
|
namespace app {
|
||||||
|
class Doc;
|
||||||
class Preferences;
|
class Preferences;
|
||||||
|
|
||||||
void initialize_color_spaces(Preferences& pref);
|
void initialize_color_spaces(Preferences& pref);
|
||||||
|
|
||||||
os::ColorSpaceRef get_screen_color_space();
|
|
||||||
|
|
||||||
// Returns the color space of the current document.
|
// Returns the color space of the current document.
|
||||||
os::ColorSpaceRef get_current_color_space();
|
os::ColorSpaceRef get_current_color_space(ui::Display* display, Doc* doc = nullptr);
|
||||||
|
|
||||||
gfx::ColorSpaceRef get_working_rgb_space_from_preferences();
|
gfx::ColorSpaceRef get_working_rgb_space_from_preferences();
|
||||||
|
|
||||||
class ConvertCS {
|
class ConvertCS {
|
||||||
public:
|
public:
|
||||||
ConvertCS();
|
ConvertCS() = delete;
|
||||||
|
ConvertCS(ui::Display* display, Doc* doc = nullptr);
|
||||||
ConvertCS(const os::ColorSpaceRef& srcCS, const os::ColorSpaceRef& dstCS);
|
ConvertCS(const os::ColorSpaceRef& srcCS, const os::ColorSpaceRef& dstCS);
|
||||||
ConvertCS(ConvertCS&&);
|
ConvertCS(ConvertCS&&);
|
||||||
ConvertCS& operator=(const ConvertCS&) = delete;
|
ConvertCS& operator=(const ConvertCS&) = delete;
|
||||||
|
|
@ -40,7 +44,7 @@ private:
|
||||||
os::Ref<os::ColorSpaceConversion> m_conversion;
|
os::Ref<os::ColorSpaceConversion> m_conversion;
|
||||||
};
|
};
|
||||||
|
|
||||||
ConvertCS convert_from_current_to_screen_color_space();
|
ConvertCS convert_from_current_to_display_color_space(ui::Display* display);
|
||||||
ConvertCS convert_from_custom_to_srgb(const os::ColorSpaceRef& from);
|
ConvertCS convert_from_custom_to_srgb(const os::ColorSpaceRef& from);
|
||||||
|
|
||||||
} // namespace app
|
} // namespace app
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
// Aseprite
|
||||||
|
// Copyright (C) 2025 Igara Studio S.A.
|
||||||
|
//
|
||||||
|
// This program is distributed under the terms of
|
||||||
|
// the End-User License Agreement for Aseprite.
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "app/commands/command.h"
|
||||||
|
#include "app/context.h"
|
||||||
|
#include "app/ui/editor/editor.h"
|
||||||
|
|
||||||
|
namespace app {
|
||||||
|
|
||||||
|
// Depends on the current context/state, used to apply the current
|
||||||
|
// transformation (drop pixels).
|
||||||
|
class ApplyCommand : public Command {
|
||||||
|
public:
|
||||||
|
ApplyCommand();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void onExecute(Context* ctx) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
ApplyCommand::ApplyCommand() : Command(CommandId::Apply())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApplyCommand::onExecute(Context* ctx)
|
||||||
|
{
|
||||||
|
if (!ctx->isUIAvailable())
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto* editor = Editor::activeEditor();
|
||||||
|
if (editor && editor->isMovingPixels())
|
||||||
|
editor->dropMovingPixels();
|
||||||
|
}
|
||||||
|
|
||||||
|
Command* CommandFactory::createApplyCommand()
|
||||||
|
{
|
||||||
|
return new ApplyCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace app
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2020-2023 Igara Studio S.A.
|
// Copyright (C) 2020-2025 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
|
|
@ -100,12 +100,12 @@ public:
|
||||||
|
|
||||||
if (countCels() > 0) {
|
if (countCels() > 0) {
|
||||||
m_userDataView.configureAndSet((m_cel ? m_cel->data()->userData() : UserData()),
|
m_userDataView.configureAndSet((m_cel ? m_cel->data()->userData() : UserData()),
|
||||||
g_window->propertiesGrid());
|
propertiesGrid());
|
||||||
}
|
}
|
||||||
else if (!m_cel)
|
else if (!m_cel)
|
||||||
m_userDataView.setVisible(false, false);
|
m_userDataView.setVisible(false, false);
|
||||||
|
|
||||||
g_window->expandWindow(gfx::Size(g_window->bounds().w, g_window->sizeHint().h));
|
expandWindow(gfx::Size(bounds().w, sizeHint().h));
|
||||||
updateFromCel();
|
updateFromCel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -280,7 +280,7 @@ private:
|
||||||
{
|
{
|
||||||
if (countCels() > 0) {
|
if (countCels() > 0) {
|
||||||
m_userDataView.toggleVisibility();
|
m_userDataView.toggleVisibility();
|
||||||
g_window->expandWindow(gfx::Size(g_window->bounds().w, g_window->sizeHint().h));
|
expandWindow(gfx::Size(bounds().w, sizeHint().h));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,121 @@
|
||||||
|
// Aseprite
|
||||||
|
// Copyright (C) 2025 Igara Studio S.A.
|
||||||
|
//
|
||||||
|
// This program is distributed under the terms of
|
||||||
|
// the End-User License Agreement for Aseprite.
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "app/cmd/add_slice.h"
|
||||||
|
#include "app/commands/command.h"
|
||||||
|
#include "app/context.h"
|
||||||
|
#include "app/context_access.h"
|
||||||
|
#include "app/context_flags.h"
|
||||||
|
#include "app/i18n/strings.h"
|
||||||
|
#include "app/site.h"
|
||||||
|
#include "app/tx.h"
|
||||||
|
#include "app/ui/status_bar.h"
|
||||||
|
#include "app/util/slice_utils.h"
|
||||||
|
#include "base/convert_to.h"
|
||||||
|
#include "doc/object_id.h"
|
||||||
|
#include "doc/slice.h"
|
||||||
|
|
||||||
|
namespace app {
|
||||||
|
|
||||||
|
// Moves the given slice by the dx and dy values
|
||||||
|
void offset(Slice* slice, int dx, int dy)
|
||||||
|
{
|
||||||
|
for (auto it = slice->begin(); it != slice->end(); ++it) {
|
||||||
|
auto* sk = (*it).value();
|
||||||
|
gfx::Rect bounds = sk->bounds();
|
||||||
|
bounds.offset(gfx::Point{ dx, dy });
|
||||||
|
sk->setBounds(bounds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DuplicateSliceCommand : public Command {
|
||||||
|
public:
|
||||||
|
DuplicateSliceCommand();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void onLoadParams(const Params& params) override;
|
||||||
|
bool onEnabled(Context* context) override;
|
||||||
|
void onExecute(Context* context) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ObjectId m_sliceId;
|
||||||
|
};
|
||||||
|
|
||||||
|
DuplicateSliceCommand::DuplicateSliceCommand() : Command(CommandId::DuplicateSlice())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void DuplicateSliceCommand::onLoadParams(const Params& params)
|
||||||
|
{
|
||||||
|
std::string id = params.get("id");
|
||||||
|
if (!id.empty())
|
||||||
|
m_sliceId = ObjectId(base::convert_to<doc::ObjectId>(id));
|
||||||
|
else
|
||||||
|
m_sliceId = NullId;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DuplicateSliceCommand::onEnabled(Context* context)
|
||||||
|
{
|
||||||
|
return context->checkFlags(ContextFlags::ActiveDocumentIsWritable |
|
||||||
|
ContextFlags::HasActiveSprite | ContextFlags::HasActiveLayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DuplicateSliceCommand::onExecute(Context* context)
|
||||||
|
{
|
||||||
|
std::vector<Slice*> selectedSlices;
|
||||||
|
{
|
||||||
|
const ContextReader reader(context);
|
||||||
|
if (m_sliceId == NullId) {
|
||||||
|
selectedSlices = get_selected_slices(reader.site());
|
||||||
|
if (selectedSlices.empty())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
selectedSlices.push_back(reader.sprite()->slices().getById(m_sliceId));
|
||||||
|
}
|
||||||
|
|
||||||
|
ContextWriter writer(context);
|
||||||
|
Tx tx(writer, "Duplicate Slice");
|
||||||
|
Sprite* sprite = writer.site().sprite();
|
||||||
|
|
||||||
|
Doc* doc = static_cast<Doc*>(sprite->document());
|
||||||
|
doc->notifyBeforeSlicesDuplication();
|
||||||
|
for (auto* s : selectedSlices) {
|
||||||
|
Slice* slice = new Slice(*s);
|
||||||
|
slice->setName(Strings::general_copy_of(slice->name()));
|
||||||
|
// Offset a bit the duplicated slice to avoid overlapping
|
||||||
|
offset(slice, 2, 2);
|
||||||
|
|
||||||
|
tx(new cmd::AddSlice(sprite, slice));
|
||||||
|
doc->notifySliceDuplicated(slice);
|
||||||
|
}
|
||||||
|
tx.commit();
|
||||||
|
|
||||||
|
std::string sliceName;
|
||||||
|
if (selectedSlices.size() == 1)
|
||||||
|
sliceName = selectedSlices[0]->name();
|
||||||
|
|
||||||
|
StatusBar::instance()->invalidate();
|
||||||
|
if (!sliceName.empty()) {
|
||||||
|
StatusBar::instance()->showTip(1000, Strings::duplicate_slice_x_duplicated(sliceName));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
StatusBar::instance()->showTip(
|
||||||
|
1000,
|
||||||
|
Strings::duplicate_slice_n_slices_duplicated(selectedSlices.size()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Command* CommandFactory::createDuplicateSliceCommand()
|
||||||
|
{
|
||||||
|
return new DuplicateSliceCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace app
|
||||||
|
|
@ -212,7 +212,7 @@ private:
|
||||||
if (m_showUI) {
|
if (m_showUI) {
|
||||||
app::gen::GotoFrame window;
|
app::gen::GotoFrame window;
|
||||||
TagsEntry combobox(editor->sprite()->tags());
|
TagsEntry combobox(editor->sprite()->tags());
|
||||||
|
combobox.setId("frame");
|
||||||
window.framePlaceholder()->addChild(&combobox);
|
window.framePlaceholder()->addChild(&combobox);
|
||||||
|
|
||||||
combobox.setFocusMagnet(true);
|
combobox.setFocusMagnet(true);
|
||||||
|
|
|
||||||
|
|
@ -220,7 +220,7 @@ private:
|
||||||
LockButtons lock(this);
|
LockButtons lock(this);
|
||||||
// We need to create a copy of the shortcut because
|
// We need to create a copy of the shortcut because
|
||||||
// Key::disableShortcut() will modify the shortcuts() collection itself.
|
// Key::disableShortcut() will modify the shortcuts() collection itself.
|
||||||
ui::Shortcut shortcut = m_key->shortcuts()[index];
|
Shortcut shortcut = m_key->shortcuts()[index];
|
||||||
|
|
||||||
if (ui::Alert::show(Strings::alerts_delete_shortcut(shortcut.toString())) != 1)
|
if (ui::Alert::show(Strings::alerts_delete_shortcut(shortcut.toString())) != 1)
|
||||||
return;
|
return;
|
||||||
|
|
@ -264,7 +264,7 @@ private:
|
||||||
|
|
||||||
if (m_key && m_key->keycontext() != KeyContext::Any) {
|
if (m_key && m_key->keycontext() != KeyContext::Any) {
|
||||||
int w = m_headerItem->contextXPos() +
|
int w = m_headerItem->contextXPos() +
|
||||||
font()->textLength(convertKeyContextToUserFriendlyString(m_key->keycontext()));
|
font()->textLength(convert_keycontext_to_user_friendly_string(m_key->keycontext()));
|
||||||
size.w = std::max(size.w, w);
|
size.w = std::max(size.w, w);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -312,7 +312,7 @@ private:
|
||||||
|
|
||||||
if (m_key && !m_key->shortcuts().empty()) {
|
if (m_key && !m_key->shortcuts().empty()) {
|
||||||
if (m_key->keycontext() != KeyContext::Any) {
|
if (m_key->keycontext() != KeyContext::Any) {
|
||||||
g->drawText(convertKeyContextToUserFriendlyString(m_key->keycontext()),
|
g->drawText(convert_keycontext_to_user_friendly_string(m_key->keycontext()),
|
||||||
fg,
|
fg,
|
||||||
bg,
|
bg,
|
||||||
gfx::Point(contextXPos, y));
|
gfx::Point(contextXPos, y));
|
||||||
|
|
@ -324,7 +324,7 @@ private:
|
||||||
gfx::Rect(keyXPos, y, contextXPos - keyXPos, dh * m_key->shortcuts().size()));
|
gfx::Rect(keyXPos, y, contextXPos - keyXPos, dh * m_key->shortcuts().size()));
|
||||||
if (clip) {
|
if (clip) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (const Shortcut& shortcut : m_key->shortcuts()) {
|
for (const AppShortcut& shortcut : m_key->shortcuts()) {
|
||||||
if (i != m_hotShortcut || !m_changeButton) {
|
if (i != m_hotShortcut || !m_changeButton) {
|
||||||
g->drawText(getShortcutText(shortcut), fg, bg, gfx::Point(keyXPos, y));
|
g->drawText(getShortcutText(shortcut), fg, bg, gfx::Point(keyXPos, y));
|
||||||
}
|
}
|
||||||
|
|
@ -357,7 +357,7 @@ private:
|
||||||
gfx::Rect bounds = this->bounds();
|
gfx::Rect bounds = this->bounds();
|
||||||
MouseMessage* mouseMsg = static_cast<MouseMessage*>(msg);
|
MouseMessage* mouseMsg = static_cast<MouseMessage*>(msg);
|
||||||
|
|
||||||
const Shortcuts* shortcuts = (m_key ? &m_key->shortcuts() : NULL);
|
const AppShortcuts* shortcuts = (m_key ? &m_key->shortcuts() : nullptr);
|
||||||
int y = bounds.y;
|
int y = bounds.y;
|
||||||
int dh = textSize().h + 4 * guiscale();
|
int dh = textSize().h + 4 * guiscale();
|
||||||
int maxi = (shortcuts && shortcuts->size() > 1 ? shortcuts->size() : 1);
|
int maxi = (shortcuts && shortcuts->size() > 1 ? shortcuts->size() : 1);
|
||||||
|
|
@ -452,7 +452,7 @@ private:
|
||||||
m_hotShortcut = -1;
|
m_hotShortcut = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string getShortcutText(const Shortcut& shortcut) const
|
std::string getShortcutText(const AppShortcut& shortcut) const
|
||||||
{
|
{
|
||||||
if (m_key && m_key->type() == KeyType::WheelAction && shortcut.isEmpty()) {
|
if (m_key && m_key->type() == KeyType::WheelAction && shortcut.isEmpty()) {
|
||||||
return Strings::keyboard_shortcuts_default_action();
|
return Strings::keyboard_shortcuts_default_action();
|
||||||
|
|
@ -590,7 +590,7 @@ private:
|
||||||
case KeyContext::MoveTool:
|
case KeyContext::MoveTool:
|
||||||
case KeyContext::FreehandTool:
|
case KeyContext::FreehandTool:
|
||||||
case KeyContext::ShapeTool:
|
case KeyContext::ShapeTool:
|
||||||
text = convertKeyContextToUserFriendlyString(key->keycontext()) + ": " + text;
|
text = convert_keycontext_to_user_friendly_string(key->keycontext()) + ": " + text;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
KeyItem* keyItem = new KeyItem(m_keys, m_menuKeys, text, key, nullptr, 0, &m_headerItem);
|
KeyItem* keyItem = new KeyItem(m_keys, m_menuKeys, text, key, nullptr, 0, &m_headerItem);
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void onLoadParams(const Params& params) override;
|
void onLoadParams(const Params& params) override;
|
||||||
|
bool onNeedsParams() const override { return true; };
|
||||||
void onExecute(Context* context) override;
|
void onExecute(Context* context) override;
|
||||||
std::string onGetFriendlyName() const override;
|
std::string onGetFriendlyName() const override;
|
||||||
bool isListed(const Params& params) const override { return !params.get("path").empty(); }
|
bool isListed(const Params& params) const override { return !params.get("path").empty(); }
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2020-2024 Igara Studio S.A.
|
// Copyright (C) 2020-2025 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
|
|
@ -165,7 +165,7 @@ public:
|
||||||
m_document->add_observer(this);
|
m_document->add_observer(this);
|
||||||
|
|
||||||
if (countLayers() > 0) {
|
if (countLayers() > 0) {
|
||||||
m_userDataView.configureAndSet(m_layer->userData(), g_window->propertiesGrid());
|
m_userDataView.configureAndSet(m_layer->userData(), propertiesGrid());
|
||||||
if (m_remapAfterConfigure) {
|
if (m_remapAfterConfigure) {
|
||||||
remapWindow();
|
remapWindow();
|
||||||
centerWindow();
|
centerWindow();
|
||||||
|
|
@ -367,8 +367,7 @@ private:
|
||||||
{
|
{
|
||||||
if (m_layer) {
|
if (m_layer) {
|
||||||
m_userDataView.toggleVisibility();
|
m_userDataView.toggleVisibility();
|
||||||
g_window->remapWindow();
|
expandWindow(gfx::Size(bounds().w, sizeHint().h));
|
||||||
manager()->invalidate();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -227,6 +227,7 @@ void NewLayerCommand::onExecute(Context* context)
|
||||||
if (isTilemap) {
|
if (isTilemap) {
|
||||||
tilesetSelector = new TilesetSelector(sprite, tilesetInfo);
|
tilesetSelector = new TilesetSelector(sprite, tilesetInfo);
|
||||||
window.tilesetOptions()->addChild(tilesetSelector);
|
window.tilesetOptions()->addChild(tilesetSelector);
|
||||||
|
window.tilesetLabel()->setBuddy(tilesetSelector->tilesets());
|
||||||
}
|
}
|
||||||
|
|
||||||
window.openWindowInForeground();
|
window.openWindowInForeground();
|
||||||
|
|
@ -264,16 +265,8 @@ void NewLayerCommand::onExecute(Context* context)
|
||||||
bool afterBackground = false;
|
bool afterBackground = false;
|
||||||
|
|
||||||
switch (m_type) {
|
switch (m_type) {
|
||||||
case Type::Layer:
|
case Type::Layer: layer = api.newLayer(parent, name); break;
|
||||||
|
case Type::Group: layer = api.newGroup(parent, name); break;
|
||||||
if (m_place == Place::BeforeActiveLayer) {
|
|
||||||
layer = api.newLayer(parent, name);
|
|
||||||
api.restackLayerBefore(layer, parent, activeLayer);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
layer = api.newLayerAfter(parent, name, activeLayer);
|
|
||||||
break;
|
|
||||||
case Type::Group: layer = api.newGroupAfter(parent, name, activeLayer); break;
|
|
||||||
case Type::ReferenceLayer:
|
case Type::ReferenceLayer:
|
||||||
layer = api.newLayer(parent, name);
|
layer = api.newLayer(parent, name);
|
||||||
if (layer)
|
if (layer)
|
||||||
|
|
@ -308,6 +301,15 @@ void NewLayerCommand::onExecute(Context* context)
|
||||||
|
|
||||||
ASSERT(layer->parent());
|
ASSERT(layer->parent());
|
||||||
|
|
||||||
|
// Reorder the resulting layer.
|
||||||
|
switch (m_place) {
|
||||||
|
case Place::AfterActiveLayer: api.restackLayerAfter(layer, parent, activeLayer); break;
|
||||||
|
case Place::BeforeActiveLayer: api.restackLayerBefore(layer, parent, activeLayer); break;
|
||||||
|
case Place::Top:
|
||||||
|
api.restackLayerAfter(layer, sprite->root(), sprite->root()->lastLayer());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Put new layer as an overlay of the background or in the first
|
// Put new layer as an overlay of the background or in the first
|
||||||
// layer in case the sprite is transparent.
|
// layer in case the sprite is transparent.
|
||||||
if (afterBackground) {
|
if (afterBackground) {
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool onEnabled(Context* context) override;
|
bool onEnabled(Context* context) override;
|
||||||
|
bool onNeedsParams() const override { return true; };
|
||||||
void onLoadParams(const Params& params) override;
|
void onLoadParams(const Params& params) override;
|
||||||
void onExecute(Context* context) override;
|
void onExecute(Context* context) override;
|
||||||
std::string onGetFriendlyName() const override;
|
std::string onGetFriendlyName() const override;
|
||||||
|
|
|
||||||
|
|
@ -1096,6 +1096,7 @@ private:
|
||||||
m_themeVars->deferDelete();
|
m_themeVars->deferDelete();
|
||||||
}
|
}
|
||||||
m_themeVars = list;
|
m_themeVars = list;
|
||||||
|
themeModeLabel()->setBuddy(m_themeVars);
|
||||||
themeVariants()->setVisible(list ? true : false);
|
themeVariants()->setVisible(list ? true : false);
|
||||||
themeVariants()->initTheme();
|
themeVariants()->initTheme();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,570 @@
|
||||||
|
// Aseprite
|
||||||
|
// Copyright (C) 2025 Igara Studio S.A.
|
||||||
|
//
|
||||||
|
// This program is distributed under the terms of
|
||||||
|
// the End-User License Agreement for Aseprite.
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "app/app.h"
|
||||||
|
#include "app/app_menus.h"
|
||||||
|
#include "app/commands/command.h"
|
||||||
|
#include "app/context.h"
|
||||||
|
#include "app/i18n/strings.h"
|
||||||
|
#include "app/ini_file.h"
|
||||||
|
#include "app/match_words.h"
|
||||||
|
#include "app/modules/gui.h"
|
||||||
|
#include "app/ui/app_menuitem.h"
|
||||||
|
#include "app/ui/keyboard_shortcuts.h"
|
||||||
|
#include "app/ui/main_window.h"
|
||||||
|
#include "app/ui/skin/skin_theme.h"
|
||||||
|
#include "app/ui/status_bar.h"
|
||||||
|
#include "base/chrono.h"
|
||||||
|
#include "commands.h"
|
||||||
|
#include "tinyexpr.h"
|
||||||
|
#include "ui/entry.h"
|
||||||
|
#include "ui/fit_bounds.h"
|
||||||
|
#include "ui/label.h"
|
||||||
|
#include "ui/message.h"
|
||||||
|
#include "ui/system.h"
|
||||||
|
|
||||||
|
#ifdef ENABLE_SCRIPTING
|
||||||
|
#include "app/script/engine.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "run_command.xml.h"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
namespace app {
|
||||||
|
|
||||||
|
using namespace ui;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
constexpr auto kMaxVisibleResults = 10;
|
||||||
|
constexpr double kDisabledScore = 200;
|
||||||
|
|
||||||
|
struct RunnerDB {
|
||||||
|
struct Item {
|
||||||
|
std::string label;
|
||||||
|
std::vector<std::string> labelWords;
|
||||||
|
std::string searchableText;
|
||||||
|
std::string shortcutString;
|
||||||
|
Command* command;
|
||||||
|
Params params;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<Item> items;
|
||||||
|
};
|
||||||
|
|
||||||
|
class RunnerWindow final : public gen::RunCommand {
|
||||||
|
enum class Mode : uint8_t { Search, Script, Expression, ShowHelp };
|
||||||
|
|
||||||
|
class CommandItemView final : public HBox {
|
||||||
|
public:
|
||||||
|
explicit CommandItemView()
|
||||||
|
: m_shortcutLabel(new Label(""))
|
||||||
|
, m_pluginTagLabel(new Label(Strings::run_command_extension_tag()))
|
||||||
|
, m_checkIndicator(new Widget)
|
||||||
|
, m_item(nullptr)
|
||||||
|
{
|
||||||
|
disableFlags(IGNORE_MOUSE);
|
||||||
|
setFocusStop(true);
|
||||||
|
|
||||||
|
auto* filler = new BoxFiller();
|
||||||
|
filler->setTransparent(true);
|
||||||
|
addChild(filler);
|
||||||
|
|
||||||
|
m_pluginTagLabel->setVisible(false);
|
||||||
|
m_pluginTagLabel->InitTheme.connect([this] {
|
||||||
|
const auto* theme = skin::SkinTheme::get(this);
|
||||||
|
m_pluginTagLabel->setStyle(theme->styles.runnerExtensionTag());
|
||||||
|
});
|
||||||
|
m_pluginTagLabel->initTheme();
|
||||||
|
addChild(m_pluginTagLabel);
|
||||||
|
|
||||||
|
m_shortcutLabel->setTransparent(true);
|
||||||
|
m_shortcutLabel->setEnabled(false);
|
||||||
|
addChild(m_shortcutLabel);
|
||||||
|
|
||||||
|
m_checkIndicator->setVisible(false);
|
||||||
|
m_checkIndicator->setMinSize(gfx::Size(8, 8));
|
||||||
|
m_checkIndicator->InitTheme.connect([this] {
|
||||||
|
const auto* theme = skin::SkinTheme::get(m_checkIndicator);
|
||||||
|
m_checkIndicator->setStyle(theme->styles.runnerCommandChecked());
|
||||||
|
});
|
||||||
|
m_checkIndicator->initTheme();
|
||||||
|
addChild(m_checkIndicator);
|
||||||
|
|
||||||
|
InitTheme.connect([this] {
|
||||||
|
const auto* theme = skin::SkinTheme::get(this);
|
||||||
|
this->setStyle(theme->styles.runnerCommandItem());
|
||||||
|
});
|
||||||
|
initTheme();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setChecked(bool checked) const { m_checkIndicator->setVisible(checked); }
|
||||||
|
|
||||||
|
void setItem(const RunnerDB::Item* item)
|
||||||
|
{
|
||||||
|
m_item = item;
|
||||||
|
|
||||||
|
if (item != nullptr) {
|
||||||
|
setText(item->label);
|
||||||
|
processMnemonicFromText();
|
||||||
|
|
||||||
|
m_pluginTagLabel->setVisible(item->command->isPlugin());
|
||||||
|
|
||||||
|
if (item->shortcutString.empty()) {
|
||||||
|
m_shortcutLabel->setVisible(false);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_shortcutLabel->setText(item->shortcutString);
|
||||||
|
m_shortcutLabel->setVisible(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
setVisible(false);
|
||||||
|
|
||||||
|
layout();
|
||||||
|
}
|
||||||
|
|
||||||
|
void run()
|
||||||
|
{
|
||||||
|
if (isEnabled())
|
||||||
|
Click(m_item);
|
||||||
|
}
|
||||||
|
|
||||||
|
obs::signal<void(const RunnerDB::Item*)> Click;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool onProcessMessage(Message* msg) override
|
||||||
|
{
|
||||||
|
if (isEnabled()) {
|
||||||
|
switch (msg->type()) {
|
||||||
|
case kMouseDownMessage: {
|
||||||
|
Click(m_item);
|
||||||
|
} break;
|
||||||
|
case kMouseEnterMessage:
|
||||||
|
case kFocusEnterMessage: {
|
||||||
|
setSelected(true);
|
||||||
|
} break;
|
||||||
|
case kMouseLeaveMessage:
|
||||||
|
case kFocusLeaveMessage: {
|
||||||
|
setSelected(false);
|
||||||
|
} break;
|
||||||
|
case kSetCursorMessage: {
|
||||||
|
set_mouse_cursor(kHandCursor);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Widget::onProcessMessage(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Label* m_shortcutLabel;
|
||||||
|
Label* m_pluginTagLabel;
|
||||||
|
Widget* m_checkIndicator;
|
||||||
|
const RunnerDB::Item* m_item;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit RunnerWindow(Context* ctx, RunnerDB* db) : m_db(db), m_context(ctx)
|
||||||
|
{
|
||||||
|
search()->Change.connect(&RunnerWindow::onTextChange, this);
|
||||||
|
#ifndef ENABLE_SCRIPTING
|
||||||
|
helpLua()->setVisible(false);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (int i = 0; i <= kMaxVisibleResults; i++) {
|
||||||
|
auto* view = new CommandItemView;
|
||||||
|
view->Click.connect(&RunnerWindow::executeItem, this);
|
||||||
|
commandList()->addChild(view);
|
||||||
|
}
|
||||||
|
commandList()->InitTheme.connect([this] { commandList()->noBorderNoChildSpacing(); });
|
||||||
|
commandList()->initTheme();
|
||||||
|
|
||||||
|
setSizeable(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool onProcessMessage(Message* msg) override
|
||||||
|
{
|
||||||
|
switch (msg->type()) {
|
||||||
|
case kKeyDownMessage: {
|
||||||
|
const auto* keyMessage = static_cast<KeyMessage*>(msg);
|
||||||
|
if (!search()->hasFocus() &&
|
||||||
|
(keyMessage->scancode() == kKeyBackspace || keyMessage->scancode() == kKeyHome)) {
|
||||||
|
// Go back to the search
|
||||||
|
search()->requestFocus();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keyMessage->scancode() != kKeyEnter && keyMessage->scancode() != kKeyEnterPad)
|
||||||
|
break;
|
||||||
|
|
||||||
|
switch (m_mode) {
|
||||||
|
case Mode::Search: {
|
||||||
|
for (auto* child : commandList()->children()) {
|
||||||
|
if (!child->hasFlags(HIDDEN) && child->isSelected()) {
|
||||||
|
static_cast<CommandItemView*>(child)->run();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Mode::Expression: {
|
||||||
|
// TODO: We could copy the result to the keyboard on Enter? Should tell the user tho.
|
||||||
|
closeWindow(nullptr);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#ifdef ENABLE_SCRIPTING
|
||||||
|
case Mode::Script: {
|
||||||
|
executeScript();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Window::onProcessMessage(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Avoids invalidating every keystroke.
|
||||||
|
void setText(const std::string& t)
|
||||||
|
{
|
||||||
|
if (t != text())
|
||||||
|
Window::setText(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
void refit()
|
||||||
|
{
|
||||||
|
if (bounds().size() != sizeHint())
|
||||||
|
expandWindow(sizeHint());
|
||||||
|
}
|
||||||
|
|
||||||
|
void executeItem(const RunnerDB::Item* item)
|
||||||
|
{
|
||||||
|
closeWindow(nullptr);
|
||||||
|
StatusBar::instance()->showTip(1000, Strings::run_command_tip_executed_command(item->label));
|
||||||
|
m_context->executeCommand(item->command, item->params);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ENABLE_SCRIPTING
|
||||||
|
void executeScript()
|
||||||
|
{
|
||||||
|
closeWindow(nullptr);
|
||||||
|
|
||||||
|
const base::Chrono timer;
|
||||||
|
const std::string& text = search()->text();
|
||||||
|
const bool result = App::instance()->scriptEngine()->evalCode(text.substr(1, text.length()));
|
||||||
|
|
||||||
|
// Give some feedback that the code executed, for errors the console will take care of that.
|
||||||
|
// We use the timer to avoid showing the tip in cases where the command was obviously
|
||||||
|
// successful, like after showing a modal window.
|
||||||
|
if (result && timer.elapsed() < 0.5)
|
||||||
|
StatusBar::instance()->showTip(1000, Strings::run_command_tip_code_executed());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void clear() const
|
||||||
|
{
|
||||||
|
// Switch between mode or make modeWidget()->
|
||||||
|
expressionResult()->setVisible(false);
|
||||||
|
help()->setVisible(false);
|
||||||
|
commandList()->setVisible(false);
|
||||||
|
moreResults()->setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setMode(const Mode newMode)
|
||||||
|
{
|
||||||
|
if (m_mode != newMode)
|
||||||
|
clear();
|
||||||
|
|
||||||
|
m_mode = newMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onTextChange()
|
||||||
|
{
|
||||||
|
const std::string& text = search()->text();
|
||||||
|
|
||||||
|
switch (text[0]) {
|
||||||
|
#ifdef ENABLE_SCRIPTING
|
||||||
|
case '@':
|
||||||
|
setMode(Mode::Script);
|
||||||
|
setText(Strings::run_command_title_script());
|
||||||
|
// Will only execute when pressing enter.
|
||||||
|
// TODO: Add an engine function to check the syntax before running it with luaL_loadstring
|
||||||
|
// && lua_isfunction
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
case '=':
|
||||||
|
setMode(Mode::Expression);
|
||||||
|
setText(Strings::run_command_title_expression());
|
||||||
|
calculateExpression(text.substr(1, text.length()));
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
setMode(Mode::ShowHelp);
|
||||||
|
setText(Strings::run_command_title_help());
|
||||||
|
help()->setVisible(true);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
setMode(Mode::Search);
|
||||||
|
setText(Strings::run_command_title());
|
||||||
|
searchCommand(text);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
refit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void searchCommand(const std::string& text)
|
||||||
|
{
|
||||||
|
if (text.empty()) {
|
||||||
|
clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& lowerText = base::string_to_lower(text);
|
||||||
|
const MatchWords match(lowerText);
|
||||||
|
std::multimap<double, const RunnerDB::Item*> results;
|
||||||
|
|
||||||
|
for (RunnerDB::Item& item : m_db->items) {
|
||||||
|
if (match(item.searchableText) || match.fuzzyWords(item.labelWords)) {
|
||||||
|
// Crude "score" to affect ordering in the multimap of results.
|
||||||
|
// Lower is better.
|
||||||
|
double score = 0;
|
||||||
|
const std::string& lowerLabel = base::string_to_lower(item.label);
|
||||||
|
if (lowerLabel != lowerText) {
|
||||||
|
// Deprioritize non-exact matches.
|
||||||
|
score = 50;
|
||||||
|
|
||||||
|
// Prioritize the ones starting with what we're typing.
|
||||||
|
if (lowerLabel.find(lowerText) == 0)
|
||||||
|
score -= 10;
|
||||||
|
|
||||||
|
// Simpler commands go first.
|
||||||
|
if (item.params.empty())
|
||||||
|
score -= 10;
|
||||||
|
|
||||||
|
// Prioritize listed commands or ones with keyboard shortcuts
|
||||||
|
if (item.command->isListed(item.params) || item.shortcutString.empty())
|
||||||
|
score -= 5;
|
||||||
|
|
||||||
|
// Bias against longer labels vs our search text
|
||||||
|
if (lowerLabel.size() > lowerText.size())
|
||||||
|
score += std::clamp(static_cast<int>(lowerLabel.size() - lowerText.size()), 1, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.command->isPlugin())
|
||||||
|
score += 5;
|
||||||
|
|
||||||
|
// Disabled commands go at the bottom.
|
||||||
|
item.command->loadParams(item.params);
|
||||||
|
if (!item.command->isEnabled(m_context))
|
||||||
|
score += kDisabledScore;
|
||||||
|
|
||||||
|
results.emplace(score, &item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int resultCount = 0;
|
||||||
|
for (const auto& [score, itemPtr] : results) {
|
||||||
|
auto* view = static_cast<CommandItemView*>(commandList()->at(resultCount));
|
||||||
|
view->setVisible(true);
|
||||||
|
view->setEnabled(score < kDisabledScore);
|
||||||
|
view->setItem(itemPtr);
|
||||||
|
view->setSelected(resultCount == 0);
|
||||||
|
view->setChecked(itemPtr->command->isChecked(m_context));
|
||||||
|
|
||||||
|
resultCount++;
|
||||||
|
|
||||||
|
if (resultCount >= kMaxVisibleResults) {
|
||||||
|
moreCount()->setText(Strings::run_command_more_result_count(results.size() - resultCount));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = resultCount; i <= kMaxVisibleResults; i++)
|
||||||
|
commandList()->at(i)->setVisible(false);
|
||||||
|
|
||||||
|
commandList()->setVisible(resultCount > 0);
|
||||||
|
moreResults()->setVisible(resultCount >= kMaxVisibleResults);
|
||||||
|
|
||||||
|
refit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void calculateExpression(const std::string_view& expression) const
|
||||||
|
{
|
||||||
|
if (expression.empty()) {
|
||||||
|
expressionResult()->setVisible(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int err = 0;
|
||||||
|
double v = te_interp(expression.data(), &err);
|
||||||
|
if (err == 0)
|
||||||
|
expressionResult()->setText(fmt::format(" = {}", v));
|
||||||
|
else
|
||||||
|
expressionResult()->setText(" = NaN");
|
||||||
|
expressionResult()->setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
RunnerDB* m_db;
|
||||||
|
Context* m_context;
|
||||||
|
Mode m_mode = Mode::Search;
|
||||||
|
};
|
||||||
|
} // Unnamed namespace
|
||||||
|
|
||||||
|
class RunCommandCommand final : public Command {
|
||||||
|
public:
|
||||||
|
RunCommandCommand();
|
||||||
|
|
||||||
|
void invalidateDatabase();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool onEnabled(Context* context) override;
|
||||||
|
void onExecute(Context* context) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void loadDatabase();
|
||||||
|
|
||||||
|
std::unique_ptr<RunnerDB> m_db;
|
||||||
|
obs::connection m_invalidateConn;
|
||||||
|
};
|
||||||
|
|
||||||
|
RunCommandCommand::RunCommandCommand() : Command(CommandId::RunCommand())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunCommandCommand::invalidateDatabase()
|
||||||
|
{
|
||||||
|
m_db.reset(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RunCommandCommand::onEnabled(Context* context)
|
||||||
|
{
|
||||||
|
return context->isUIAvailable();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunCommandCommand::onExecute(Context* context)
|
||||||
|
{
|
||||||
|
if (!m_db)
|
||||||
|
loadDatabase();
|
||||||
|
|
||||||
|
RunnerWindow window(context, m_db.get());
|
||||||
|
window.centerWindow();
|
||||||
|
fit_bounds(window.display(),
|
||||||
|
&window,
|
||||||
|
gfx::Rect(window.bounds().x, 23 * guiscale(), window.bounds().w, window.bounds().h));
|
||||||
|
window.openWindowInForeground();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunCommandCommand::loadDatabase()
|
||||||
|
{
|
||||||
|
std::vector<std::string> allCommandIds;
|
||||||
|
Commands::instance()->getAllIds(allCommandIds);
|
||||||
|
|
||||||
|
m_db.reset(new RunnerDB);
|
||||||
|
m_db->items.reserve(allCommandIds.size());
|
||||||
|
|
||||||
|
{
|
||||||
|
std::unordered_map<std::string, RunnerDB::Item> items;
|
||||||
|
for (const KeyPtr& key : *KeyboardShortcuts::instance()) {
|
||||||
|
if (const auto* cmd = key->command()) {
|
||||||
|
std::string paramString;
|
||||||
|
if (!key->params().empty()) {
|
||||||
|
std::ostringstream stream;
|
||||||
|
for (const auto& [k, v] : key->params()) {
|
||||||
|
stream << k << ' ' << v << ' ';
|
||||||
|
}
|
||||||
|
paramString = stream.str();
|
||||||
|
paramString.pop_back(); // Trailing space.
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string shortcutString;
|
||||||
|
if (!key->shortcuts().empty())
|
||||||
|
shortcutString = key->shortcuts()[0].toString();
|
||||||
|
|
||||||
|
// Detect any duplicates, since multiple commands with the same parameter set
|
||||||
|
// can have both custom and default keyboard shortcuts.
|
||||||
|
const std::string itemKey = cmd->id() + paramString;
|
||||||
|
if (items.find(itemKey) != items.end()) {
|
||||||
|
if (!shortcutString.empty())
|
||||||
|
items[itemKey].shortcutString += ", " + shortcutString;
|
||||||
|
|
||||||
|
continue; // Ignore duplicate.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ideally we'd want to have translatable "tags" of some kind for commands so they're easier
|
||||||
|
// to find, for example if you search "Sprite New" you can't find "New File" (but you can
|
||||||
|
// find New Sprite from Clipboard)
|
||||||
|
std::ostringstream searchableStringStream;
|
||||||
|
searchableStringStream << key->triggerString() << ' ' << cmd->id() << ' ' << shortcutString;
|
||||||
|
|
||||||
|
// Separate the labels into words for fuzzy matching
|
||||||
|
std::vector<std::string> labelWords;
|
||||||
|
base::split_string(base::string_to_lower(key->triggerString()), labelWords, " ");
|
||||||
|
|
||||||
|
const RunnerDB::Item item{
|
||||||
|
key->triggerString(), labelWords, searchableStringStream.str(),
|
||||||
|
shortcutString, key->command(), key->params()
|
||||||
|
};
|
||||||
|
items.try_emplace(itemKey, item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add any commands not covered by KeyboardShortcuts
|
||||||
|
for (const std::string& id : allCommandIds) {
|
||||||
|
// Ignore if it's already been added.
|
||||||
|
if (items.find(id) != items.end())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Command* command = Commands::instance()->byId(id.c_str());
|
||||||
|
|
||||||
|
// We can't run commands that need params without having them.
|
||||||
|
if (command->needsParams())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
std::vector<std::string> labelWords;
|
||||||
|
base::split_string(base::string_to_lower(command->friendlyName()), labelWords, " ");
|
||||||
|
|
||||||
|
const RunnerDB::Item item{ command->friendlyName(),
|
||||||
|
labelWords,
|
||||||
|
command->friendlyName() + " " + command->id(),
|
||||||
|
{},
|
||||||
|
command,
|
||||||
|
{} };
|
||||||
|
items.try_emplace(id, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move from the result map to the item db vector
|
||||||
|
std::transform(
|
||||||
|
std::move_iterator(items.begin()),
|
||||||
|
std::move_iterator(items.end()),
|
||||||
|
std::back_inserter(m_db->items),
|
||||||
|
[](std::pair<std::string, RunnerDB::Item>&& item) { return std::move(item.second); });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort alphabetically by label
|
||||||
|
std::sort(m_db->items.begin(),
|
||||||
|
m_db->items.end(),
|
||||||
|
[](const RunnerDB::Item& a, const RunnerDB::Item& b) { return a.label < b.label; });
|
||||||
|
|
||||||
|
if (!m_invalidateConn)
|
||||||
|
m_invalidateConn =
|
||||||
|
AppMenus::instance()->MenusLoaded.connect(&RunCommandCommand::invalidateDatabase, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
Command* CommandFactory::createRunCommandCommand()
|
||||||
|
{
|
||||||
|
return new RunCommandCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace app
|
||||||
|
|
@ -34,6 +34,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void onLoadParams(const Params& params) override;
|
void onLoadParams(const Params& params) override;
|
||||||
|
bool onNeedsParams() const override { return true; };
|
||||||
void onExecute(Context* context) override;
|
void onExecute(Context* context) override;
|
||||||
std::string onGetFriendlyName() const override;
|
std::string onGetFriendlyName() const override;
|
||||||
bool isListed(const Params& params) const override { return !params.empty(); }
|
bool isListed(const Params& params) const override { return !params.empty(); }
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2018-2024 Igara Studio S.A.
|
// Copyright (C) 2018-2025 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
|
|
@ -187,8 +187,7 @@ private:
|
||||||
void onToggleUserData()
|
void onToggleUserData()
|
||||||
{
|
{
|
||||||
m_userDataView.toggleVisibility();
|
m_userDataView.toggleVisibility();
|
||||||
remapWindow();
|
expandWindow(gfx::Size(bounds().w, sizeHint().h));
|
||||||
manager()->invalidate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void onTilesedDuplicated(const Tileset* tilesetClone)
|
void onTilesedDuplicated(const Tileset* tilesetClone)
|
||||||
|
|
@ -304,7 +303,7 @@ void SpritePropertiesCommand::onExecute(Context* context)
|
||||||
color_button = new ColorButton(app::Color::fromIndex(sprite->transparentColor()),
|
color_button = new ColorButton(app::Color::fromIndex(sprite->transparentColor()),
|
||||||
IMAGE_INDEXED,
|
IMAGE_INDEXED,
|
||||||
ColorButtonOptions());
|
ColorButtonOptions());
|
||||||
|
color_button->setId("transparent_color");
|
||||||
window.transparentColorPlaceholder()->addChild(color_button);
|
window.transparentColorPlaceholder()->addChild(color_button);
|
||||||
|
|
||||||
// TODO add a way to get or create an existent TooltipManager
|
// TODO add a way to get or create an existent TooltipManager
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ public:
|
||||||
// Returns true if the command must be displayed in the Keyboard
|
// Returns true if the command must be displayed in the Keyboard
|
||||||
// Shortcuts list.
|
// Shortcuts list.
|
||||||
virtual bool isListed(const Params& params) const { return true; }
|
virtual bool isListed(const Params& params) const { return true; }
|
||||||
|
virtual bool isPlugin() { return false; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool onNeedsParams() const;
|
virtual bool onNeedsParams() const;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2018-2024 Igara Studio S.A.
|
// Copyright (C) 2018-2025 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
FOR_EACH_COMMAND(About)
|
FOR_EACH_COMMAND(About)
|
||||||
FOR_EACH_COMMAND(AddColor)
|
FOR_EACH_COMMAND(AddColor)
|
||||||
FOR_EACH_COMMAND(AdvancedMode)
|
FOR_EACH_COMMAND(AdvancedMode)
|
||||||
|
FOR_EACH_COMMAND(Apply)
|
||||||
FOR_EACH_COMMAND(AutocropSprite)
|
FOR_EACH_COMMAND(AutocropSprite)
|
||||||
FOR_EACH_COMMAND(BackgroundFromLayer)
|
FOR_EACH_COMMAND(BackgroundFromLayer)
|
||||||
FOR_EACH_COMMAND(BrightnessContrast)
|
FOR_EACH_COMMAND(BrightnessContrast)
|
||||||
|
|
@ -40,6 +41,7 @@ FOR_EACH_COMMAND(DeselectMask)
|
||||||
FOR_EACH_COMMAND(Despeckle)
|
FOR_EACH_COMMAND(Despeckle)
|
||||||
FOR_EACH_COMMAND(DiscardBrush)
|
FOR_EACH_COMMAND(DiscardBrush)
|
||||||
FOR_EACH_COMMAND(DuplicateLayer)
|
FOR_EACH_COMMAND(DuplicateLayer)
|
||||||
|
FOR_EACH_COMMAND(DuplicateSlice)
|
||||||
FOR_EACH_COMMAND(DuplicateSprite)
|
FOR_EACH_COMMAND(DuplicateSprite)
|
||||||
FOR_EACH_COMMAND(DuplicateView)
|
FOR_EACH_COMMAND(DuplicateView)
|
||||||
FOR_EACH_COMMAND(Exit)
|
FOR_EACH_COMMAND(Exit)
|
||||||
|
|
@ -125,6 +127,7 @@ FOR_EACH_COMMAND(ReplaceColor)
|
||||||
FOR_EACH_COMMAND(ReselectMask)
|
FOR_EACH_COMMAND(ReselectMask)
|
||||||
FOR_EACH_COMMAND(ReverseFrames)
|
FOR_EACH_COMMAND(ReverseFrames)
|
||||||
FOR_EACH_COMMAND(Rotate)
|
FOR_EACH_COMMAND(Rotate)
|
||||||
|
FOR_EACH_COMMAND(RunCommand)
|
||||||
FOR_EACH_COMMAND(SaveFile)
|
FOR_EACH_COMMAND(SaveFile)
|
||||||
FOR_EACH_COMMAND(SaveFileAs)
|
FOR_EACH_COMMAND(SaveFileAs)
|
||||||
FOR_EACH_COMMAND(SaveFileCopyAs)
|
FOR_EACH_COMMAND(SaveFileCopyAs)
|
||||||
|
|
|
||||||
|
|
@ -325,10 +325,15 @@ void FilterManagerImpl::applyToTarget()
|
||||||
void FilterManagerImpl::initTransaction()
|
void FilterManagerImpl::initTransaction()
|
||||||
{
|
{
|
||||||
ASSERT(!m_tx);
|
ASSERT(!m_tx);
|
||||||
m_writer.reset(new ContextWriter(m_reader));
|
m_writer = std::make_unique<ContextWriter>(m_reader);
|
||||||
m_tx.reset(new Tx(*m_writer, m_filter->getName(), ModifyDocument));
|
m_tx.reset(new Tx(*m_writer, m_filter->getName(), ModifyDocument));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FilterManagerImpl::updateWriterThread()
|
||||||
|
{
|
||||||
|
document()->updateWriterThread();
|
||||||
|
}
|
||||||
|
|
||||||
bool FilterManagerImpl::isTransaction() const
|
bool FilterManagerImpl::isTransaction() const
|
||||||
{
|
{
|
||||||
return (m_tx != nullptr);
|
return (m_tx != nullptr);
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,7 @@ public:
|
||||||
void applyToTarget();
|
void applyToTarget();
|
||||||
|
|
||||||
void initTransaction();
|
void initTransaction();
|
||||||
|
void updateWriterThread();
|
||||||
bool isTransaction() const;
|
bool isTransaction() const;
|
||||||
void commitTransaction();
|
void commitTransaction();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -118,7 +118,13 @@ FilterWorker::~FilterWorker()
|
||||||
|
|
||||||
void FilterWorker::run()
|
void FilterWorker::run()
|
||||||
{
|
{
|
||||||
// Initialize writting transaction
|
// Initialize writing transaction from the main thread. This is
|
||||||
|
// required to get the activeSite() from the UIContext from
|
||||||
|
// CmdTransaction::calcSpritePosition().
|
||||||
|
//
|
||||||
|
// The document will keep the UI thread associated as the "writer"
|
||||||
|
// thread, but that will be updated later in
|
||||||
|
// applyFilterInBackground() with the worker thread ID.
|
||||||
m_filterMgr->initTransaction();
|
m_filterMgr->initTransaction();
|
||||||
|
|
||||||
std::thread thread;
|
std::thread thread;
|
||||||
|
|
@ -182,6 +188,11 @@ bool FilterWorker::isCancelled()
|
||||||
void FilterWorker::applyFilterInBackground()
|
void FilterWorker::applyFilterInBackground()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
// This background thread is the new writer. This is required to
|
||||||
|
// avoid read-locking from the UI thread from Editor and Timeline
|
||||||
|
// onPaint() events.
|
||||||
|
m_filterMgr->updateWriterThread();
|
||||||
|
|
||||||
// Apply the filter
|
// Apply the filter
|
||||||
m_filterMgr->applyToTarget();
|
m_filterMgr->applyToTarget();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ public:
|
||||||
|
|
||||||
~ConsoleWindow() { TRACE_CON("CON: ~ConsoleWindow this=", this); }
|
~ConsoleWindow() { TRACE_CON("CON: ~ConsoleWindow this=", this); }
|
||||||
|
|
||||||
void addMessage(const std::string& msg)
|
void addMessage(std::string msg)
|
||||||
{
|
{
|
||||||
if (!m_hasText) {
|
if (!m_hasText) {
|
||||||
m_hasText = true;
|
m_hasText = true;
|
||||||
|
|
@ -93,6 +93,17 @@ public:
|
||||||
gfx::Point pt = m_view.viewScroll();
|
gfx::Point pt = m_view.viewScroll();
|
||||||
const bool autoScroll = (pt.y >= maxSize.h - visible.h);
|
const bool autoScroll = (pt.y >= maxSize.h - visible.h);
|
||||||
|
|
||||||
|
// Escape characters we can't show properly
|
||||||
|
for (size_t i = 0; i < msg.size(); i++) {
|
||||||
|
switch (msg[i]) {
|
||||||
|
case '\a':
|
||||||
|
case '\b':
|
||||||
|
case '\r':
|
||||||
|
case '\t':
|
||||||
|
case '\v': msg[i] = ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_textbox.setText(m_textbox.text() + msg);
|
m_textbox.setText(m_textbox.text() + msg);
|
||||||
|
|
||||||
if (autoScroll) {
|
if (autoScroll) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2018-2024 Igara Studio S.A.
|
// Copyright (C) 2018-2025 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
|
|
@ -124,6 +124,11 @@ Doc::LockResult Doc::upgradeToWrite(int timeout)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Doc::updateWriterThread()
|
||||||
|
{
|
||||||
|
m_rwLock.updateWriterThread();
|
||||||
|
}
|
||||||
|
|
||||||
void Doc::downgradeToRead(LockResult lockResult)
|
void Doc::downgradeToRead(LockResult lockResult)
|
||||||
{
|
{
|
||||||
DOC_TRACE("DOC: downgradeToRead", this, (int)lockResult);
|
DOC_TRACE("DOC: downgradeToRead", this, (int)lockResult);
|
||||||
|
|
@ -338,6 +343,19 @@ void Doc::notifyAfterAddTile(LayerTilemap* layer, frame_t frame, tile_index ti)
|
||||||
notify_observers<DocEvent&>(&DocObserver::onAfterAddTile, ev);
|
notify_observers<DocEvent&>(&DocObserver::onAfterAddTile, ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Doc::notifyBeforeSlicesDuplication()
|
||||||
|
{
|
||||||
|
DocEvent ev(this);
|
||||||
|
notify_observers<DocEvent&>(&DocObserver::onBeforeSlicesDuplication, ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Doc::notifySliceDuplicated(Slice* slice)
|
||||||
|
{
|
||||||
|
DocEvent ev(this);
|
||||||
|
ev.slice(slice);
|
||||||
|
notify_observers<DocEvent&>(&DocObserver::onSliceDuplicated, ev);
|
||||||
|
}
|
||||||
|
|
||||||
bool Doc::isModified() const
|
bool Doc::isModified() const
|
||||||
{
|
{
|
||||||
return !m_undo->isInSavedStateOrSimilar();
|
return !m_undo->isInSavedStateOrSimilar();
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,7 @@ public:
|
||||||
LockResult readLock(int timeout);
|
LockResult readLock(int timeout);
|
||||||
LockResult writeLock(int timeout);
|
LockResult writeLock(int timeout);
|
||||||
LockResult upgradeToWrite(int timeout);
|
LockResult upgradeToWrite(int timeout);
|
||||||
|
void updateWriterThread();
|
||||||
void downgradeToRead(LockResult lockResult);
|
void downgradeToRead(LockResult lockResult);
|
||||||
void unlock(LockResult lockResult);
|
void unlock(LockResult lockResult);
|
||||||
|
|
||||||
|
|
@ -141,6 +142,8 @@ public:
|
||||||
void notifyTilesetChanged(Tileset* tileset);
|
void notifyTilesetChanged(Tileset* tileset);
|
||||||
void notifyLayerGroupCollapseChange(Layer* layer);
|
void notifyLayerGroupCollapseChange(Layer* layer);
|
||||||
void notifyAfterAddTile(LayerTilemap* layer, frame_t frame, tile_index ti);
|
void notifyAfterAddTile(LayerTilemap* layer, frame_t frame, tile_index ti);
|
||||||
|
void notifyBeforeSlicesDuplication();
|
||||||
|
void notifySliceDuplicated(Slice* slice);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// File related properties
|
// File related properties
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2018-2024 Igara Studio S.A.
|
// Copyright (C) 2018-2025 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
|
|
@ -90,6 +90,8 @@ public:
|
||||||
|
|
||||||
// Slices
|
// Slices
|
||||||
virtual void onSliceNameChange(DocEvent& ev) {}
|
virtual void onSliceNameChange(DocEvent& ev) {}
|
||||||
|
virtual void onBeforeSlicesDuplication(DocEvent& ev) {}
|
||||||
|
virtual void onSliceDuplicated(DocEvent& ev) {}
|
||||||
|
|
||||||
// The tileset has changed.
|
// The tileset has changed.
|
||||||
virtual void onTilesetChanged(DocEvent& ev) {}
|
virtual void onTilesetChanged(DocEvent& ev) {}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2020-2024 Igara Studio S.A.
|
// Copyright (C) 2020-2025 Igara Studio S.A.
|
||||||
// Copyright (C) 2017-2018 David Capello
|
// Copyright (C) 2017-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
|
|
@ -42,6 +42,7 @@
|
||||||
#include "archive_entry.h"
|
#include "archive_entry.h"
|
||||||
#include "json11.hpp"
|
#include "json11.hpp"
|
||||||
|
|
||||||
|
#include <cctype>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
@ -535,6 +536,19 @@ void Extension::updateCategory(const Category newCategory)
|
||||||
|
|
||||||
#ifdef ENABLE_SCRIPTING
|
#ifdef ENABLE_SCRIPTING
|
||||||
|
|
||||||
|
static bool is_simple_id(const char* k)
|
||||||
|
{
|
||||||
|
if (!*k)
|
||||||
|
return false;
|
||||||
|
if (!std::isalpha(*k) && *k != '_')
|
||||||
|
return false;
|
||||||
|
for (const char* p = k + 1; *p; ++p) {
|
||||||
|
if (!std::isalnum(*p) && *p != '_')
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO move this to app/script/tableutils.h
|
// TODO move this to app/script/tableutils.h
|
||||||
static void serialize_table(lua_State* L, int idx, std::string& result)
|
static void serialize_table(lua_State* L, int idx, std::string& result)
|
||||||
{
|
{
|
||||||
|
|
@ -555,7 +569,21 @@ static void serialize_table(lua_State* L, int idx, std::string& result)
|
||||||
// Save key
|
// Save key
|
||||||
if (lua_type(L, -2) == LUA_TSTRING) {
|
if (lua_type(L, -2) == LUA_TSTRING) {
|
||||||
if (const char* k = lua_tostring(L, -2)) {
|
if (const char* k = lua_tostring(L, -2)) {
|
||||||
|
// If this is a simple identifier we can avoid using ["..."] to enclose
|
||||||
|
// the key name.
|
||||||
|
if (is_simple_id(k)) {
|
||||||
result += k;
|
result += k;
|
||||||
|
}
|
||||||
|
// In other cases, we enclose the key name in brackets and
|
||||||
|
// double quotes ["..."] to avoid syntax errors when the name
|
||||||
|
// has unicode characters.
|
||||||
|
else {
|
||||||
|
result.push_back('[');
|
||||||
|
result.push_back('"');
|
||||||
|
result += k;
|
||||||
|
result.push_back('"');
|
||||||
|
result.push_back(']');
|
||||||
|
}
|
||||||
result.push_back('=');
|
result.push_back('=');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,12 @@
|
||||||
|
|
||||||
#include "app/fonts/font_info.h"
|
#include "app/fonts/font_info.h"
|
||||||
|
|
||||||
|
#include "app/app.h"
|
||||||
#include "app/fonts/font_data.h"
|
#include "app/fonts/font_data.h"
|
||||||
|
#include "app/i18n/strings.h"
|
||||||
#include "app/pref/preferences.h"
|
#include "app/pref/preferences.h"
|
||||||
|
#include "app/ui/main_window.h"
|
||||||
|
#include "app/ui/skin/skin_theme.h"
|
||||||
#include "base/fs.h"
|
#include "base/fs.h"
|
||||||
#include "base/split_string.h"
|
#include "base/split_string.h"
|
||||||
#include "fmt/format.h"
|
#include "fmt/format.h"
|
||||||
|
|
@ -116,6 +120,12 @@ FontInfo FontInfo::getFromPreferences()
|
||||||
fontInfo = base::convert_to<FontInfo>(pref.textTool.fontInfo());
|
fontInfo = base::convert_to<FontInfo>(pref.textTool.fontInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!fontInfo.isValid()) {
|
||||||
|
// No valid settings found, use the default widget font
|
||||||
|
fontInfo = static_cast<app::skin::SkinTheme*>(App::instance()->mainWindow()->theme())
|
||||||
|
->getDefaultFontInfo();
|
||||||
|
}
|
||||||
|
|
||||||
return fontInfo;
|
return fontInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -142,19 +152,22 @@ std::string FontInfo::humanString() const
|
||||||
}
|
}
|
||||||
result += fmt::format(" {}pt", size());
|
result += fmt::format(" {}pt", size());
|
||||||
if (!result.empty()) {
|
if (!result.empty()) {
|
||||||
if (style().weight() >= text::FontStyle::Weight::SemiBold)
|
if (style().weight() != text::FontStyle::Weight::Normal)
|
||||||
result += " Bold";
|
result +=
|
||||||
|
" " +
|
||||||
|
Strings::Translate(
|
||||||
|
fmt::format("font_style.font_weight_{}", static_cast<int>(style().weight())).c_str());
|
||||||
if (style().slant() != text::FontStyle::Slant::Upright)
|
if (style().slant() != text::FontStyle::Slant::Upright)
|
||||||
result += " Italic";
|
result += " " + Strings::font_style_italic();
|
||||||
if (antialias())
|
if (antialias())
|
||||||
result += " Antialias";
|
result += " " + Strings::font_style_antialias();
|
||||||
if (ligatures())
|
if (ligatures())
|
||||||
result += " Ligatures";
|
result += " " + Strings::font_style_ligatures();
|
||||||
switch (hinting()) {
|
switch (hinting()) {
|
||||||
case text::FontHinting::None: result += " No Hinting"; break;
|
case text::FontHinting::None: result += " " + Strings::font_style_hinting_none(); break;
|
||||||
case text::FontHinting::Slight: result += " Slight Hinting"; break;
|
case text::FontHinting::Slight: result += " " + Strings::font_style_hinting_slight(); break;
|
||||||
case text::FontHinting::Normal: break;
|
case text::FontHinting::Normal: break;
|
||||||
case text::FontHinting::Full: result += " Full Hinting"; break;
|
case text::FontHinting::Full: result += " " + Strings::font_style_hinting_full(); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -177,6 +190,7 @@ app::FontInfo convert_to(const std::string& from)
|
||||||
bool italic = false;
|
bool italic = false;
|
||||||
app::FontInfo::Flags flags = app::FontInfo::Flags::None;
|
app::FontInfo::Flags flags = app::FontInfo::Flags::None;
|
||||||
text::FontHinting hinting = text::FontHinting::Normal;
|
text::FontHinting hinting = text::FontHinting::Normal;
|
||||||
|
text::FontStyle::Weight weight = text::FontStyle::Weight::Normal;
|
||||||
|
|
||||||
if (!parts.empty()) {
|
if (!parts.empty()) {
|
||||||
if (parts[0].compare(0, 5, "file=") == 0) {
|
if (parts[0].compare(0, 5, "file=") == 0) {
|
||||||
|
|
@ -214,16 +228,17 @@ app::FontInfo convert_to(const std::string& from)
|
||||||
else if (hintingStr == "full")
|
else if (hintingStr == "full")
|
||||||
hinting = text::FontHinting::Full;
|
hinting = text::FontHinting::Full;
|
||||||
}
|
}
|
||||||
|
else if (parts[i].compare(0, 7, "weight=") == 0) {
|
||||||
|
std::string weightStr = parts[i].substr(7);
|
||||||
|
weight = static_cast<text::FontStyle::Weight>(std::atoi(weightStr.c_str()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
text::FontStyle style;
|
const text::FontStyle style(
|
||||||
if (bold && italic)
|
bold ? text::FontStyle::Weight::Bold : weight,
|
||||||
style = text::FontStyle::BoldItalic();
|
text::FontStyle::Width::Normal,
|
||||||
else if (bold)
|
italic ? text::FontStyle::Slant::Italic : text::FontStyle::Slant::Upright);
|
||||||
style = text::FontStyle::Bold();
|
|
||||||
else if (italic)
|
|
||||||
style = text::FontStyle::Italic();
|
|
||||||
|
|
||||||
return app::FontInfo(type, name, size, style, flags, hinting);
|
return app::FontInfo(type, name, size, style, flags, hinting);
|
||||||
}
|
}
|
||||||
|
|
@ -243,7 +258,7 @@ std::string convert_to(const app::FontInfo& from)
|
||||||
if (!result.empty()) {
|
if (!result.empty()) {
|
||||||
if (from.size() > 0.0f)
|
if (from.size() > 0.0f)
|
||||||
result += fmt::format(",size={}", from.size());
|
result += fmt::format(",size={}", from.size());
|
||||||
if (from.style().weight() >= text::FontStyle::Weight::SemiBold)
|
if (from.style().weight() == text::FontStyle::Weight::Bold)
|
||||||
result += ",bold";
|
result += ",bold";
|
||||||
if (from.style().slant() != text::FontStyle::Slant::Upright)
|
if (from.style().slant() != text::FontStyle::Slant::Upright)
|
||||||
result += ",italic";
|
result += ",italic";
|
||||||
|
|
@ -262,6 +277,8 @@ std::string convert_to(const app::FontInfo& from)
|
||||||
case text::FontHinting::Full: result += "full"; break;
|
case text::FontHinting::Full: result += "full"; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (from.style().weight() != text::FontStyle::Weight::Bold)
|
||||||
|
result += ",weight=" + std::to_string(static_cast<int>(from.style().weight()));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
#include "base/split_string.h"
|
#include "base/split_string.h"
|
||||||
#include "base/string.h"
|
#include "base/string.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
@ -22,11 +23,40 @@ public:
|
||||||
MatchWords(const std::string& search = {})
|
MatchWords(const std::string& search = {})
|
||||||
{
|
{
|
||||||
base::split_string(base::string_to_lower(search), m_parts, " ");
|
base::split_string(base::string_to_lower(search), m_parts, " ");
|
||||||
|
if (m_parts.size() > 1 && m_parts.back().empty())
|
||||||
|
m_parts.pop_back(); // Avoid an empty part when the search text is something like "hello "
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finds a match with the given word using Levenshtein distance
|
||||||
|
// Expects lower case input, unlike operator()
|
||||||
|
bool fuzzy(const std::string& word, size_t threshold = 3) const
|
||||||
|
{
|
||||||
|
std::size_t matches = 0;
|
||||||
|
for (const auto& part : m_parts) {
|
||||||
|
if (levenshteinDistance(part, word) < threshold)
|
||||||
|
++matches;
|
||||||
|
}
|
||||||
|
return (matches == m_parts.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finds a match with any of the given words using Levenshtein distance
|
||||||
|
// Expects lower case input, unlike operator()
|
||||||
|
bool fuzzyWords(const std::vector<std::string>& words, size_t threshold = 3) const
|
||||||
|
{
|
||||||
|
std::size_t matches = 0;
|
||||||
|
for (const auto& part : m_parts) {
|
||||||
|
for (const auto& word : words) {
|
||||||
|
if (levenshteinDistance(part, word) < threshold)
|
||||||
|
++matches;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (matches == m_parts.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator()(const std::string& item) const
|
bool operator()(const std::string& item) const
|
||||||
{
|
{
|
||||||
std::string lowerItem = base::string_to_lower(item);
|
const std::string& lowerItem = base::string_to_lower(item);
|
||||||
std::size_t matches = 0;
|
std::size_t matches = 0;
|
||||||
|
|
||||||
for (const auto& part : m_parts) {
|
for (const auto& part : m_parts) {
|
||||||
|
|
@ -37,6 +67,33 @@ public:
|
||||||
return (matches == m_parts.size());
|
return (matches == m_parts.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t levenshteinDistance(const std::string_view& word1, const std::string_view& word2)
|
||||||
|
{
|
||||||
|
if (word1 == word2)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
std::vector distance1(word2.size() + 1, 0);
|
||||||
|
std::vector distance2(word2.size() + 1, 0);
|
||||||
|
|
||||||
|
for (int i = 0; i <= word2.size(); ++i)
|
||||||
|
distance1[i] = i;
|
||||||
|
|
||||||
|
for (int i = 0; i < word1.size(); ++i) {
|
||||||
|
distance2[0] = i + 1;
|
||||||
|
|
||||||
|
for (int j = 0; j < word2.size(); ++j) {
|
||||||
|
const int deletionCost = distance1[j + 1] + 1;
|
||||||
|
const int insertionCost = distance2[j] + 1;
|
||||||
|
const int substitutionCost = (word1[i] == word2[j]) ? distance1[j] : distance1[j] + 1;
|
||||||
|
distance2[j + 1] = std::min({ deletionCost, insertionCost, substitutionCost });
|
||||||
|
}
|
||||||
|
|
||||||
|
std::swap(distance1, distance2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return distance1[word2.size()];
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<std::string> m_parts;
|
std::vector<std::string> m_parts;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2018-2024 Igara Studio S.A.
|
// Copyright (C) 2018-2025 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
|
|
@ -30,6 +30,7 @@
|
||||||
#include "os/surface.h"
|
#include "os/surface.h"
|
||||||
#include "os/system.h"
|
#include "os/system.h"
|
||||||
#include "ui/intern.h"
|
#include "ui/intern.h"
|
||||||
|
#include "ui/paint.h"
|
||||||
#include "ui/system.h"
|
#include "ui/system.h"
|
||||||
#include "ui/theme.h"
|
#include "ui/theme.h"
|
||||||
|
|
||||||
|
|
@ -118,9 +119,6 @@ void draw_color(ui::Graphics* g,
|
||||||
app::Color color = _color;
|
app::Color color = _color;
|
||||||
const int alpha = color.getAlpha();
|
const int alpha = color.getAlpha();
|
||||||
|
|
||||||
// Color space conversion
|
|
||||||
auto convertColor = convert_from_current_to_screen_color_space();
|
|
||||||
|
|
||||||
if (alpha < 255) {
|
if (alpha < 255) {
|
||||||
if (rc.w == rc.h)
|
if (rc.w == rc.h)
|
||||||
draw_checkered_grid(g, rc, gfx::Size(rc.w / 2, rc.h / 2));
|
draw_checkered_grid(g, rc, gfx::Size(rc.w / 2, rc.h / 2));
|
||||||
|
|
@ -133,11 +131,15 @@ void draw_color(ui::Graphics* g,
|
||||||
color = app::Color::fromGray(color.getGray(), color.getAlpha());
|
color = app::Color::fromGray(color.getGray(), color.getAlpha());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The color is in the current sprite color space.
|
||||||
|
ui::Paint paint;
|
||||||
|
paint.color(color_utils::color_for_ui(color), get_current_color_space(g->display()).get());
|
||||||
|
|
||||||
if (color.getType() == app::Color::IndexType) {
|
if (color.getType() == app::Color::IndexType) {
|
||||||
int index = color.getIndex();
|
int index = color.getIndex();
|
||||||
|
|
||||||
if (index >= 0 && index < get_current_palette()->size()) {
|
if (index >= 0 && index < get_current_palette()->size()) {
|
||||||
g->fillRect(convertColor(color_utils::color_for_ui(color)), rc);
|
g->drawRect(rc, paint);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
g->fillRect(gfx::rgba(0, 0, 0), rc);
|
g->fillRect(gfx::rgba(0, 0, 0), rc);
|
||||||
|
|
@ -147,7 +149,7 @@ void draw_color(ui::Graphics* g,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
g->fillRect(convertColor(color_utils::color_for_ui(color)), rc);
|
g->drawRect(rc, paint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -219,7 +221,8 @@ void draw_tile(ui::Graphics* g, const Rect& rc, const Site& site, doc::tile_t ti
|
||||||
int w = tileImage->width();
|
int w = tileImage->width();
|
||||||
int h = tileImage->height();
|
int h = tileImage->height();
|
||||||
|
|
||||||
os::SurfaceRef surface = os::System::instance()->makeRgbaSurface(w, h);
|
os::SurfaceRef surface =
|
||||||
|
os::System::instance()->makeRgbaSurface(w, h, get_current_color_space(g->display()));
|
||||||
convert_image_to_surface(tileImage.get(), get_current_palette(), surface.get(), 0, 0, 0, 0, w, h);
|
convert_image_to_surface(tileImage.get(), get_current_palette(), surface.get(), 0, 0, 0, 0, w, h);
|
||||||
|
|
||||||
ui::Paint paint;
|
ui::Paint paint;
|
||||||
|
|
|
||||||
|
|
@ -407,7 +407,7 @@ void load_window_pos(Window* window, const char* section, const bool limitMinSiz
|
||||||
if (get_multiple_displays()) {
|
if (get_multiple_displays()) {
|
||||||
Rect frame = get_config_rect(section, "WindowFrame", gfx::Rect());
|
Rect frame = get_config_rect(section, "WindowFrame", gfx::Rect());
|
||||||
if (!frame.isEmpty()) {
|
if (!frame.isEmpty()) {
|
||||||
limit_with_workarea(parentDisplay, frame);
|
limit_least(frame);
|
||||||
window->loadNativeFrame(frame);
|
window->loadNativeFrame(frame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -698,14 +698,13 @@ bool CustomizedGuiManager::onEnqueueMouseDown(MouseMessage* mouseMsg)
|
||||||
|
|
||||||
bool CustomizedGuiManager::processKey(Message* msg)
|
bool CustomizedGuiManager::processKey(Message* msg)
|
||||||
{
|
{
|
||||||
App* app = App::instance();
|
|
||||||
const KeyboardShortcuts* keys = KeyboardShortcuts::instance();
|
const KeyboardShortcuts* keys = KeyboardShortcuts::instance();
|
||||||
const KeyContext contexts[] = { KeyboardShortcuts::getCurrentKeyContext(), KeyContext::Normal };
|
const KeyPtr key = keys->findBestKeyFromMessage(msg);
|
||||||
int n = (contexts[0] != contexts[1] ? 2 : 1);
|
if (!key)
|
||||||
for (int i = 0; i < n; ++i) {
|
return false;
|
||||||
for (const KeyPtr& key : *keys) {
|
|
||||||
if (key->isPressed(msg, contexts[i])) {
|
|
||||||
// Cancel menu-bar loops (to close any popup menu)
|
// Cancel menu-bar loops (to close any popup menu)
|
||||||
|
App* app = App::instance();
|
||||||
app->mainWindow()->getMenuBar()->cancelMenuLoop();
|
app->mainWindow()->getMenuBar()->cancelMenuLoop();
|
||||||
|
|
||||||
switch (key->type()) {
|
switch (key->type()) {
|
||||||
|
|
@ -726,8 +725,7 @@ bool CustomizedGuiManager::processKey(Message* msg)
|
||||||
bool done = false;
|
bool done = false;
|
||||||
|
|
||||||
for (size_t i = 0; i < possibles.size(); ++i) {
|
for (size_t i = 0; i < possibles.size(); ++i) {
|
||||||
if (possibles[i] != current_tool &&
|
if (possibles[i] != current_tool && ToolBar::instance()->isToolVisible(possibles[i])) {
|
||||||
ToolBar::instance()->isToolVisible(possibles[i])) {
|
|
||||||
select_this_tool = possibles[i];
|
select_this_tool = possibles[i];
|
||||||
done = true;
|
done = true;
|
||||||
break;
|
break;
|
||||||
|
|
@ -770,10 +768,7 @@ bool CustomizedGuiManager::processKey(Message* msg)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,6 @@
|
||||||
|
|
||||||
// Increment this value if the scripting API is modified between two
|
// Increment this value if the scripting API is modified between two
|
||||||
// released Aseprite versions.
|
// released Aseprite versions.
|
||||||
#define API_VERSION 35
|
#define API_VERSION 36
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -34,10 +34,10 @@
|
||||||
#include "app/tools/tool_loop_manager.h"
|
#include "app/tools/tool_loop_manager.h"
|
||||||
#include "app/tx.h"
|
#include "app/tx.h"
|
||||||
#include "app/ui/context_bar.h"
|
#include "app/ui/context_bar.h"
|
||||||
#include "app/ui/doc_view.h"
|
|
||||||
#include "app/ui/editor/editor.h"
|
#include "app/ui/editor/editor.h"
|
||||||
#include "app/ui/editor/tool_loop_impl.h"
|
#include "app/ui/editor/tool_loop_impl.h"
|
||||||
#include "app/ui/main_window.h"
|
#include "app/ui/main_window.h"
|
||||||
|
#include "app/ui/status_bar.h"
|
||||||
#include "app/ui/timeline/timeline.h"
|
#include "app/ui/timeline/timeline.h"
|
||||||
#include "app/ui_context.h"
|
#include "app/ui_context.h"
|
||||||
#include "base/fs.h"
|
#include "base/fs.h"
|
||||||
|
|
@ -498,6 +498,44 @@ int App_useTool(lua_State* L)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int App_tip(lua_State* L)
|
||||||
|
{
|
||||||
|
const auto* ctx = App::instance()->context();
|
||||||
|
if (!ctx || !ctx->isUIAvailable() || !StatusBar::instance())
|
||||||
|
return 0; // No UI to show the tooltip
|
||||||
|
|
||||||
|
std::string text;
|
||||||
|
double duration = 2.0;
|
||||||
|
|
||||||
|
if (lua_istable(L, 1)) {
|
||||||
|
int type = lua_getfield(L, 1, "text");
|
||||||
|
if (type == LUA_TSTRING)
|
||||||
|
text = lua_tostring(L, -1);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
type = lua_getfield(L, 1, "duration");
|
||||||
|
if (type == LUA_TNUMBER)
|
||||||
|
duration = lua_tonumber(L, -1);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!lua_isstring(L, 1))
|
||||||
|
return luaL_error(L, "app.tip text parameter must be a string");
|
||||||
|
|
||||||
|
text = lua_tostring(L, 1);
|
||||||
|
|
||||||
|
if (lua_isnumber(L, 2))
|
||||||
|
duration = lua_tonumber(L, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (text.empty())
|
||||||
|
return luaL_error(L, "app.tip text cannot be empty");
|
||||||
|
|
||||||
|
int msecs = std::clamp<int>(duration * 1000.0, 500, 30000);
|
||||||
|
StatusBar::instance()->showTip(msecs, text);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int App_get_events(lua_State* L)
|
int App_get_events(lua_State* L)
|
||||||
{
|
{
|
||||||
push_app_events(L);
|
push_app_events(L);
|
||||||
|
|
@ -820,6 +858,7 @@ const luaL_Reg App_methods[] = {
|
||||||
{ "alert", App_alert },
|
{ "alert", App_alert },
|
||||||
{ "refresh", App_refresh },
|
{ "refresh", App_refresh },
|
||||||
{ "useTool", App_useTool },
|
{ "useTool", App_useTool },
|
||||||
|
{ "tip", App_tip },
|
||||||
{ nullptr, nullptr }
|
{ nullptr, nullptr }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (c) 2022-2024 Igara Studio S.A.
|
// Copyright (c) 2022-2025 Igara Studio S.A.
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
// the End-User License Agreement for Aseprite.
|
// the End-User License Agreement for Aseprite.
|
||||||
|
|
||||||
#include "app/script/canvas_widget.h"
|
#include "app/script/canvas_widget.h"
|
||||||
|
|
||||||
|
#include "app/color_spaces.h"
|
||||||
#include "app/script/graphics_context.h"
|
#include "app/script/graphics_context.h"
|
||||||
#include "app/ui/skin/skin_theme.h"
|
#include "app/ui/skin/skin_theme.h"
|
||||||
#include "os/system.h"
|
#include "os/system.h"
|
||||||
|
|
@ -45,7 +46,7 @@ void Canvas::callPaint()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
os::Paint p;
|
os::Paint p;
|
||||||
p.color(bgColor());
|
p.color(bgColor(), m_surface->colorSpace().get());
|
||||||
m_surface->drawRect(m_surface->bounds(), p);
|
m_surface->drawRect(m_surface->bounds(), p);
|
||||||
|
|
||||||
// Draw only on resize (onPaint we draw the cached m_surface)
|
// Draw only on resize (onPaint we draw the cached m_surface)
|
||||||
|
|
@ -189,7 +190,9 @@ void Canvas::onResize(ui::ResizeEvent& ev)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_surface || m_surface->width() != w || m_surface->height() != h) {
|
if (!m_surface || m_surface->width() != w || m_surface->height() != h) {
|
||||||
m_surface = system->makeSurface(w, h);
|
ui::Display* display = this->display();
|
||||||
|
os::ColorSpaceRef cs = (display ? display->colorSpace() : nullptr);
|
||||||
|
m_surface = system->makeSurface(w, h, cs);
|
||||||
callPaint();
|
callPaint();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,8 @@ namespace app { namespace script {
|
||||||
|
|
||||||
using namespace ui;
|
using namespace ui;
|
||||||
|
|
||||||
|
static constexpr const int kDefaultAutofit = ui::LEFT | ui::TOP;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
class DialogWindow : public WindowWithHand {
|
class DialogWindow : public WindowWithHand {
|
||||||
|
|
@ -107,6 +109,7 @@ struct Dialog {
|
||||||
std::map<std::string, ui::Widget*> dataWidgets;
|
std::map<std::string, ui::Widget*> dataWidgets;
|
||||||
std::map<std::string, ui::Widget*> labelWidgets;
|
std::map<std::string, ui::Widget*> labelWidgets;
|
||||||
int currentRadioGroup = 0;
|
int currentRadioGroup = 0;
|
||||||
|
int autofit = kDefaultAutofit;
|
||||||
|
|
||||||
// Member used to hold current state about the creation of a tabs
|
// Member used to hold current state about the creation of a tabs
|
||||||
// widget. After creation it is reset to null to be ready for the
|
// widget. After creation it is reset to null to be ready for the
|
||||||
|
|
@ -193,11 +196,19 @@ struct Dialog {
|
||||||
it->second->setText(text);
|
it->second->setText(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setAutofit(int align)
|
||||||
|
{
|
||||||
|
// Accept both 0 or a valid subset of align parameters.
|
||||||
|
if (align == 0 || (align & (ui::LEFT | ui::RIGHT | ui::TOP | ui::BOTTOM)))
|
||||||
|
autofit = align;
|
||||||
|
}
|
||||||
|
|
||||||
Display* parentDisplay() const
|
Display* parentDisplay() const
|
||||||
{
|
{
|
||||||
Display* parentDisplay = window.parentDisplay();
|
Display* parentDisplay = window.parentDisplay();
|
||||||
if (!parentDisplay) {
|
if (!parentDisplay) {
|
||||||
const auto mainWindow = App::instance()->mainWindow();
|
const auto* mainWindow = App::instance()->mainWindow();
|
||||||
|
if (mainWindow)
|
||||||
parentDisplay = mainWindow->display();
|
parentDisplay = mainWindow->display();
|
||||||
}
|
}
|
||||||
return parentDisplay;
|
return parentDisplay;
|
||||||
|
|
@ -210,6 +221,9 @@ struct Dialog {
|
||||||
// origin/scale (or main window if a parent window wasn't specified).
|
// origin/scale (or main window if a parent window wasn't specified).
|
||||||
if (window.ownDisplay()) {
|
if (window.ownDisplay()) {
|
||||||
const Display* parentDisplay = this->parentDisplay();
|
const Display* parentDisplay = this->parentDisplay();
|
||||||
|
if (!parentDisplay)
|
||||||
|
return bounds;
|
||||||
|
|
||||||
const int scale = parentDisplay->scale();
|
const int scale = parentDisplay->scale();
|
||||||
const gfx::Point dialogOrigin = window.display()->nativeWindow()->contentRect().origin();
|
const gfx::Point dialogOrigin = window.display()->nativeWindow()->contentRect().origin();
|
||||||
const gfx::Point mainOrigin = parentDisplay->nativeWindow()->contentRect().origin();
|
const gfx::Point mainOrigin = parentDisplay->nativeWindow()->contentRect().origin();
|
||||||
|
|
@ -224,6 +238,9 @@ struct Dialog {
|
||||||
window.expandWindow(rc.size());
|
window.expandWindow(rc.size());
|
||||||
|
|
||||||
Display* parentDisplay = this->parentDisplay();
|
Display* parentDisplay = this->parentDisplay();
|
||||||
|
if (!parentDisplay)
|
||||||
|
return;
|
||||||
|
|
||||||
const int scale = parentDisplay->scale();
|
const int scale = parentDisplay->scale();
|
||||||
const gfx::Point mainOrigin = parentDisplay->nativeWindow()->contentRect().origin();
|
const gfx::Point mainOrigin = parentDisplay->nativeWindow()->contentRect().origin();
|
||||||
gfx::Rect frame = window.display()->nativeWindow()->contentRect();
|
gfx::Rect frame = window.display()->nativeWindow()->contentRect();
|
||||||
|
|
@ -231,8 +248,10 @@ struct Dialog {
|
||||||
window.display()->nativeWindow()->setFrame(frame);
|
window.display()->nativeWindow()->setFrame(frame);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
gfx::Rect oldBounds(window.bounds());
|
||||||
window.setBounds(rc);
|
window.setBounds(rc);
|
||||||
window.invalidate();
|
window.invalidate();
|
||||||
|
parentDisplay()->invalidateRect(oldBounds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -367,6 +386,7 @@ int Dialog_new(lua_State* L)
|
||||||
ui::Window::Type windowType = ui::Window::WithTitleBar;
|
ui::Window::Type windowType = ui::Window::WithTitleBar;
|
||||||
std::string title = "Script";
|
std::string title = "Script";
|
||||||
bool sizeable = true;
|
bool sizeable = true;
|
||||||
|
int autofit = kDefaultAutofit;
|
||||||
if (lua_isstring(L, 1)) {
|
if (lua_isstring(L, 1)) {
|
||||||
title = lua_tostring(L, 1);
|
title = lua_tostring(L, 1);
|
||||||
}
|
}
|
||||||
|
|
@ -385,9 +405,16 @@ int Dialog_new(lua_State* L)
|
||||||
if (type != LUA_TNIL && !lua_toboolean(L, -1))
|
if (type != LUA_TNIL && !lua_toboolean(L, -1))
|
||||||
sizeable = false;
|
sizeable = false;
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
type = lua_getfield(L, 1, "autofit");
|
||||||
|
if (type != LUA_TNIL) {
|
||||||
|
autofit = lua_tointeger(L, -1);
|
||||||
|
}
|
||||||
|
lua_pop(L, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto dlg = push_new<Dialog>(L, windowType, title, sizeable);
|
auto dlg = push_new<Dialog>(L, windowType, title, sizeable);
|
||||||
|
dlg->setAutofit(autofit);
|
||||||
|
|
||||||
// The uservalue of the dialog userdata will contain a table that
|
// The uservalue of the dialog userdata will contain a table that
|
||||||
// stores all the callbacks to handle events. As these callbacks can
|
// stores all the callbacks to handle events. As these callbacks can
|
||||||
|
|
@ -631,6 +658,8 @@ int Dialog_add_widget(lua_State* L, Widget* widget)
|
||||||
if (label || !dlg->hbox) {
|
if (label || !dlg->hbox) {
|
||||||
if (label) {
|
if (label) {
|
||||||
auto labelWidget = new ui::Label(label);
|
auto labelWidget = new ui::Label(label);
|
||||||
|
labelWidget->setBuddy(widget);
|
||||||
|
|
||||||
if (!visible)
|
if (!visible)
|
||||||
labelWidget->setVisible(false);
|
labelWidget->setVisible(false);
|
||||||
|
|
||||||
|
|
@ -1637,6 +1666,10 @@ int Dialog_modify(lua_State* L)
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
|
|
||||||
type = lua_getfield(L, 2, "mouseCursor");
|
type = lua_getfield(L, 2, "mouseCursor");
|
||||||
|
if (type == LUA_TNIL) {
|
||||||
|
lua_pop(L, 1);
|
||||||
|
type = lua_getfield(L, 2, "mousecursor");
|
||||||
|
}
|
||||||
if (type != LUA_TNIL) {
|
if (type != LUA_TNIL) {
|
||||||
if (auto canvas = dynamic_cast<Canvas*>(widget)) {
|
if (auto canvas = dynamic_cast<Canvas*>(widget)) {
|
||||||
auto cursor = (ui::CursorType)lua_tointeger(L, -1);
|
auto cursor = (ui::CursorType)lua_tointeger(L, -1);
|
||||||
|
|
@ -1654,8 +1687,26 @@ int Dialog_modify(lua_State* L)
|
||||||
if (relayout && !dlg->window.isResizing()) {
|
if (relayout && !dlg->window.isResizing()) {
|
||||||
dlg->window.layout();
|
dlg->window.layout();
|
||||||
|
|
||||||
gfx::Rect bounds(dlg->window.bounds().w, dlg->window.sizeHint().h);
|
if (dlg->autofit > 0) {
|
||||||
dlg->window.expandWindow(bounds.size());
|
gfx::Rect oldBounds = dlg->window.bounds();
|
||||||
|
gfx::Size resize(oldBounds.size());
|
||||||
|
|
||||||
|
if (dlg->autofit & ui::TOP || dlg->autofit & ui::BOTTOM)
|
||||||
|
resize.h = dlg->window.sizeHint().h;
|
||||||
|
if (dlg->autofit & ui::LEFT || dlg->autofit & ui::RIGHT)
|
||||||
|
resize.w = dlg->window.sizeHint().w;
|
||||||
|
|
||||||
|
gfx::Size difference = resize - oldBounds.size();
|
||||||
|
const auto& bounds = dlg->getWindowBounds();
|
||||||
|
gfx::Rect newBounds(bounds.x, bounds.y, resize.w, resize.h);
|
||||||
|
|
||||||
|
if (dlg->autofit & ui::BOTTOM)
|
||||||
|
newBounds.y = bounds.y - difference.h;
|
||||||
|
if (dlg->autofit & ui::RIGHT)
|
||||||
|
newBounds.x = bounds.x - difference.w;
|
||||||
|
|
||||||
|
dlg->setWindowBounds(newBounds);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lua_pushvalue(L, 1);
|
lua_pushvalue(L, 1);
|
||||||
|
|
@ -1877,6 +1928,27 @@ int Dialog_get_bounds(lua_State* L)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Dialog_get_sizeHint(lua_State* L)
|
||||||
|
{
|
||||||
|
auto dlg = get_obj<Dialog>(L, 1);
|
||||||
|
push_new<gfx::Size>(L, dlg->window.sizeHint());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Dialog_get_autofit(lua_State* L)
|
||||||
|
{
|
||||||
|
auto dlg = get_obj<Dialog>(L, 1);
|
||||||
|
lua_pushinteger(L, dlg->autofit);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Dialog_set_autofit(lua_State* L)
|
||||||
|
{
|
||||||
|
auto dlg = get_obj<Dialog>(L, 1);
|
||||||
|
dlg->setAutofit(lua_tointeger(L, 2));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int Dialog_set_bounds(lua_State* L)
|
int Dialog_set_bounds(lua_State* L)
|
||||||
{
|
{
|
||||||
auto dlg = get_obj<Dialog>(L, 1);
|
auto dlg = get_obj<Dialog>(L, 1);
|
||||||
|
|
@ -1920,6 +1992,8 @@ const luaL_Reg Dialog_methods[] = {
|
||||||
const Property Dialog_properties[] = {
|
const Property Dialog_properties[] = {
|
||||||
{ "data", Dialog_get_data, Dialog_set_data },
|
{ "data", Dialog_get_data, Dialog_set_data },
|
||||||
{ "bounds", Dialog_get_bounds, Dialog_set_bounds },
|
{ "bounds", Dialog_get_bounds, Dialog_set_bounds },
|
||||||
|
{ "autofit", Dialog_get_autofit, Dialog_set_autofit },
|
||||||
|
{ "sizeHint", Dialog_get_sizeHint, nullptr },
|
||||||
{ nullptr, nullptr, nullptr }
|
{ nullptr, nullptr, nullptr }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -452,6 +452,7 @@ Engine::Engine() : L(luaL_newstate()), m_delegate(nullptr), m_printLastResult(fa
|
||||||
lua_setglobal(L, "FlipType");
|
lua_setglobal(L, "FlipType");
|
||||||
setfield_integer(L, "HORIZONTAL", doc::algorithm::FlipType::FlipHorizontal);
|
setfield_integer(L, "HORIZONTAL", doc::algorithm::FlipType::FlipHorizontal);
|
||||||
setfield_integer(L, "VERTICAL", doc::algorithm::FlipType::FlipVertical);
|
setfield_integer(L, "VERTICAL", doc::algorithm::FlipType::FlipVertical);
|
||||||
|
setfield_integer(L, "DIAGONAL", doc::algorithm::FlipType::FlipDiagonal);
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
|
|
||||||
lua_newtable(L);
|
lua_newtable(L);
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
#include "app/script/luacpp.h"
|
#include "app/script/luacpp.h"
|
||||||
#include "app/script/userdata.h"
|
#include "app/script/userdata.h"
|
||||||
#include "app/tx.h"
|
#include "app/tx.h"
|
||||||
|
#include "app/ui/timeline/timeline.h"
|
||||||
#include "doc/layer.h"
|
#include "doc/layer.h"
|
||||||
#include "doc/layer_tilemap.h"
|
#include "doc/layer_tilemap.h"
|
||||||
#include "doc/sprite.h"
|
#include "doc/sprite.h"
|
||||||
|
|
@ -355,6 +356,9 @@ int Layer_set_isCollapsed(lua_State* L)
|
||||||
{
|
{
|
||||||
auto layer = get_docobj<Layer>(L, 1);
|
auto layer = get_docobj<Layer>(L, 1);
|
||||||
layer->setCollapsed(lua_toboolean(L, 2));
|
layer->setCollapsed(lua_toboolean(L, 2));
|
||||||
|
|
||||||
|
if (auto* timeline = App::instance()->timeline())
|
||||||
|
timeline->refresh();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -362,6 +366,9 @@ int Layer_set_isExpanded(lua_State* L)
|
||||||
{
|
{
|
||||||
auto layer = get_docobj<Layer>(L, 1);
|
auto layer = get_docobj<Layer>(L, 1);
|
||||||
layer->setCollapsed(!lua_toboolean(L, 2));
|
layer->setCollapsed(!lua_toboolean(L, 2));
|
||||||
|
|
||||||
|
if (auto* timeline = App::instance()->timeline())
|
||||||
|
timeline->refresh();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,8 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isPlugin() override { return true; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::string onGetFriendlyName() const override { return m_title; }
|
std::string onGetFriendlyName() const override { return m_title; }
|
||||||
|
|
||||||
|
|
@ -99,17 +101,15 @@ private:
|
||||||
|
|
||||||
lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
|
lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
|
||||||
if (lua_pcall(L, 0, 1, 0)) {
|
if (lua_pcall(L, 0, 1, 0)) {
|
||||||
if (const char* s = lua_tostring(L, -1)) {
|
if (const char* s = lua_tostring(L, -1))
|
||||||
Console().printf("Error: %s", s);
|
Console().printf("Error: %s", s);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else {
|
|
||||||
bool ret = lua_toboolean(L, -1);
|
bool ret = lua_toboolean(L, -1);
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
std::string m_title;
|
std::string m_title;
|
||||||
int m_onclickRef;
|
int m_onclickRef;
|
||||||
|
|
|
||||||
|
|
@ -457,7 +457,7 @@ int Sprite_newCel(lua_State* L)
|
||||||
auto sprite = get_docobj<Sprite>(L, 1);
|
auto sprite = get_docobj<Sprite>(L, 1);
|
||||||
auto layerBase = get_docobj<Layer>(L, 2);
|
auto layerBase = get_docobj<Layer>(L, 2);
|
||||||
if (!layerBase->isImage())
|
if (!layerBase->isImage())
|
||||||
return luaL_error(L, "unexpected kinf of layer in Sprite:newCel()");
|
return luaL_error(L, "unexpected kind of layer in Sprite:newCel()");
|
||||||
|
|
||||||
frame_t frame = get_frame_number_from_arg(L, 3);
|
frame_t frame = get_frame_number_from_arg(L, 3);
|
||||||
if (frame < 0 || frame > sprite->lastFrame())
|
if (frame < 0 || frame > sprite->lastFrame())
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2019-2024 Igara Studio S.A.
|
// Copyright (C) 2019-2025 Igara Studio S.A.
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
// the End-User License Agreement for Aseprite.
|
// the End-User License Agreement for Aseprite.
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue