* Moved app::DocRange to view::Range
* Moved range_utils to view/cels.cpp
* Moved layer_utils to view/layers.cpp
* Created more functions in app::Site to access selected cels
(they use the functions from view/cels.h)
This was originated for #1279 (CLI-only Aseprite) which can be
achieved with LAF_BACKEND=none anyway.
In this way we simplify the development process, and checking for the
availability of the GUI can be done in run-time through App::isGui()
or Context::isUIAvailable().
There is a third-party translation (and can happen with our own
translations) that a fmt format string is ill-formed in the .ini file
of the translation (this could happen even if the en.ini file was
manually modified/broken by hand).
This patch includes a refactor of the Strings class so we can:
1) Static check at compile-time about the number of required arguments
to format a string (no need to call fmt::format() directly with
arbitrary number of args)
2) If a string is not valid for the fmt library, the runtime exception
is caught and the default (English) string is returned.
Regression introduced with 8722c8ec16
and d3562b140c.
Our re-entrant RWLock implementation is tricky because it doesn't
support to unlock in different order than it was locked.
E.g. If we create a DocWriter (e.g. paste command), and try to create
a DocReader (e.g. PixelsMovement) inside the DocWriter scope, the
reader will return a LockResult::Reentrant, but if we unlock the
write, then the reader cannot be used to upgradeToWrite() because the
lock will have just 0 locks (the re-entrant one didn't modify the
count of the RWLock). This is because it was thought that the
DocReader was going to be unlocked before the writer lock (in the
exact inverse order).
Basically these re-entrant RWLocks will not work fine if we mix up the
order of locks/unlocks in the same thread.
This already fixes a lot of possible problems that can happen when a
script is running and modifying some part of a sprite that is being
backed up in a background thread.
We still need some work to being able to lock a sprite two or more
times in the same thread to write it. E.g. an app.transaction() should
lock the sprite for write access, but the script transaction function
could call a command, and that command could use a ContextWriter to
lock the sprite again. At the moment this is not possible because we
need a re-entrant RWLock implementation.
By default Aseprite will not try to match flipped versions of the
tiles (as it requires more CPU), but when we create a tileset we can
specify which flips can be matched automatically (new
Tileset::matchFlags() property).
These flags are just for the Auto mode, if we manually insert a
flipped tile, that is always supported, even when the matchFlags() are
not specified.
In this way we always have an empty tile available in the drawing
process. We've also added the Tileset::firstVisibleIndex field to
change the visible index of the tile 1 so we can offset the visible
number by the user (just as a visual aid / simulate old tilesets with
index=0=non-empty tile).
* Moved all clipboard:: functions inside app::Clipboard class
* Convert app:📋:ClipboardFormat enum to
app::ClipboardFormat enum class
* Added app::Context::clipboard()
This is the first commit with a simple tilemap editor. Still buggy but
functional in several ways. Several changes were made:
* NewLayer command can receive a tilemap=true to create a new tilemap
layer
* New ToggleTilesMode command added to switch between the palette and
the tileset in the ColorBar (the ColorBar was expanded to show
colors or tilesets with a generic AbstractPaletteViewAdapter)
* All commands to create new layers were moved to Layer >
New... submenu
* There are a new tileset chunk to save tilesets in .aseprite files,
and a new kind of cels to save tilemaps
* Added doc::LayerTilemap, doc::Tileset, etc. and several other types
to handle tilesets/tilemaps in the doc layer.
* Added doc::Grid class with grid specifications that indicates how a
tilemap <-> tileset must be drawn
* Added and expanded cel operations to work with tilemaps and
conversions between regular LayerImage cels <-> LayerTilemap cels
(e.g. copy cels in the timeline between layer types)