mirror of https://github.com/aseprite/aseprite.git
Compare commits
7 Commits
c343ebdf1f
...
133653ca15
Author | SHA1 | Date |
---|---|---|
|
133653ca15 | |
|
f0f9e34b94 | |
|
cef92c1a38 | |
|
22e72ab5cb | |
|
80fa065bd5 | |
|
de1ccb24dd | |
|
7d91c4b9d9 |
2
laf
2
laf
|
@ -1 +1 @@
|
||||||
Subproject commit a2bb9ec7fb98354279a2c49870a4a47a67a8e86e
|
Subproject commit 8ec4b553f1618f7a4b47cdcf4cfc2663266111ac
|
|
@ -180,8 +180,8 @@ if(ENABLE_ASEPRITE_EXE)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
set(main_resources
|
set(main_resources
|
||||||
main/resources_win32.rc
|
main/win/resources_win32.rc
|
||||||
main/settings.manifest)
|
main/win/settings.manifest)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_executable(${main_target}
|
add_executable(${main_target}
|
||||||
|
|
|
@ -10,11 +10,18 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "app/app.h"
|
#include "app/app.h"
|
||||||
|
#include "app/cmd/copy_region.h"
|
||||||
|
#include "app/cmd/patch_cel.h"
|
||||||
#include "app/color_utils.h"
|
#include "app/color_utils.h"
|
||||||
#include "app/commands/command.h"
|
#include "app/commands/command.h"
|
||||||
|
#include "app/commands/commands.h"
|
||||||
|
#include "app/commands/new_params.h"
|
||||||
#include "app/console.h"
|
#include "app/console.h"
|
||||||
#include "app/context.h"
|
#include "app/context.h"
|
||||||
|
#include "app/context_access.h"
|
||||||
#include "app/pref/preferences.h"
|
#include "app/pref/preferences.h"
|
||||||
|
#include "app/site.h"
|
||||||
|
#include "app/tx.h"
|
||||||
#include "app/ui/editor/editor.h"
|
#include "app/ui/editor/editor.h"
|
||||||
#include "app/ui/timeline/timeline.h"
|
#include "app/ui/timeline/timeline.h"
|
||||||
#include "app/util/render_text.h"
|
#include "app/util/render_text.h"
|
||||||
|
@ -22,6 +29,8 @@
|
||||||
#include "doc/image_ref.h"
|
#include "doc/image_ref.h"
|
||||||
#include "render/dithering.h"
|
#include "render/dithering.h"
|
||||||
#include "render/quantization.h"
|
#include "render/quantization.h"
|
||||||
|
#include "render/rasterize.h"
|
||||||
|
#include "render/render.h"
|
||||||
#include "ui/manager.h"
|
#include "ui/manager.h"
|
||||||
|
|
||||||
#include "paste_text.xml.h"
|
#include "paste_text.xml.h"
|
||||||
|
@ -30,7 +39,17 @@ namespace app {
|
||||||
|
|
||||||
static std::string last_text_used;
|
static std::string last_text_used;
|
||||||
|
|
||||||
class PasteTextCommand : public Command {
|
struct PasteTextParams : public NewParams {
|
||||||
|
Param<bool> ui{ this, true, "ui" };
|
||||||
|
Param<app::Color> color{ this, app::Color::fromMask(), "color" };
|
||||||
|
Param<std::string> text{ this, "", "text" };
|
||||||
|
Param<std::string> fontName{ this, "Aseprite", "fontName" };
|
||||||
|
Param<double> fontSize{ this, 6, "fontSize" };
|
||||||
|
Param<int> x{ this, 0, "x" };
|
||||||
|
Param<int> y{ this, 0, "y" };
|
||||||
|
};
|
||||||
|
|
||||||
|
class PasteTextCommand : public CommandWithNewParams<PasteTextParams> {
|
||||||
public:
|
public:
|
||||||
PasteTextCommand();
|
PasteTextCommand();
|
||||||
|
|
||||||
|
@ -39,13 +58,13 @@ protected:
|
||||||
void onExecute(Context* ctx) override;
|
void onExecute(Context* ctx) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
PasteTextCommand::PasteTextCommand() : Command(CommandId::PasteText())
|
PasteTextCommand::PasteTextCommand() : CommandWithNewParams(CommandId::PasteText())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PasteTextCommand::onEnabled(Context* ctx)
|
bool PasteTextCommand::onEnabled(Context* ctx)
|
||||||
{
|
{
|
||||||
return ctx->isUIAvailable() && ctx->checkFlags(ContextFlags::ActiveDocumentIsWritable |
|
return ctx->checkFlags(ContextFlags::ActiveDocumentIsWritable |
|
||||||
ContextFlags::ActiveLayerIsEditable);
|
ContextFlags::ActiveLayerIsEditable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,43 +81,57 @@ public:
|
||||||
|
|
||||||
void PasteTextCommand::onExecute(Context* ctx)
|
void PasteTextCommand::onExecute(Context* ctx)
|
||||||
{
|
{
|
||||||
auto editor = Editor::activeEditor();
|
const bool ui = params().ui() && ctx->isUIAvailable();
|
||||||
if (editor == nullptr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Preferences& pref = Preferences::instance();
|
|
||||||
FontInfo fontInfo = FontInfo::getFromPreferences();
|
FontInfo fontInfo = FontInfo::getFromPreferences();
|
||||||
|
Preferences& pref = Preferences::instance();
|
||||||
|
|
||||||
|
std::string text;
|
||||||
|
app::Color color;
|
||||||
|
ui::Paint paint;
|
||||||
|
|
||||||
|
if (ui) {
|
||||||
PasteTextWindow window(fontInfo, pref.colorBar.fgColor());
|
PasteTextWindow window(fontInfo, pref.colorBar.fgColor());
|
||||||
|
|
||||||
window.userText()->setText(last_text_used);
|
window.userText()->setText(params().text().empty() ? last_text_used : params().text());
|
||||||
|
|
||||||
window.openWindowInForeground();
|
window.openWindowInForeground();
|
||||||
if (window.closer() != window.ok())
|
if (window.closer() != window.ok())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
last_text_used = window.userText()->text();
|
text = window.userText()->text();
|
||||||
|
last_text_used = text;
|
||||||
|
color = window.fontColor()->getColor();
|
||||||
|
paint = window.fontFace()->paint();
|
||||||
|
|
||||||
fontInfo = window.fontInfo();
|
fontInfo = window.fontInfo();
|
||||||
fontInfo.updatePreferences();
|
fontInfo.updatePreferences();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
text = params().text();
|
||||||
|
color = params().color.isSet() ? params().color() : pref.colorBar.fgColor();
|
||||||
|
|
||||||
|
FontInfo info(FontInfo::Type::Unknown, params().fontName(), params().fontSize());
|
||||||
|
fontInfo = info;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
std::string text = window.userText()->text();
|
|
||||||
app::Color color = window.fontColor()->getColor();
|
|
||||||
|
|
||||||
ui::Paint paint = window.fontFace()->paint();
|
|
||||||
paint.color(color_utils::color_for_ui(color));
|
paint.color(color_utils::color_for_ui(color));
|
||||||
|
|
||||||
doc::ImageRef image = render_text(fontInfo, text, paint);
|
doc::ImageRef image = render_text(fontInfo, text, paint);
|
||||||
if (image) {
|
if (!image)
|
||||||
Sprite* sprite = editor->sprite();
|
return;
|
||||||
|
|
||||||
|
auto site = ctx->activeSite();
|
||||||
|
Sprite* sprite = site.sprite();
|
||||||
if (image->pixelFormat() != sprite->pixelFormat()) {
|
if (image->pixelFormat() != sprite->pixelFormat()) {
|
||||||
RgbMap* rgbmap = sprite->rgbMap(editor->frame());
|
RgbMap* rgbmap = sprite->rgbMap(site.frame());
|
||||||
image.reset(render::convert_pixel_format(image.get(),
|
image.reset(render::convert_pixel_format(image.get(),
|
||||||
NULL,
|
NULL,
|
||||||
sprite->pixelFormat(),
|
sprite->pixelFormat(),
|
||||||
render::Dithering(),
|
render::Dithering(),
|
||||||
rgbmap,
|
rgbmap,
|
||||||
sprite->palette(editor->frame()),
|
sprite->palette(site.frame()),
|
||||||
false,
|
false,
|
||||||
sprite->transparentColor()));
|
sprite->transparentColor()));
|
||||||
}
|
}
|
||||||
|
@ -109,8 +142,43 @@ void PasteTextCommand::onExecute(Context* ctx)
|
||||||
if (auto timeline = App::instance()->timeline())
|
if (auto timeline = App::instance()->timeline())
|
||||||
timeline->clearAndInvalidateRange();
|
timeline->clearAndInvalidateRange();
|
||||||
|
|
||||||
editor->pasteImage(image.get());
|
auto point = sprite->bounds().center() - gfx::Point(image->size().w / 2, image->size().h / 2);
|
||||||
|
if (params().x.isSet())
|
||||||
|
point.x = params().x();
|
||||||
|
if (params().y.isSet())
|
||||||
|
point.y = params().y();
|
||||||
|
|
||||||
|
if (ui) {
|
||||||
|
// TODO: Do we want to make this selectable result available when not using UI?
|
||||||
|
Editor::activeEditor()->pasteImage(image.get(), nullptr, &point);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ContextWriter writer(ctx);
|
||||||
|
Tx tx(writer, "Paste Text");
|
||||||
|
ImageRef finalImage = image;
|
||||||
|
if (writer.cel()->image()) {
|
||||||
|
gfx::Rect celRect(point, image->size());
|
||||||
|
ASSERT(!celRect.isEmpty() && celRect.x >= 0 && celRect.y >= 0);
|
||||||
|
finalImage.reset(
|
||||||
|
doc::crop_image(writer.cel()->image(), celRect, writer.cel()->image()->maskColor()));
|
||||||
|
render::Render render;
|
||||||
|
render.setNewBlend(pref.experimental.newBlend());
|
||||||
|
render.setBgOptions(render::BgOptions::MakeTransparent());
|
||||||
|
render.renderImage(finalImage.get(),
|
||||||
|
image.get(),
|
||||||
|
writer.palette(),
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
255,
|
||||||
|
doc::BlendMode::NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
tx(new cmd::CopyRegion(writer.cel()->image(),
|
||||||
|
finalImage.get(),
|
||||||
|
gfx::Region(finalImage->bounds()),
|
||||||
|
point));
|
||||||
|
tx.commit();
|
||||||
}
|
}
|
||||||
catch (const std::exception& ex) {
|
catch (const std::exception& ex) {
|
||||||
Console::showException(ex);
|
Console::showException(ex);
|
||||||
|
|
|
@ -10,12 +10,12 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "app/commands/command.h"
|
#include "app/commands/command.h"
|
||||||
|
#include "app/commands/new_params.h"
|
||||||
#include "app/context_access.h"
|
#include "app/context_access.h"
|
||||||
#include "app/file_selector.h"
|
#include "app/file_selector.h"
|
||||||
#include "app/i18n/strings.h"
|
#include "app/i18n/strings.h"
|
||||||
#include "app/util/msk_file.h"
|
#include "app/util/msk_file.h"
|
||||||
#include "base/fs.h"
|
#include "base/fs.h"
|
||||||
#include "new_params.h"
|
|
||||||
#include "ui/alert.h"
|
#include "ui/alert.h"
|
||||||
|
|
||||||
namespace app {
|
namespace app {
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
#include "app/app.h"
|
#include "app/app.h"
|
||||||
#include "app/commands/commands.h"
|
#include "app/commands/commands.h"
|
||||||
|
#include "app/commands/new_params.h"
|
||||||
#include "app/commands/params.h"
|
#include "app/commands/params.h"
|
||||||
#include "app/context.h"
|
#include "app/context.h"
|
||||||
#include "app/doc.h"
|
#include "app/doc.h"
|
||||||
|
@ -19,7 +20,6 @@
|
||||||
#include "app/i18n/strings.h"
|
#include "app/i18n/strings.h"
|
||||||
#include "app/modules/palettes.h"
|
#include "app/modules/palettes.h"
|
||||||
#include "base/fs.h"
|
#include "base/fs.h"
|
||||||
#include "new_params.h"
|
|
||||||
#include "ui/alert.h"
|
#include "ui/alert.h"
|
||||||
|
|
||||||
namespace app {
|
namespace app {
|
||||||
|
|
|
@ -213,7 +213,7 @@ void ResourceFinder::includeDesktopDir(const char* filename)
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
||||||
std::vector<wchar_t> buf(MAX_PATH);
|
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) {
|
if (hr == S_OK) {
|
||||||
addPath(base::join_path(base::to_utf8(&buf[0]), filename));
|
addPath(base::join_path(base::to_utf8(&buf[0]), filename));
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
#include "app/console.h"
|
#include "app/console.h"
|
||||||
#include "app/context.h"
|
#include "app/context.h"
|
||||||
#include "app/context_observer.h"
|
#include "app/context_observer.h"
|
||||||
|
#include "app/doc.h"
|
||||||
|
#include "app/doc_undo.h"
|
||||||
#include "app/script/docobj.h"
|
#include "app/script/docobj.h"
|
||||||
#include "app/script/engine.h"
|
#include "app/script/engine.h"
|
||||||
#include "app/script/luacpp.h"
|
#include "app/script/luacpp.h"
|
||||||
|
|
|
@ -64,6 +64,7 @@
|
||||||
#include "doc/tag.h"
|
#include "doc/tag.h"
|
||||||
#include "doc/tileset.h"
|
#include "doc/tileset.h"
|
||||||
#include "doc/tilesets.h"
|
#include "doc/tilesets.h"
|
||||||
|
#include "undo/undo_state.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
@ -1029,6 +1030,42 @@ int Sprite_set_useLayerUuids(lua_State* L)
|
||||||
return 0;
|
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[] = {
|
const luaL_Reg Sprite_methods[] = {
|
||||||
{ "__eq", Sprite_eq },
|
{ "__eq", Sprite_eq },
|
||||||
{ "resize", Sprite_resize },
|
{ "resize", Sprite_resize },
|
||||||
|
@ -1094,6 +1131,7 @@ const Property Sprite_properties[] = {
|
||||||
{ "events", Sprite_get_events, nullptr },
|
{ "events", Sprite_get_events, nullptr },
|
||||||
{ "tileManagementPlugin", Sprite_get_tileManagementPlugin, Sprite_set_tileManagementPlugin },
|
{ "tileManagementPlugin", Sprite_get_tileManagementPlugin, Sprite_set_tileManagementPlugin },
|
||||||
{ "useLayerUuids", Sprite_get_useLayerUuids, Sprite_set_useLayerUuids },
|
{ "useLayerUuids", Sprite_get_useLayerUuids, Sprite_set_useLayerUuids },
|
||||||
|
{ "undoHistory", Sprite_get_undoHistory, nullptr },
|
||||||
{ nullptr, nullptr, nullptr }
|
{ nullptr, nullptr, nullptr }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -443,12 +443,7 @@ bool WritingTextState::onSetCursor(Editor* editor, const gfx::Point& mouseScreen
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WritingTextState::onKeyDown(Editor*, KeyMessage*)
|
bool WritingTextState::onKeyDown(Editor*, KeyMessage* msg)
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WritingTextState::onKeyUp(Editor*, KeyMessage* msg)
|
|
||||||
{
|
{
|
||||||
// Cancel loop pressing Esc key
|
// Cancel loop pressing Esc key
|
||||||
if (msg->scancode() == ui::kKeyEsc) {
|
if (msg->scancode() == ui::kKeyEsc) {
|
||||||
|
@ -457,7 +452,17 @@ bool WritingTextState::onKeyUp(Editor*, KeyMessage* msg)
|
||||||
// Drop text pressing Enter key
|
// Drop text pressing Enter key
|
||||||
else if (msg->scancode() == ui::kKeyEnter) {
|
else if (msg->scancode() == ui::kKeyEnter) {
|
||||||
drop();
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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>
|
|
@ -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>
|
|
@ -228,3 +228,69 @@ do
|
||||||
c = app.open(fn)
|
c = app.open(fn)
|
||||||
assert(c.tileManagementPlugin == nil)
|
assert(c.tileManagementPlugin == nil)
|
||||||
end
|
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
|
||||||
|
|
Loading…
Reference in New Issue