Compare commits

..

229 Commits

Author SHA1 Message Date
David Capello 1ac451de03
Merge branch 'beta' into isometric-grid 2025-08-21 08:09:33 -03:00
David Capello ed3c8c510b Merge branch 'main' into beta 2025-08-13 09:27:20 -03:00
David Capello f23e3255bb Fix compilation w/ENABLE_DEVMODE 2025-08-12 16:12:35 -03:00
David Capello 90282dbc40 Fix cast error in HarfBuzz library between function types
This includes the following patch:
60c6b7786d
2025-08-11 15:29:58 -03:00
Martín Capello 1227f9c49c Refactor getLayerIndexFromSprite into LayerGroup 2025-08-11 14:47:56 -03:00
Martín Capello d61ae919ad Fix crash dropping file on timeline (fix #5289) 2025-08-11 14:47:56 -03:00
David Capello 58a5a64cd2 Simplify some code introduced in #5222 to draw different MaskBoundaries
* Added a new Editor::drawMaskBoundaries() and
  Editor::m_selectionToolMaskBoundaries to store the generated
  boundaries for the active SelectionToolLoopImpl.
* Removed app::Doc::setMaskBoundaries() used to restore the active
  mask boundaries.
* Removed Editor::MaskIndex
2025-08-08 18:15:08 -03:00
David Capello b2b2583176 [lua] Update scripting API version to 35 2025-08-07 20:18:10 -03:00
David Capello b535212642 Update laf module 2025-08-07 20:14:43 -03:00
Liebranca 2dbfaf746b Remove m_expandCelCanvas from SelectionToolLoopImpl 2025-08-07 19:54:33 -03:00
Liebranca 23d4543272 Implement tool loop for selection tools 2025-08-07 19:54:33 -03:00
Christian Kaiser 229a3cdf65 [lua] Add onchecked parameter to Commands 2025-08-07 18:57:28 -03:00
Christian Kaiser b3814ec912 Unify ContextBar updates when moving pixels, tooltips (fix #5329) 2025-08-06 20:20:42 -03:00
David Capello e88f3bb413 Show error if curl/unzip tools aren't available (fix #5309) 2025-08-06 14:44:21 -03:00
Christian Kaiser 366751d1f2 Command refresh and refactor, ui availability consistency (fix #3025) 2025-08-05 19:03:21 -03:00
David Capello 7434db6882 Merge branch 'dock' into beta (#518, #3485) 2025-08-05 16:23:53 -03:00
David Capello 5e12a5d3d8 Restore the "Position" section in Timeline configuration
We're going to keep this section for a couple of versions as old users
get used to the new Workspace Layout customization.

The "Position" section will contain the layout icon so we can switch
the Workspace Layout combobox from there too,
2025-08-04 19:41:59 -03:00
David Capello 60112cd929 Close layout combobox after clicking the reset/delete layout button
Without this, the combobox is still visible and clicking the button
again will crash the program.
2025-08-04 19:41:59 -03:00
David Capello a1fb751323 Remove base field from "New Layout" dialog 2025-08-04 19:41:59 -03:00
David Capello 24046600ec Fix loading modified default layouts at the very beginning 2025-08-04 19:41:59 -03:00
David Capello 34aae80eab Fix some strings
From https://github.com/aseprite/aseprite/pull/3485#pullrequestreview-2824195211
2025-08-04 19:41:59 -03:00
David Capello c8ae1017b3 Fix crashes resetting the default layout + remove some hacks
With this patch we've also simplified some hacks handling the
populateComboBox() call, deferring the deletion of widgets/items when
we are inside an event generated by those items.
2025-08-04 19:41:59 -03:00
David Capello 9c5d1feaf5 Fix several layout saving/loading issues
* Better support to load legacy timeline information: we have to
  estimate workspace bounds)
* Auto-save layouts after resizing a splitter/dock
* Fix resetting expansive widgets inside docks after switching tabs
* Load mirrored layout correctly if it was the last selected layout
2025-08-04 19:41:59 -03:00
David Capello aa66d260ad Fix switch/break style 2025-08-04 19:41:59 -03:00
David Capello 86c7fae42c Move LayoutSelector::setActiveLayoutId() impl to .cpp file 2025-08-04 19:41:59 -03:00
David Capello 778e62a411 Minor changes (format, remove unused/unnecessary vars/keywords) 2025-08-04 19:41:59 -03:00
David Capello b08662eeca Change notification flag location inside the layout selector widget
This improves the look of the flag as another icon above the tabs
bottom and at the right of the layout selector icon.
2025-08-04 19:41:59 -03:00
David Capello d6c5ac6786 [theme] New layout selector icon + bg color fixes 2025-08-04 19:41:59 -03:00
David Capello e0226d95d9 Improve layout selector widget location when menu bar is visible/hidden 2025-08-04 19:41:59 -03:00
David Capello 7eb2df6965 Remove unused member variable from ui::Dock 2025-08-04 19:41:59 -03:00
Christian Kaiser c445075a79 Polish layout handling
@dacap's notes: A description of the included changes:

* Improve UX auto-saving layouts when docks are modified, and new 'X'
  icon to delete layouts (or reset the 'Default' layout).
* Remove old timeline position controls (Left/Right/Bottom buttons)
  from the Timeline configuration and from the layout selector
* Add support to drag and drop docks to other sides with real-time
  feedback using a semi-transparent UILayer
* Add a context menu w/right-click to dock the widget at the supported
  sides without drag-and-drop

Some review comments in https://github.com/dacap/aseprite/pull/2
2025-08-04 19:41:59 -03:00
David Capello f556052fc6 Show handles in dockable areas to drag-and-drop them 2025-08-04 19:41:58 -03:00
David Capello c8e9b33ad3 Fix bug where the ToolBar popup wasn't being opened
This was a new issue with combination of
9b90159d1b, probably we should close the
popup when the window is resized (instead of onSizeHint()).
2025-08-04 19:41:58 -03:00
David Capello 37d2be7668 Update saving/loading dock layouts w/tinyxml2 library 2025-08-04 19:41:58 -03:00
David Capello 43140e71ec Save layout changes immediately when docks are resized
This patch includes:

* The layout is updated immediately when docks are resized (before
  this the layout was like a snapshot of the configuration when the
  layout was created or overwritten with the "New Layout" option)
* Saving the active layout used in
  preferences.general.workspace_layout so we can restore it after
  restarting Aseprite
* Change "UI Layout" to "Workspace Layout"
* Some strings moved to en.ini file for i18n
* Fixed a crash on MainWindow::onActiveViewChange() when the
  application was being closed
2025-08-04 19:41:58 -03:00
David Capello eecc14153d Improve borders of context & color bars for both sides (left/right) 2025-08-04 19:41:58 -03:00
David Capello 131aa8b3df Add View > Workspace Layout option to switch the layout w/keys 2025-08-04 19:41:58 -03:00
David Capello ab69421096 Add possibility to overwrite existent layouts 2025-08-04 19:41:58 -03:00
David Capello 0e4e776bc0 Include StatusBar in the set of customizable widgets in the layout 2025-08-04 19:41:58 -03:00
David Capello 78b9f340f7 Save/Load user defined layouts in new user.aseprite-layouts file
And now we store the TiXmlElement for each Layout, instead of
converting from/to text back and forth.
2025-08-04 19:41:58 -03:00
David Capello 92a039a619 Add option to save/restore user-defined layouts on memory
This happens only in memory at the moment (layouts are not saved in
disk yet), and the customization is quite simple (only size of
splitters, timeline position). But in the future we should be able to
dock elements in any place.
2025-08-04 19:41:58 -03:00
David Capello dc040e81e7 Set the initial timeline position in the LayoutSelector correctly 2025-08-04 19:41:58 -03:00
David Capello 465574e2db Show the timeline when we set its position from the LayoutSelector 2025-08-04 19:41:58 -03:00
David Capello 544f711adc Improve the layout selector UI
Changes:
* Now we use the "user data" icon as the button to expand the layouts
  combobox
* Added a tooltip to this icon
* Added buttons to configure the Timeline position in the same
  combobox
* Fixed some bugs in Dock using space for hidden widgets
2025-08-04 19:41:58 -03:00
David Capello ec95323856 Save/restore color bar splitter position correctly 2025-08-04 19:41:58 -03:00
David Capello 9b56d5ba3d Save/restore timeline splitter position correctly 2025-08-04 19:41:58 -03:00
David Capello 2c0920f514 Fix popups & tooltips direction when ToolBar is docked at the left side 2025-08-04 19:41:58 -03:00
David Capello ba39b56096 Fix std::clamp() max bound in TipWindow::pointAt() 2025-08-04 19:41:58 -03:00
David Capello ad4d00ced2 Use std::unique_ptr in ToolBar members 2025-08-04 19:41:58 -03:00
David Capello 6df6037fdc Fix memory leaks in MainWindow
Temporary/created subdocks must be deleted automatically, and children
that are not part of the window hierarchy must be deleted explicitly
now (using some std::unique_ptrs).
2025-08-04 19:41:58 -03:00
David Capello bb65296a1a Add Dock widget, initial & basic version of dockable elements (#518)
Some missing features so far:

1) Restore old layout configuration (color bar split pos, timeline
   pos, etc.) and migrate to new Dock layout
2) Load/saving Dock layout
3) Create & customize current layoout (drag-and-drop widgets, etc.)
2025-08-04 19:41:58 -03:00
Christian Kaiser eaa2bdf0af [lua] Process mnemonics consistently for plugins (fix #5250) 2025-08-04 15:58:29 -03:00
Christian Kaiser 57309e5aa5 Allow gif encoding to be stopped (fix #2619) 2025-08-01 20:46:32 -03:00
Christian Kaiser 4bb9239f50 [lua] Add `resizeable` property to Dialog constructor (fix #5177)
build / build (Debug, macos-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, macos-latest, noscripts, cli) (push) Has been cancelled Details
build / build (Debug, ubuntu-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, ubuntu-latest, noscripts, cli) (push) Has been cancelled Details
build / build (Debug, windows-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, windows-latest, noscripts, cli) (push) Has been cancelled Details
build / build (RelWithDebInfo, macos-latest, lua, gui) (push) Has been cancelled Details
build / build (RelWithDebInfo, ubuntu-latest, lua, gui) (push) Has been cancelled Details
build / build (RelWithDebInfo, windows-latest, lua, gui) (push) Has been cancelled Details
2025-08-01 18:57:50 -03:00
David Capello cef92c1a38 Add .plist files for macOS
build-auto / build-auto (Debug, macos-latest) (push) Has been cancelled Details
build-auto / build-auto (Debug, ubuntu-latest) (push) Has been cancelled Details
build-auto / build-auto (Debug, windows-latest) (push) Has been cancelled Details
build-auto / build-auto (RelWithDebInfo, macos-latest) (push) Has been cancelled Details
build-auto / build-auto (RelWithDebInfo, ubuntu-latest) (push) Has been cancelled Details
build-auto / build-auto (RelWithDebInfo, windows-latest) (push) Has been cancelled Details
build / build (Debug, macos-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, macos-latest, noscripts, cli) (push) Has been cancelled Details
build / build (Debug, ubuntu-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, ubuntu-latest, noscripts, cli) (push) Has been cancelled Details
build / build (Debug, windows-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, windows-latest, noscripts, cli) (push) Has been cancelled Details
build / build (RelWithDebInfo, macos-latest, lua, gui) (push) Has been cancelled Details
build / build (RelWithDebInfo, ubuntu-latest, lua, gui) (push) Has been cancelled Details
build / build (RelWithDebInfo, windows-latest, lua, gui) (push) Has been cancelled Details
We don't have an Aseprite.app target in cmake files yet, but we might
add it in a near future.
2025-07-28 16:18:19 -03:00
Christian Kaiser 22e72ab5cb [win] Fix includeDesktopDir returning the default path
build / build (Debug, macos-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, macos-latest, noscripts, cli) (push) Waiting to run Details
build / build (Debug, ubuntu-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, ubuntu-latest, noscripts, cli) (push) Waiting to run Details
build / build (Debug, windows-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, windows-latest, noscripts, cli) (push) Waiting to run Details
build / build (RelWithDebInfo, macos-latest, lua, gui) (push) Waiting to run Details
build / build (RelWithDebInfo, ubuntu-latest, lua, gui) (push) Waiting to run Details
build / build (RelWithDebInfo, windows-latest, lua, gui) (push) Waiting to run Details
Uses SHGFP_TYPE_CURRENT which returns the Desktop that the user has configured instead of the default, fixes Windows 11's OneDrive Desktop folder.
2025-07-28 10:47:53 -03:00
Christian Kaiser 80fa065bd5 [lua] Add sprite.undoHistory
build / build (Debug, macos-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, macos-latest, noscripts, cli) (push) Has been cancelled Details
build / build (Debug, ubuntu-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, ubuntu-latest, noscripts, cli) (push) Has been cancelled Details
build / build (Debug, windows-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, windows-latest, noscripts, cli) (push) Has been cancelled Details
build / build (RelWithDebInfo, macos-latest, lua, gui) (push) Has been cancelled Details
build / build (RelWithDebInfo, ubuntu-latest, lua, gui) (push) Has been cancelled Details
build / build (RelWithDebInfo, windows-latest, lua, gui) (push) Has been cancelled Details
2025-07-25 13:58:52 -03:00
David Capello de1ccb24dd [win] Don't drop text when IME dialog composition is accepted w/Enter
build / build (Debug, macos-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, macos-latest, noscripts, cli) (push) Waiting to run Details
build / build (Debug, ubuntu-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, ubuntu-latest, noscripts, cli) (push) Waiting to run Details
build / build (Debug, windows-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, windows-latest, noscripts, cli) (push) Waiting to run Details
build / build (RelWithDebInfo, macos-latest, lua, gui) (push) Waiting to run Details
build / build (RelWithDebInfo, ubuntu-latest, lua, gui) (push) Waiting to run Details
build / build (RelWithDebInfo, windows-latest, lua, gui) (push) Waiting to run Details
build-auto / build-auto (Debug, macos-latest) (push) Has been cancelled Details
build-auto / build-auto (Debug, ubuntu-latest) (push) Has been cancelled Details
build-auto / build-auto (Debug, windows-latest) (push) Has been cancelled Details
build-auto / build-auto (RelWithDebInfo, macos-latest) (push) Has been cancelled Details
build-auto / build-auto (RelWithDebInfo, ubuntu-latest) (push) Has been cancelled Details
build-auto / build-auto (RelWithDebInfo, windows-latest) (push) Has been cancelled Details
With #5230, now that we can show the IME dialog on Windows, when we
are selecting a specific word/composition in the IME dialog, if we
press Enter we'll receive that Enter onKeyUp(). It's better if we
process the Enter key onKeyDown() (as the IME enter key is not
received in that case).
2025-07-25 09:19:50 -03:00
David Capello 7d91c4b9d9 [win] Fix dead keys on Windows 2025-07-24 17:45:46 -03:00
Cerallin 6d89a6bc15 fix entry
build-auto / build-auto (Debug, macos-latest) (push) Has been cancelled Details
build-auto / build-auto (Debug, ubuntu-latest) (push) Has been cancelled Details
build-auto / build-auto (Debug, windows-latest) (push) Has been cancelled Details
build-auto / build-auto (RelWithDebInfo, macos-latest) (push) Has been cancelled Details
build-auto / build-auto (RelWithDebInfo, ubuntu-latest) (push) Has been cancelled Details
build-auto / build-auto (RelWithDebInfo, windows-latest) (push) Has been cancelled Details
build / build (Debug, macos-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, macos-latest, noscripts, cli) (push) Has been cancelled Details
build / build (Debug, ubuntu-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, ubuntu-latest, noscripts, cli) (push) Has been cancelled Details
build / build (Debug, windows-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, windows-latest, noscripts, cli) (push) Has been cancelled Details
build / build (RelWithDebInfo, macos-latest, lua, gui) (push) Has been cancelled Details
build / build (RelWithDebInfo, ubuntu-latest, lua, gui) (push) Has been cancelled Details
build / build (RelWithDebInfo, windows-latest, lua, gui) (push) Has been cancelled Details
2025-07-24 12:50:32 -03:00
Cerallin d4e97b5a96 Add const method Entry::caretPosOnScreen()
This method is for Entry::setTextInput() and IME positioning.
2025-07-24 12:50:32 -03:00
Cerallin 205b18dc0f Make Entry::getCharBoxBounds() a const method 2025-07-24 12:50:32 -03:00
David Capello 2ba051b59b Fix crash deselecting moved pixels when using certain extensions (fix #5280)
build / build (Debug, macos-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, macos-latest, noscripts, cli) (push) Waiting to run Details
build / build (Debug, ubuntu-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, ubuntu-latest, noscripts, cli) (push) Waiting to run Details
build / build (Debug, windows-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, windows-latest, noscripts, cli) (push) Waiting to run Details
build / build (RelWithDebInfo, macos-latest, lua, gui) (push) Waiting to run Details
build / build (RelWithDebInfo, ubuntu-latest, lua, gui) (push) Waiting to run Details
build / build (RelWithDebInfo, windows-latest, lua, gui) (push) Waiting to run Details
Although the issue refers to deselecting MovingPixelsState, the same
crash could happen when canceling/finishing WritingTextState or
MovingSelectionState. This fixes the crash for all these states.
2025-07-23 19:01:37 -03:00
Christian Kaiser 3fcb000eb1 Fix slice transformations not updating editors
build / build (Debug, macos-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, macos-latest, noscripts, cli) (push) Has been cancelled Details
build / build (Debug, ubuntu-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, ubuntu-latest, noscripts, cli) (push) Has been cancelled Details
build / build (Debug, windows-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, windows-latest, noscripts, cli) (push) Has been cancelled Details
build / build (RelWithDebInfo, macos-latest, lua, gui) (push) Has been cancelled Details
build / build (RelWithDebInfo, ubuntu-latest, lua, gui) (push) Has been cancelled Details
build / build (RelWithDebInfo, windows-latest, lua, gui) (push) Has been cancelled Details
2025-07-22 02:11:07 -03:00
David Capello af9dc3c817 Fix brush boundaries accumulation switching brush type only (fix #5281)
build / build (Debug, macos-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, macos-latest, noscripts, cli) (push) Waiting to run Details
build / build (Debug, ubuntu-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, ubuntu-latest, noscripts, cli) (push) Waiting to run Details
build / build (Debug, windows-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, windows-latest, noscripts, cli) (push) Waiting to run Details
build / build (RelWithDebInfo, macos-latest, lua, gui) (push) Waiting to run Details
build / build (RelWithDebInfo, ubuntu-latest, lua, gui) (push) Waiting to run Details
build / build (RelWithDebInfo, windows-latest, lua, gui) (push) Waiting to run Details
2025-07-21 17:28:11 -03:00
David Capello 250dfdc86a Convert the brush generation counter into an atomic var 2025-07-21 17:27:23 -03:00
David Capello c904c41b39 Don't show stroke/fill option for theme fonts
build / build (Debug, macos-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, macos-latest, noscripts, cli) (push) Has been cancelled Details
build / build (Debug, ubuntu-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, ubuntu-latest, noscripts, cli) (push) Has been cancelled Details
build / build (Debug, windows-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, windows-latest, noscripts, cli) (push) Has been cancelled Details
build / build (RelWithDebInfo, macos-latest, lua, gui) (push) Has been cancelled Details
build / build (RelWithDebInfo, ubuntu-latest, lua, gui) (push) Has been cancelled Details
build / build (RelWithDebInfo, windows-latest, lua, gui) (push) Has been cancelled Details
2025-07-18 18:48:35 -03:00
David Capello 9e941e9a8b [win32] Fix listing hidden files on Windows (related to #5269 / #3079) 2025-07-18 18:37:44 -03:00
Liebranca bbab4d5875 Add 'Show hidden' check to file selector 2025-07-18 18:26:35 -03:00
David Capello 5c4daff128 Add options to stroke/fill text (fix #5271)
build-auto / build-auto (Debug, macos-latest) (push) Has been cancelled Details
build-auto / build-auto (Debug, ubuntu-latest) (push) Has been cancelled Details
build-auto / build-auto (Debug, windows-latest) (push) Has been cancelled Details
build-auto / build-auto (RelWithDebInfo, macos-latest) (push) Has been cancelled Details
build-auto / build-auto (RelWithDebInfo, ubuntu-latest) (push) Has been cancelled Details
build-auto / build-auto (RelWithDebInfo, windows-latest) (push) Has been cancelled Details
build / build (Debug, macos-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, macos-latest, noscripts, cli) (push) Has been cancelled Details
build / build (Debug, ubuntu-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, ubuntu-latest, noscripts, cli) (push) Has been cancelled Details
build / build (Debug, windows-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, windows-latest, noscripts, cli) (push) Has been cancelled Details
build / build (RelWithDebInfo, macos-latest, lua, gui) (push) Has been cancelled Details
build / build (RelWithDebInfo, ubuntu-latest, lua, gui) (push) Has been cancelled Details
build / build (RelWithDebInfo, windows-latest, lua, gui) (push) Has been cancelled Details
2025-07-14 23:17:25 -03:00
David Capello 11a7b061ff Remove unused var 2025-07-14 20:24:32 -03:00
David Capello 283bedf77e Add pinned/recent folders to export file popup menus
build / build (Debug, macos-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, macos-latest, noscripts, cli) (push) Has been cancelled Details
build / build (Debug, ubuntu-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, ubuntu-latest, noscripts, cli) (push) Has been cancelled Details
build / build (Debug, windows-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, windows-latest, noscripts, cli) (push) Has been cancelled Details
build / build (RelWithDebInfo, macos-latest, lua, gui) (push) Has been cancelled Details
build / build (RelWithDebInfo, ubuntu-latest, lua, gui) (push) Has been cancelled Details
build / build (RelWithDebInfo, windows-latest, lua, gui) (push) Has been cancelled Details
Related to https://community.aseprite.org/t/25920
2025-07-10 18:55:28 -03:00
David Capello 2eeb6f04a7 Fix "buttononly" bool attribute for <filename> widget 2025-07-10 18:13:10 -03:00
David Capello 706d0b8a7a Add possibility to select export file names w/"one click"
It's not with one click, it requires dragging the mouse but it's
better than two clicks.

Related to https://community.aseprite.org/t/25920
2025-07-10 18:12:38 -03:00
David Capello 2f3a7f5dec Update to new laf API: setTranslateDeadKeys -> setTextInput
build / build (Debug, macos-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, macos-latest, noscripts, cli) (push) Waiting to run Details
build / build (Debug, ubuntu-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, ubuntu-latest, noscripts, cli) (push) Waiting to run Details
build / build (Debug, windows-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, windows-latest, noscripts, cli) (push) Waiting to run Details
build / build (RelWithDebInfo, macos-latest, lua, gui) (push) Waiting to run Details
build / build (RelWithDebInfo, ubuntu-latest, lua, gui) (push) Waiting to run Details
build / build (RelWithDebInfo, windows-latest, lua, gui) (push) Waiting to run Details
2025-07-10 16:06:03 -03:00
David Capello d5de74b715 Update laf module
build / build (Debug, macos-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, macos-latest, noscripts, cli) (push) Waiting to run Details
build / build (Debug, ubuntu-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, ubuntu-latest, noscripts, cli) (push) Waiting to run Details
build / build (Debug, windows-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, windows-latest, noscripts, cli) (push) Waiting to run Details
build / build (RelWithDebInfo, macos-latest, lua, gui) (push) Waiting to run Details
build / build (RelWithDebInfo, ubuntu-latest, lua, gui) (push) Waiting to run Details
build / build (RelWithDebInfo, windows-latest, lua, gui) (push) Waiting to run Details
build-auto / build-auto (Debug, macos-latest) (push) Has been cancelled Details
build-auto / build-auto (Debug, ubuntu-latest) (push) Has been cancelled Details
build-auto / build-auto (Debug, windows-latest) (push) Has been cancelled Details
build-auto / build-auto (RelWithDebInfo, macos-latest) (push) Has been cancelled Details
build-auto / build-auto (RelWithDebInfo, ubuntu-latest) (push) Has been cancelled Details
build-auto / build-auto (RelWithDebInfo, windows-latest) (push) Has been cancelled Details
2025-07-10 08:52:01 -03:00
David Capello 2d87a7b184 [ui] Fix drawing cursor at the end of the Entry/Combobox field
build / build (Debug, macos-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, macos-latest, noscripts, cli) (push) Has been cancelled Details
build / build (Debug, ubuntu-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, ubuntu-latest, noscripts, cli) (push) Has been cancelled Details
build / build (Debug, windows-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, windows-latest, noscripts, cli) (push) Has been cancelled Details
build / build (RelWithDebInfo, macos-latest, lua, gui) (push) Has been cancelled Details
build / build (RelWithDebInfo, ubuntu-latest, lua, gui) (push) Has been cancelled Details
build / build (RelWithDebInfo, windows-latest, lua, gui) (push) Has been cancelled Details
Regression introduced in 1a6a39700e
2025-07-07 22:21:58 -03:00
Gaspar Capello 2f22804fe8 Fix GIF animations with semi-transparent colors (fix #5226)
Prior to this fix, animations were incorrectly converted to GIF when
the animation contained semi-transparent colors or backgrounds
(specifically, colors with alpha <= 128). Essentially, semi-transparent
pixels didn't repaint the pixel of the processed frame, meaning they
retained the color from the previous frame.
2025-07-07 17:43:19 -03:00
Gaspar Capello bf1b4c6f50 Fix session 'isRunning' detection (fix #5252)
Before this fix, sometimes files available for recovery aren't
displayed due to the coincidence of the pid number of a crashed
session with the current pid number of the current session. This
coincidence caused Aseprite to falsely detect that it was
the current session.
2025-07-07 17:15:36 -03:00
David Capello 250244c777 [ui] Fix possible crash when there is no TextBlob to paint (fix #5255)
build / build (Debug, macos-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, macos-latest, noscripts, cli) (push) Waiting to run Details
build / build (Debug, ubuntu-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, ubuntu-latest, noscripts, cli) (push) Waiting to run Details
build / build (Debug, windows-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, windows-latest, noscripts, cli) (push) Waiting to run Details
build / build (RelWithDebInfo, macos-latest, lua, gui) (push) Waiting to run Details
build / build (RelWithDebInfo, ubuntu-latest, lua, gui) (push) Waiting to run Details
build / build (RelWithDebInfo, windows-latest, lua, gui) (push) Waiting to run Details
2025-07-07 12:39:12 -03:00
David Capello b4555fc098 Add "Initial State" string for "Undo History" window to en.ini
build / build (Debug, macos-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, macos-latest, noscripts, cli) (push) Has been cancelled Details
build / build (Debug, ubuntu-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, ubuntu-latest, noscripts, cli) (push) Has been cancelled Details
build / build (Debug, windows-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, windows-latest, noscripts, cli) (push) Has been cancelled Details
build / build (RelWithDebInfo, macos-latest, lua, gui) (push) Has been cancelled Details
build / build (RelWithDebInfo, ubuntu-latest, lua, gui) (push) Has been cancelled Details
build / build (RelWithDebInfo, windows-latest, lua, gui) (push) Has been cancelled Details
2025-07-03 11:18:21 -03:00
Gaspar Capello 8783135bf7 Fix convert_image_to_surface function (fix #5257)
build / build (Debug, macos-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, macos-latest, noscripts, cli) (push) Waiting to run Details
build / build (Debug, ubuntu-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, ubuntu-latest, noscripts, cli) (push) Waiting to run Details
build / build (Debug, windows-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, windows-latest, noscripts, cli) (push) Waiting to run Details
build / build (RelWithDebInfo, macos-latest, lua, gui) (push) Waiting to run Details
build / build (RelWithDebInfo, ubuntu-latest, lua, gui) (push) Waiting to run Details
build / build (RelWithDebInfo, windows-latest, lua, gui) (push) Waiting to run Details
Before this fix, 'convert_image_to_surface' would generate saturated
colors when converting semi-transparent colors. This happened because
 Skia Surfaces assumed colors with pre-multiplied alpha.
2025-07-02 20:44:33 -03:00
David Capello 1a6a39700e Fix suffix separation in Entry fields w/TTF fonts (fix #5261) 2025-07-02 20:43:17 -03:00
David Capello ce742bcbc1 Fix typo in GitHub profile URL
build / build (Debug, macos-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, macos-latest, noscripts, cli) (push) Waiting to run Details
build / build (Debug, ubuntu-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, ubuntu-latest, noscripts, cli) (push) Waiting to run Details
build / build (Debug, windows-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, windows-latest, noscripts, cli) (push) Waiting to run Details
build / build (RelWithDebInfo, macos-latest, lua, gui) (push) Waiting to run Details
build / build (RelWithDebInfo, ubuntu-latest, lua, gui) (push) Waiting to run Details
build / build (RelWithDebInfo, windows-latest, lua, gui) (push) Waiting to run Details
2025-07-01 21:44:51 -03:00
David Capello 3c350c3e67 Update laf module
build-auto / build-auto (Debug, macos-latest) (push) Has been cancelled Details
build-auto / build-auto (Debug, ubuntu-latest) (push) Has been cancelled Details
build-auto / build-auto (Debug, windows-latest) (push) Has been cancelled Details
build-auto / build-auto (RelWithDebInfo, macos-latest) (push) Has been cancelled Details
build-auto / build-auto (RelWithDebInfo, ubuntu-latest) (push) Has been cancelled Details
build-auto / build-auto (RelWithDebInfo, windows-latest) (push) Has been cancelled Details
build / build (Debug, macos-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, macos-latest, noscripts, cli) (push) Has been cancelled Details
build / build (Debug, ubuntu-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, ubuntu-latest, noscripts, cli) (push) Has been cancelled Details
build / build (Debug, windows-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, windows-latest, noscripts, cli) (push) Has been cancelled Details
build / build (RelWithDebInfo, macos-latest, lua, gui) (push) Has been cancelled Details
build / build (RelWithDebInfo, ubuntu-latest, lua, gui) (push) Has been cancelled Details
build / build (RelWithDebInfo, windows-latest, lua, gui) (push) Has been cancelled Details
2025-06-25 08:20:50 -03:00
David Capello 220d2d3a2d Update laf module
build-auto / build-auto (Debug, macos-latest) (push) Has been cancelled Details
build-auto / build-auto (Debug, ubuntu-latest) (push) Has been cancelled Details
build-auto / build-auto (Debug, windows-latest) (push) Has been cancelled Details
build-auto / build-auto (RelWithDebInfo, macos-latest) (push) Has been cancelled Details
build-auto / build-auto (RelWithDebInfo, ubuntu-latest) (push) Has been cancelled Details
build-auto / build-auto (RelWithDebInfo, windows-latest) (push) Has been cancelled Details
build / build (Debug, macos-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, macos-latest, noscripts, cli) (push) Has been cancelled Details
build / build (Debug, ubuntu-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, ubuntu-latest, noscripts, cli) (push) Has been cancelled Details
build / build (Debug, windows-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, windows-latest, noscripts, cli) (push) Has been cancelled Details
build / build (RelWithDebInfo, macos-latest, lua, gui) (push) Has been cancelled Details
build / build (RelWithDebInfo, ubuntu-latest, lua, gui) (push) Has been cancelled Details
build / build (RelWithDebInfo, windows-latest, lua, gui) (push) Has been cancelled Details
2025-06-24 11:16:06 -03:00
Martín Capello 322040c4fb Recover Windows Vista compatibility (fix #5211) 2025-06-24 10:10:55 -03:00
David Capello ee69a2f2f6 Fix baseline alignment of file list items/names w/multiple fonts/emojis
build-auto / build-auto (Debug, macos-latest) (push) Waiting to run Details
build-auto / build-auto (Debug, ubuntu-latest) (push) Waiting to run Details
build-auto / build-auto (Debug, windows-latest) (push) Waiting to run Details
build-auto / build-auto (RelWithDebInfo, macos-latest) (push) Waiting to run Details
build-auto / build-auto (RelWithDebInfo, ubuntu-latest) (push) Waiting to run Details
build-auto / build-auto (RelWithDebInfo, windows-latest) (push) Waiting to run Details
build / build (Debug, macos-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, macos-latest, noscripts, cli) (push) Waiting to run Details
build / build (Debug, ubuntu-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, ubuntu-latest, noscripts, cli) (push) Waiting to run Details
build / build (Debug, windows-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, windows-latest, noscripts, cli) (push) Waiting to run Details
build / build (RelWithDebInfo, macos-latest, lua, gui) (push) Waiting to run Details
build / build (RelWithDebInfo, ubuntu-latest, lua, gui) (push) Waiting to run Details
build / build (RelWithDebInfo, windows-latest, lua, gui) (push) Waiting to run Details
2025-06-23 23:03:16 -03:00
David Capello 91f8410749 Fix bug in news items when multiple fonts are needed (fix #5221) 2025-06-23 22:49:05 -03:00
Gaspar Capello 8d5534d4eb Fix do not move the pivot when dragging a selection with Alt key to snap to grid (fix #5238) 2025-06-23 18:54:32 -03:00
David Capello 2ee8c68d94 Update laf module (fix #5240) 2025-06-23 17:56:38 -03:00
David Capello f7040190cc Fix implicit conversion of nullptr constant to 'bool'
build / build (Debug, macos-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, macos-latest, noscripts, cli) (push) Waiting to run Details
build / build (Debug, ubuntu-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, ubuntu-latest, noscripts, cli) (push) Waiting to run Details
build / build (Debug, windows-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, windows-latest, noscripts, cli) (push) Waiting to run Details
build / build (RelWithDebInfo, macos-latest, lua, gui) (push) Waiting to run Details
build / build (RelWithDebInfo, ubuntu-latest, lua, gui) (push) Waiting to run Details
build / build (RelWithDebInfo, windows-latest, lua, gui) (push) Waiting to run Details
2025-06-23 09:12:36 -03:00
David Capello 68bf0839aa Don't use userConfigPath to output automated test files 2025-06-23 09:08:02 -03:00
Necronomison e5917389cb
Export user & extension defined properties (fix #5186, #5187) 2025-06-23 09:06:05 -03:00
LeSnow-Ye 27eecb3bdc Greedy merge pixels on saving to SVG formats
build / build (Debug, macos-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, macos-latest, noscripts, cli) (push) Has been cancelled Details
build / build (Debug, ubuntu-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, ubuntu-latest, noscripts, cli) (push) Has been cancelled Details
build / build (Debug, windows-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, windows-latest, noscripts, cli) (push) Has been cancelled Details
build / build (RelWithDebInfo, macos-latest, lua, gui) (push) Has been cancelled Details
build / build (RelWithDebInfo, ubuntu-latest, lua, gui) (push) Has been cancelled Details
build / build (RelWithDebInfo, windows-latest, lua, gui) (push) Has been cancelled Details
2025-06-20 10:15:06 -03:00
David Capello b6cbeefb6e [lua] Update scripting API version to 34 2025-06-20 10:00:33 -03:00
Christian Kaiser 5596c3270d Add blendMode, name, opacity and visibility Sprite layer events 2025-06-20 09:58:09 -03:00
David Capello ab29b84f25 Fix crash accessing null extra cel when rendering interactive text (fix #5227)
build / build (Debug, macos-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, macos-latest, noscripts, cli) (push) Has been cancelled Details
build / build (Debug, ubuntu-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, ubuntu-latest, noscripts, cli) (push) Has been cancelled Details
build / build (Debug, windows-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, windows-latest, noscripts, cli) (push) Has been cancelled Details
build / build (RelWithDebInfo, macos-latest, lua, gui) (push) Has been cancelled Details
build / build (RelWithDebInfo, ubuntu-latest, lua, gui) (push) Has been cancelled Details
build / build (RelWithDebInfo, windows-latest, lua, gui) (push) Has been cancelled Details
2025-06-20 09:51:04 -03:00
David Capello 444ef0f6b4 Update laf (fix #5233)
build / build (Debug, macos-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, macos-latest, noscripts, cli) (push) Waiting to run Details
build / build (Debug, ubuntu-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, ubuntu-latest, noscripts, cli) (push) Waiting to run Details
build / build (Debug, windows-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, windows-latest, noscripts, cli) (push) Waiting to run Details
build / build (RelWithDebInfo, macos-latest, lua, gui) (push) Waiting to run Details
build / build (RelWithDebInfo, ubuntu-latest, lua, gui) (push) Waiting to run Details
build / build (RelWithDebInfo, windows-latest, lua, gui) (push) Waiting to run Details
build-auto / build-auto (Debug, macos-latest) (push) Has been cancelled Details
build-auto / build-auto (Debug, ubuntu-latest) (push) Has been cancelled Details
build-auto / build-auto (Debug, windows-latest) (push) Has been cancelled Details
build-auto / build-auto (RelWithDebInfo, macos-latest) (push) Has been cancelled Details
build-auto / build-auto (RelWithDebInfo, ubuntu-latest) (push) Has been cancelled Details
build-auto / build-auto (RelWithDebInfo, windows-latest) (push) Has been cancelled Details
2025-06-19 19:38:50 -03:00
David Capello b3b956516b Fix themes loading custom TTF fonts without specifying a size (fix #5229)
build / build (Debug, macos-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, macos-latest, noscripts, cli) (push) Has been cancelled Details
build / build (Debug, ubuntu-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, ubuntu-latest, noscripts, cli) (push) Has been cancelled Details
build / build (Debug, windows-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, windows-latest, noscripts, cli) (push) Has been cancelled Details
build / build (RelWithDebInfo, macos-latest, lua, gui) (push) Has been cancelled Details
build / build (RelWithDebInfo, ubuntu-latest, lua, gui) (push) Has been cancelled Details
build / build (RelWithDebInfo, windows-latest, lua, gui) (push) Has been cancelled Details
2025-06-13 18:22:00 -03:00
David Capello 32bf699655 Mitigate Linux/X11 lag when resizing windows (#5028)
build-auto / build-auto (Debug, macos-latest) (push) Has been cancelled Details
build-auto / build-auto (Debug, ubuntu-latest) (push) Has been cancelled Details
build-auto / build-auto (Debug, windows-latest) (push) Has been cancelled Details
build-auto / build-auto (RelWithDebInfo, macos-latest) (push) Has been cancelled Details
build-auto / build-auto (RelWithDebInfo, ubuntu-latest) (push) Has been cancelled Details
build-auto / build-auto (RelWithDebInfo, windows-latest) (push) Has been cancelled Details
build / build (Debug, macos-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, macos-latest, noscripts, cli) (push) Has been cancelled Details
build / build (Debug, ubuntu-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, ubuntu-latest, noscripts, cli) (push) Has been cancelled Details
build / build (Debug, windows-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, windows-latest, noscripts, cli) (push) Has been cancelled Details
build / build (RelWithDebInfo, macos-latest, lua, gui) (push) Has been cancelled Details
build / build (RelWithDebInfo, ubuntu-latest, lua, gui) (push) Has been cancelled Details
build / build (RelWithDebInfo, windows-latest, lua, gui) (push) Has been cancelled Details
In relation to these findings:
https://github.com/aseprite/aseprite/pull/5166#issuecomment-2944585171
https://github.com/aseprite/aseprite/pull/5166#issuecomment-2945369914
2025-06-11 17:30:00 -03:00
David Capello 5ceeac2f26 Add possibility to disable hinting for theme ttf/otf fonts (fix #5215) 2025-06-11 17:20:17 -03:00
David Capello 0ddf7d939b [ui] Align text with different fonts correctly to ui::Entry baseline
Regression introduced in af6e8b65c3
2025-06-11 17:06:55 -03:00
David Capello bd13e5d574 Fix bug w/user themes with odd size value for the Aseprite font 2025-06-11 15:45:23 -03:00
David Capello e53aa99080 Possible fix to crashes using the FontEntry widget (fix #5214) 2025-06-11 15:42:03 -03:00
David Capello af6e8b65c3 Fix default font for CJK and other translations (fix #5210)
Now we use the correct fallback font with its size for non-existent
glyph in the sprite sheet font.
2025-06-11 14:40:56 -03:00
Martín Capello 68342bdb66 Call parent's class onOpen (fix #5209)
This makes the window's Open signal to be triggered as usual
2025-06-11 12:57:07 -03:00
David Capello 8ff208d8d5 Fix warnings about unused var
build / build (Debug, macos-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, macos-latest, noscripts, cli) (push) Waiting to run Details
build / build (Debug, ubuntu-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, ubuntu-latest, noscripts, cli) (push) Waiting to run Details
build / build (Debug, windows-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, windows-latest, noscripts, cli) (push) Waiting to run Details
build / build (RelWithDebInfo, macos-latest, lua, gui) (push) Waiting to run Details
build / build (RelWithDebInfo, ubuntu-latest, lua, gui) (push) Waiting to run Details
build / build (RelWithDebInfo, windows-latest, lua, gui) (push) Waiting to run Details
2025-06-11 10:58:12 -03:00
David Capello 2bc4f0582d Fix crash (and show error message) when default font is nullptr (fix #5208)
build / build (Debug, macos-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, macos-latest, noscripts, cli) (push) Waiting to run Details
build / build (Debug, ubuntu-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, ubuntu-latest, noscripts, cli) (push) Waiting to run Details
build / build (Debug, windows-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, windows-latest, noscripts, cli) (push) Waiting to run Details
build / build (RelWithDebInfo, macos-latest, lua, gui) (push) Waiting to run Details
build / build (RelWithDebInfo, ubuntu-latest, lua, gui) (push) Waiting to run Details
build / build (RelWithDebInfo, windows-latest, lua, gui) (push) Waiting to run Details
Probably an edge-case for users that are creating new themes.
2025-06-10 22:02:12 -03:00
David Capello 2be4dc1474 Revert part of "Startup optimizations (#5090)" (fix #5207)
This reverts part of commit b130601716.
2025-06-10 21:19:37 -03:00
David Capello 2b522e222b Rename ui::Accelerator to ui::Shortcut
This was a pending refactor, where "user.aseprite-keys" files were
already using the "shortcut" attribute (instead of "accelerator").
This will include a refactor in the Weblate projects/all translations
to change [select_accelerator] section to [select_shortcut]. But that
must be coordinated after this commit is merged.
2025-06-09 17:20:16 -03:00
Maplegecko 698d79b049 [lua] Make Dialog:separator more in line with other widgets (fix #4989) 2025-06-09 13:26:39 -03:00
David Capello 03422e7251 [lua] Update scripting API version to 33 2025-06-07 12:08:00 -03:00
David Capello 3f1f131a39 Update laf 2025-06-07 12:05:56 -03:00
Christian Kaiser 54ea61fe58 Re-add os.rename and os.remove support 2025-06-07 12:05:34 -03:00
JoshuaL03 4c31c950c5
Fix file dialog size not being loaded properly (fix #4460) (#5202) 2025-06-07 11:30:27 -03:00
martincapello afbd28b3b4 Improve panel resizing performance
By avoiding calculating bounds for HIDDEN panel's children.
2025-06-05 11:11:20 -03:00
Joshua Lopez 1519589184 Fix user data visibility after window size reset (fix aseprite#4923) 2025-06-04 13:37:38 -03:00
Luke Barcenas 2c917e30c0 Fix: Prevent scrollbar from shifting on click 2025-06-03 16:54:42 -03:00
Gaspar Capello 5d0214a89d Fix wrong export of tileset (fix #5053)
Before this fix, when a sprite's color mode was set to Grayscale and
a tileset was exported, the resulting sheet was full of broken
tile images due to a misinterpretation of the pixel format in
the samples.

An unnecessary conversion of the original sprite was also observed
during the "Export Sprite Sheet" command. Specifically,
in the DocExporter::renderTexture function (fix #5088).
2025-06-03 13:19:56 -03:00
David Capello 4b1d49f5dc [ci][clang-tidy] Update clang-tidy-review version
We require the following fix: https://github.com/ZedThree/clang-tidy-review/issues/144
2025-06-02 22:24:42 -03:00
David Capello 0ccc800819 [clang-tidy] Allow if (intCondition) { } to ask for != 0 2025-06-02 20:44:17 -03:00
David Capello 14c0baa3db Convert standalone functions into snake_case 2025-06-02 19:50:05 -03:00
Martín Capello 30dcac99c6 Update copyright's year 2025-06-02 19:45:37 -03:00
Martín Capello d209971f07 Improve feedback when dropping into a cel
Show indicator to let the user know between which layers will the
dropped stuff be inserted
2025-06-02 19:45:37 -03:00
Martín Capello 0a88b86c99 Improve wording and linkage of some functions 2025-06-02 19:45:37 -03:00
Martín Capello ab449a2978 [win] Fix compilation when not using skia backend 2025-06-02 19:45:37 -03:00
Martín Capello b32cd0ff47 Avoid creating surface to determine color mode 2025-06-02 19:45:37 -03:00
Martín Capello ce0b9a6405 Fix tileset addition into destination sprite
Now the tileset addition is made using a command, which allows it to be
undone/redone properly
2025-06-02 19:45:37 -03:00
Martín Capello 67656c4977 Fix crash dropping elements at edge of bottom cel 2025-06-02 19:45:37 -03:00
Martín Capello 7817e7b37a Fix frame displacement of dropped layers 2025-06-02 19:45:37 -03:00
Martín Capello 45fbeda95b Avoid enqueuing events directly to laf-os 2025-06-02 19:45:37 -03:00
Martín Capello a3236bc1e9 Remove ui::Manager as friend of ui::Widget 2025-06-02 19:45:37 -03:00
Martín Capello d37e0df18f Replace use of reset(new...) by std::make_unique() 2025-06-02 19:45:37 -03:00
Martín Capello 7103829e60 Refactor DropOnTimeline command 2025-06-02 19:45:37 -03:00
Martín Capello eab8df6854 Support duplicating layers from other documents
Update DocApi::duplicateLayerAfter and DocApi::duplicateLayerBefore to
allow duplicating layers from documents that are not the same as the
source layer's document
2025-06-02 19:45:37 -03:00
Martín Capello 99a407f0c5 Move OpenFileJob impl from header to cpp file 2025-06-02 19:45:37 -03:00
David Capello 66123e9d57 Update flic module 2025-05-29 13:39:05 -03:00
David Capello f1b6dd8594 [lua] Fix regression overwriting path specified in Dialog:file{filename} (fix #5061)
If no 'basepath' is specified and the 'filename' argument has a path,
we must use that path as 'basepath' to keep backward compatibility
with the previous behavior of Dialog:file{}.
2025-05-22 14:39:36 -03:00
David Capello 79de4da82a Update laf module 2025-05-22 09:06:35 -03:00
David Capello 9c3f985ee5 [build] Remove xargs and echo -n (fix #5179?)
This is a test to check if "echo -n" and "xargs" are necessary.
2025-05-21 21:28:24 -03:00
Reese Rivers 2cb42b343f Add missing Esperanto accents (ŜŝŬŭ) 2025-05-21 13:56:51 -03:00
Gaspar Capello 38b5f3b283 Fix in Export As dialog the '-export' string never included (fix #5035) 2025-05-19 18:34:58 -03:00
David Capello 41a8249afd New AUTHORS file 2025-05-11 12:14:01 -03:00
David Capello 5dae7e203f Add a summary of open source projects in LICENSES file 2025-05-11 10:26:35 -03:00
David Capello d8e8074345 Fix some ToolBar issues calculating the required min height
* The calculation was moved to onResize() event (when bounds are set)
  instead of kPaintMessage
* All groups can be collapsed: in case the available space is so
  small that we can only show one button to expand all tools
* Don't calculate the min height using the "lastToolBounds" absolute
  position, we have to adjust that coordinate with the ToolBar origin
* Make the min height calculation a little more accurate
2025-05-09 21:51:26 -03:00
David Capello 95d65d8163 Update json11 module (#5158) 2025-05-07 17:09:42 -03:00
David Capello a8e190a133 [ui] Fit main menu bar in main window width 2025-05-01 15:35:14 -03:00
David Capello 7c74619c94 Update building instructions
Update SDK versions, use libstdc++ on Linux (as we're only pre-compiling
Skia with libstdc++), add some initial information about build.sh
script.
2025-04-29 12:17:41 -03:00
David Capello 5678086310 Update laf module 2025-04-28 19:23:40 -03:00
David Capello 8158345cea Allow to use the close button when a popup window/menu box is displayed (fix #5111, #5134) 2025-04-28 19:22:54 -03:00
David Capello 06d3bbf953 Integrate fixup_image_transparent_colors() in resize_image() (#5048)
With this patch we've even fixed a couple of bugs:

1. In resize_image() where fixup_image_transparent_colors() was being
   called in the new image instead of the source image.

2. When a bilinear resize was done to a tileset in SpriteSizeCommand,
   each tile was being resized directly without calling
   fixup_image_transparent_colors().
2025-04-24 20:58:16 -03:00
lightovernight 6aabfef0b8 Fix Un-replaceable transparent pixels created by resize (fix #5032, #5048) 2025-04-24 20:37:11 -03:00
David Capello 206065fb80 Add a way to change default Timeline options
Fixes https://community.aseprite.org/t/19863
Related to #5083 / https://community.aseprite.org/t/25097
and #1485 in some way, although we've opted to avoid moving these
options to the Preferences dialog as it's quite a big refactor.
2025-04-24 19:38:25 -03:00
cybardev 90be6aac30 [build] Use local .deps directory for users (fix #4998)
For an user setup we'd prefer to download Skia inside a .deps
directory (just to simplify the setup). For developers it's better if
we offer a common/shared/absolute directory so different local
Aseprite clones can share the same downloaded Skia version.

Co-authored-by: David Capello <david@igara.com>
2025-04-24 19:34:09 -03:00
David Capello 600882352e Avoid warning using std::stable_sort() from gcc/clang 2025-04-22 22:23:09 -03:00
David Capello aca46a28c5 Remove unused variables 2025-04-22 21:59:21 -03:00
David Capello b099d8f780 Fix initialization order of DelayedMouseMove members 2025-04-22 21:58:27 -03:00
David Capello 378f7ac6c2 Fix small int type for the given kPinnedLimit value 2025-04-22 21:57:48 -03:00
Martín Capello 3bc84cca53 Fix timeline scrolling when creating layer
Fix #4930
2025-04-22 21:54:22 -03:00
Gaspar Capello 3549d3538f Fix regression with timeline thumbnails (fix #5083)
This fix adds an option to scale timeline thumbnails to fill
the entire cell, or simply leave the timeline thumbnails at 1:1 scale
as before issue #4974.
2025-04-22 20:18:21 -03:00
Christian Kaiser 39d69ac8cf Palette picker pinning, loading speed, misc improvements (fix #2365) 2025-04-22 12:45:56 -03:00
Martín Capello ba5adcaa7d Change uuidsForLayers by useLayerUuids 2025-04-22 12:42:12 -03:00
Martín Capello 9e35fd817a [lua] Add uuid field to layers (fix #5033) 2025-04-22 12:42:12 -03:00
David Capello 65c2ed6a35 [build] Use platform.sh file after checking submodules
As this script is part of laf submodule, we have to check the existence
of submodules first, and then run the script.

We've also moved the cl.exe check to build.sh directly.
2025-04-22 07:58:34 -03:00
David Capello c59f1825be Remove extra whitespace between in copyright lines 2025-04-21 19:41:02 -03:00
Gaspar Capello 7f07becd74 Fix cel.image:clear() cannot be undone (fix #5015) 2025-04-21 19:39:32 -03:00
Gaspar Capello fdc9b2f000 Fix symmetry button is kept pressed when we didn't pressed (fix #4760)
This fix removes the 'non sense symmetry filter' to prevent
some buttons from being unintentionally held down.

Moved the drawing process for symmetry axes from
'Editor::drawSpriteUnclippedRect' to
'Editor::drawOneSpriteUnclippedRect' to allow semi-transparent axes.
This also produces axes on every tile in tile mode.

Pixel ratios other than 1:1 are now considered in the drawing logic of
diagonal axes.
2025-04-21 19:20:43 -03:00
David Capello 2e37ac9b83 [build] Don't use unsupported ${var,,} syntax on some shells (fix #5082) 2025-04-18 22:43:36 -03:00
David Capello 753d892af2 [build] read -N 1 is not supported on macOS bash 2025-04-18 22:43:18 -03:00
David Capello 8a8ddbc630 Improve performance loading list of fonts using an app::Task
We list the fonts in a background thread to fill the list of fonts in
the UI. And now we are inserting the fonts in alphabetical order.
2025-04-18 19:56:56 -03:00
David Capello 943c3b28df Merge branch 'main' into beta 2025-04-17 21:10:04 -03:00
David Capello d9a138357e Update modules 2025-04-17 20:34:07 -03:00
David Capello 978000a9dd Better support to use system fonts from themes
* There is a new system="" attribute for <font> elements
* New <font><windows ... /><macos ... /><linux /></font> elements to
  select platform specific fonts
* Fixed several bugs related to re-using fonts from the cache when
  customizing the current theme font from Edit > Preferences > Theme
* Removed Fonts::infoFromFont() adding FontInfo(FontData) constructor
2025-04-17 19:43:32 -03:00
David Capello b3f4e37b69 Add option to switch font hinting (fix #4931, aseprite/laf#138) 2025-04-11 17:26:03 -03:00
David Capello d8632b6208 Move misc/ scripts to laf library 2025-04-11 09:03:28 -03:00
David Capello 3c4d012210 [ci] Fix slow tests 2025-04-10 09:56:46 -03:00
David Capello d51a6d4f51 [ci] New build-auto job to test the build.sh script
This runs only when the build.sh (or some misc/ script) is modified.
2025-04-10 09:21:06 -03:00
David Capello 2c9eb2a801 New misc/skia-url.sh script to simplify downloading the required Skia branch 2025-04-10 09:08:06 -03:00
David Capello bae8520580 Update modules due cmake_minimum_required() issues (#5087, #5071) 2025-04-02 21:44:03 -03:00
David Capello 7167969963 [theme] Fix horizontal separator alignment 2025-04-02 09:32:34 -03:00
David Capello 537ccd393f Prevent polling keyboard state for each created ui::Message
Getting the keyboard state to fill the keyboard modifiers can be
expensive (mainly on Windows calling GetAsyncKeyState). So we can lazy
evaluate the modifiers when they are needed.
2025-04-02 08:00:11 -03:00
Christian Kaiser b130601716
Startup optimizations (#5090)
* Delay DitheringSelector startup
* Delay setting the drag target
* Delay & enqueue menu reloading
2025-04-02 07:59:52 -03:00
David Capello 816be744ac Add Widget::textBaseline() to fix several misalignments using scalable fonts
* Each widget can customize its text baseline (onGetTextBaseline()) to
  know where to draw text when it's vertically aligned to the middle
  (now more correctly "aligned to the baseline").
* Add PAINT_BASELINE to test where the baseline is on each widget.
* "Aseprite" and "Aseprite Mini" fonts now have a special
  descent/ascent configuration with a specific baseline position.
2025-03-27 18:22:51 -03:00
David Capello 50bccf85fc Add support to scale sprite sheet fonts
We've highlighted (with an "*") the sprite sheet font size, so it's
easy to select its default size.
2025-03-24 23:19:30 -03:00
David Capello 2ee4819bf9 Show link to go to the Themes section to customize the font for certain languages 2025-03-14 16:02:31 -03:00
David Capello 805d98e943 Fix font rendering issues in non-English languages (fix #4804)
Graphics::measureText() wasn't shaping text correctly using the
FontMgr to get more fonts when they were required. And now
SkinTheme::drawText() can use Widget::textSize() (the cached size of
the widget text blob) to calculate the required text size.
2025-03-13 16:20:11 -03:00
Martín Capello c68b4923f8 Prevent using an invalid drawing point (fix #5055) 2025-03-12 15:47:23 -03:00
David Capello 53c415c933 Fix entry height in ColorSliders when UI Scaling > 100% 2025-03-10 10:02:14 -03:00
David Capello d3265a1711 Fix UI vs Screen Scaling bugs w/window buttons and button sets/grids (fix #5043)
Includes:
* New ui::Style::rawMargin/Border/Padding() to detect what values are
  undefined, and ui::Style::margin/border/padding() to return normalized
  values (replacing kUndefinedSide with 0 when a value is not defined in
  the whole hierarchy of styles). With this change we avoid using a
  margin/border/padding value of -1 by mistake.
* New guiscaled_div() to calculate an integer division taking care the
  guiscale() for a scaled value.
* CALC_FOR_CENTER() renamed to guiscaled_center() and moved to ui/scale.h

There are still a lot of work to be done to fully fix these UI issues
between Screen Scaling=200%/UI Scaling=100% vs Screen Scaling=100%/UI
Scaling=200%
2025-03-09 22:01:55 -03:00
David Capello c949f4a5a6 Centralize defined fonts in new app::Fonts class 2025-03-04 13:54:15 -03:00
David Capello 2706d2d75a Move font related types to src/app/fonts 2025-03-03 22:36:11 -03:00
David Capello ce989684d0 Don't save custom theme fonts when we uncheck these options 2025-03-03 21:48:47 -03:00
David Capello da5909639b Use the new Surface::applyScale() 2025-03-03 16:42:03 -03:00
David Capello fc63532fef Ignore .vscode directory 2025-03-03 11:24:52 -03:00
David Capello be6d2251aa Merge branch 'main' into beta 2025-02-26 10:26:09 -03:00
David Capello 9378f44191 Show warning when raw cel format for .aseprite files is selected (#4901, #4951) 2025-02-26 10:22:36 -03:00
David Capello f7f93c64f2 [lua] Update scripting API version to 32 2025-02-26 09:38:31 -03:00
David Capello 28d31a0b41 Change background color of read-only ui::Entry fields 2025-02-26 09:13:38 -03:00
David Capello 1e96c4640f Fix indentation of layer UUID in Aseprite file format spec 2025-02-26 08:36:35 -03:00
Gaspar Capello e4b3981ca6 Fix when Slices are set to a semi-transparent color they become opaque as we draw. 2025-02-25 15:10:41 -03:00
Liebranca ed56011a0f Fix set_sat() blend function 2025-02-25 10:22:48 -03:00
lightovernight ad765723c9 Fix Straight line via SHIFT + Tiled mode starts at wrong position 2025-02-25 09:46:31 -03:00
Gaspar Capello 63f918cf2a Fix onionskin visiblity is not updated if cel is empty (fix #4969) 2025-02-24 22:11:15 -03:00
Gaspar Capello e17c3400fb Fix "Straight Line from Last Point” bug in Tilemaps (fix #4623)
Prior to this fix, when the following conditions were met:
- On a tilemap layer
- Tilemap mode = OFF
- Tool = Pencil
- Tileset mode = Manual
- Modifying an existing tile with the "quick line"
  (i.e. holding down the SHIFT key)
resulted in incorrect tool behavior.
2025-02-24 21:56:36 -03:00
Martín Capello fa3fd501e0 Read and write layer's uuid as last element 2025-02-24 16:36:39 -03:00
Martín Capello 6580580e4e Replace <iostream> by <iosfwd> 2025-02-24 15:14:20 -03:00
Martín Capello 7454ec2d06 Rename m_useUuidsForLayers by m_uuidsForLayers 2025-02-24 15:14:14 -03:00
Martín Capello 9e69df53d1 Add assert when setting a layer's UUID 2025-02-24 14:58:28 -03:00
Martín Capello efc2a308b2 Fix includes order 2025-02-24 11:27:05 -03:00
Martín Capello dd644865cb Fix m_uuid field's comment 2025-02-24 11:23:39 -03:00
Martín Capello 7a03e45475 Generate UUIDs for Layers lazily 2025-02-24 11:12:54 -03:00
Martín Capello d398bd7a2a Replace "" by std::string() 2025-02-24 10:48:55 -03:00
Martín Capello 2071e465a1 Replace label by entry to show the layer's UUID 2025-02-24 10:47:24 -03:00
Martín Capello 7ced9af5d1 Reword some "UUIDs for layers" related text 2025-02-24 10:47:17 -03:00
Martín Capello c3cfae666b Add io part for layers UUIDs 2025-02-24 10:14:33 -03:00
Martín Capello 86ad09291f Add UUIDs to layers 2025-02-24 10:10:28 -03:00
David Capello 5739bfe287 Fix crash canceling "Apply" filter and then using "OK"
This fixes the ASSERT(!m_tx) in FilterManagerImpl::initTransaction()
in Debug mode, and a crash in Release that happens in any filter if we
cancel a filter progress in the middle, and then press the "OK"
button.
2025-02-20 12:23:31 -03:00
Gaspar Capello f2b870a17f Fix image:drawImage+BlendMode.SRC doesn't draw mask pixels (fix #5001)
Also added tests for Image:drawImage + BlendMode::SRC + ColorMode.RGBA
2025-02-20 12:14:04 -03:00
David Capello 919f4f3321 Update laf module 2025-02-19 17:35:13 -03:00
David Capello a4e0636c9f [lua] don't allow to set invalid pixel ratios (fix #3285) 2025-02-19 17:19:27 -03:00
Gaspar Capello 26f6a210b6 Fix crash with custom pixel ratios (e.g. Size(4, 3)) (fix #4632)
Prior this fix some custom pixel ratios + old render engine +
zoom level <= 50% resulted in crashes.
2025-02-19 15:47:16 -03:00
David Capello b7967a078e Select the default theme font when clicking custom font check boxes 2025-02-15 13:04:49 -03:00
David Capello 698c581c39 Fix FontEntry/::FontFace (SearchEntry) look when it's disabled 2025-02-15 12:58:25 -03:00
David Capello d4406629e6 Add possibility to customize theme fonts (#712, #4307)
From Edit > Preferences > Themes we now can customize the theme Font
and Mini Font.
2025-02-15 12:58:25 -03:00
David Capello bc3433fcf2 Add new ui::TranslationDelegate to translate Entry popup items
Parts of this commit are from #4968 and will be useful to reuse in the
multiline TextEdit widget.

Co-authored-by: Christian Kaiser <info@ckaiser.com.ar>
2025-02-15 12:09:37 -03:00
Martín Capello 2e6d6cfb14 Avoid delayed filter preview start after stop 2025-02-12 17:17:01 -03:00
David Capello d5738fb492 Avoid capturing the mouse from widgets in background windows
This avoids clicking buttons that are not in the foreground/modal
window. At the same time the onBroadcastMouseMessage() functionality
was expanded in such a way that added widgets to the broadcast are the
only ones allowed to re-capture the mouse (even if they are not in the
current foreground window). This is required so the Editor can be
scrolled when we are visualizing a Filter window with preview.

New functions added to simplify some code:

* Manager::transferAsMouseDownMessage()
* Manager::allowCapture()
* base::contains()

Related to #4963 and #4973.
2025-02-12 11:01:59 -03:00
Gaspar Capello 3e3dd2a653 Fix timeline thumbnail zoom can't scale beyond 1:1 pixels (fix #4974)
Prior this fix when using large thumbnail sizes on the timeline with
smaller cel images, instead of enlarging the thumbnail image to fit
the full area available, it just adds transparent whitespace around
the thumbnail image.
2025-02-11 11:06:23 -03:00
443 changed files with 10016 additions and 4034 deletions

View File

@ -60,6 +60,8 @@ Checks: >
-readability-uppercase-literal-suffix
WarningsAsErrors: ''
CheckOptions:
- key: readability-implicit-bool-conversion.AllowIntegerConditions
value: true
- key: readability-implicit-bool-conversion.AllowPointerConditions
value: true
- key: misc-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic

43
.github/workflows/build-auto.yml vendored Normal file
View File

@ -0,0 +1,43 @@
name: build-auto
on:
push:
paths:
- '.github/workflows/build-auto.yml'
- 'build.sh'
- 'laf'
jobs:
build-auto:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [windows-latest, macos-latest, ubuntu-latest]
build_type: [RelWithDebInfo, Debug]
steps:
- uses: actions/checkout@v4
with:
submodules: 'recursive'
- name: Install Dependencies
if: runner.os == 'Linux'
shell: bash
run: |
sudo apt-get update -qq
sudo apt-get install -y \
libpixman-1-dev libfreetype6-dev libharfbuzz-dev zlib1g-dev \
libx11-dev libxcursor-dev libxi-dev libgl1-mesa-dev libfontconfig1-dev
- uses: aseprite/get-ninja@main
- uses: ilammy/msvc-dev-cmd@v1
if: runner.os == 'Windows'
- name: Building
shell: bash
run: |
bash build.sh --auto --norun
- name: Running CLI Tests
shell: bash
run: |
if [[ "${{ runner.os }}" == "Linux" ]] ; then
export XVFB=xvfb-run
fi
export ASEPRITE=$PWD/build/bin/aseprite
cd tests
$XVFB bash run-tests.sh

View File

@ -34,16 +34,14 @@ jobs:
shell: bash
run: |
if [[ "${{ runner.os }}" == "Windows" ]] ; then
choco install wget -y --no-progress
wget https://github.com/aseprite/skia/releases/download/m124-08a5439a6b/Skia-Windows-Release-x64.zip
unzip Skia-Windows-Release-x64.zip -d skia
elif [[ "${{ runner.os }}" == "macOS" ]] ; then
wget https://github.com/aseprite/skia/releases/download/m124-08a5439a6b/Skia-macOS-Release-arm64.zip
unzip Skia-macOS-Release-arm64.zip -d skia
this_dir=$(cygpath "${{ github.workspace }}")
else
wget https://github.com/aseprite/skia/releases/download/m124-08a5439a6b/Skia-Linux-Release-x64.zip
unzip Skia-Linux-Release-x64.zip -d skia
this_dir="${{ github.workspace }}"
fi
skia_url=$(source $this_dir/laf/misc/skia-url.sh | xargs)
skia_file=$(basename $skia_url)
curl --ssl-revoke-best-effort -L -o "$skia_file" "$skia_url"
unzip "$skia_file" -d skia
- name: ccache
uses: hendrikmuhs/ccache-action@v1.2.17
if: ${{ runner.os == 'Linux' || runner.os == 'macOS' }}

View File

@ -13,6 +13,6 @@ jobs:
post-comments:
runs-on: ubuntu-latest
steps:
- uses: ZedThree/clang-tidy-review/post@v0.20.1
- uses: ZedThree/clang-tidy-review/post@v0.21.0
with:
token: ${{ secrets.CLANG_TIDY_TOKEN }}

2
.gitignore vendored
View File

@ -12,7 +12,9 @@
*.res
.DS_Store
.vs
.vscode
tests/_test*
build
.build
.deps
CMakeSettings.json

98
AUTHORS.md Normal file
View File

@ -0,0 +1,98 @@
# Credits
Aseprite is being developed and maintained currently by [Igara Studio](https://igara.com/).
The active team of developers is:
* [David Capello](https://github.com/dacap)
* [Gaspar Capello](https://github.com/Gasparoken)
* [Martín Capello](https://github.com/martincapello)
* [Christian Kaiser](https://github.com/ckaiser)
* [Dante Paola](https://github.com/Liebranca)
Previous team members that contributed with code/docs/scripts/graphics:
* [Kacper Woźniak](https://github.com/thkwznk)
* [Joshua Ogunyinka](https://github.com/iamOgunyinka)
* [David Campo](https://github.com/dncampo)
## Translations
The translation work of Aseprite is only possible thanks to the
contribution, help, and good will of several translators coordinated
through our Weblate project:
* [Translation Credits](strings/README.md)
## Graphics
Aseprite logo was created by David Capello. Graphics used as background
of [Aseprite home page](https://www.aseprite.org),
on [Steam Store](https://store.steampowered.com/app/431730/Aseprite/),
and [social media channels](https://bsky.app/profile/aseprite.org),
were created by:
* [Ilija Melentijevic](https://ilkke.net/)
## Themes
The default Aseprite font was created by David Capello, and the
default Aseprite theme was introduced in v0.8, originally created by:
* Ilija Melentijevic
A modified dark version of this theme was introduced in v1.3-beta1, created by:
* [Nicolas Desilets](https://twitter.com/MapleGecko)
These themes are now being maintained by Igara Studio and external
contributors from time to time.
## Palettes
Aseprite includes color palettes created by:
* [Richard "DawnBringer" Fhager](http://pixeljoint.com/p/23821.htm), [DB16](http://pixeljoint.com/forum/forum_posts.asp?TID=12795), [DB32](http://pixeljoint.com/forum/forum_posts.asp?TID=16247) (default Aseprite color palette)
* [Arne Niklas Jansson](http://androidarts.com/), [16 colors](http://androidarts.com/palette/16pal.htm), [32 colors](http://wayofthepixel.net/index.php?topic=15824.msg144494)
* [ENDESGA Studios](https://twitter.com/ENDESGA), [EDG16 and EDG32](https://forums.tigsource.com/index.php?topic=46126.msg1279124#msg1279124), and [other palettes](https://twitter.com/ENDESGA/status/865812366931353600)
* [Hyohnoo Games](https://twitter.com/Hyohnoo), [mail24](https://twitter.com/Hyohnoo/status/797472587974639616) palette
* [Davit Masia](https://twitter.com/DavitMasia), [matriax8c](https://twitter.com/DavitMasia/status/834862452164612096) palette
* [Javier Guerrero](https://twitter.com/Xavier_Gd), [nyx8](https://twitter.com/Xavier_Gd/status/868519467864686594) palette
* [Adigun A. Polack](https://twitter.com/adigunpolack), [AAP-64](http://pixeljoint.com/pixelart/119466.htm), [AAP-Splendor128](http://pixeljoint.com/pixelart/120714.htm), [SimpleJPC-16](http://pixeljoint.com/pixelart/119844.htm), and [AAP-Micro12](http://pixeljoint.com/pixelart/121151.htm) palette
* [PineTreePizza](https://twitter.com/PineTreePizza), [Rosy-42](https://twitter.com/PineTreePizza/status/1006536191955623938) palette
## Pixel-art Features
Aseprite tries to replicate some pixel-art algorithms:
* [Shading Ink](https://aseprite.org/docs/shading/): created as a simplification of GrafX2 shade mode, thanks to Ilija Melentijevic for introducing me to this feature in 2009
* [RotSprite](http://forums.sonicretro.org/index.php?showtopic=8848&st=15&p=159754&#entry159754) by Xenowhirl.
* [Pixel perfect drawing algorithm](https://deepnight.net/blog/tools/pixel-perfect-drawing/)
by [Sébastien Bénard](https://twitter.com/deepnightfr) and
[Carduus](https://twitter.com/CarduusHimself/status/420554200737935361).
## Community
A special thanks to @Outlander for helping us moderating our [Discord server](https://discord.gg/Yb2CeX8).
Thanks to all the people that hung around for such a long time.
## Contributors
Thank you everyone who contributed to Aseprite with ideas, patches,
code, bug reports, new features, donations, tutorials, videos,
personal messages, chats, emails, tweets, posts, questions, libraries,
compilers, and any other tools that made this program possible today.
* Thanks to all [contributors](https://github.com/aseprite/aseprite/graphs/contributors)
* Thanks to all developers and maintainers behind [other open source projects](docs/LICENSES.md) used by Aseprite
* Thanks to all early PayPal donors and donors from our Pledgie Campaign (before Aseprite was commercialized)
* Thanks to every who support our business model: this source-available / sell-binaries combo
* Thanks to schools and [educational institutions](https://aseprite.org/educational)
that are using Aseprite in their classrooms <3
* Thanks to our family and friends who always support our work
It's been more years than I can remember, sorry if we missed someone,
please drop me a line to [david@igara.com](mailto:david@igara.com) to
fix something or say hi. We'll try to keep this updated (for past and
future contributors).
Sincerely, David.

View File

@ -243,7 +243,13 @@ if(USE_SHARED_LIBPNG)
add_definitions(${PNG_DEFINITIONS})
else()
set(PNG_FOUND ON)
set(PNG_LIBRARY png_static)
# Skia on Linux includes libpng symbols
if(UNIX AND NOT APPLE AND LAF_BACKEND STREQUAL "skia")
set(PNG_LIBRARY skia)
else()
set(PNG_LIBRARY png_static)
endif()
set(PNG_LIBRARIES ${PNG_LIBRARY})
set(PNG_INCLUDE_DIRS
${LIBPNG_DIR}

View File

@ -6,7 +6,8 @@
* [Windows dependencies](#windows-dependencies)
* [macOS dependencies](#macos-dependencies)
* [Linux dependencies](#linux-dependencies)
* [Compiling](#compiling)
* [Automatic Building](#automatic-building)
* [Manual Building](#manual-building)
* [Windows details](#windows-details)
* [MinGW](#mingw)
* [macOS details](#macos-details)
@ -17,11 +18,12 @@
# Platforms
You should be able to compile Aseprite successfully on the following
platforms:
platforms (older and newer versions might work):
* Windows 11 + [Visual Studio Community 2022 + Windows 10.0 SDK (the latest version available)](https://imgur.com/a/7zs51IT) (we don't support [MinGW](#mingw))
* macOS 13.0.1 Ventura + Xcode 14.1 + macOS 11.3 SDK (older version might work)
* Linux Ubuntu Bionic 18.04 + clang 10.0
* Windows 11 + [Visual Studio Community 2022 + Windows 11 SDK](https://imgur.com/a/7zs51IT)
* *Important*: We don't support [MinGW](#mingw)
* macOS 15.2 Sequoia + Xcode 16.3 + macOS 15.4 SDK
* Linux Ubuntu Focal Fossa 20.04 + clang 12
# Get the source code
@ -49,7 +51,7 @@ clone the repository on Windows.
To compile Aseprite you will need:
* The latest version of [CMake](https://cmake.org) (3.16 or greater)
* The latest version of [CMake](https://cmake.org)
* [Ninja](https://ninja-build.org) build system
* And a compiled version of the `aseprite-m124` branch of
the [Skia library](https://github.com/aseprite/skia#readme).
@ -59,25 +61,24 @@ To compile Aseprite you will need:
## Windows dependencies
* Windows 10/11 (we don't support cross-compiling)
* Windows 11 (we don't support cross-compiling)
* [Visual Studio Community 2022](https://visualstudio.microsoft.com/downloads/) (we don't support [MinGW](#mingw))
* The [Desktop development with C++ item + Windows 10.0.18362.0 SDK](https://imgur.com/a/7zs51IT)
from the Visual Studio installer
* The [Desktop development with C++ item + Windows 10.0.26100.0 SDK](https://imgur.com/a/7zs51IT)
from Visual Studio installer
## macOS dependencies
On macOS you will need macOS 11.3 SDK and Xcode 13.1 (older versions
might work).
On macOS you will need macOS 15.4 SDK and Xcode 16.3 (older versions might work).
## Linux dependencies
You will need the following dependencies on Ubuntu/Debian:
sudo apt-get install -y g++ clang libc++-dev libc++abi-dev 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 libgl1-mesa-dev libfontconfig1-dev
Or use clang-10 packages (or newer) in case that clang in your distribution is older than clang 10.0:
Or use clang-12 packages (or newer) in case that clang in your distribution is older than clang 12.0:
sudo apt-get install -y clang-10 libc++-10-dev libc++abi-10-dev
sudo apt-get install -y clang-12
On Fedora:
@ -85,13 +86,24 @@ On Fedora:
On Arch:
sudo pacman -S gcc clang libc++ cmake ninja libx11 libxcursor mesa-libgl fontconfig libwebp
sudo pacman -S gcc clang cmake ninja libx11 libxcursor mesa-libgl fontconfig libwebp
On SUSE:
sudo zypper install gcc-c++ clang libc++-devel libc++abi-devel 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 Mesa-libGL-devel fontconfig-devel
# Compiling
# Automatic Building
We offer a new [build script](build.sh) that automates and help you to
compile Aseprite following instructions on screen. This will be the
preferred method for new users and developers to compile Aseprite.
After you get [get Aseprite code](#get-the-source-code) and install
[its dependencies](#dependencies), you can run [build.cmd](build.cmd)
file on Windows double-clicking it, or [build.sh](build.sh) on macOS or
Linux running it from the terminal from the same Aseprite folder.
# Manual Building
1. [Get Aseprite code](#get-the-source-code), put it in a folder like
`C:\aseprite`, and create a `build` directory inside to leave all
@ -223,7 +235,9 @@ If you have a Retina display, check the following issue:
## Linux details
You need to use clang and libc++ to compile Aseprite:
You can compile Aseprite with gcc or clang. In case that you are using
the [pre-compiled Skia version](https://github.com/aseprite/skia/releases/),
you must use libstdc++ to compile Aseprite:
cd aseprite
mkdir build
@ -232,8 +246,8 @@ You need to use clang and libc++ to compile Aseprite:
export CXX=clang++
cmake \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DCMAKE_CXX_FLAGS:STRING=-stdlib=libc++ \
-DCMAKE_EXE_LINKER_FLAGS:STRING=-stdlib=libc++ \
-DCMAKE_CXX_FLAGS:STRING=-stdlib=libstdc++ \
-DCMAKE_EXE_LINKER_FLAGS:STRING=-stdlib=libstdc++ \
-DLAF_BACKEND=skia \
-DSKIA_DIR=$HOME/deps/skia \
-DSKIA_LIBRARY_DIR=$HOME/deps/skia/out/Release-x64 \
@ -245,13 +259,6 @@ You need to use clang and libc++ to compile Aseprite:
In this case, `$HOME/deps/skia` is the directory where Skia was
compiled or uncompressed.
### GCC compiler
In case that you are using the pre-compiled Skia version, you must use
the clang compiler and libc++ to compile Aseprite. Only if you compile
Skia with GCC, you will be able to compile Aseprite with GCC, and this
is not recommended as you will have a performance penalty doing so.
# Using shared third party libraries
If you don't want to use the embedded code of third party libraries

View File

@ -48,45 +48,14 @@ You can ask for help in:
[YouTube](https://www.youtube.com/user/aseprite),
[Instagram](https://www.instagram.com/aseprite/).
## Authors
Aseprite is being developed by [Igara Studio](https://igara.com/):
* [David Capello](https://davidcapello.com/)
* [Gaspar Capello](https://github.com/Gasparoken)
* [Martín Capello](https://github.com/martincapello)
## Credits
The default Aseprite theme was introduced in v0.8, created by:
Aseprite was originally created by [David Capello](https://davidcapello.com/)
and is now being developed and maintained by [Igara Studio](https://igara.com/)
and contributors.
* [Ilija Melentijevic](https://ilkke.net/)
A modified dark version of this theme introduced in v1.3-beta1 was created by:
* [Nicolas Desilets](https://twitter.com/MapleGecko)
* [David Capello](https://twitter.com/davidcapello)
Aseprite includes color palettes created by:
* [Richard "DawnBringer" Fhager](http://pixeljoint.com/p/23821.htm), [16 colors](http://pixeljoint.com/forum/forum_posts.asp?TID=12795), [32 colors](http://pixeljoint.com/forum/forum_posts.asp?TID=16247).
* [Arne Niklas Jansson](http://androidarts.com/), [16 colors](http://androidarts.com/palette/16pal.htm), [32 colors](http://wayofthepixel.net/index.php?topic=15824.msg144494).
* [ENDESGA Studios](https://twitter.com/ENDESGA), [EDG16 and EDG32](https://forums.tigsource.com/index.php?topic=46126.msg1279124#msg1279124), and [other palettes](https://twitter.com/ENDESGA/status/865812366931353600).
* [Hyohnoo Games](https://twitter.com/Hyohnoo), [mail24](https://twitter.com/Hyohnoo/status/797472587974639616) palette.
* [Davit Masia](https://twitter.com/DavitMasia), [matriax8c](https://twitter.com/DavitMasia/status/834862452164612096) palette.
* [Javier Guerrero](https://twitter.com/Xavier_Gd), [nyx8](https://twitter.com/Xavier_Gd/status/868519467864686594) palette.
* [Adigun A. Polack](https://twitter.com/adigunpolack), [AAP-64](http://pixeljoint.com/pixelart/119466.htm), [AAP-Splendor128](http://pixeljoint.com/pixelart/120714.htm), [SimpleJPC-16](http://pixeljoint.com/pixelart/119844.htm), and [AAP-Micro12](http://pixeljoint.com/pixelart/121151.htm) palette.
* [PineTreePizza](https://twitter.com/PineTreePizza), [Rosy-42](https://twitter.com/PineTreePizza/status/1006536191955623938) palette.
It tries to replicate some pixel-art algorithms:
* [RotSprite](http://forums.sonicretro.org/index.php?showtopic=8848&st=15&p=159754&#entry159754) by Xenowhirl.
* [Pixel perfect drawing algorithm](https://deepnight.net/blog/tools/pixel-perfect-drawing/) by [Sébastien Bénard](https://twitter.com/deepnightfr) and [Carduus](https://twitter.com/CarduusHimself/status/420554200737935361).
Thanks to [third-party open source projects](docs/LICENSES.md), to
[contributors](https://www.aseprite.org/contributors/), and all the
people who have contributed ideas, patches, bugs report, feature
requests, donations, and help us to develop Aseprite.
Check the [AUTHORS](AUTHORS.md) file for details about the active team
of developers working on Aseprite.
## License

141
build.sh
View File

@ -56,31 +56,6 @@ if [ "$1" == "--norun" ] ; then
norun=1
fi
# Platform.
if [[ "$(uname)" =~ "MINGW32" ]] || [[ "$(uname)" =~ "MINGW64" ]] || [[ "$(uname)" =~ "MSYS_NT-10.0" ]] ; then
is_win=1
cpu=x64
if ! cl.exe >/dev/null 2>/dev/null ; then
echo ""
echo "MSVC compiler (cl.exe) not found in PATH"
echo ""
echo " PATH=$PATH"
echo ""
exit 1
fi
elif [[ "$(uname)" == "Linux" ]] ; then
is_linux=1
cpu=x64
elif [[ "$(uname)" =~ "Darwin" ]] ; then
is_macos=1
if [[ $(uname -m) == "arm64" ]]; then
cpu=arm64
else
cpu=x64
fi
fi
# Check utilities.
if ! cmake --version >/dev/null ; then
echo ""
@ -137,6 +112,23 @@ if [ $run_submodule_update ] ; then
echo "Done"
fi
# Platform.
if ! source "$pwd/laf/misc/platform.sh" ; then
exit $?
fi
if [ $is_win ] ; then
# Check MSVC compiler.
if ! cl.exe >/dev/null 2>/dev/null ; then
echo ""
echo "MSVC compiler (cl.exe) not found in PATH"
echo ""
echo " PATH=$PATH"
echo ""
exit 1
fi
fi
# Create the directory to store the configuration.
if [ ! -d "$pwd/.build" ] ; then
mkdir "$pwd/.build"
@ -150,25 +142,25 @@ if [ ! -f "$pwd/.build/userkind" ] ; then
echo "user" > $pwd/.build/userkind
else
echo ""
echo "Select what kind of user you are (press U or D keys):"
echo "Select what kind of user you are (press U or D key and then Enter):"
echo ""
echo " [U]ser: give a try to Aseprite"
echo " [D]eveloper: develop/modify Aseprite"
echo ""
read -sN 1 -p "[U/D]? "
echo ""
if [[ "$REPLY" == "d" || "$REPLY" == "D" ]] ; then
read -p "[U/D]? "
REPLY=$(echo $REPLY | tr '[:upper:]' '[:lower:]')
if [[ "$REPLY" == "d" || "$REPLY" == "dev" || "$REPLY" == "developer" ]] ; then
echo "developer" > $pwd/.build/userkind
elif [[ "$REPLY" == "u" || "$REPLY" == "U" ]] ; then
elif [[ "$REPLY" == "u" || "$REPLY" == "user" ]] ; then
echo "user" > $pwd/.build/userkind
else
echo "Use U or D keys to select kind of user/build process"
echo "Use U or D keys (and press Enter) to select kind of user/build process"
exit 1
fi
fi
fi
userkind=$(echo -n $(cat $pwd/.build/userkind))
userkind=$(cat $pwd/.build/userkind)
if [ "$userkind" == "developer" ] ; then
echo "======================= BUILDING FOR DEVELOPER ======================="
else
@ -229,7 +221,7 @@ if [ ! -f "$pwd/.build/builds_dir" ] ; then
echo "$builds_dir" > "$pwd/.build/builds_dir"
fi
# Overwrite $builds_dir variable from the config content.
builds_dir="$(echo -n $(cat $pwd/.build/builds_dir))"
builds_dir="$(cat $pwd/.build/builds_dir)"
# List all builds.
builds_list="$(mktemp)"
@ -265,7 +257,8 @@ else
# New build
if [[ "$build_n" == "n" || "$build_n" == "N" ]] ; then
read -p "Select build type [RELEASE/debug]? "
if [[ "${REPLY,,}" == "debug" ]] ; then
REPLY=$(echo $REPLY | tr '[:upper:]' '[:lower:]')
if [[ "${REPLY}" == "debug" ]] ; then
build_type=Debug
new_build_name=aseprite-debug
else
@ -348,10 +341,7 @@ else
elif git --git-dir="$source_dir/.git" branch --contains "$remote/main" | grep -q "^\* $branch_name\$" ; then
base_branch_name=main
else
echo ""
echo "Error: Branch $branch_name looks like doesn't belong to main or beta"
echo ""
exit 1
base_branch_name=$branch_name
fi
fi
@ -366,15 +356,9 @@ else
fi
# Required Skia for the base branch.
if [ "$base_branch_name" == "beta" ] ; then
skia_tag=m124-08a5439a6b
file_skia_dir=beta_skia_dir
possible_skia_dir_name=skia-m124
else
skia_tag=m102-861e4743af
file_skia_dir=main_skia_dir
possible_skia_dir_name=skia
fi
skia_tag=$(cat "$pwd/laf/misc/skia-tag.txt")
possible_skia_dir_name=skia-$(echo $skia_tag | cut -d "-" -f 1)
file_skia_dir="$base_branch_name"_skia_dir
# Check Skia dependency.
if [ ! -f "$pwd/.build/$file_skia_dir" ] ; then
@ -385,23 +369,33 @@ if [ ! -f "$pwd/.build/$file_skia_dir" ] ; then
skia_dir="$HOME/deps/$possible_skia_dir_name"
fi
# Set default location if not found
if [ ! -d "$skia_dir" ] ; then
echo ""
echo "Skia directory wasn't found."
echo ""
echo "Select Skia directory to create [$skia_dir]? "
if [ ! $auto ] ; then
read skia_dir_read
if [ "$skia_dir_read" != "" ] ; then
skia_dir="$skia_dir_read"
fi
# Use .deps directory to download Skia for users (which is a
# simple setup). In case of developers we'd prefer the shared
# directory by default.
if [ "$userkind" == "user" ] ; then
skia_dir="$pwd/.deps/$possible_skia_dir_name"
fi
if [ ! -d "$skia_dir" ] ; then
echo ""
echo "Skia directory wasn't found."
echo ""
echo "Select Skia directory to create [$skia_dir]? "
if [ ! $auto ] ; then
read skia_dir_read
if [ "$skia_dir_read" != "" ] ; then
skia_dir="$skia_dir_read"
fi
fi
mkdir -p $skia_dir || exit 1
fi
mkdir -p $skia_dir || exit 1
fi
echo $skia_dir > "$pwd/.build/$file_skia_dir"
fi
skia_dir=$(echo -n $(cat $pwd/.build/$file_skia_dir))
skia_dir=$(cat $pwd/.build/$file_skia_dir)
if [ ! -d "$skia_dir" ] ; then
mkdir "$skia_dir"
fi
@ -421,27 +415,30 @@ if [ ! -d "$skia_library_dir" ] ; then
echo "Skia library wasn't found."
echo ""
if [ ! $auto ] ; then
read -sN 1 -p "Download pre-compiled Skia automatically [Y/n]? "
read -p "Download pre-compiled Skia automatically [Y/n]? "
# Convert the Enter key as the default option: an empty string
REPLY=$(echo $REPLY | tr '[:upper:]' '[:lower:]')
fi
if [[ $auto || "$REPLY" == "" || "$REPLY" == "y" || "$REPLY" == "Y" ]] ; then
if [[ $auto || "$REPLY" == "" || "$REPLY" == "y" || "$REPLY" == "yes" ]] ; then
if [[ $is_win && "$build_type" == "Debug" ]] ; then
skia_build=Debug
else
skia_build=Release
fi
if [ $is_win ] ; then
skia_file=Skia-Windows-$skia_build-$cpu.zip
elif [ $is_macos ] ; then
skia_file=Skia-macOS-$skia_build-$cpu.zip
else
skia_file=Skia-Linux-$skia_build-$cpu-libstdc++.zip
fi
skia_url=https://github.com/aseprite/skia/releases/download/$skia_tag/$skia_file
skia_url=$(bash laf/misc/skia-url.sh $skia_build)
skia_file=$(basename $skia_url)
if [ ! -f "$skia_dir/$skia_file" ] ; then
curl -L -o "$skia_dir/$skia_file" "$skia_url"
if ! command -v curl >/dev/null 2>&1 ; then
echo "Error: 'curl' command line tool is not available in PATH"
exit 1
fi
curl --ssl-revoke-best-effort -L -o "$skia_dir/$skia_file" "$skia_url"
fi
if [ ! -d "$skia_library_dir" ] ; then
if ! command -v unzip >/dev/null 2>&1 ; then
echo "Error: 'unzip' command line tool is not available in PATH"
exit 1
fi
unzip -n -d "$skia_dir" "$skia_dir/$skia_file"
fi
else
@ -468,7 +465,7 @@ if [ ! -f "$active_build_dir/ninja.build" ] ; then
echo "This will take some minutes."
echo ""
if [ ! $auto ] ; then
read -sN 1 -p "Press any key to continue. "
read -p "Press Enter to continue."
fi
if [ $is_macos ] ; then

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -216,7 +216,7 @@
<part id="tab_normal" x="2" y="112" w1="4" w2="5" w3="5" h1="4" h2="6" h3="2" />
<part id="tab_active" x="16" y="112" w1="4" w2="7" w3="5" h1="4" h2="6" h3="2" />
<part id="tab_bottom_active" x="16" y="124" w1="4" w2="7" w3="5" h1="2" h2="1" h3="2" />
<part id="tab_bottom_normal" x="2" y="124" w="12" h="5" />
<part id="tab_bottom_normal" x="2" y="124" w1="4" w2="5" w3="3" h1="2" h2="1" h3="2" />
<part id="tab_filler" x="0" y="112" w="2" h="12" />
<part id="tab_modified_icon_normal" x="32" y="112" w="5" h="5" />
<part id="tab_modified_icon_active" x="32" y="117" w="5" h="5" />
@ -374,6 +374,7 @@
<part id="icon_close" x="152" y="256" w="7" h="7" />
<part id="icon_search" x="160" y="256" w="8" h="8" />
<part id="icon_user_data" x="168" y="256" w="8" h="8" />
<part id="icon_layout" x="176" y="256" w="5" h="6" />
<part id="icon_pos" x="144" y="264" w="8" h="8" />
<part id="icon_size" x="152" y="264" w="8" h="8" />
<part id="icon_selsize" x="160" y="264" w="8" h="8" />
@ -485,25 +486,25 @@
<icon part="window_close_icon" color="button_hot_text" state="mouse" />
<icon part="window_close_icon" color="button_selected_text" state="selected" />
</style>
<style id="window_center_button" extends="window_button" margin-top="3" margin-right="2">
<style id="window_center_button" extends="window_button" margin-top="3" margin-right="1">
<newlayer />
<icon part="window_center_icon" color="button_normal_text" />
<icon part="window_center_icon" color="button_hot_text" state="mouse" />
<icon part="window_center_icon" color="button_selected_text" state="selected" />
</style>
<style id="window_play_button" extends="window_button" margin-top="3" margin-right="2">
<style id="window_play_button" extends="window_button" margin-top="3" margin-right="1">
<newlayer />
<icon part="window_play_icon" color="button_normal_text" />
<icon part="window_play_icon" color="button_hot_text" state="mouse" />
<icon part="window_play_icon" color="button_selected_text" state="selected" />
</style>
<style id="window_stop_button" extends="window_button" margin-top="3" margin-right="2">
<style id="window_stop_button" extends="window_button" margin-top="3" margin-right="1">
<newlayer />
<icon part="window_stop_icon" color="button_normal_text" />
<icon part="window_stop_icon" color="button_hot_text" state="mouse" />
<icon part="window_stop_icon" color="button_selected_text" state="selected" />
</style>
<style id="window_help_button" extends="window_button" margin-top="3" margin-right="2">
<style id="window_help_button" extends="window_button" margin-top="3" margin-right="1">
<newlayer />
<icon part="window_help_icon" color="button_normal_text" />
<icon part="window_help_icon" color="button_hot_text" state="mouse" />
@ -550,10 +551,13 @@
<text color="disabled" align="left" state="disabled" />
</style>
<style id="mini_label" extends="label" font="mini" />
<style id="warning_label" extends="label">
<icon part="warning_box" align="right" />
</style>
<style id="list_header_label" padding="2">
<text color="text" align="left" x="2" />
</style>
<style id="link">
<style id="link" padding="1">
<text color="link_text" align="left" />
<text color="link_hover" align="left" state="mouse" />
</style>
@ -706,10 +710,11 @@
<style id="workspace_splitter">
<background color="workspace" />
</style>
<style id="horizontal_separator" border-left="2" border-top="4" border-right="2" border-bottom="0">
<style id="horizontal_separator" border="2">
<background color="window_face" />
<background-border part="separator_horz" align="middle" />
<text color="separator_label" x="4" align="left middle" />
<text color="disabled" x="4" align="left middle" state="disabled"/>
</style>
<style id="menu_separator" extends="horizontal_separator" />
<style id="separator_in_view" extends="horizontal_separator">

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -212,7 +212,7 @@
<part id="tab_normal" x="2" y="112" w1="4" w2="5" w3="5" h1="4" h2="6" h3="2" />
<part id="tab_active" x="16" y="112" w1="4" w2="7" w3="5" h1="4" h2="6" h3="2" />
<part id="tab_bottom_active" x="16" y="124" w1="4" w2="7" w3="5" h1="2" h2="1" h3="2" />
<part id="tab_bottom_normal" x="2" y="124" w="12" h="5" />
<part id="tab_bottom_normal" x="2" y="124" w1="4" w2="5" w3="3" h1="2" h2="1" h3="2" />
<part id="tab_filler" x="0" y="112" w="2" h="12" />
<part id="tab_modified_icon_normal" x="32" y="112" w="5" h="5" />
<part id="tab_modified_icon_active" x="32" y="117" w="5" h="5" />
@ -370,6 +370,7 @@
<part id="icon_close" x="152" y="256" w="7" h="7" />
<part id="icon_search" x="160" y="256" w="8" h="8" />
<part id="icon_user_data" x="168" y="256" w="8" h="8" />
<part id="icon_layout" x="176" y="256" w="5" h="6" />
<part id="icon_pos" x="144" y="264" w="8" h="8" />
<part id="icon_size" x="152" y="264" w="8" h="8" />
<part id="icon_selsize" x="160" y="264" w="8" h="8" />
@ -481,25 +482,25 @@
<icon part="window_close_icon" color="button_hot_text" state="mouse" />
<icon part="window_close_icon" color="button_selected_text" state="selected" />
</style>
<style id="window_center_button" extends="window_button" margin-top="3" margin-right="2">
<style id="window_center_button" extends="window_button" margin-top="3" margin-right="1">
<newlayer />
<icon part="window_center_icon" color="button_normal_text" />
<icon part="window_center_icon" color="button_hot_text" state="mouse" />
<icon part="window_center_icon" color="button_selected_text" state="selected" />
</style>
<style id="window_play_button" extends="window_button" margin-top="3" margin-right="2">
<style id="window_play_button" extends="window_button" margin-top="3" margin-right="1">
<newlayer />
<icon part="window_play_icon" color="button_normal_text" />
<icon part="window_play_icon" color="button_hot_text" state="mouse" />
<icon part="window_play_icon" color="button_selected_text" state="selected" />
</style>
<style id="window_stop_button" extends="window_button" margin-top="3" margin-right="2">
<style id="window_stop_button" extends="window_button" margin-top="3" margin-right="1">
<newlayer />
<icon part="window_stop_icon" color="button_normal_text" />
<icon part="window_stop_icon" color="button_hot_text" state="mouse" />
<icon part="window_stop_icon" color="button_selected_text" state="selected" />
</style>
<style id="window_help_button" extends="window_button" margin-top="3" margin-right="2">
<style id="window_help_button" extends="window_button" margin-top="3" margin-right="1">
<newlayer />
<icon part="window_help_icon" color="button_normal_text" />
<icon part="window_help_icon" color="button_hot_text" state="mouse" />
@ -543,10 +544,13 @@
<text color="disabled" align="left" state="disabled" />
</style>
<style id="mini_label" extends="label" font="mini" />
<style id="warning_label" extends="label">
<icon part="warning_box" align="right" />
</style>
<style id="list_header_label" padding="2">
<text color="text" align="left" x="2" />
</style>
<style id="link">
<style id="link" padding="1">
<text color="link_text" align="left" />
<text color="link_hover" align="left" state="mouse" />
</style>
@ -699,10 +703,11 @@
<style id="workspace_splitter">
<background color="workspace" />
</style>
<style id="horizontal_separator" border-left="2" border-top="4" border-right="2" border-bottom="0">
<style id="horizontal_separator" border="2">
<background color="window_face" />
<background-border part="separator_horz" align="middle" />
<text color="separator_label" x="4" align="left middle" />
<text color="disabled" x="4" align="left middle" state="disabled"/>
</style>
<style id="menu_separator" extends="horizontal_separator" />
<style id="separator_in_view" extends="horizontal_separator">

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

@ -32,14 +32,16 @@
<font name="Aseprite"
type="spritesheet"
descent="2"
file="aseprite_font.png">
<fallback font="Unicode" size="8" />
<fallback font="Unicode" size="14" />
</font>
<font name="Aseprite Mini"
type="spritesheet"
descent="1"
file="aseprite_mini.png">
<fallback font="Unicode" size="6" />
<fallback font="Unicode" size="10" />
</font>
</fonts>

View File

@ -175,6 +175,7 @@
<param name="popup" value="background" />
</key>
<key command="ShowExtras" shortcut="Ctrl+H" />
<key command="ToggleWorkspaceLayout" shortcut="Shift+W" />
<!-- Tabs -->
<key command="GotoNextTab" shortcut="Ctrl+Tab" />
<key command="GotoPreviousTab" shortcut="Ctrl+Shift+Tab" />
@ -1002,6 +1003,7 @@
</menu>
<menu text="@.view" id="view_menu">
<item command="DuplicateView" text="@.view_duplicate_view" group="view_new" />
<item command="ToggleWorkspaceLayout" text="@.view_workspace_layout" />
<separator />
<item command="ShowExtras" text="@.view_show_extras" />
<menu text="@.view_show" group="view_extras">

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Aseprite -->
<!-- Copyright (C) 2018-2024 Igara Studio S.A. -->
<!-- Copyright (C) 2018-2025 Igara Studio S.A. -->
<!-- Copyright (C) 2014-2018 David Capello -->
<preferences>
@ -167,6 +167,7 @@
<option id="keep_closed_sprite_on_memory_for" type="double" default="15.0" />
<option id="show_full_path" type="bool" default="true" />
<option id="edit_full_path" type="bool" default="false" />
<option id="workspace_layout" type="std::string" />
<option id="timeline_position" type="TimelinePosition" default="TimelinePosition::BOTTOM" />
<option id="timeline_layer_panel_width" type="int" default="100" />
<option id="show_menu_bar" type="bool" default="true" />
@ -255,6 +256,7 @@
<option id="one_finger_as_mouse_movement" type="bool" default="true" />
<option id="load_wintab_driver" type="bool" default="false" />
<option id="flash_layer" type="bool" default="false" />
<option id="use_selection_tool_loop" type="bool" default="false" />
<option id="nonactive_layers_opacity" type="int" default="255" />
<option id="nonactive_layers_opacity_preview" type="int" default="255" />
</section>
@ -356,6 +358,7 @@
<section id="file_selector">
<option id="current_folder" type="std::string" default="&quot;&lt;empty&gt;&quot;" />
<option id="zoom" type="double" default="1.0" />
<option id="show_hidden" type="bool" default="false" />
</section>
<section id="text_tool">
<option id="font_face" type="std::string" />
@ -551,6 +554,7 @@
<option id="enabled" type="bool" default="false" />
<option id="overlay_enabled" type="bool" default="false" />
<option id="overlay_size" type="int" default="5" />
<option id="scale_up_to_fit" type="bool" default="false" />
</section>
<section id="onionskin">
<option id="active" type="bool" default="false" />

View File

@ -1,5 +1,5 @@
# Aseprite
# Copyright (C) 2018-2024 Igara Studio S.A.
# Copyright (C) 2018-2025 Igara Studio S.A.
# Copyright (C) 2016-2018 David Capello
#
# This work is licensed under the Creative Commons Attribution 4.0
@ -43,7 +43,6 @@ locked_layers = There are locked layers
no_active_layers = There is no active layer
layer_x_is_hidden = Layer "{}" is hidden
unmodifiable_reference_layer = Layer "{}" is reference, cannot be modified
filter_no_unlocked_layer = No unlocked layers to apply filter
cannot_move_bg_layer = The background layer cannot be moved
nothing_to_move = Nothing to move
recovery_task_using_sprite = Sprite is used by a backup/data recovery task
@ -489,6 +488,7 @@ TilesetDuplicate = Duplicate Tileset
Undo = Undo
UndoHistory = Undo History
UnlinkCel = Unlink Cel
ToggleWorkspaceLayout = Toggle Workspace Layout
Zoom = Zoom
Zoom_In = Zoom In
Zoom_Out = Zoom Out
@ -622,6 +622,14 @@ current_layer = Current Layer
first_ref_layer = First Reference Layer
pick = Pick:
sample = Sample:
position_label = P:
rotation_label = R:
position_x = X Position
position_y = Y Position
size_width = Width
size_height = Height
rotation_angle = Angle
rotation_skew = Skew
[convolution_matrix]
reload_stock = &Reload Stock
@ -766,6 +774,7 @@ pinned_folders = Pinned Folders
recent_folders = Recent Folders
all_formats = All formats
all_files = All files
show_hidden = Show hidden
[filters]
selected_cels = Selected
@ -786,6 +795,11 @@ load = Load External Font
select_truetype_fonts = Select a Font File
empty_fonts = No system fonts were found
[font_style]
antialias = Antialias
hinting = Hinting
ligatures = Ligatures
[frame_combo]
all_frames = All frames
selected_frames = Selected frames
@ -813,6 +827,12 @@ opacity = Opacity:
tolerance = Tolerance:
show_more = Show more...
[general_text]
copy = &Copy
cut = Cu&t
paste = &Paste
select_all = Select &All
[gif_options]
title = GIF Options
general_options = General Options:
@ -981,6 +1001,7 @@ visible_layers = Visible layers
[layer_properties]
title = Layer Properties
name = Name:
uuid = UUID:
mode = Mode:
opacity = Opacity:
tileset_tooltip = Tileset
@ -1155,6 +1176,7 @@ select_load_from_file = &Load from MSK file
select_save_to_file = &Save to MSK file
view = &View
view_duplicate_view = Duplicate &View
view_workspace_layout = Workspace &Layout
view_show_extras = &Extras
view_show = &Show
view_show_layer_edges = &Layer Edges
@ -1196,6 +1218,14 @@ help_twitter = Twitter
help_enter_license = Enter &License
help_about = &About
[main_window]
layout = Workspace Layout
default_layout = Default
mirrored_default_layout = Mirrored Default
timeline = Timeline
user_layouts = User Layouts
new_layout = New Layout...
[mask_by_color]
title = Select Color
label_color = Color:
@ -1224,6 +1254,20 @@ name = Name:
tileset = Tileset:
default_new_layer_name = New Layer
[new_layout]
title = New Workspace Layout
name = Name:
deleting_layout = Deleting Layout
deleting_layout_confirmation = Are you sure you want to delete the '{}' layout?
restoring_layout = Restoring Layout
restoring_layout_confirmation = Are you sure you want to restore the '{}' layout?
[dock]
left = Dock Left
right = Dock Right
top = Dock Top
bottom = Dock Bottom
[news_listbox]
more = More...
problem_loading = Problems loading news. Please retry.
@ -1326,7 +1370,7 @@ theme_mode = Theme Mode:
screen_scaling = Screen Scaling:
ui_scaling = UI Element Scaling:
language = Language:
download_translations = Download Translations
font_warning = Customize font for this language
gpu_acceleration = GPU acceleration [DEVMODE/INTERNAL TESTING ONLY]
gpu_acceleration_tooltip = Check this option to enable hardware acceleration
show_menu_bar = Show Aseprite menu bar
@ -1513,6 +1557,12 @@ alpha_range = Alpha Range:
opacity_range = Opacity Range:
8bit_value = 0-255
percentage = 0%-100%
customize_theme = Customize Theme
font = Font:
mini_font = Mini Font:
preview = Preview:
font_preview = Font Preview
mini_font_preview = Mini Font Preview
available_themes = Available Themes
extension_themes = Extension Themes
select_theme = &Select
@ -1550,11 +1600,13 @@ set_cursor_fix = Set cursor position from stylus location
set_cursor_fix_tooltip = Sets the mouse position to the pen location when\nyou have two pointers available (e.g. mouse and pen)\n\nUseful to zoom in/out from the pen position and to get the\ncorrect cursor location when screencasting/live streaming.
wintab_more_info = (More Information)
flash_selected_layer = Flash layer when it is selected
use_selection_tool_loop = New selection tools implementation
non_active_layer_opacity = Opacity for non-active layers:
cel_content_format = Cel content format:
cel_format_compressed = Compressed
cel_format_keep = Keep format as is in file
cel_format_raw = Raw image
cel_format_raw_warning = This will increase .aseprite file sizes considerably
reset_title = Reset Preferences
reset_default = Reset configuration options available in the Preferences window
reset_tools = Reset all tool preferences
@ -1659,6 +1711,11 @@ n_slices_removed = {} slice(s) removed
x_removed = Layer "{}" removed
layers_removed = Layers removed
[resource_listbox]
loading = Loading
pin = Pin this item
unpin = Unpin this item
[save_file]
title = Save File
save_as = Save As
@ -1675,7 +1732,8 @@ title = Save Selection (.msk file)
[script_access]
title = Security
script_label = The following script:
file_label = wants to access to this file:
file_label = wants to access this file:
file_write_label = wants to write to this file:
command_label = wants to execute the following command:
websocket_label = wants to open a WebSocket connection to this URL:
clipboard_label = wants to access the system clipboard
@ -1689,7 +1747,7 @@ allow_load_lib_access = &Allow Load External Library
give_full_access = Give Script Full &Access
stop_script = &Stop Script
[select_accelerator]
[select_shortcut]
title = Keyboard Shortcut
key = Key:
clear = Clear
@ -1769,6 +1827,8 @@ change_sprite_props = Change Sprite Properties
tilesets = Tilesets
delete_tileset = Delete
duplicate_tileset = Duplicate
use_uuid_for_layers = Create UUID for layers
use_uuid_for_layers_tooltip = By checking this an UUID (Universally Unique Identifiers)\nwill be automatically assigned to each layer\nand saved in .aseprite files
[sprite_size]
title = Sprite Size
@ -1814,16 +1874,26 @@ pixel_scale = Pixel Scale
with_vars = Use CSS3 Variables
generate_html = Generate Sample HTML File
[shape]
fill = Fill
stroke = Stroke
stroke_width = Stroke Width
[text_tool]
font_family = Font Family
font_size = Font Size
bold = Bold
italic = Italic
more_options = More Options
[timeline_conf]
position = Position:
left = &Left
right = &Right
bottom = &Bottom
frame_header = Frame Header:
first_frame = First Frame:
thumbnails = Thumbnails
thumbnail_size = Thumbnail Size:
overlay_size = Overlay Size:
scale_up_to_fit = Scale up to fit
onion_skin = Onion Skin:
merge_frames = Merge Frames
red_blue_tint = Red/Blue Tint
@ -1836,6 +1906,7 @@ behind_sprite = Behind sprite
behind_sprite_toolip = Only for transparent layers.\nBackground is not included in this onion skin mode.
in_front = In front of sprite
in_front_toolip = For all kind of layers (background and transparent)
set_as_defaults = Set as Defaults
[tools]
rectangular_marquee = Rectangular Marquee Tool
@ -1874,6 +1945,7 @@ timeline_show = Show Timeline
[undo_history]
title = Undo History
initial_state = Initial State
[user_data]
user_data = User Data:

View File

@ -1,29 +1,14 @@
<!-- Aseprite -->
<!-- Copyright (C) 2018-2024 Igara Studio S.A. -->
<!-- Copyright (C) 2018-2025 Igara Studio S.A. -->
<!-- Copyright (C) 2018 David Capello -->
<gui i18nwarnings="false">
<window id="about" text="About Aseprite">
<vbox>
<label text="" id="title" />
<label text="Animated sprite editor &amp;&amp; pixel art tool" />
<hbox homogeneous="true">
<hbox>
<vbox expansive="true">
<separator text="Developer Team" horizontal="true" />
<link text="David Capello" url="https://twitter.com/davidcapello" />
<link text="Gaspar Capello" url="https://twitter.com/Gasparoken" />
<link text="Martín Capello" url="https://twitter.com/martincapell0" />
<vbox minheight="8" />
</vbox>
<separator vertical="true" />
</hbox>
<vbox>
<separator text="Credits" horizontal="true" cell_hspan="2" />
<link text="Contributors" url="" id="credits" />
<link text="Translators" url="" id="i18n_credits" />
<link text="Open Source Projects" url="" id="licenses" />
</vbox>
</hbox>
<link text="Authors &amp;&amp; Credits" url="" id="credits" />
<link text="Translators" url="" id="i18n_credits" />
<link text="Open Source Projects" url="" id="licenses" />
<separator horizontal="true" />
<hbox>
<label text="Copyright (C) 2001-2025" />

View File

@ -23,6 +23,7 @@
<combobox id="location" expansive="true" />
<button text="" id="refresh_button" style="refresh_button"
tooltip="@.refresh_button_tooltip" tooltip_dir="bottom" />
<check id="show_hidden_check" text="@.show_hidden" />
</box>
<vbox id="file_view_placeholder" expansive="true" />
<grid columns="2">

View File

@ -0,0 +1,10 @@
<!-- Aseprite -->
<!-- Copyright (C) 2025 by Igara Studio S.A. -->
<gui>
<vbox id="font_style">
<check id="antialias" text="@.antialias" />
<check id="hinting" text="@.hinting" />
<separator horizontal="true" />
<check id="ligatures" text="@.ligatures" />
</vbox>
</gui>

View File

@ -15,6 +15,9 @@
<label text="@.opacity" />
<opacityslider id="opacity" width="128" cell_align="horizontal" cell_hspan="2" />
<label id="uuid_label" text="@.uuid" visible="false" />
<entry id="uuid" readonly="true" maxsize="36" cell_hspan="2" visible="false"/>
</grid>
</vbox>
</window>

View File

@ -1,30 +0,0 @@
<!-- Aseprite -->
<!-- Copyright (C) 2001-2017 by David Capello -->
<gui>
<window id="main_window" noborders="true" desktop="true">
<vbox noborders="true" expansive="true">
<hbox noborders="true" id="menu_bar_placeholder" />
<hbox noborders="true" id="tabs_placeholder" />
<splitter id="color_bar_splitter"
horizontal="true" expansive="true"
by="pixel"
style="workspace_splitter">
<vbox noborders="true" id="color_bar_placeholder" />
<vbox noborders="true" expansive="true">
<vbox noborders="true" id="context_bar_placeholder" />
<hbox noborders="true" expansive="true">
<splitter id="timeline_splitter"
vertical="true" expansive="true"
by="percetage" position="100"
style="workspace_splitter">
<hbox noborders="true" id="workspace_placeholder" expansive="true" />
<vbox noborders="true" id="timeline_placeholder" expansive="true" />
</splitter>
<vbox noborders="true" id="tool_bar_placeholder" />
</hbox>
</vbox>
</splitter>
<hbox noborders="true" id="status_bar_placeholder" />
</vbox>
</window>
</gui>

View File

@ -0,0 +1,19 @@
<!-- Aseprite -->
<!-- Copyright (C) 2025 by Igara Studio S.A. -->
<gui>
<window id="new_layout" text="@.title">
<vbox>
<hbox>
<label text="@.name" />
<entry maxsize="128" id="name" magnet="true" expansive="true" />
</hbox>
<separator horizontal="true" />
<hbox homogeneous="true" cell_align="right">
<button text="@general.ok" closewindow="true" id="ok" disabled="true" minwidth="60" magnet="true" />
<button text="@general.cancel" closewindow="true" />
</hbox>
</vbox>
</window>
</gui>

View File

@ -1,5 +1,6 @@
<!-- Aseprite -->
<!-- Copyright (C) 2018-2024 Igara Studio S.A. -->
<!-- Copyright (C) 2018-2025 Igara Studio S.A. -->
<!-- Copyright (C) 2001-2018 David Capello -->
<gui>
<window id="options" text="@.title" help="preferences">
@ -34,7 +35,7 @@
<!-- General -->
<vbox id="section_general">
<separator text="@.section_general" horizontal="true" />
<grid columns="3">
<grid columns="2">
<label text="@.ui_windows" />
<hbox>
<buttonset columns="2" id="ui_windows">
@ -45,7 +46,6 @@
<label text="@.theme_mode" />
</hbox>
</hbox>
<boxfiller />
<label text="@.screen_scaling" />
<combobox id="screen_scale">
@ -54,7 +54,6 @@
<listitem text="300%" value="3" />
<listitem text="400%" value="4" />
</combobox>
<boxfiller />
<label text="@.ui_scaling" />
<combobox id="ui_scale">
@ -63,12 +62,14 @@
<listitem text="300%" value="3" />
<listitem text="400%" value="4" />
</combobox>
<boxfiller />
<label text="@.language" />
<link text="@.language" url="https://www.aseprite.org/languages/" />
<combobox id="language" />
<link text="@.download_translations" url="https://www.aseprite.org/languages/" />
<boxfiller id="font_warning_filler" visible="false" />
<link text="@.font_warning" id="font_warning" visible="false" />
</grid>
<separator horizontal="true" />
<check id="gpu_acceleration"
text="@.gpu_acceleration"
tooltip="@.gpu_acceleration_tooltip" />
@ -545,6 +546,20 @@
<!-- Theme -->
<vbox id="section_theme">
<separator text="@.customize_theme" horizontal="true" />
<grid columns="2">
<label text="@.preview" />
<vbox cell_align="horizontal" >
<label id="font_preview" text="@.font_preview" />
<label id="mini_font_preview" text="@.mini_font_preview" />
</vbox>
<check id="custom_theme_font" text="@.font" />
<font id="theme_font" cell_align="horizontal" />
<check id="custom_mini_font" text="@.mini_font" />
<font id="theme_mini_font" cell_align="horizontal" />
</grid>
<separator text="@.available_themes" horizontal="true" />
<view expansive="true" maxsize="true">
<listbox id="theme_list" />
@ -581,6 +596,10 @@
<listitem text="@.cel_format_keep" />
<listitem text="@.cel_format_raw" />
</combobox>
<boxfiller />
<label id="cel_format_warning"
text="@.cel_format_raw_warning" style="warning_label" />
</grid>
</vbox>
@ -613,6 +632,7 @@
text="@.hue_with_sat_value"
pref="experimental.hue_with_sat_value_for_color_selector" />
<check id="flash_layer" text="@.flash_selected_layer" />
<check id="use_selection_tool_loop" text="@.use_selection_tool_loop" />
<hbox>
<label text="@.non_active_layer_opacity" />
<slider id="nonactive_layers_opacity" min="0" max="255" width="128" />

View File

@ -1,7 +1,8 @@
<!-- Aseprite -->
<!-- Copyright (C) 2025 by Igara Studio S.A. -->
<!-- Copyright (C) 2001-2016 by David Capello -->
<gui>
<window id="select_accelerator" text="@.title">
<window id="select_shortcut" text="@.title">
<vbox expansive="true">
<grid columns="3">
<label text="@.key" />

View File

@ -42,6 +42,8 @@
<button id="convert_color_profile" text="@.convert" />
</hbox>
</hbox>
<check text="@.use_uuid_for_layers" id="use_uuid_for_layers" tooltip="@.use_uuid_for_layers_tooltip" cell_hspan="2" />
</grid>
<vbox expansive="true" id="tilesets_placeholder">

View File

@ -1,17 +1,12 @@
<!-- Aseprite -->
<!-- Copyright (C) 2025 Igara Studio S.A. -->
<!-- Copyright (C) 2014-2018 by David Capello -->
<gui>
<vbox id="timeline_conf">
<hbox>
<vbox>
<separator cell_hspan="2" text="@.position" left="true" horizontal="true" />
<hbox>
<buttonset columns="2" id="position">
<item text="@.left" />
<item text="@.right" />
<item text="@.bottom" hspan="2" />
</buttonset>
</hbox>
<button id="layout" icon="icon_layout" />
</vbox>
<vbox>
<separator text="@.frame_header" left="true" horizontal="true" />
@ -30,6 +25,7 @@
<check id="thumb_overlay_enabled" text="@.overlay_size"/>
<slider min="2" max="10" id="thumb_overlay_size" cell_align="horizontal" width="128" />
<check id="thumb_scale_up_to_fit" text="@.scale_up_to_fit" cell_hspan="2" />
</grid>
</vbox>
</hbox>
@ -55,5 +51,11 @@
<radio group="2" text="@.in_front" id="infront" tooltip="@.in_front_toolip" />
</hbox>
</grid>
<separator horizontal="true" />
<hbox>
<boxfiller />
<button id="defaults" text="@.set_as_defaults" />
</hbox>
</vbox>
</gui>

View File

@ -1,5 +1,34 @@
Aseprite uses the following open source projects:
* [Allegro 4](http://liballeg.org/)
* [Bresenham algorithm implementations by Alois Zingl](http://members.chello.at/easyfilter/bresenham.html)
* [cityhash](https://github.com/google/cityhash)
* [cmark](https://github.com/jgm/cmark)
* [curl](http://curl.haxx.se/)
* [fmt](https://github.com/fmtlib/fmt)
* [FreeType](http://www.freetype.org/)
* [giflib](http://sourceforge.net/projects/giflib/)
* [Google Test](https://github.com/google/googletest)
* [harfbuzz](http://harfbuzz.org)
* [IXWebSocket](https://github.com/machinezone/IXWebSocket)
* [json11](https://github.com/dropbox/json11/)
* [libarchive](http://www.libarchive.org/)
* [libjpeg-turbo](https://libjpeg-turbo.org/)
* [libpng](http://www.libpng.org/pub/png/)
* [libwebp](https://developers.google.com/speed/webp/)
* [Lua](https://www.lua.org/)
* [pixman](http://www.pixman.org/)
* [qoi](https://github.com/phoboslab/qoi)
* [Sentry](https://sentry.io)
* [skia](https://skia.org)
* [simpleini](https://github.com/aseprite/simpleini/)
* [TinyEXIF](https://github.com/cdcseacave/TinyEXIF)
* [tinyexpr](https://github.com/codeplea/tinyexpr)
* [tinyxml2](https://github.com/leethomason/tinyxml2)
* [ucdn](https://github.com/grigorig/ucdn)
* [Wintab API](http://www.wacomeng.com/windows/docs/WintabBackground.htm)
* [zlib](http://www.zlib.net/)
# [Allegro 4](http://liballeg.org/)
```

View File

@ -79,6 +79,7 @@ A 128-byte header (same as FLC/FLI header, but with other magic number):
1 = Layer opacity has valid value
2 = Layer blend mode/opacity is valid for groups
(composite groups separately first when rendering)
4 = Layers have an UUID
WORD Speed (milliseconds between frame, like in FLC files)
DEPRECATED: You should use the frame duration field
from each frame header
@ -202,6 +203,8 @@ entire layers layout:
STRING Layer name
+ If layer type = 2
DWORD Tileset index
+ If file header flags have bit 4:
UUID Layer's universally unique identifier
### Cel Chunk (0x2005)

2
laf

@ -1 +1 @@
Subproject commit 339a0fa13584853bda8559de486e715e743a5763
Subproject commit 01571537bc6002a2e039a66497837365c394d7fa

View File

@ -1,5 +1,5 @@
# Aseprite
# Copyright (C) 2019-2024 Igara Studio S.A.
# Copyright (C) 2019-2025 Igara Studio S.A.
# Copyright (C) 2001-2018 David Capello
######################################################################
@ -152,6 +152,12 @@ add_custom_command(
MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/../README.md)
list(APPEND out_data_files ${DATA_OUTPUT_DIR}/README.md)
add_custom_command(
OUTPUT ${DATA_OUTPUT_DIR}/AUTHORS.md
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/../AUTHORS.md ${DATA_OUTPUT_DIR}/AUTHORS.md
MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/../AUTHORS.md)
list(APPEND out_data_files ${DATA_OUTPUT_DIR}/AUTHORS.md)
add_custom_command(
OUTPUT ${DATA_OUTPUT_DIR}/EULA.txt
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/../EULA.txt ${DATA_OUTPUT_DIR}/EULA.txt
@ -174,8 +180,8 @@ if(ENABLE_ASEPRITE_EXE)
if(WIN32)
set(main_resources
main/resources_win32.rc
main/settings.manifest)
main/win/resources_win32.rc
main/win/settings.manifest)
endif()
add_executable(${main_target}

View File

@ -72,6 +72,10 @@ In Debug mode (`_DEBUG`):
* [`TRACEARGS`](https://github.com/aseprite/laf/blob/f3222bdee2d21556e9da55343e73803c730ecd97/base/debug.h#L40):
in debug mode, it prints in the terminal/console each given argument
In release mode you can use a similar function:
* `PRINTARGS` prints in the terminal/console each given argument
# Detect Platform
You can check the platform using some `laf` macros:

View File

@ -1,5 +1,5 @@
# Aseprite
# Copyright (C) 2018-2024 Igara Studio S.A.
# Copyright (C) 2018-2025 Igara Studio S.A.
# Copyright (C) 2001-2018 David Capello
# Generate a ui::Widget for each widget in a XML file
@ -98,17 +98,17 @@ add_library(app-lib ${generated_files})
# These specific-platform files should be in an external library
# (e.g. "base" or "os").
if(WIN32)
target_sources(app-lib PRIVATE font_path_win.cpp)
target_sources(app-lib PRIVATE fonts/font_path_win.cpp)
elseif(APPLE)
target_sources(app-lib PRIVATE font_path_osx.mm)
target_sources(app-lib PRIVATE fonts/font_path_osx.mm)
else()
target_sources(app-lib PRIVATE font_path_unix.cpp)
target_sources(app-lib PRIVATE fonts/font_path_unix.cpp)
endif()
# This defines a specific webp decoding utility function for using
# in Windows when dragging and dropping images that are stored as
# webp files (like Chrome does).
if(WIN32 AND ENABLE_WEBP)
if(WIN32 AND ENABLE_WEBP AND LAF_BACKEND STREQUAL "skia")
target_sources(app-lib PRIVATE util/decode_webp.cpp)
endif()
@ -290,7 +290,6 @@ target_sources(app-lib PRIVATE
cmd/copy_region.cpp
cmd/crop_cel.cpp
cmd/deselect_mask.cpp
cmd/drop_on_timeline.cpp
cmd/flatten_layers.cpp
cmd/flip_image.cpp
cmd/flip_mask.cpp
@ -522,11 +521,13 @@ target_sources(app-lib PRIVATE
commands/tileset_mode.cpp
commands/toggle_other_layers_opacity.cpp
commands/toggle_play_option.cpp
commands/toggle_workspace_layout.cpp
console.cpp
context.cpp
context_flags.cpp
doc.cpp
doc_api.cpp
doc_api_dnd_helper.cpp
doc_diff.cpp
doc_exporter.cpp
doc_range_ops.cpp
@ -545,8 +546,10 @@ target_sources(app-lib PRIVATE
file_system.cpp
filename_formatter.cpp
flatten.cpp
font_info.cpp
font_path.cpp
fonts/font_data.cpp
fonts/font_info.cpp
fonts/font_path.cpp
fonts/fonts.cpp
gui_xml.cpp
i18n/strings.cpp
i18n/xml_translator.cpp
@ -608,6 +611,7 @@ target_sources(app-lib PRIVATE
ui/context_bar.cpp
ui/dithering_selector.cpp
ui/doc_view.cpp
ui/dock.cpp
ui/drop_down_button.cpp
ui/dynamics_popup.cpp
ui/editor/brush_preview.cpp
@ -652,6 +656,9 @@ target_sources(app-lib PRIVATE
ui/input_chain.cpp
ui/keyboard_shortcuts.cpp
ui/layer_frame_comboboxes.cpp
ui/layout.cpp
ui/layouts.cpp
ui/layout_selector.cpp
ui/main_menu_bar.cpp
ui/main_window.cpp
ui/mini_help_button.cpp
@ -668,9 +675,8 @@ target_sources(app-lib PRIVATE
ui/rgbmap_algorithm_selector.cpp
ui/sampling_selector.cpp
ui/search_entry.cpp
ui/select_accelerator.cpp
ui/select_shortcut.cpp
ui/selection_mode_field.cpp
ui/skin/font_data.cpp
ui/skin/skin_part.cpp
ui/skin/skin_property.cpp
ui/skin/skin_slider_property.cpp
@ -684,6 +690,7 @@ target_sources(app-lib PRIVATE
ui/tile_button.cpp
ui/tileset_selector.cpp
ui/timeline/ani_controls.cpp
ui/timeline/doc_providers.cpp
ui/timeline/timeline.cpp
ui/toolbar.cpp
ui/user_data_view.cpp
@ -706,6 +713,7 @@ target_sources(app-lib PRIVATE
util/layer_utils.cpp
util/msk_file.cpp
util/new_image_from_mask.cpp
util/open_file_job.cpp
util/pal_ops.cpp
util/pic_file.cpp
util/pixel_ratio.cpp

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2018-2024 Igara Studio S.A.
// Copyright (C) 2018-2025 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
@ -79,7 +79,7 @@
#include "os/x11/system.h"
#endif
#if ENABLE_WEBP && LAF_WINDOWS
#if ENABLE_WEBP && LAF_WINDOWS && LAF_SKIA
#include "app/util/decode_webp.h"
#endif
@ -485,7 +485,7 @@ void App::run(const bool runGuiManager)
// How to interpret one finger on Windows tablets.
manager->display()->nativeWindow()->setInterpretOneFingerGestureAsMouseMovement(
preferences().experimental.oneFingerAsMouseMovement());
#if ENABLE_WEBP
#if ENABLE_WEBP && LAF_SKIA
// In Windows we use a custom webp decoder for drag & drop operations.
os::set_decode_webp(util::decode_webp);
#endif

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2019-2024 Igara Studio S.A.
// Copyright (C) 2019-2025 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
@ -113,11 +113,11 @@ bool can_call_global_shortcut(const AppMenuItem::Native* native)
(focus == nullptr || focus->type() != ui::kEntryWidget ||
!is_text_entry_shortcut(native->shortcut)) &&
(native->keyContext == KeyContext::Any ||
native->keyContext == KeyboardShortcuts::instance()->getCurrentKeyContext());
native->keyContext == KeyboardShortcuts::getCurrentKeyContext());
}
// TODO this should be on "she" library (or we should use
// os::Shortcut instead of ui::Accelerators)
// TODO this should be on laf-os library (or we should use
// os::Shortcut instead of ui::Shortcuts)
int from_scancode_to_unicode(KeyScancode scancode)
{
static int map[] = {
@ -284,22 +284,21 @@ void destroy_menu_item(ui::Widget* item)
os::Shortcut get_os_shortcut_from_key(const Key* key)
{
if (key && !key->accels().empty()) {
const ui::Accelerator& accel = key->accels().front();
if (key && !key->shortcuts().empty()) {
const ui::Shortcut& shortcut = key->shortcuts().front();
#if LAF_MACOS
// Shortcuts with spacebar as modifier do not work well in macOS
// (they will be called when the space bar is unpressed too).
if ((accel.modifiers() & ui::kKeySpaceModifier) == ui::kKeySpaceModifier)
if ((shortcut.modifiers() & ui::kKeySpaceModifier) == ui::kKeySpaceModifier)
return os::Shortcut();
#endif
return os::Shortcut(
(accel.unicodeChar() ? accel.unicodeChar() : from_scancode_to_unicode(accel.scancode())),
accel.modifiers());
return os::Shortcut((shortcut.unicodeChar() ? shortcut.unicodeChar() :
from_scancode_to_unicode(shortcut.scancode())),
shortcut.modifiers());
}
else
return os::Shortcut();
return {};
}
AppMenus* AppMenus::s_instance = nullptr;
@ -719,7 +718,6 @@ Widget* AppMenus::convertXmlelemToMenuitem(XMLElement* elem, Menu* menu)
{
const char* id = elem->Attribute("id");
const char* group = elem->Attribute("group");
const char* standard = elem->Attribute("standard");
// is it a <separator>?
if (strcmp(elem->Value(), "separator") == 0) {
@ -781,6 +779,7 @@ Widget* AppMenus::convertXmlelemToMenuitem(XMLElement* elem, Menu* menu)
}
#if LAF_MACOS
const char* standard = elem->Attribute("standard");
if (standard && strcmp(standard, "edit") == 0)
menuitem->setAsStandardEditMenu();
#endif

View File

@ -1,4 +1,5 @@
// Aseprite
// Copyright (C) 2025 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
@ -20,7 +21,20 @@ namespace app { namespace cmd {
using namespace doc;
ClearRect::ClearRect(Cel* cel, const gfx::Rect& bounds, color_t color)
{
ASSERT(cel);
initialize(cel, bounds, color);
}
ClearRect::ClearRect(Cel* cel, const gfx::Rect& bounds)
{
ASSERT(cel);
Doc* doc = static_cast<Doc*>(cel->document());
initialize(cel, bounds, doc->bgColor(cel->layer()));
}
void ClearRect::initialize(Cel* cel, const gfx::Rect& bounds, color_t color)
{
ASSERT(cel);
@ -37,9 +51,7 @@ ClearRect::ClearRect(Cel* cel, const gfx::Rect& bounds)
return;
m_dstImage.reset(new WithImage(image));
Doc* doc = static_cast<Doc*>(cel->document());
m_bgcolor = doc->bgColor(cel->layer());
m_bgcolor = color;
m_copy.reset(crop_image(image, bounds2.x, bounds2.y, bounds2.w, bounds2.h, m_bgcolor));
}

View File

@ -1,4 +1,5 @@
// Aseprite
// Copyright (C) 2025 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
@ -26,6 +27,7 @@ using namespace doc;
class ClearRect : public Cmd {
public:
ClearRect(Cel* cel, const gfx::Rect& bounds);
ClearRect(Cel* cel, const gfx::Rect& bounds, color_t color);
protected:
void onExecute() override;
@ -37,6 +39,7 @@ protected:
}
private:
void initialize(Cel* cel, const gfx::Rect& bounds, color_t color);
void clear();
void restore();

View File

@ -1,397 +0,0 @@
// Aseprite
// Copyright (C) 2024 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/drop_on_timeline.h"
#include "app/cmd/add_layer.h"
#include "app/cmd/move_cel.h"
#include "app/cmd/set_pixel_format.h"
#include "app/console.h"
#include "app/context_flags.h"
#include "app/doc.h"
#include "app/doc_event.h"
#include "app/file/file.h"
#include "app/tx.h"
#include "app/util/layer_utils.h"
#include "app/util/open_file_job.h"
#include "base/serialization.h"
#include "doc/layer_io.h"
#include "doc/layer_list.h"
#include "doc/subobjects_io.h"
#include "render/dithering.h"
#include <algorithm>
namespace app { namespace cmd {
using namespace base::serialization::little_endian;
DropOnTimeline::DropOnTimeline(app::Doc* doc,
doc::frame_t frame,
doc::layer_t layerIndex,
InsertionPoint insert,
DroppedOn droppedOn,
const base::paths& paths)
: WithDocument(doc)
, m_size(0)
, m_paths(paths)
, m_frame(frame)
, m_layerIndex(layerIndex)
, m_insert(insert)
, m_droppedOn(droppedOn)
{
ASSERT(m_layerIndex >= 0);
for (const auto& path : m_paths)
m_size += path.size();
// Zero layers stored.
write32(m_stream, 0);
m_size += sizeof(uint32_t);
}
DropOnTimeline::DropOnTimeline(app::Doc* doc,
doc::frame_t frame,
doc::layer_t layerIndex,
InsertionPoint insert,
DroppedOn droppedOn,
const doc::ImageRef& image)
: WithDocument(doc)
, m_size(0)
, m_image(image)
, m_frame(frame)
, m_layerIndex(layerIndex)
, m_insert(insert)
, m_droppedOn(droppedOn)
{
ASSERT(m_layerIndex >= 0);
// Zero layers stored.
write32(m_stream, 0);
m_size += sizeof(uint32_t);
}
void DropOnTimeline::onExecute()
{
Doc* destDoc = document();
m_previousTotalFrames = destDoc->sprite()->totalFrames();
int docsProcessed = 0;
while (hasPendingWork()) {
std::unique_ptr<Doc> srcDoc;
if (!getNextDoc(srcDoc))
return;
if (srcDoc) {
docsProcessed++;
// If source document doesn't match the destination document's color
// mode, change it.
if (srcDoc->colorMode() != destDoc->colorMode()) {
// Execute in a source doc transaction because we don't need undo/redo
// this.
Tx tx(srcDoc.get());
tx(new cmd::SetPixelFormat(srcDoc->sprite(),
destDoc->sprite()->pixelFormat(),
render::Dithering(),
Preferences::instance().quantization.rgbmapAlgorithm(),
nullptr,
nullptr,
FitCriteria::DEFAULT));
tx.commit();
}
// If there is only one source document to process and it has a cel that
// can be moved, then move the cel from the source doc into the
// destination doc's selected frame.
const bool isJustOneDoc = (docsProcessed == 1 && !hasPendingWork());
if (isJustOneDoc && canMoveCelFrom(srcDoc.get())) {
auto* srcLayer = static_cast<LayerImage*>(srcDoc->sprite()->firstLayer());
auto* destLayer = static_cast<LayerImage*>(destDoc->sprite()->allLayers()[m_layerIndex]);
executeAndAdd(new MoveCel(srcLayer, 0, destLayer, m_frame, false));
break;
}
// If there is no room for the source frames, add frames to the
// destination sprite.
if (m_frame + srcDoc->sprite()->totalFrames() > destDoc->sprite()->totalFrames()) {
destDoc->sprite()->setTotalFrames(m_frame + srcDoc->sprite()->totalFrames());
}
// Save dropped layers from source document.
saveDroppedLayers(srcDoc->sprite()->root()->layers(), destDoc->sprite());
}
}
if (m_droppedLayersIds.empty())
return;
destDoc->sprite()->incrementVersion();
destDoc->incrementVersion();
insertDroppedLayers();
}
void DropOnTimeline::onUndo()
{
CmdSequence::onUndo();
if (m_droppedLayersIds.empty()) {
notifyGeneralUpdate();
return;
}
Doc* doc = document();
frame_t currentTotalFrames = doc->sprite()->totalFrames();
for (auto id : m_droppedLayersIds) {
auto* layer = doc::get<Layer>(id);
ASSERT(layer);
if (layer) {
DocEvent ev(doc);
ev.sprite(layer->sprite());
ev.layer(layer);
doc->notify_observers<DocEvent&>(&DocObserver::onBeforeRemoveLayer, ev);
LayerGroup* group = layer->parent();
group->removeLayer(layer);
group->incrementVersion();
group->sprite()->incrementVersion();
doc->notify_observers<DocEvent&>(&DocObserver::onAfterRemoveLayer, ev);
delete layer;
}
}
doc->sprite()->setTotalFrames(m_previousTotalFrames);
doc->sprite()->incrementVersion();
m_previousTotalFrames = currentTotalFrames;
}
void DropOnTimeline::onRedo()
{
CmdSequence::onRedo();
if (m_droppedLayersIds.empty()) {
notifyGeneralUpdate();
return;
}
Doc* doc = document();
frame_t currentTotalFrames = doc->sprite()->totalFrames();
doc->sprite()->setTotalFrames(m_previousTotalFrames);
doc->sprite()->incrementVersion();
m_previousTotalFrames = currentTotalFrames;
insertDroppedLayers();
}
void DropOnTimeline::setupInsertionLayer(Layer*& layer, LayerGroup*& group)
{
const LayerList& allLayers = document()->sprite()->allLayers();
layer = allLayers[m_layerIndex];
if (m_insert == InsertionPoint::BeforeLayer && layer->isGroup()) {
group = static_cast<LayerGroup*>(layer);
// The user is trying to drop layers into an empty group, so there is no after
// nor before layer...
if (group->layersCount() == 0) {
layer = nullptr;
return;
}
layer = group->lastLayer();
m_insert = InsertionPoint::AfterLayer;
}
group = layer->parent();
}
bool DropOnTimeline::hasPendingWork()
{
return m_image || !m_paths.empty();
}
bool DropOnTimeline::getNextDocFromImage(std::unique_ptr<Doc>& srcDoc)
{
if (!m_image)
return true;
Sprite* sprite = new Sprite(m_image->spec(), 256);
LayerImage* layer = new LayerImage(sprite);
sprite->root()->addLayer(layer);
Cel* cel = new Cel(0, m_image);
layer->addCel(cel);
srcDoc = std::make_unique<Doc>(sprite);
m_image = nullptr;
return true;
}
bool DropOnTimeline::getNextDocFromPaths(std::unique_ptr<Doc>& srcDoc)
{
Console console;
Context* context = document()->context();
int flags = FILE_LOAD_DATA_FILE | FILE_LOAD_AVOID_BACKGROUND_LAYER | FILE_LOAD_CREATE_PALETTE |
FILE_LOAD_SEQUENCE_YES;
std::unique_ptr<FileOp> fop(FileOp::createLoadDocumentOperation(context, m_paths.front(), flags));
// Remove the path that is currently being processed
m_paths.erase(m_paths.begin());
// Do nothing (the user cancelled or something like that)
if (!fop)
return false;
if (fop->hasError()) {
console.printf(fop->error().c_str());
return true;
}
base::paths fopFilenames;
fop->getFilenameList(fopFilenames);
// Remove paths that will be loaded by the current file operation.
for (const auto& filename : fopFilenames) {
auto it = std::find(m_paths.begin(), m_paths.end(), filename);
if (it != m_paths.end())
m_paths.erase(it);
}
OpenFileJob task(fop.get(), true);
task.showProgressWindow();
// Post-load processing, it is called from the GUI because may require user intervention.
fop->postLoad();
// Show any error
if (fop->hasError() && !fop->isStop())
console.printf(fop->error().c_str());
srcDoc.reset(fop->releaseDocument());
return true;
}
bool DropOnTimeline::getNextDoc(std::unique_ptr<Doc>& srcDoc)
{
if (m_image == nullptr && !m_paths.empty())
return getNextDocFromPaths(srcDoc);
return getNextDocFromImage(srcDoc);
}
void DropOnTimeline::storeDroppedLayerIds(const Layer* layer)
{
if (layer->isGroup()) {
const auto* group = static_cast<const LayerGroup*>(layer);
for (auto* child : group->layers())
storeDroppedLayerIds(child);
m_droppedLayersIds.push_back(group->id());
}
else {
m_droppedLayersIds.push_back(layer->id());
}
}
void DropOnTimeline::saveDroppedLayers(const LayerList& layers, Sprite* sprite)
{
size_t start = m_stream.tellp();
// Calculate the new number of layers.
m_stream.seekg(0);
uint32_t nLayers = read32(m_stream) + layers.size();
// Flat list of all the dropped layers.
LayerList allDroppedLayers;
// Write number of layers (at the beginning of the stream).
m_stream.seekp(0);
write32(m_stream, nLayers);
// Move to where we must start writing.
m_stream.seekp(start);
for (auto it = layers.cbegin(); it != layers.cend(); ++it) {
auto* layer = *it;
// TODO: If we could "relocate" a layer from the source document to the
// destination document we could avoid making a copy here.
std::unique_ptr<Layer> layerCopy(copy_layer_with_sprite(layer, sprite));
layerCopy->displaceFrames(0, m_frame);
write_layer(m_stream, layerCopy.get());
storeDroppedLayerIds(layerCopy.get());
}
size_t end = m_stream.tellp();
m_size += end - start;
}
void DropOnTimeline::insertDroppedLayers()
{
// Layer used as a reference to determine if the dropped layers will be
// inserted after or before it.
Layer* refLayer = nullptr;
// Parent group of the reference layer layer.
LayerGroup* group = nullptr;
// Keep track of the current insertion point.
InsertionPoint insert = m_insert;
setupInsertionLayer(refLayer, group);
SubObjectsFromSprite io(group->sprite());
m_stream.seekg(0);
auto nLayers = read32(m_stream);
for (int i = 0; i < nLayers; ++i) {
auto* layer = read_layer(m_stream, &io);
if (!refLayer) {
group->addLayer(layer);
refLayer = layer;
insert = InsertionPoint::AfterLayer;
}
else if (insert == InsertionPoint::AfterLayer) {
group->insertLayer(layer, refLayer);
refLayer = layer;
}
else if (insert == InsertionPoint::BeforeLayer) {
group->insertLayerBefore(layer, refLayer);
refLayer = layer;
insert = InsertionPoint::AfterLayer;
}
group->incrementVersion();
group->sprite()->incrementVersion();
Doc* doc = static_cast<Doc*>(group->sprite()->document());
DocEvent ev(doc);
ev.sprite(group->sprite());
ev.layer(layer);
doc->notify_observers<DocEvent&>(&DocObserver::onAddLayer, ev);
}
}
// Returns true if the document srcDoc has a cel that can be moved.
// The cel from the srcDoc can be moved only when all of the following
// conditions are met:
// * Drop took place in a cel.
// * Source doc has only one layer with just one frame.
// * The layer from the source doc and the destination cel's layer are both
// Image layers.
// Otherwise this function returns false.
bool DropOnTimeline::canMoveCelFrom(app::Doc* srcDoc)
{
auto* srcLayer = srcDoc->sprite()->firstLayer();
auto* destLayer = document()->sprite()->allLayers()[m_layerIndex];
return m_droppedOn == DroppedOn::Cel && srcDoc->sprite()->allLayersCount() == 1 &&
srcDoc->sprite()->totalFrames() == 1 && srcLayer->isImage() && destLayer->isImage();
}
void DropOnTimeline::notifyGeneralUpdate()
{
Doc* doc = document();
if (!doc)
return;
doc->notifyGeneralUpdate();
}
}} // namespace app::cmd

View File

@ -1,95 +0,0 @@
// Aseprite
// Copyright (C) 2024 Igara Studio S.A.
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
#ifndef APP_CMD_drop_on_timeline_H_INCLUDED
#define APP_CMD_drop_on_timeline_H_INCLUDED
#pragma once
#include "app/cmd/with_document.h"
#include "app/cmd_sequence.h"
#include "app/doc_observer.h"
#include "base/paths.h"
#include "doc/frame.h"
#include "doc/image_ref.h"
#include "doc/layer.h"
#include "doc/layer_list.h"
namespace app { namespace cmd {
class DropOnTimeline : public CmdSequence,
public WithDocument {
public:
enum class InsertionPoint {
BeforeLayer,
AfterLayer,
};
enum class DroppedOn {
Unspecified,
Frame,
Layer,
Cel,
};
// Inserts the layers and frames of the documents pointed by the specified
// paths, at the specified frame and before or after the specified layer index.
DropOnTimeline(app::Doc* doc,
doc::frame_t frame,
doc::layer_t layerIndex,
InsertionPoint insert,
DroppedOn droppedOn,
const base::paths& paths);
// Inserts the image as if it were a document with just one layer and one
// frame, at the specified frame and before or after the specified layer index.
DropOnTimeline(app::Doc* doc,
doc::frame_t frame,
doc::layer_t layerIndex,
InsertionPoint insert,
DroppedOn droppedOn,
const doc::ImageRef& image);
protected:
void onExecute() override;
void onUndo() override;
void onRedo() override;
size_t onMemSize() const override { return sizeof(*this) + m_size; }
private:
void setupInsertionLayer(doc::Layer*& layer, doc::LayerGroup*& group);
void insertDroppedLayers();
bool canMoveCelFrom(app::Doc* srcDoc);
void notifyGeneralUpdate();
bool hasPendingWork();
// Returns the next document to be processed.
// Returns false when the user cancelled the process, or true when the
// process must go on.
bool getNextDoc(std::unique_ptr<Doc>& srcDoc);
bool getNextDocFromImage(std::unique_ptr<Doc>& srcDoc);
bool getNextDocFromPaths(std::unique_ptr<Doc>& srcDoc);
void storeDroppedLayerIds(const doc::Layer* layer);
void saveDroppedLayers(const doc::LayerList& layers, doc::Sprite* sprite);
size_t m_size;
base::paths m_paths;
doc::ImageRef m_image = nullptr;
doc::frame_t m_frame;
doc::layer_t m_layerIndex;
InsertionPoint m_insert;
DroppedOn m_droppedOn;
// Serialized dropped layers' data. Used for redo operation.
std::stringstream m_stream;
// Holds the Object IDs of the dropped layers. Used when determining which
// layers should be removed in an undo operation.
std::vector<doc::ObjectId> m_droppedLayersIds;
// Number of frames the doc had before dropping.
doc::frame_t m_previousTotalFrames;
};
}} // namespace app::cmd
#endif

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2020-2024 Igara Studio S.A.
// Copyright (C) 2020-2025 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
@ -11,12 +11,12 @@
#include "app/app.h"
#include "app/commands/command.h"
#include "app/modules/gui.h"
#include "app/ui/main_window.h"
#include "fmt/format.h"
#include "ver/info.h"
#include "about.xml.h"
#include "app/context.h"
namespace app {
@ -27,13 +27,19 @@ public:
AboutCommand();
protected:
bool onEnabled(Context* context) override;
void onExecute(Context* context) override;
};
AboutCommand::AboutCommand() : Command(CommandId::About(), CmdUIOnlyFlag)
AboutCommand::AboutCommand() : Command(CommandId::About())
{
}
bool AboutCommand::onEnabled(Context* context)
{
return context->isUIAvailable();
}
void AboutCommand::onExecute(Context* context)
{
gen::About window;
@ -44,7 +50,7 @@ void AboutCommand::onExecute(Context* context)
});
window.credits()->Click.connect([&window] {
window.closeWindow(nullptr);
App::instance()->mainWindow()->showBrowser("README.md", "Authors");
App::instance()->mainWindow()->showBrowser("AUTHORS.md", "Authors");
});
window.i18nCredits()->Click.connect([&window] {
window.closeWindow(nullptr);

View File

@ -63,8 +63,7 @@ protected:
std::string onGetFriendlyName() const override;
};
AddColorCommand::AddColorCommand()
: CommandWithNewParams<AddColorParams>(CommandId::AddColor(), CmdUIOnlyFlag)
AddColorCommand::AddColorCommand() : CommandWithNewParams<AddColorParams>(CommandId::AddColor())
{
}

View File

@ -1,4 +1,5 @@
// Aseprite
// Copyright (C) 2025 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
@ -16,8 +17,7 @@
#include "ui/ui.h"
#include "advanced_mode.xml.h"
#include <cstdio>
#include "app/context.h"
namespace app {
@ -28,13 +28,19 @@ public:
AdvancedModeCommand();
protected:
bool onEnabled(Context* context) override;
void onExecute(Context* context) override;
};
AdvancedModeCommand::AdvancedModeCommand() : Command(CommandId::AdvancedMode(), CmdUIOnlyFlag)
AdvancedModeCommand::AdvancedModeCommand() : Command(CommandId::AdvancedMode())
{
}
bool AdvancedModeCommand::onEnabled(Context* context)
{
return context->isUIAvailable();
}
void AdvancedModeCommand::onExecute(Context* context)
{
// Switch advanced mode.
@ -54,11 +60,11 @@ void AdvancedModeCommand::onExecute(Context* context)
if (oldMode == MainWindow::NormalMode && pref.advancedMode.showAlert()) {
KeyPtr key = KeyboardShortcuts::instance()->command(this->id().c_str());
if (!key->accels().empty()) {
if (!key->shortcuts().empty()) {
app::gen::AdvancedMode window;
window.warningLabel()->setTextf("You can go back pressing \"%s\" key.",
key->accels().front().toString().c_str());
key->shortcuts().front().toString().c_str());
window.openWindowInForeground();

View File

@ -15,7 +15,6 @@
#include "app/modules/gui.h"
#include "app/tx.h"
#include "doc/layer.h"
#include "doc/sprite.h"
namespace app {
@ -28,8 +27,7 @@ protected:
void onExecute(Context* context) override;
};
BackgroundFromLayerCommand::BackgroundFromLayerCommand()
: Command(CommandId::BackgroundFromLayer(), CmdRecordableFlag)
BackgroundFromLayerCommand::BackgroundFromLayerCommand() : Command(CommandId::BackgroundFromLayer())
{
}

View File

@ -37,7 +37,7 @@ private:
Type m_type;
};
CancelCommand::CancelCommand() : Command(CommandId::Cancel(), CmdUIOnlyFlag), m_type(NoOp)
CancelCommand::CancelCommand() : Command(CommandId::Cancel()), m_type(NoOp)
{
}

View File

@ -22,7 +22,6 @@
#include "app/ui/skin/skin_theme.h"
#include "app/ui_context.h"
#include "doc/image.h"
#include "doc/mask.h"
#include "doc/sprite.h"
#include "ui/ui.h"
@ -282,8 +281,7 @@ protected:
void onExecute(Context* context) override;
};
CanvasSizeCommand::CanvasSizeCommand()
: CommandWithNewParams(CommandId::CanvasSize(), CmdRecordableFlag)
CanvasSizeCommand::CanvasSizeCommand() : CommandWithNewParams(CommandId::CanvasSize())
{
}

View File

@ -20,8 +20,6 @@
#include "app/tx.h"
#include "app/ui/timeline/timeline.h"
#include "doc/cel.h"
#include "doc/cels_range.h"
#include "doc/sprite.h"
#include <string>
@ -42,7 +40,7 @@ private:
int m_opacity;
};
CelOpacityCommand::CelOpacityCommand() : Command(CommandId::CelOpacity(), CmdUIOnlyFlag)
CelOpacityCommand::CelOpacityCommand() : Command(CommandId::CelOpacity())
{
m_opacity = 255;
}

View File

@ -23,7 +23,6 @@
#include "app/ui/timeline/timeline.h"
#include "app/ui/user_data_view.h"
#include "app/ui_context.h"
#include "base/mem_utils.h"
#include "base/scoped_value.h"
#include "doc/cel.h"
#include "doc/cels_range.h"
@ -385,14 +384,14 @@ protected:
void onExecute(Context* context) override;
};
CelPropertiesCommand::CelPropertiesCommand() : Command(CommandId::CelProperties(), CmdUIOnlyFlag)
CelPropertiesCommand::CelPropertiesCommand() : Command(CommandId::CelProperties())
{
}
bool CelPropertiesCommand::onEnabled(Context* context)
{
return context->checkFlags(ContextFlags::ActiveDocumentIsWritable |
ContextFlags::ActiveLayerIsImage);
return context->isUIAvailable() && context->checkFlags(ContextFlags::ActiveDocumentIsWritable |
ContextFlags::ActiveLayerIsImage);
}
void CelPropertiesCommand::onExecute(Context* context)

View File

@ -21,7 +21,6 @@
#include "app/tools/tool.h"
#include "app/ui/context_bar.h"
#include "app/ui/main_window.h"
#include "base/convert_to.h"
#include "doc/algorithm/flip_image.h"
#include "doc/brush.h"
#include "doc/image_ref.h"
@ -64,7 +63,7 @@ private:
int m_slot;
};
ChangeBrushCommand::ChangeBrushCommand() : Command(CommandId::ChangeBrush(), CmdUIOnlyFlag)
ChangeBrushCommand::ChangeBrushCommand() : Command(CommandId::ChangeBrush())
{
m_change = None;
m_slot = 0;

View File

@ -14,6 +14,7 @@
#include "app/app.h"
#include "app/commands/command.h"
#include "app/commands/params.h"
#include "app/context.h"
#include "app/i18n/strings.h"
#include "app/modules/palettes.h"
#include "app/ui/color_bar.h"
@ -39,18 +40,24 @@ public:
ChangeColorCommand();
protected:
bool onEnabled(Context* context) override;
bool onNeedsParams() const override { return true; }
void onLoadParams(const Params& params) override;
void onExecute(Context* context) override;
std::string onGetFriendlyName() const override;
};
ChangeColorCommand::ChangeColorCommand() : Command(CommandId::ChangeColor(), CmdUIOnlyFlag)
ChangeColorCommand::ChangeColorCommand() : Command(CommandId::ChangeColor())
{
m_background = false;
m_change = None;
}
bool ChangeColorCommand::onEnabled(Context* context)
{
return context->isUIAvailable();
}
void ChangeColorCommand::onLoadParams(const Params& params)
{
std::string target = params.get("target");

View File

@ -21,9 +21,7 @@
#include "app/i18n/strings.h"
#include "app/load_matrix.h"
#include "app/modules/gui.h"
#include "app/modules/palettes.h"
#include "app/sprite_job.h"
#include "app/transaction.h"
#include "app/ui/best_fit_criteria_selector.h"
#include "app/ui/dithering_selector.h"
#include "app/ui/editor/editor.h"
@ -37,12 +35,10 @@
#include "fmt/format.h"
#include "render/dithering.h"
#include "render/dithering_algorithm.h"
#include "render/ordered_dither.h"
#include "render/quantization.h"
#include "render/render.h"
#include "render/task_delegate.h"
#include "ui/listitem.h"
#include "ui/paint_event.h"
#include "ui/size_hint_event.h"
#include "color_mode.xml.h"
@ -507,7 +503,7 @@ private:
};
ChangePixelFormatCommand::ChangePixelFormatCommand()
: CommandWithNewParams(CommandId::ChangePixelFormat(), CmdUIOnlyFlag)
: CommandWithNewParams(CommandId::ChangePixelFormat())
{
}

View File

@ -23,7 +23,7 @@ protected:
void onExecute(Context* ctx) override;
};
ClearCommand::ClearCommand() : Command(CommandId::Clear(), CmdUIOnlyFlag)
ClearCommand::ClearCommand() : Command(CommandId::Clear())
{
}

View File

@ -19,7 +19,6 @@
#include "app/ui/status_bar.h"
#include "doc/cel.h"
#include "doc/layer.h"
#include "doc/sprite.h"
namespace app {
@ -32,7 +31,7 @@ protected:
void onExecute(Context* context) override;
};
ClearCelCommand::ClearCelCommand() : Command(CommandId::ClearCel(), CmdRecordableFlag)
ClearCelCommand::ClearCelCommand() : Command(CommandId::ClearCel())
{
}
@ -76,7 +75,7 @@ void ClearCelCommand::onExecute(Context* context)
tx.commit();
}
if (nonEditableLayers)
if (context->isUIAvailable() && nonEditableLayers)
StatusBar::instance()->showTip(1000, Strings::statusbar_tips_locked_layers());
update_screen_for_document(document);

View File

@ -23,8 +23,7 @@ protected:
void onExecute(Context* ctx) override;
};
ClearRecentFilesCommand::ClearRecentFilesCommand()
: Command(CommandId::ClearRecentFiles(), CmdUIOnlyFlag)
ClearRecentFilesCommand::ClearRecentFilesCommand() : Command(CommandId::ClearRecentFiles())
{
}

View File

@ -12,15 +12,9 @@
#include "app/app.h"
#include "app/commands/command.h"
#include "app/commands/commands.h"
#include "app/context_access.h"
#include "app/ui/doc_view.h"
#include "app/ui/status_bar.h"
#include "app/ui/workspace.h"
#include "app/ui_context.h"
#include "doc/sprite.h"
#include "ui/ui.h"
#include <memory>
namespace app {
@ -28,7 +22,7 @@ using namespace ui;
class CloseFileCommand : public Command {
public:
CloseFileCommand() : Command(CommandId::CloseFile(), CmdUIOnlyFlag) {}
CloseFileCommand() : Command(CommandId::CloseFile()) {}
protected:
bool onEnabled(Context* context) override
@ -51,12 +45,15 @@ protected:
class CloseAllFilesCommand : public Command {
public:
CloseAllFilesCommand() : Command(CommandId::CloseAllFiles(), CmdRecordableFlag)
{
m_quitting = false;
}
CloseAllFilesCommand() : Command(CommandId::CloseAllFiles()) { m_quitting = false; }
protected:
bool onEnabled(Context* context) override
{
// Null if we are in --batch mode
return App::instance()->workspace() != nullptr;
}
void onLoadParams(const Params& params) override { m_quitting = params.get_as<bool>("quitting"); }
void onExecute(Context* context) override

View File

@ -21,7 +21,6 @@
#include "app/transaction.h"
#include "app/ui/color_bar.h"
#include "app/ui/rgbmap_algorithm_selector.h"
#include "app/ui_context.h"
#include "doc/palette.h"
#include "doc/sprite.h"
#include "render/quantization.h"
@ -71,7 +70,7 @@ protected:
};
ColorQuantizationCommand::ColorQuantizationCommand()
: CommandWithNewParams<ColorQuantizationParams>(CommandId::ColorQuantization(), CmdRecordableFlag)
: CommandWithNewParams<ColorQuantizationParams>(CommandId::ColorQuantization())
{
}

View File

@ -24,7 +24,7 @@ protected:
void onExecute(Context* context) override;
};
ContiguousFillCommand::ContiguousFillCommand() : Command(CommandId::ContiguousFill(), CmdUIOnlyFlag)
ContiguousFillCommand::ContiguousFillCommand() : Command(CommandId::ContiguousFill())
{
}

View File

@ -23,7 +23,7 @@ protected:
void onExecute(Context* ctx) override;
};
CopyCommand::CopyCommand() : Command(CommandId::Copy(), CmdUIOnlyFlag)
CopyCommand::CopyCommand() : Command(CommandId::Copy())
{
}

View File

@ -10,9 +10,7 @@
#include "app/app.h"
#include "app/commands/command.h"
#include "app/context_access.h"
#include "app/ui/timeline/timeline.h"
#include "ui/base.h"
namespace app {
@ -25,13 +23,13 @@ protected:
void onExecute(Context* context) override;
};
CopyCelCommand::CopyCelCommand() : Command(CommandId::CopyCel(), CmdUIOnlyFlag)
CopyCelCommand::CopyCelCommand() : Command(CommandId::CopyCel())
{
}
bool CopyCelCommand::onEnabled(Context* context)
{
return App::instance()->timeline()->isMovingCel();
return App::instance()->timeline() && App::instance()->timeline()->isMovingCel();
}
void CopyCelCommand::onExecute(Context* context)

View File

@ -24,7 +24,7 @@ protected:
void onExecute(Context* ctx) override;
};
CopyMergedCommand::CopyMergedCommand() : Command(CommandId::CopyMerged(), CmdUIOnlyFlag)
CopyMergedCommand::CopyMergedCommand() : Command(CommandId::CopyMerged())
{
}

View File

@ -16,11 +16,7 @@
#include "app/modules/gui.h"
#include "app/tx.h"
#include "app/ui/color_bar.h"
#include "app/util/autocrop.h"
#include "doc/image.h"
#include "doc/layer.h"
#include "doc/mask.h"
#include "doc/sprite.h"
namespace app {
@ -37,7 +33,7 @@ private:
gfx::Rect m_bounds;
};
CropSpriteCommand::CropSpriteCommand() : Command(CommandId::CropSprite(), CmdRecordableFlag)
CropSpriteCommand::CropSpriteCommand() : Command(CommandId::CropSprite())
{
}
@ -95,8 +91,7 @@ private:
bool m_byGrid = false;
};
AutocropSpriteCommand::AutocropSpriteCommand()
: Command(CommandId::AutocropSprite(), CmdRecordableFlag)
AutocropSpriteCommand::AutocropSpriteCommand() : Command(CommandId::AutocropSprite())
{
}

View File

@ -23,7 +23,7 @@ protected:
void onExecute(Context* ctx) override;
};
CutCommand::CutCommand() : Command(CommandId::Cut(), CmdUIOnlyFlag)
CutCommand::CutCommand() : Command(CommandId::Cut())
{
}

View File

@ -14,8 +14,6 @@
#include "app/context_access.h"
#include "app/modules/gui.h"
#include "app/tx.h"
#include "doc/mask.h"
#include "doc/sprite.h"
namespace app {
@ -28,7 +26,7 @@ protected:
void onExecute(Context* context) override;
};
DeselectMaskCommand::DeselectMaskCommand() : Command(CommandId::DeselectMask(), CmdRecordableFlag)
DeselectMaskCommand::DeselectMaskCommand() : Command(CommandId::DeselectMask())
{
}

View File

@ -29,8 +29,7 @@ protected:
void onExecute(Context* context);
};
DeveloperConsoleCommand::DeveloperConsoleCommand()
: Command(CommandId::DeveloperConsole(), CmdUIOnlyFlag)
DeveloperConsoleCommand::DeveloperConsoleCommand() : Command(CommandId::DeveloperConsole())
{
}

View File

@ -12,8 +12,6 @@
#include "app/app.h"
#include "app/commands/command.h"
#include "app/commands/commands.h"
#include "app/context_access.h"
#include "app/tools/tool_box.h"
#include "app/ui/context_bar.h"
#include "app/ui_context.h"
@ -28,12 +26,15 @@ protected:
void onExecute(Context* context) override;
};
DiscardBrushCommand::DiscardBrushCommand() : Command(CommandId::DiscardBrush(), CmdUIOnlyFlag)
DiscardBrushCommand::DiscardBrushCommand() : Command(CommandId::DiscardBrush())
{
}
bool DiscardBrushCommand::onEnabled(Context* context)
{
if (!context->isUIAvailable())
return false;
ContextBar* ctxBar = App::instance()->contextBar();
return (ctxBar->activeBrush()->type() == kImageBrushType);
}

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2018 David Capello
// Copyright (C) 2001-2025 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@ -10,16 +10,11 @@
#include "app/app.h"
#include "app/commands/command.h"
#include "app/console.h"
#include "app/context_access.h"
#include "app/doc_api.h"
#include "app/doc_undo.h"
#include "app/modules/gui.h"
#include "app/tx.h"
#include "app/ui/editor/editor.h"
#include "doc/layer.h"
#include "doc/sprite.h"
#include "ui/ui.h"
namespace app {
@ -32,8 +27,7 @@ protected:
void onExecute(Context* context) override;
};
DuplicateLayerCommand::DuplicateLayerCommand()
: Command(CommandId::DuplicateLayer(), CmdRecordableFlag)
DuplicateLayerCommand::DuplicateLayerCommand() : Command(CommandId::DuplicateLayer())
{
}
@ -51,7 +45,7 @@ void DuplicateLayerCommand::onExecute(Context* context)
Tx tx(writer, "Layer Duplication");
LayerImage* sourceLayer = static_cast<LayerImage*>(writer.layer());
DocApi api = document->getApi(tx);
api.duplicateLayerAfter(sourceLayer, sourceLayer->parent(), sourceLayer);
api.duplicateLayerAfter(sourceLayer, sourceLayer->parent(), sourceLayer, " Copy");
tx.commit();
}

View File

@ -16,13 +16,10 @@
#include "app/ini_file.h"
#include "app/ui_context.h"
#include "base/fs.h"
#include "doc/sprite.h"
#include "ui/ui.h"
#include "duplicate_sprite.xml.h"
#include <cstdio>
namespace app {
using namespace ui;
@ -43,7 +40,7 @@ protected:
};
DuplicateSpriteCommand::DuplicateSpriteCommand()
: CommandWithNewParams<DuplicateSpriteParams>(CommandId::DuplicateSprite(), CmdRecordableFlag)
: CommandWithNewParams<DuplicateSpriteParams>(CommandId::DuplicateSprite())
{
}

View File

@ -13,8 +13,6 @@
#include "app/commands/command.h"
#include "app/ui/workspace.h"
#include <cstdio>
namespace app {
// using namespace ui;
@ -28,7 +26,7 @@ protected:
void onExecute(Context* context) override;
};
DuplicateViewCommand::DuplicateViewCommand() : Command(CommandId::DuplicateView(), CmdUIOnlyFlag)
DuplicateViewCommand::DuplicateViewCommand() : Command(CommandId::DuplicateView())
{
}

View File

@ -5,7 +5,6 @@
// the End-User License Agreement for Aseprite.
#include "app/commands/command.h"
#include "app/context.h"
#ifdef ENABLE_DRM
#include "app/ui/enter_license.h"
@ -24,7 +23,7 @@ protected:
void onExecute(Context* context) override;
};
EnterLicenseCommand::EnterLicenseCommand() : Command(CommandId::EnterLicense(), CmdUIOnlyFlag)
EnterLicenseCommand::EnterLicenseCommand() : Command(CommandId::EnterLicense())
{
}

View File

@ -16,7 +16,6 @@
#include "app/doc.h"
#include "app/job.h"
#include "app/ui/main_window.h"
#include "ui/alert.h"
#ifdef ENABLE_SCRIPTING
#include "app/commands/debugger.h"
@ -32,7 +31,7 @@ protected:
void onExecute(Context* context) override;
};
ExitCommand::ExitCommand() : Command(CommandId::Exit(), CmdUIOnlyFlag)
ExitCommand::ExitCommand() : Command(CommandId::Exit())
{
}

View File

@ -33,15 +33,12 @@
#include "app/ui/status_bar.h"
#include "app/ui/timeline/timeline.h"
#include "app/util/layer_utils.h"
#include "base/convert_to.h"
#include "base/fs.h"
#include "base/string.h"
#include "base/thread.h"
#include "doc/layer.h"
#include "doc/layer_tilemap.h"
#include "doc/tag.h"
#include "doc/tileset.h"
#include "doc/tilesets.h"
#include "fmt/format.h"
#include "ui/message.h"
#include "ui/system.h"
@ -1187,8 +1184,7 @@ private:
} // anonymous namespace
ExportSpriteSheetCommand::ExportSpriteSheetCommand(const char* id)
: CommandWithNewParams(id, CmdRecordableFlag)
ExportSpriteSheetCommand::ExportSpriteSheetCommand(const char* id) : CommandWithNewParams(id)
{
}

View File

@ -17,7 +17,6 @@
#include "app/context.h"
#include "app/pref/preferences.h"
#include "app/site.h"
#include "app/tools/tool.h"
#include "app/tools/tool_box.h"
#include "app/ui/color_bar.h"
#include "app/ui/editor/editor.h"
@ -28,7 +27,7 @@ namespace app {
using namespace ui;
EyedropperCommand::EyedropperCommand() : Command(CommandId::Eyedropper(), CmdUIOnlyFlag)
EyedropperCommand::EyedropperCommand() : Command(CommandId::Eyedropper())
{
m_background = false;
}

View File

@ -39,7 +39,7 @@ private:
};
FillCommand::FillCommand(Type type)
: Command(type == Stroke ? CommandId::Stroke() : CommandId::Fill(), CmdUIOnlyFlag)
: Command(type == Stroke ? CommandId::Stroke() : CommandId::Fill())
, m_type(type)
{
}

View File

@ -11,7 +11,6 @@
#include "app/app.h"
#include "app/commands/command.h"
#include "app/context_access.h"
#include "app/ui/editor/editor.h"
namespace app {
@ -25,7 +24,7 @@ protected:
void onExecute(Context* context) override;
};
FitScreenCommand::FitScreenCommand() : Command(CommandId::FitScreen(), CmdUIOnlyFlag)
FitScreenCommand::FitScreenCommand() : Command(CommandId::FitScreen())
{
}

View File

@ -36,7 +36,7 @@ protected:
bool m_visibleOnly;
};
FlattenLayersCommand::FlattenLayersCommand() : Command(CommandId::FlattenLayers(), CmdUIOnlyFlag)
FlattenLayersCommand::FlattenLayersCommand() : Command(CommandId::FlattenLayers())
{
m_visibleOnly = false;
}

View File

@ -20,7 +20,6 @@
#include "app/commands/params.h"
#include "app/context_access.h"
#include "app/doc_api.h"
#include "app/doc_range.h"
#include "app/i18n/strings.h"
#include "app/modules/gui.h"
#include "app/tools/tool_box.h"
@ -38,11 +37,10 @@
#include "doc/layer.h"
#include "doc/mask.h"
#include "doc/sprite.h"
#include "gfx/size.h"
namespace app {
FlipCommand::FlipCommand() : Command(CommandId::Flip(), CmdRecordableFlag)
FlipCommand::FlipCommand() : Command(CommandId::Flip())
{
m_flipMask = false;
m_flipType = doc::algorithm::FlipHorizontal;

View File

@ -44,12 +44,11 @@ private:
// Frame to be shown. It can be ALL_FRAMES, CURRENT_RANGE, or a
// number indicating a specific frame (1 is the first frame).
Target m_target;
frame_t m_frame;
Target m_target = CURRENT_RANGE;
frame_t m_frame = 1;
};
FramePropertiesCommand::FramePropertiesCommand()
: Command(CommandId::FrameProperties(), CmdUIOnlyFlag)
FramePropertiesCommand::FramePropertiesCommand() : Command(CommandId::FrameProperties())
{
}
@ -59,7 +58,7 @@ void FramePropertiesCommand::onLoadParams(const Params& params)
if (frame == "all") {
m_target = ALL_FRAMES;
}
else if (frame == "current") {
else if (frame == "current" || !params.has_param("frame")) {
m_target = CURRENT_RANGE;
}
else {
@ -70,7 +69,7 @@ void FramePropertiesCommand::onLoadParams(const Params& params)
bool FramePropertiesCommand::onEnabled(Context* context)
{
return context->checkFlags(ContextFlags::ActiveDocumentIsWritable);
return context->isUIAvailable() && context->checkFlags(ContextFlags::ActiveDocumentIsWritable);
}
void FramePropertiesCommand::onExecute(Context* context)

View File

@ -15,7 +15,6 @@
#include "app/cmd/set_tag_range.h"
#include "app/cmd/set_tag_repeat.h"
#include "app/cmd/set_user_data.h"
#include "app/color.h"
#include "app/commands/command.h"
#include "app/commands/params.h"
#include "app/context_access.h"
@ -48,7 +47,7 @@ private:
};
FrameTagPropertiesCommand::FrameTagPropertiesCommand()
: Command(CommandId::FrameTagProperties(), CmdUIOnlyFlag)
: Command(CommandId::FrameTagProperties())
, m_tagId(NullId)
{
}
@ -66,7 +65,7 @@ void FrameTagPropertiesCommand::onLoadParams(const Params& params)
bool FrameTagPropertiesCommand::onEnabled(Context* context)
{
return context->checkFlags(ContextFlags::ActiveDocumentIsWritable);
return context->isUIAvailable() && context->checkFlags(ContextFlags::ActiveDocumentIsWritable);
}
void FrameTagPropertiesCommand::onExecute(Context* context)

View File

@ -27,7 +27,7 @@ protected:
void onExecute(Context* context) override;
};
FullscreenModeCommand::FullscreenModeCommand() : Command(CommandId::FullscreenMode(), CmdUIOnlyFlag)
FullscreenModeCommand::FullscreenModeCommand() : Command(CommandId::FullscreenMode())
{
}

View File

@ -23,10 +23,7 @@
#include "app/ui/main_window.h"
#include "app/ui/preview_editor.h"
#include "app/ui/status_bar.h"
#include "app/util/conversion_to_surface.h"
#include "doc/image.h"
#include "doc/palette.h"
#include "doc/primitives.h"
#include "doc/sprite.h"
#include "gfx/matrix.h"
#include "os/surface.h"
@ -308,8 +305,7 @@ protected:
void onExecute(Context* context) override;
};
FullscreenPreviewCommand::FullscreenPreviewCommand()
: Command(CommandId::FullscreenPreview(), CmdUIOnlyFlag)
FullscreenPreviewCommand::FullscreenPreviewCommand() : Command(CommandId::FullscreenPreview())
{
}

View File

@ -31,7 +31,7 @@ using namespace doc;
class GotoCommand : public Command {
protected:
GotoCommand(const char* id) : Command(id, CmdRecordableFlag) {}
GotoCommand(const char* id) : Command(id) {}
bool onEnabled(Context* context) override { return (Editor::activeEditor() != nullptr); }

View File

@ -24,11 +24,7 @@ namespace app {
class GotoLayerCommand : public Command {
public:
GotoLayerCommand(int offset, const char* id, CommandFlags flags)
: Command(id, flags)
, m_offset(offset)
{
}
GotoLayerCommand(int offset, const char* id) : Command(id), m_offset(offset) {}
protected:
bool onEnabled(Context* context) override
@ -88,12 +84,12 @@ private:
class GotoPreviousLayerCommand : public GotoLayerCommand {
public:
GotoPreviousLayerCommand() : GotoLayerCommand(-1, "GotoPreviousLayer", CmdUIOnlyFlag) {}
GotoPreviousLayerCommand() : GotoLayerCommand(-1, CommandId::GotoPreviousLayer()) {}
};
class GotoNextLayerCommand : public GotoLayerCommand {
public:
GotoNextLayerCommand() : GotoLayerCommand(+1, "GotoNextLayer", CmdUIOnlyFlag) {}
GotoNextLayerCommand() : GotoLayerCommand(+1, CommandId::GotoNextLayer()) {}
};
Command* CommandFactory::createGotoPreviousLayerCommand()

View File

@ -24,7 +24,7 @@ protected:
void onExecute(Context* context) override;
};
GotoNextTabCommand::GotoNextTabCommand() : Command(CommandId::GotoNextTab(), CmdUIOnlyFlag)
GotoNextTabCommand::GotoNextTabCommand() : Command(CommandId::GotoNextTab())
{
}
@ -50,8 +50,7 @@ protected:
void onExecute(Context* context) override;
};
GotoPreviousTabCommand::GotoPreviousTabCommand()
: Command(CommandId::GotoPreviousTab(), CmdRecordableFlag)
GotoPreviousTabCommand::GotoPreviousTabCommand() : Command(CommandId::GotoPreviousTab())
{
}

View File

@ -16,13 +16,9 @@
#include "app/context.h"
#include "app/context_access.h"
#include "app/doc.h"
#include "app/find_widget.h"
#include "app/load_widget.h"
#include "app/pref/preferences.h"
#include "app/tx.h"
#include "app/ui/status_bar.h"
#include "app/ui_context.h"
#include "doc/document.h"
#include "doc/mask.h"
#include "ui/window.h"
@ -37,7 +33,7 @@ using namespace gfx;
class SnapToGridCommand : public Command {
public:
SnapToGridCommand() : Command(CommandId::SnapToGrid(), CmdUIOnlyFlag) {}
SnapToGridCommand() : Command(CommandId::SnapToGrid()) {}
protected:
bool onChecked(Context* ctx) override
@ -52,13 +48,14 @@ protected:
bool newValue = !docPref.grid.snap();
docPref.grid.snap(newValue);
StatusBar::instance()->showSnapToGridWarning(newValue);
if (ctx->isUIAvailable())
StatusBar::instance()->showSnapToGridWarning(newValue);
}
};
class SelectionAsGridCommand : public Command {
public:
SelectionAsGridCommand() : Command(CommandId::SelectionAsGrid(), CmdUIOnlyFlag) {}
SelectionAsGridCommand() : Command(CommandId::SelectionAsGrid()) {}
protected:
bool onEnabled(Context* ctx) override
@ -93,13 +90,13 @@ protected:
void onExecute(Context* context) override;
};
GridSettingsCommand::GridSettingsCommand() : Command(CommandId::GridSettings(), CmdUIOnlyFlag)
GridSettingsCommand::GridSettingsCommand() : Command(CommandId::GridSettings())
{
}
bool GridSettingsCommand::onEnabled(Context* context)
{
return true;
return context->isUIAvailable();
}
void GridSettingsCommand::onExecute(Context* context)

View File

@ -10,6 +10,7 @@
#include "app/app.h"
#include "app/commands/command.h"
#include "app/context.h"
#include "app/ui/main_window.h"
namespace app {
@ -26,7 +27,7 @@ protected:
bool onEnabled(Context* context) override;
};
HomeCommand::HomeCommand() : Command(CommandId::Home(), CmdUIOnlyFlag)
HomeCommand::HomeCommand() : Command(CommandId::Home())
{
}
@ -41,7 +42,7 @@ void HomeCommand::onExecute(Context* context)
bool HomeCommand::onEnabled(Context* context)
{
return !App::instance()->mainWindow()->isHomeSelected();
return context->isUIAvailable() && !App::instance()->mainWindow()->isHomeSelected();
}
Command* CommandFactory::createHomeCommand()

View File

@ -20,20 +20,14 @@
#include "app/doc_api.h"
#include "app/i18n/strings.h"
#include "app/modules/gui.h"
#include "app/modules/palettes.h"
#include "app/pref/preferences.h"
#include "app/tx.h"
#include "app/ui/drop_down_button.h"
#include "app/ui/editor/editor.h"
#include "app/ui/editor/editor_decorator.h"
#include "app/ui/editor/select_box_state.h"
#include "app/ui/editor/standby_state.h"
#include "app/ui/workspace.h"
#include "doc/cel.h"
#include "doc/image.h"
#include "doc/layer.h"
#include "doc/palette.h"
#include "doc/primitives.h"
#include "doc/sprite.h"
#include "render/render.h"
#include "ui/ui.h"
@ -518,7 +512,7 @@ protected:
};
ImportSpriteSheetCommand::ImportSpriteSheetCommand()
: CommandWithNewParams(CommandId::ImportSpriteSheet(), CmdRecordableFlag)
: CommandWithNewParams(CommandId::ImportSpriteSheet())
{
}

View File

@ -31,7 +31,7 @@ protected:
void onExecute(Context* context) override;
};
InvertMaskCommand::InvertMaskCommand() : Command(CommandId::InvertMask(), CmdRecordableFlag)
InvertMaskCommand::InvertMaskCommand() : Command(CommandId::InvertMask())
{
}

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2018-2024 Igara Studio S.A.
// Copyright (C) 2018-2025 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
@ -23,25 +23,20 @@
#include "app/ui/app_menuitem.h"
#include "app/ui/keyboard_shortcuts.h"
#include "app/ui/search_entry.h"
#include "app/ui/select_accelerator.h"
#include "app/ui/select_shortcut.h"
#include "app/ui/separator_in_view.h"
#include "app/ui/skin/skin_theme.h"
#include "base/fs.h"
#include "base/pi.h"
#include "base/scoped_value.h"
#include "base/split_string.h"
#include "base/string.h"
#include "ui/alert.h"
#include "ui/fit_bounds.h"
#include "ui/graphics.h"
#include "ui/listitem.h"
#include "ui/message.h"
#include "ui/paint_event.h"
#include "ui/resize_event.h"
#include "ui/separator.h"
#include "ui/size_hint_event.h"
#include "ui/splitter.h"
#include "ui/system.h"
#include "keyboard_shortcuts.xml.h"
@ -151,7 +146,7 @@ public:
, m_keyOrig(key ? new Key(*key) : nullptr)
, m_menuitem(menuitem)
, m_level(level)
, m_hotAccel(-1)
, m_hotShortcut(-1)
, m_lockButtons(false)
, m_headerItem(headerItem)
{
@ -204,45 +199,45 @@ public:
}
private:
void onChangeAccel(int index)
void onChangeShortcut(int index)
{
LockButtons lock(this);
Accelerator origAccel = m_key->accels()[index];
SelectAccelerator window(origAccel, m_key->keycontext(), m_keys);
Shortcut origShortcut = m_key->shortcuts()[index];
SelectShortcut window(origShortcut, m_key->keycontext(), m_keys);
window.openWindowInForeground();
if (window.isModified()) {
m_key->disableAccel(origAccel, KeySource::UserDefined);
if (!window.accel().isEmpty())
m_key->add(window.accel(), KeySource::UserDefined, m_keys);
m_key->disableShortcut(origShortcut, KeySource::UserDefined);
if (!window.shortcut().isEmpty())
m_key->add(window.shortcut(), KeySource::UserDefined, m_keys);
}
this->window()->layout();
}
void onDeleteAccel(int index)
void onDeleteShortcut(int index)
{
LockButtons lock(this);
// We need to create a copy of the accelerator because
// Key::disableAccel() will modify the accels() collection itself.
ui::Accelerator accel = m_key->accels()[index];
// We need to create a copy of the shortcut because
// Key::disableShortcut() will modify the shortcuts() collection itself.
ui::Shortcut shortcut = m_key->shortcuts()[index];
if (ui::Alert::show(Strings::alerts_delete_shortcut(accel.toString())) != 1)
if (ui::Alert::show(Strings::alerts_delete_shortcut(shortcut.toString())) != 1)
return;
m_key->disableAccel(accel, KeySource::UserDefined);
m_key->disableShortcut(shortcut, KeySource::UserDefined);
window()->layout();
}
void onAddAccel()
void onAddShortcut()
{
LockButtons lock(this);
ui::Accelerator accel;
SelectAccelerator window(accel, m_key ? m_key->keycontext() : KeyContext::Any, m_keys);
ui::Shortcut shortcut;
SelectShortcut window(shortcut, m_key ? m_key->keycontext() : KeyContext::Any, m_keys);
window.openWindowInForeground();
if ((window.isModified()) ||
// We can assign a "None" accelerator to mouse wheel actions
// We can assign a "None" shortcut to mouse wheel actions
(m_key && m_key->type() == KeyType::WheelAction && window.isOK())) {
if (!m_key) {
ASSERT(m_menuitem);
@ -256,7 +251,7 @@ private:
m_menuKeys[m_menuitem] = m_key;
}
m_key->add(window.accel(), KeySource::UserDefined, m_keys);
m_key->add(window.shortcut(), KeySource::UserDefined, m_keys);
}
this->window()->layout();
@ -273,8 +268,8 @@ private:
size.w = std::max(size.w, w);
}
if (m_key && !m_key->accels().empty()) {
size_t combos = m_key->accels().size();
if (m_key && !m_key->shortcuts().empty()) {
size_t combos = m_key->shortcuts().size();
if (combos > 1)
size.h *= combos;
}
@ -315,7 +310,7 @@ private:
}
}
if (m_key && !m_key->accels().empty()) {
if (m_key && !m_key->shortcuts().empty()) {
if (m_key->keycontext() != KeyContext::Any) {
g->drawText(convertKeyContextToUserFriendlyString(m_key->keycontext()),
fg,
@ -324,13 +319,14 @@ private:
}
const int dh = th + 4 * guiscale();
IntersectClip clip(g,
gfx::Rect(keyXPos, y, contextXPos - keyXPos, dh * m_key->accels().size()));
IntersectClip clip(
g,
gfx::Rect(keyXPos, y, contextXPos - keyXPos, dh * m_key->shortcuts().size()));
if (clip) {
int i = 0;
for (const Accelerator& accel : m_key->accels()) {
if (i != m_hotAccel || !m_changeButton) {
g->drawText(getAccelText(accel), fg, bg, gfx::Point(keyXPos, y));
for (const Shortcut& shortcut : m_key->shortcuts()) {
if (i != m_hotShortcut || !m_changeButton) {
g->drawText(getShortcutText(shortcut), fg, bg, gfx::Point(keyXPos, y));
}
y += dh;
++i;
@ -361,40 +357,41 @@ private:
gfx::Rect bounds = this->bounds();
MouseMessage* mouseMsg = static_cast<MouseMessage*>(msg);
const Accelerators* accels = (m_key ? &m_key->accels() : NULL);
const Shortcuts* shortcuts = (m_key ? &m_key->shortcuts() : NULL);
int y = bounds.y;
int dh = textSize().h + 4 * guiscale();
int maxi = (accels && accels->size() > 1 ? accels->size() : 1);
int maxi = (shortcuts && shortcuts->size() > 1 ? shortcuts->size() : 1);
auto theme = SkinTheme::get(this);
auto* theme = SkinTheme::get(this);
for (int i = 0; i < maxi; ++i, y += dh) {
int w = font()->textLength(
(accels && i < (int)accels->size() ? getAccelText((*accels)[i]) : std::string()));
int w = font()->textLength((shortcuts && i < (int)shortcuts->size() ?
getShortcutText((*shortcuts)[i]) :
std::string()));
gfx::Rect itemBounds(bounds.x + m_headerItem->keyXPos(), y, w, dh);
itemBounds = itemBounds.enlarge(
gfx::Border(4 * guiscale(), 0, 6 * guiscale(), 1 * guiscale()));
if (accels && i < (int)accels->size() && mouseMsg->position().y >= itemBounds.y &&
if (shortcuts && i < (int)shortcuts->size() && mouseMsg->position().y >= itemBounds.y &&
mouseMsg->position().y < itemBounds.y + itemBounds.h) {
if (m_hotAccel != i) {
m_hotAccel = i;
if (m_hotShortcut != i) {
m_hotShortcut = i;
m_changeConn = obs::connection();
m_changeButton.reset(new Button(""));
m_changeConn = m_changeButton->Click.connect([this, i] { onChangeAccel(i); });
m_changeConn = m_changeButton->Click.connect([this, i] { onChangeShortcut(i); });
m_changeButton->setStyle(theme->styles.miniButton());
addChild(m_changeButton.get());
m_deleteConn = obs::connection();
m_deleteButton.reset(new Button(""));
m_deleteConn = m_deleteButton->Click.connect([this, i] { onDeleteAccel(i); });
m_deleteConn = m_deleteButton->Click.connect([this, i] { onDeleteShortcut(i); });
m_deleteButton->setStyle(theme->styles.miniButton());
addChild(m_deleteButton.get());
m_changeButton->setBgColor(gfx::ColorNone);
m_changeButton->setBounds(itemBounds);
m_changeButton->setText(getAccelText((*accels)[i]));
m_changeButton->setText(getShortcutText((*shortcuts)[i]));
const char* label = "x";
m_deleteButton->setBgColor(gfx::ColorNone);
@ -411,7 +408,7 @@ private:
if (i == 0 && !m_addButton && (!m_menuitem || m_menuitem->getCommand())) {
m_addConn = obs::connection();
m_addButton.reset(new Button(""));
m_addConn = m_addButton->Click.connect([this] { onAddAccel(); });
m_addConn = m_addButton->Click.connect([this] { onAddShortcut(); });
m_addButton->setStyle(theme->styles.miniButton());
addChild(m_addButton.get());
@ -452,17 +449,15 @@ private:
m_addButton->setVisible(false);
}
m_hotAccel = -1;
m_hotShortcut = -1;
}
std::string getAccelText(const Accelerator& accel) const
std::string getShortcutText(const Shortcut& shortcut) const
{
if (m_key && m_key->type() == KeyType::WheelAction && accel.isEmpty()) {
if (m_key && m_key->type() == KeyType::WheelAction && shortcut.isEmpty()) {
return Strings::keyboard_shortcuts_default_action();
}
else {
return accel.toString();
}
return shortcut.toString();
}
KeyboardShortcuts& m_keys;
@ -471,14 +466,14 @@ private:
KeyPtr m_keyOrig;
AppMenuItem* m_menuitem;
int m_level;
ui::Accelerators m_newAccels;
ui::Shortcuts m_newShortcuts;
std::shared_ptr<ui::Button> m_changeButton;
std::shared_ptr<ui::Button> m_deleteButton;
std::shared_ptr<ui::Button> m_addButton;
obs::scoped_connection m_changeConn;
obs::scoped_connection m_deleteConn;
obs::scoped_connection m_addConn;
int m_hotAccel;
int m_hotShortcut;
bool m_lockButtons;
HeaderItem* m_headerItem;
};
@ -977,6 +972,7 @@ public:
KeyboardShortcutsCommand();
protected:
bool onEnabled(Context* context) override;
void onLoadParams(const Params& params) override;
void onExecute(Context* context) override;
@ -986,11 +982,15 @@ private:
std::string m_search;
};
KeyboardShortcutsCommand::KeyboardShortcutsCommand()
: Command(CommandId::KeyboardShortcuts(), CmdUIOnlyFlag)
KeyboardShortcutsCommand::KeyboardShortcutsCommand() : Command(CommandId::KeyboardShortcuts())
{
}
bool KeyboardShortcutsCommand::onEnabled(Context* context)
{
return context->isUIAvailable();
}
void KeyboardShortcutsCommand::onLoadParams(const Params& params)
{
m_search = params.get("search");

View File

@ -34,10 +34,7 @@ private:
std::string m_path;
};
LaunchCommand::LaunchCommand()
: Command(CommandId::Launch(), CmdUIOnlyFlag)
, m_type(Url)
, m_path("")
LaunchCommand::LaunchCommand() : Command(CommandId::Launch()), m_type(Url), m_path("")
{
}

View File

@ -14,8 +14,6 @@
#include "app/context_access.h"
#include "app/modules/gui.h"
#include "app/tx.h"
#include "doc/layer.h"
#include "doc/sprite.h"
namespace app {
@ -28,8 +26,7 @@ protected:
void onExecute(Context* context) override;
};
LayerFromBackgroundCommand::LayerFromBackgroundCommand()
: Command(CommandId::LayerFromBackground(), CmdRecordableFlag)
LayerFromBackgroundCommand::LayerFromBackgroundCommand() : Command(CommandId::LayerFromBackground())
{
}

View File

@ -9,11 +9,9 @@
#include "config.h"
#endif
#include "app/app.h"
#include "app/commands/command.h"
#include "app/context_access.h"
#include "app/modules/gui.h"
#include "doc/image.h"
#include "doc/layer.h"
namespace app {
@ -30,7 +28,7 @@ protected:
void onExecute(Context* context) override;
};
LayerLockCommand::LayerLockCommand() : Command(CommandId::LayerLock(), CmdRecordableFlag)
LayerLockCommand::LayerLockCommand() : Command(CommandId::LayerLock())
{
}

View File

@ -9,7 +9,6 @@
#include "config.h"
#endif
#include "app/app.h"
#include "app/cmd/set_layer_opacity.h"
#include "app/commands/command.h"
#include "app/commands/params.h"
@ -40,7 +39,7 @@ private:
int m_opacity;
};
LayerOpacityCommand::LayerOpacityCommand() : Command(CommandId::LayerOpacity(), CmdUIOnlyFlag)
LayerOpacityCommand::LayerOpacityCommand() : Command(CommandId::LayerOpacity())
{
m_opacity = 255;
}

View File

@ -32,8 +32,8 @@
#include "app/ui/timeline/timeline.h"
#include "app/ui/user_data_view.h"
#include "app/ui_context.h"
#include "base/convert_to.h"
#include "base/scoped_value.h"
#include "doc/image.h"
#include "doc/layer.h"
#include "doc/layer_tilemap.h"
#include "doc/sprite.h"
@ -134,8 +134,16 @@ public:
remapWindow();
centerWindow();
gfx::Rect originalBounds = bounds();
load_window_pos(this, "LayerProperties");
// Queue a remap for after the user data view is configured
// if the window size has been reset and user data is visible
if (originalBounds == bounds() && Preferences::instance().layers.userDataVisibility())
m_remapAfterConfigure = true;
UIContext::instance()->add_observer(this);
}
@ -158,6 +166,11 @@ public:
if (countLayers() > 0) {
m_userDataView.configureAndSet(m_layer->userData(), g_window->propertiesGrid());
if (m_remapAfterConfigure) {
remapWindow();
centerWindow();
m_remapAfterConfigure = false;
}
}
updateFromLayer();
@ -463,6 +476,13 @@ private:
m_userDataView.setVisible(false, false);
}
bool uuidVisible = m_document && m_document->sprite() && m_document->sprite()->useLayerUuids();
uuidLabel()->setVisible(uuidVisible);
uuid()->setVisible(uuidVisible);
if (uuidVisible)
uuid()->setText(m_layer ? base::convert_to<std::string>(m_layer->uuid()) : std::string());
if (tileset()->isVisible() != tilemapVisibility) {
tileset()->setVisible(tilemapVisibility);
tileset()->parent()->layout();
@ -476,16 +496,17 @@ private:
view::RealRange m_range;
bool m_selfUpdate = false;
UserDataView m_userDataView;
bool m_remapAfterConfigure = false;
};
LayerPropertiesCommand::LayerPropertiesCommand()
: Command(CommandId::LayerProperties(), CmdRecordableFlag)
LayerPropertiesCommand::LayerPropertiesCommand() : Command(CommandId::LayerProperties())
{
}
bool LayerPropertiesCommand::onEnabled(Context* context)
{
return context->checkFlags(ContextFlags::ActiveDocumentIsWritable | ContextFlags::HasActiveLayer);
return context->isUIAvailable() &&
context->checkFlags(ContextFlags::ActiveDocumentIsWritable | ContextFlags::HasActiveLayer);
}
void LayerPropertiesCommand::onExecute(Context* context)

View File

@ -12,7 +12,6 @@
#include "app/commands/command.h"
#include "app/context_access.h"
#include "app/modules/gui.h"
#include "doc/image.h"
#include "doc/layer.h"
namespace app {
@ -29,8 +28,7 @@ protected:
void onExecute(Context* context) override;
};
LayerVisibilityCommand::LayerVisibilityCommand()
: Command(CommandId::LayerVisibility(), CmdRecordableFlag)
LayerVisibilityCommand::LayerVisibilityCommand() : Command(CommandId::LayerVisibility())
{
}

View File

@ -18,7 +18,6 @@
#include "app/ui/status_bar.h"
#include "doc/cel.h"
#include "doc/layer.h"
#include "doc/sprite.h"
namespace app {
@ -31,7 +30,7 @@ protected:
void onExecute(Context* context) override;
};
LinkCelsCommand::LinkCelsCommand() : Command(CommandId::LinkCels(), CmdRecordableFlag)
LinkCelsCommand::LinkCelsCommand() : Command(CommandId::LinkCels())
{
}
@ -88,7 +87,7 @@ void LinkCelsCommand::onExecute(Context* context)
tx.commit();
}
if (nonEditableLayers)
if (context->isUIAvailable() && nonEditableLayers)
StatusBar::instance()->showTip(1000, Strings::statusbar_tips_locked_layers());
update_screen_for_document(document);

View File

@ -26,6 +26,7 @@ namespace app {
class LoadMaskCommand : public Command {
std::string m_filename;
bool m_ui = true;
public:
LoadMaskCommand();
@ -36,13 +37,16 @@ protected:
void onExecute(Context* context) override;
};
LoadMaskCommand::LoadMaskCommand() : Command(CommandId::LoadMask(), CmdRecordableFlag)
LoadMaskCommand::LoadMaskCommand() : Command(CommandId::LoadMask())
{
m_filename = "";
}
void LoadMaskCommand::onLoadParams(const Params& params)
{
if (params.has_param("ui"))
m_ui = params.get_as<bool>("ui");
else
m_ui = true;
m_filename = params.get("filename");
}
@ -55,7 +59,7 @@ void LoadMaskCommand::onExecute(Context* context)
{
const ContextReader reader(context);
if (context->isUIAvailable()) {
if (context->isUIAvailable() && m_ui) {
base::paths exts = { "msk" };
base::paths selectedFilename;
if (!app::show_file_selector(Strings::load_selection_title(),
@ -70,7 +74,8 @@ void LoadMaskCommand::onExecute(Context* context)
std::unique_ptr<Mask> mask(load_msk_file(m_filename.c_str()));
if (!mask) {
ui::Alert::show(Strings::alerts_error_loading_file(m_filename));
if (context->isUIAvailable())
ui::Alert::show(Strings::alerts_error_loading_file(m_filename));
return;
}

View File

@ -37,14 +37,19 @@ protected:
private:
std::string m_preset;
std::string m_filename;
bool m_ui = true;
};
LoadPaletteCommand::LoadPaletteCommand() : Command(CommandId::LoadPalette(), CmdRecordableFlag)
LoadPaletteCommand::LoadPaletteCommand() : Command(CommandId::LoadPalette())
{
}
void LoadPaletteCommand::onLoadParams(const Params& params)
{
if (params.has_param("ui"))
m_ui = params.get_as<bool>("ui");
else
m_ui = true;
m_preset = params.get("preset");
m_filename = params.get("filename");
}
@ -58,20 +63,20 @@ void LoadPaletteCommand::onExecute(Context* context)
if (!base::is_file(filename))
filename = get_preset_palette_filename(m_preset, ".gpl");
}
else if (!m_filename.empty()) {
filename = m_filename;
}
else if (context->isUIAvailable()) {
base::paths exts = get_readable_palette_extensions();
else if (context->isUIAvailable() && m_ui) {
const base::paths exts = get_readable_palette_extensions();
base::paths filenames;
if (app::show_file_selector(Strings::load_palette_title(),
"",
m_filename,
exts,
FileSelectorType::Open,
filenames)) {
filename = filenames.front();
}
}
else if (!m_filename.empty()) {
filename = m_filename;
}
// Do nothing
if (filename.empty())

View File

@ -29,7 +29,7 @@ protected:
void onExecute(Context* context) override;
};
MaskAllCommand::MaskAllCommand() : Command(CommandId::MaskAll(), CmdRecordableFlag)
MaskAllCommand::MaskAllCommand() : Command(CommandId::MaskAll())
{
}

View File

@ -15,7 +15,6 @@
#include "app/color_utils.h"
#include "app/commands/command.h"
#include "app/commands/new_params.h"
#include "app/console.h"
#include "app/context.h"
#include "app/context_access.h"
#include "app/doc.h"
@ -26,9 +25,6 @@
#include "app/ui/color_bar.h"
#include "app/ui/color_button.h"
#include "app/ui/selection_mode_field.h"
#include "base/chrono.h"
#include "base/convert_to.h"
#include "base/scoped_value.h"
#include "doc/image.h"
#include "doc/mask.h"
#include "doc/sprite.h"
@ -203,8 +199,7 @@ protected:
void onExecute(Context* context) override;
};
MaskByColorCommand::MaskByColorCommand()
: CommandWithNewParams(CommandId::MaskByColor(), CmdUIOnlyFlag)
MaskByColorCommand::MaskByColorCommand() : CommandWithNewParams(CommandId::MaskByColor())
{
}

Some files were not shown because too many files have changed in this diff Show More