Compare commits

...

8 Commits

Author SHA1 Message Date
asqude 1cd97d34c6
Merge 0f32b43475 into cef92c1a38 2025-07-29 09:02:40 -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
asqude 0f32b43475
Make handle-bars the same legth by using the smallest sprite dimesion 2025-07-01 19:12:16 +02:00
Biggy ausm Bürro a811dd320a Add point symmetry mode and update related UI elements 2025-06-30 19:37:43 +02:00
23 changed files with 281 additions and 30 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -256,12 +256,12 @@
<part id="pal_presets" x="160" y="200" w="5" h="5" />
<part id="pal_options" x="168" y="200" w="5" h="5" />
<part id="pal_resize" x="176" y="200" w="5" h="5" />
<part id="debug_continue" x="208" y="240" w="7" h="7" />
<part id="debug_pause" x="208" y="247" w="7" h="7" />
<part id="debug_step_into" x="222" y="240" w="7" h="7" />
<part id="debug_step_over" x="215" y="240" w="7" h="7" />
<part id="debug_step_out" x="229" y="240" w="7" h="7" />
<part id="debug_breakpoint" x="236" y="240" w="7" h="7" />
<part id="debug_continue" x="224" y="240" w="7" h="7" />
<part id="debug_pause" x="224" y="247" w="7" h="7" />
<part id="debug_step_into" x="238" y="240" w="7" h="7" />
<part id="debug_step_over" x="231" y="240" w="7" h="7" />
<part id="debug_step_out" x="245" y="240" w="7" h="7" />
<part id="debug_breakpoint" x="252" y="240" w="7" h="7" />
<part id="selection_replace" x="176" y="160" w="7" h="7" />
<part id="selection_add" x="184" y="160" w="7" h="7" />
<part id="selection_subtract" x="192" y="160" w="7" h="7" />
@ -456,6 +456,7 @@
<part id="spin_down" x="128" y="259" w="5" h="3" />
<part id="right_diagonal_symmetry" x="176" y="240" w="13" h="13" />
<part id="left_diagonal_symmetry" x="192" y="240" w="13" h="13" />
<part id="point_symmetry" x="208" y="240" w="13" h="13" />
</parts>
<styles>
<style id="box" />

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -252,12 +252,12 @@
<part id="pal_presets" x="160" y="200" w="5" h="5" />
<part id="pal_options" x="168" y="200" w="5" h="5" />
<part id="pal_resize" x="176" y="200" w="5" h="5" />
<part id="debug_continue" x="208" y="240" w="7" h="7" />
<part id="debug_pause" x="208" y="247" w="7" h="7" />
<part id="debug_step_into" x="222" y="240" w="7" h="7" />
<part id="debug_step_over" x="215" y="240" w="7" h="7" />
<part id="debug_step_out" x="229" y="240" w="7" h="7" />
<part id="debug_breakpoint" x="236" y="240" w="7" h="7" />
<part id="debug_continue" x="224" y="240" w="7" h="7" />
<part id="debug_pause" x="224" y="247" w="7" h="7" />
<part id="debug_step_into" x="238" y="240" w="7" h="7" />
<part id="debug_step_over" x="231" y="240" w="7" h="7" />
<part id="debug_step_out" x="245" y="240" w="7" h="7" />
<part id="debug_breakpoint" x="252" y="240" w="7" h="7" />
<part id="selection_replace" x="176" y="160" w="7" h="7" />
<part id="selection_add" x="184" y="160" w="7" h="7" />
<part id="selection_subtract" x="192" y="160" w="7" h="7" />
@ -452,6 +452,7 @@
<part id="spin_down" x="128" y="259" w="5" h="3" />
<part id="right_diagonal_symmetry" x="176" y="240" w="13" h="13" />
<part id="left_diagonal_symmetry" x="192" y="240" w="13" h="13" />
<part id="point_symmetry" x="208" y="240" w="13" h="13" />
</parts>
<styles>
<style id="box" />

View File

@ -554,6 +554,9 @@
<key command="SymmetryMode">
<param name="orientation" value="left_diagonal" />
</key>
<key command="SymmetryMode">
<param name="orientation" value="point" />
</key>
<key command="AutocropSprite" />
<key command="AutocropSprite">
<param name="byGrid" value="true" />

View File

@ -97,6 +97,7 @@
<value id="RIGHT_DIAG" value="4" />
<value id="LEFT_DIAG" value="8" />
<value id="BOTH_DIAG" value="12" />
<value id="POINT" value="16" />
<value id="ALL" value="15" />
</enum>
<enum id="PaintingCursorType">

View File

@ -1944,6 +1944,7 @@ toggle_horizontal = Toggle Horizontal Symmetry
toggle_vertical = Toggle Vertical Symmetry
toggle_right_diagonal = Toggle 45° Symmetry
toggle_left_diagonal = Toggle -45° Symmetry
toggle_point = Toggle Point Symmetry
show_options = Symmetry Options
reset_position = Reset Symmetry to Center
reset_position_to_view_center = Reset Symmetry to View Center

2
laf

@ -1 +1 @@
Subproject commit a2bb9ec7fb98354279a2c49870a4a47a67a8e86e
Subproject commit 8ec4b553f1618f7a4b47cdcf4cfc2663266111ac

View File

@ -180,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

@ -48,6 +48,7 @@ std::string SymmetryModeCommand::onGetFriendlyName() const
case app::gen::SymmetryMode::VERTICAL: return Strings::symmetry_toggle_vertical();
case app::gen::SymmetryMode::RIGHT_DIAG: return Strings::symmetry_toggle_right_diagonal();
case app::gen::SymmetryMode::LEFT_DIAG: return Strings::symmetry_toggle_left_diagonal();
case app::gen::SymmetryMode::POINT: return Strings::symmetry_toggle_point();
default: return Strings::symmetry_toggle();
}
}
@ -63,6 +64,8 @@ void SymmetryModeCommand::onLoadParams(const Params& params)
m_mode = app::gen::SymmetryMode::RIGHT_DIAG;
else if (mode == "left_diagonal")
m_mode = app::gen::SymmetryMode::LEFT_DIAG;
else if (mode == "point")
m_mode = app::gen::SymmetryMode::POINT;
else
m_mode = app::gen::SymmetryMode::NONE;
}

View File

@ -213,7 +213,7 @@ void ResourceFinder::includeDesktopDir(const char* filename)
#ifdef _WIN32
std::vector<wchar_t> buf(MAX_PATH);
HRESULT hr = SHGetFolderPath(NULL, CSIDL_DESKTOPDIRECTORY, NULL, SHGFP_TYPE_DEFAULT, &buf[0]);
HRESULT hr = SHGetFolderPath(NULL, CSIDL_DESKTOP, NULL, SHGFP_TYPE_CURRENT, &buf[0]);
if (hr == S_OK) {
addPath(base::join_path(base::to_utf8(&buf[0]), filename));
}

View File

@ -13,6 +13,8 @@
#include "app/console.h"
#include "app/context.h"
#include "app/context_observer.h"
#include "app/doc.h"
#include "app/doc_undo.h"
#include "app/script/docobj.h"
#include "app/script/engine.h"
#include "app/script/luacpp.h"

View File

@ -64,6 +64,7 @@
#include "doc/tag.h"
#include "doc/tileset.h"
#include "doc/tilesets.h"
#include "undo/undo_state.h"
#include <algorithm>
@ -1029,6 +1030,42 @@ int Sprite_set_useLayerUuids(lua_State* L)
return 0;
}
int Sprite_get_undoHistory(lua_State* L)
{
const auto* sprite = get_docobj<Sprite>(L, 1);
const auto* doc = static_cast<Doc*>(sprite->document());
const auto* history = doc->undoHistory();
if (!history) {
lua_pushnil(L);
return 1;
}
const undo::UndoState* currentState = history->currentState();
const undo::UndoState* s = history->firstState();
const bool canRedo = history->canRedo();
bool pastCurrent = !currentState && canRedo;
int undoSteps = 0;
int redoSteps = 0;
while (s) {
if (pastCurrent && canRedo)
redoSteps++;
else if (currentState || !canRedo)
undoSteps++;
if (s == currentState || !currentState)
pastCurrent = true;
s = s->next();
}
lua_newtable(L);
setfield_integer(L, "undoSteps", undoSteps);
setfield_integer(L, "redoSteps", redoSteps);
return 1;
}
const luaL_Reg Sprite_methods[] = {
{ "__eq", Sprite_eq },
{ "resize", Sprite_resize },
@ -1094,6 +1131,7 @@ const Property Sprite_properties[] = {
{ "events", Sprite_get_events, nullptr },
{ "tileManagementPlugin", Sprite_get_tileManagementPlugin, Sprite_set_tileManagementPlugin },
{ "useLayerUuids", Sprite_get_useLayerUuids, Sprite_set_useLayerUuids },
{ "undoHistory", Sprite_get_undoHistory, nullptr },
{ nullptr, nullptr, nullptr }
};

View File

@ -73,6 +73,15 @@ void Symmetry::generateStrokes(const Stroke& stroke, Strokes& strokes, ToolLoop*
break;
}
case gen::SymmetryMode::POINT: {
Stroke strokeTemp;
calculateSymmetricalStroke(stroke, strokeTemp, loop, doc::SymmetryIndex::FLIPPED_Y);
calculateSymmetricalStroke(strokeTemp, stroke2, loop, doc::SymmetryIndex::FLIPPED_XY);
strokes.push_back(stroke2);
break;
}
case gen::SymmetryMode::ALL: {
calculateSymmetricalStroke(stroke, stroke2, loop, doc::SymmetryIndex::FLIPPED_X);
strokes.push_back(stroke2);
@ -175,8 +184,13 @@ gen::SymmetryMode Symmetry::resolveMode(gen::SymmetryMode mode)
{
return (((int(mode) & int(gen::SymmetryMode::HORIZONTAL)) ||
(int(mode) & int(gen::SymmetryMode::VERTICAL))) &&
((int(mode) & int(gen::SymmetryMode::RIGHT_DIAG)) ||
(int(mode) & int(gen::SymmetryMode::LEFT_DIAG)))) ?
((int(mode) & int(gen::SymmetryMode::RIGHT_DIAG)) ||
(int(mode) & int(gen::SymmetryMode::LEFT_DIAG)))) ||
((int(mode) & int(gen::SymmetryMode::POINT)) &&
((int(mode) & int(gen::SymmetryMode::RIGHT_DIAG)) ||
(int(mode) & int(gen::SymmetryMode::LEFT_DIAG)) ||
(int(mode) & int(gen::SymmetryMode::HORIZONTAL)) ||
(int(mode) & int(gen::SymmetryMode::VERTICAL)))) ?
gen::SymmetryMode::ALL :
mode;
}

View File

@ -1502,7 +1502,7 @@ protected:
class ContextBar::SymmetryField : public ButtonSet {
public:
SymmetryField() : ButtonSet(5)
SymmetryField() : ButtonSet(6)
{
setMultiMode(MultiMode::Set);
auto theme = SkinTheme::get(this);
@ -1510,6 +1510,7 @@ public:
addItem(theme->parts.verticalSymmetry(), theme->styles.symmetryField());
addItem(theme->parts.rightDiagonalSymmetry(), theme->styles.symmetryField());
addItem(theme->parts.leftDiagonalSymmetry(), theme->styles.symmetryField());
addItem(theme->parts.pointSymmetry(), theme->styles.symmetryField());
addItem("...", theme->styles.symmetryOptions());
}
@ -1519,7 +1520,8 @@ public:
tooltipManager->addTooltipFor(at(1), Strings::symmetry_toggle_vertical(), BOTTOM);
tooltipManager->addTooltipFor(at(2), Strings::symmetry_toggle_right_diagonal(), BOTTOM);
tooltipManager->addTooltipFor(at(3), Strings::symmetry_toggle_left_diagonal(), BOTTOM);
tooltipManager->addTooltipFor(at(4), Strings::symmetry_show_options(), BOTTOM);
tooltipManager->addTooltipFor(at(4), Strings::symmetry_toggle_point(), BOTTOM);
tooltipManager->addTooltipFor(at(5), Strings::symmetry_show_options(), BOTTOM);
}
void updateWithCurrentDocument()
@ -1534,6 +1536,7 @@ public:
at(1)->setSelected(int(docPref.symmetry.mode()) & int(app::gen::SymmetryMode::VERTICAL));
at(2)->setSelected(int(docPref.symmetry.mode()) & int(app::gen::SymmetryMode::RIGHT_DIAG));
at(3)->setSelected(int(docPref.symmetry.mode()) & int(app::gen::SymmetryMode::LEFT_DIAG));
at(4)->setSelected(int(docPref.symmetry.mode()) & int(app::gen::SymmetryMode::POINT));
}
private:
@ -1556,14 +1559,16 @@ private:
mode |= int(app::gen::SymmetryMode::RIGHT_DIAG);
if (at(3)->isSelected())
mode |= int(app::gen::SymmetryMode::LEFT_DIAG);
if (at(4)->isSelected())
mode |= int(app::gen::SymmetryMode::POINT);
if (app::gen::SymmetryMode(mode) != docPref.symmetry.mode()) {
docPref.symmetry.mode(app::gen::SymmetryMode(mode));
// Redraw symmetry rules
doc->notifyGeneralUpdate();
}
else if (at(4)->isSelected()) {
auto* item = at(4);
else if (at(5)->isSelected()) {
auto* item = at(5);
gfx::Rect bounds = item->bounds();
item->setSelected(false);

View File

@ -934,6 +934,19 @@ void Editor::drawOneSpriteUnclippedRect(ui::Graphics* g,
topLeft,
bottomRight);
}
if (mode & int(app::gen::SymmetryMode::POINT)) {
int smallestDimension = std::min(enclosingRect.w, enclosingRect.h);
g->drawHLine(
symmetryButtons & int(app::gen::SymmetryMode::POINT) ? color : semiTransparentColor,
enclosingRect.x + x - smallestDimension * 0.10f,
enclosingRect.y + y,
smallestDimension * 0.10f * 2.0f);
g->drawVLine(
(symmetryButtons & int(app::gen::SymmetryMode::POINT)) ? color : semiTransparentColor,
enclosingRect.x + x,
enclosingRect.y + y - smallestDimension * 0.10f,
smallestDimension * 0.10f * 2.0f);
}
}
}
}

View File

@ -1030,7 +1030,8 @@ bool StandbyState::Decorator::getSymmetryHandles(Editor* editor, Handles& handle
if ((int(mode) & int(app::gen::SymmetryMode::HORIZONTAL)) ||
(int(mode) & int(app::gen::SymmetryMode::RIGHT_DIAG)) ||
(int(mode) & int(app::gen::SymmetryMode::LEFT_DIAG))) {
(int(mode) & int(app::gen::SymmetryMode::LEFT_DIAG)) ||
(int(mode) & int(app::gen::SymmetryMode::POINT))) {
double pos = symmetry.xAxis();
gfx::PointF pt1, pt2;
@ -1051,7 +1052,8 @@ bool StandbyState::Decorator::getSymmetryHandles(Editor* editor, Handles& handle
if ((int(mode) & int(app::gen::SymmetryMode::VERTICAL)) ||
(int(mode) & int(app::gen::SymmetryMode::RIGHT_DIAG)) ||
(int(mode) & int(app::gen::SymmetryMode::LEFT_DIAG))) {
(int(mode) & int(app::gen::SymmetryMode::LEFT_DIAG)) ||
(int(mode) & int(app::gen::SymmetryMode::POINT))) {
double pos = symmetry.yAxis();
gfx::PointF pt1, pt2;

View File

@ -443,12 +443,7 @@ bool WritingTextState::onSetCursor(Editor* editor, const gfx::Point& mouseScreen
return true;
}
bool WritingTextState::onKeyDown(Editor*, KeyMessage*)
{
return false;
}
bool WritingTextState::onKeyUp(Editor*, KeyMessage* msg)
bool WritingTextState::onKeyDown(Editor*, KeyMessage* msg)
{
// Cancel loop pressing Esc key
if (msg->scancode() == ui::kKeyEsc) {
@ -457,7 +452,17 @@ bool WritingTextState::onKeyUp(Editor*, KeyMessage* msg)
// Drop text pressing Enter key
else if (msg->scancode() == ui::kKeyEnter) {
drop();
return true;
}
return false;
}
bool WritingTextState::onKeyUp(Editor*, KeyMessage* msg)
{
// Note: We cannot process kKeyEnter key here to drop the text as it
// could be received after the Enter key is pressed in the IME
// dialog to accept the composition (not to accept the text). So we
// process kKeyEnter in onKeyDown().
return true;
}

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
</plist>

86
src/main/osx/Info.plist Normal file
View File

@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>aseprite</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>Document.icns</string>
<key>CFBundleTypeName</key>
<string>Aseprite Sprite</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSHandlerRank</key>
<string>Owner</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>ase</string>
<string>bmp</string>
<string>flc</string>
<string>fli</string>
<string>gif</string>
<string>ico</string>
<string>jpeg</string>
<string>jpg</string>
<string>pcx</string>
<string>png</string>
<string>tga</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>Document.icns</string>
<key>CFBundleTypeName</key>
<string>Aseprite Sprite</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>aseprite-extension</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>Extension.icns</string>
<key>CFBundleTypeName</key>
<string>Aseprite Extension</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSHandlerRank</key>
<string>Owner</string>
</dict>
</array>
<key>CFBundleDisplayName</key>
<string>Aseprite</string>
<key>CFBundleExecutable</key>
<string>aseprite</string>
<key>CFBundleIdentifier</key>
<string>org.aseprite.Aseprite</string>
<key>CFBundleName</key>
<string>Aseprite</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleShortVersionString</key>
<string>1.3</string>
<key>CFBundleVersion</key>
<string>1.3</string>
<key>CFBundleIconFile</key>
<string>Aseprite.icns</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.graphics-design</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2001-2025, Igara Studio S.A.
All rights reserved.</string>
<key>NSHighResolutionCapable</key>
<true/>
<key>NSRequiresAquaSystemAppearance</key>
<false/>
</dict>
</plist>

View File

@ -228,3 +228,69 @@ do
c = app.open(fn)
assert(c.tileManagementPlugin == nil)
end
-- Undo History
function test_undo_history()
local sprite = Sprite(1, 1)
assert(sprite.undoHistory.undoSteps == 0)
assert(sprite.undoHistory.redoSteps == 0)
sprite:resize(10, 10)
assert(sprite.undoHistory.undoSteps == 1)
assert(sprite.undoHistory.redoSteps == 0)
sprite:resize(10, 15)
assert(sprite.undoHistory.undoSteps == 2)
assert(sprite.undoHistory.redoSteps == 0)
sprite:resize(10, 30)
assert(sprite.undoHistory.undoSteps == 3)
assert(sprite.undoHistory.redoSteps == 0)
app.undo()
assert(sprite.undoHistory.undoSteps == 2)
assert(sprite.undoHistory.redoSteps == 1)
app.undo()
assert(sprite.undoHistory.undoSteps == 1)
assert(sprite.undoHistory.redoSteps == 2)
app.redo()
assert(sprite.undoHistory.undoSteps == 2)
assert(sprite.undoHistory.redoSteps == 1)
app.undo()
app.undo()
assert(sprite.undoHistory.undoSteps == 0)
assert(sprite.undoHistory.redoSteps == 3)
sprite:resize(10, 30)
if (app.preferences.undo.allow_nonlinear_history) then
assert(sprite.undoHistory.undoSteps == 4)
assert(sprite.undoHistory.redoSteps == 0)
else
assert(sprite.undoHistory.undoSteps == 1)
assert(sprite.undoHistory.redoSteps == 0)
end
end
do
local prevSetting = app.preferences.undo.allow_nonlinear_history
app.preferences.undo.allow_nonlinear_history = true
test_undo_history()
app.preferences.undo.allow_nonlinear_history = prevSetting
end
do
local prevSetting = app.preferences.undo.allow_nonlinear_history
app.preferences.undo.allow_nonlinear_history = false
test_undo_history()
app.preferences.undo.allow_nonlinear_history = prevSetting
end