mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-29 19:20:09 +00:00
Merge branch 'main' into beta
This commit is contained in:
commit
88594bfa0e
@ -83,6 +83,10 @@ On Arch:
|
||||
|
||||
sudo pacman -S gcc clang libc++ cmake ninja libx11 libxcursor mesa-libgl fontconfig
|
||||
|
||||
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
|
||||
|
||||
# Compiling
|
||||
|
||||
1. [Get Aseprite code](#get-the-source-code), put it in a folder like
|
||||
|
@ -1136,7 +1136,7 @@
|
||||
</menu>
|
||||
|
||||
<menu id="slice_popup_menu">
|
||||
<item command="SliceProperties" text="@.properties" grou="slice_popup_properties" />
|
||||
<item command="SliceProperties" text="@.properties" group="slice_popup_properties" />
|
||||
<item command="RemoveSlice" text="@.delete" group="slice_popup_delete" />
|
||||
</menu>
|
||||
|
||||
|
@ -510,6 +510,7 @@
|
||||
<option id="resize_scale" type="double" default="1" />
|
||||
<option id="area" type="std::string" />
|
||||
<option id="layer" type="std::string" />
|
||||
<option id="layer_index" type="int" default ="-1" />
|
||||
<option id="frame_tag" type="std::string" />
|
||||
<option id="ani_dir" type="doc::AniDir" default="doc::AniDir::FORWARD" />
|
||||
<option id="apply_pixel_ratio" type="bool" default="false" />
|
||||
@ -537,6 +538,7 @@
|
||||
<option id="ignore_empty" type="bool" default="false" />
|
||||
<option id="open_generated" type="bool" default="false" />
|
||||
<option id="layer" type="std::string" />
|
||||
<option id="layer_index" type="int" default ="-1" />
|
||||
<option id="frame_tag" type="std::string" />
|
||||
<option id="split_layers" type="bool" default="false" />
|
||||
<option id="split_tags" type="bool" default="false" />
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!-- Aseprite -->
|
||||
<!-- Copyright (C) 2020-2021 Igara Studio S.A. -->
|
||||
<!-- Copyright (C) 2020-2022 Igara Studio S.A. -->
|
||||
<gui>
|
||||
<vbox id="dynamics">
|
||||
<hbox>
|
||||
@ -16,16 +16,16 @@
|
||||
<item text="@.velocity" tooltip="@.velocity_tooltip" tooltip_dir="bottom" />
|
||||
|
||||
<item text="@.size" tooltip="@.size_tooltip" tooltip_dir="right" />
|
||||
<item text="" maxheight="1" />
|
||||
<item text="" maxheight="1" />
|
||||
<item text="" minheight="1" maxheight="1" />
|
||||
<item text="" minheight="1" maxheight="1" />
|
||||
|
||||
<item text="@.angle" tooltip="@.angle_tooltip" tooltip_dir="right" />
|
||||
<item text="" maxheight="1" />
|
||||
<item text="" maxheight="1" />
|
||||
<item text="" minheight="1" maxheight="1" />
|
||||
<item text="" minheight="1" maxheight="1" />
|
||||
|
||||
<item text="@.gradient" tooltip="@.gradient_tooltip" tooltip_dir="right" />
|
||||
<item text="" maxheight="1" />
|
||||
<item text="" maxheight="1" />
|
||||
<item text="" minheight="1" maxheight="1" />
|
||||
<item text="" minheight="1" maxheight="1" />
|
||||
</buttonset>
|
||||
</hbox>
|
||||
|
||||
|
2
laf
2
laf
@ -1 +1 @@
|
||||
Subproject commit f9760fd243ff25b85f12e8b368a699aa222671ba
|
||||
Subproject commit b4ca9e2a0946c2ecb1efdf3ecb01888f350e3e26
|
@ -160,6 +160,7 @@ Doc* generate_sprite_sheet_from_params(
|
||||
const SpriteSheetDataFormat dataFormat = params.dataFormat();
|
||||
const std::string filenameFormat = params.filenameFormat();
|
||||
const std::string layerName = params.layer();
|
||||
const int layerIndex = params.layerIndex();
|
||||
const std::string tagName = params.tag();
|
||||
const int borderPadding = std::clamp(params.borderPadding(), 0, 100);
|
||||
const int shapePadding = std::clamp(params.shapePadding(), 0, 100);
|
||||
@ -192,13 +193,16 @@ Doc* generate_sprite_sheet_from_params(
|
||||
// If the user choose to render selected layers only, we can
|
||||
// temporaly make them visible and hide the other ones.
|
||||
RestoreVisibleLayers layersVisibility;
|
||||
calculate_visible_layers(site, layerName, layersVisibility);
|
||||
calculate_visible_layers(site, layerName, layerIndex, layersVisibility);
|
||||
|
||||
SelectedLayers selLayers;
|
||||
if (layerName != kSelectedLayers) {
|
||||
// TODO add a getLayerByName
|
||||
int i = sprite->allLayersCount();
|
||||
for (const Layer* layer : sprite->allLayers()) {
|
||||
if (layer->name() == layerName) {
|
||||
i--;
|
||||
if (layer->name() == layerName && layerIndex == -1 ||
|
||||
layer->name() == layerName && layerIndex == i) {
|
||||
selLayers.insert(const_cast<Layer*>(layer));
|
||||
break;
|
||||
}
|
||||
@ -376,7 +380,7 @@ public:
|
||||
source()->setSelectedItemIndex(int(kSource_Tilesets));
|
||||
|
||||
fill_layers_combobox(
|
||||
m_sprite, layers(), params.layer());
|
||||
m_sprite, layers(), params.layer(), params.layerIndex());
|
||||
|
||||
fill_frames_combobox(
|
||||
m_sprite, frames(), params.tag());
|
||||
@ -533,6 +537,7 @@ public:
|
||||
params.ignoreEmpty (ignoreEmptyValue());
|
||||
params.openGenerated (openGeneratedValue());
|
||||
params.layer (layerValue());
|
||||
params.layerIndex (layerIndex());
|
||||
params.tag (tagValue());
|
||||
params.splitLayers (splitLayersValue());
|
||||
params.splitTags (splitTagsValue());
|
||||
@ -720,6 +725,11 @@ private:
|
||||
return layers()->getValue();
|
||||
}
|
||||
|
||||
int layerIndex() const {
|
||||
int i = layers()->getSelectedItemIndex() - kLayersComboboxExtraInitialItems;
|
||||
return i < 0 ? -1 : i;
|
||||
}
|
||||
|
||||
std::string tagValue() const {
|
||||
return frames()->getValue();
|
||||
}
|
||||
@ -1234,6 +1244,7 @@ void ExportSpriteSheetCommand::onExecute(Context* context)
|
||||
if (!params.ignoreEmpty.isSet()) params.ignoreEmpty( defPref.spriteSheet.ignoreEmpty());
|
||||
if (!params.openGenerated.isSet()) params.openGenerated( defPref.spriteSheet.openGenerated());
|
||||
if (!params.layer.isSet()) params.layer( defPref.spriteSheet.layer());
|
||||
if (!params.layerIndex.isSet()) params.layerIndex( defPref.spriteSheet.layerIndex());
|
||||
if (!params.tag.isSet()) params.tag( defPref.spriteSheet.frameTag());
|
||||
if (!params.splitLayers.isSet()) params.splitLayers( defPref.spriteSheet.splitLayers());
|
||||
if (!params.splitTags.isSet()) params.splitTags( defPref.spriteSheet.splitTags());
|
||||
@ -1281,6 +1292,7 @@ void ExportSpriteSheetCommand::onExecute(Context* context)
|
||||
docPref.spriteSheet.ignoreEmpty (params.ignoreEmpty());
|
||||
docPref.spriteSheet.openGenerated (params.openGenerated());
|
||||
docPref.spriteSheet.layer (params.layer());
|
||||
docPref.spriteSheet.layerIndex (params.layerIndex());
|
||||
docPref.spriteSheet.frameTag (params.tag());
|
||||
docPref.spriteSheet.splitLayers (params.splitLayers());
|
||||
docPref.spriteSheet.splitTags (params.splitTags());
|
||||
|
@ -40,6 +40,12 @@ struct ExportSpriteSheetParams : public NewParams {
|
||||
Param<bool> mergeDuplicates { this, false, "mergeDuplicates" };
|
||||
Param<bool> openGenerated { this, false, "openGenerated" };
|
||||
Param<std::string> layer { this, std::string(), "layer" };
|
||||
// TODO The layerIndex parameter is for internal use only, layers
|
||||
// are counted in the same order as they are displayed in the
|
||||
// Timeline or in the Export Sprite Sheet combobox. But this
|
||||
// index is different to the one specified in the .aseprite
|
||||
// file spec (where layers are counted from bottom to top).
|
||||
Param<int> layerIndex { this, -1, "_layerIndex" };
|
||||
Param<std::string> tag { this, std::string(), "tag" };
|
||||
Param<bool> splitLayers { this, false, "splitLayers" };
|
||||
Param<bool> splitTags { this, false, "splitTags" };
|
||||
|
@ -217,23 +217,23 @@ protected:
|
||||
switch (m_tiled) {
|
||||
case TiledMode::NONE:
|
||||
render.renderImage(m_doublebuf.get(), m_render.get(), m_pal, x, y,
|
||||
255, BlendMode::NORMAL);
|
||||
255, doc::BlendMode::NORMAL);
|
||||
break;
|
||||
case TiledMode::X_AXIS:
|
||||
for (u=x-w; u<displaySize.w+w; u+=w)
|
||||
render.renderImage(m_doublebuf.get(), m_render.get(), m_pal, u, y,
|
||||
255, BlendMode::NORMAL);
|
||||
255, doc::BlendMode::NORMAL);
|
||||
break;
|
||||
case TiledMode::Y_AXIS:
|
||||
for (v=y-h; v<displaySize.h+h; v+=h)
|
||||
render.renderImage(m_doublebuf.get(), m_render.get(), m_pal, x, v,
|
||||
255, BlendMode::NORMAL);
|
||||
255, doc::BlendMode::NORMAL);
|
||||
break;
|
||||
case TiledMode::BOTH:
|
||||
for (v=y-h; v<displaySize.h+h; v+=h)
|
||||
for (u=x-w; u<displaySize.w+w; u+=w)
|
||||
render.renderImage(m_doublebuf.get(), m_render.get(), m_pal, u, v,
|
||||
255, BlendMode::NORMAL);
|
||||
255, doc::BlendMode::NORMAL);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -153,7 +153,7 @@ private:
|
||||
return name()->text();
|
||||
}
|
||||
|
||||
BlendMode blendModeValue() const {
|
||||
doc::BlendMode blendModeValue() const {
|
||||
BlendModeItem* item = dynamic_cast<BlendModeItem*>(mode()->getSelectedItem());
|
||||
if (item)
|
||||
return item->mode();
|
||||
@ -232,7 +232,7 @@ private:
|
||||
std::string newName = nameValue();
|
||||
int newOpacity = opacityValue();
|
||||
const doc::UserData newUserData = m_userDataView.userData();
|
||||
BlendMode newBlendMode = blendModeValue();
|
||||
doc::BlendMode newBlendMode = blendModeValue();
|
||||
|
||||
if ((count > 1) ||
|
||||
(count == 1 && m_layer && (newName != m_layer->name() ||
|
||||
|
@ -349,6 +349,7 @@ void SaveFileCopyAsCommand::onExecute(Context* context)
|
||||
Doc* doc = context->activeDocument();
|
||||
std::string outputFilename = params().filename();
|
||||
std::string layers = kAllLayers;
|
||||
int layersIndex = -1;
|
||||
std::string frames = kAllFrames;
|
||||
bool applyPixelRatio = false;
|
||||
double scale = params().scale();
|
||||
@ -422,6 +423,7 @@ void SaveFileCopyAsCommand::onExecute(Context* context)
|
||||
win.savePref();
|
||||
|
||||
layers = win.layersValue();
|
||||
layersIndex = win.layersIndex();
|
||||
frames = win.framesValue();
|
||||
scale = win.resizeValue();
|
||||
params().slice(win.areaValue()); // Set slice
|
||||
@ -481,6 +483,7 @@ void SaveFileCopyAsCommand::onExecute(Context* context)
|
||||
// Selected layers to export
|
||||
calculate_visible_layers(site,
|
||||
layers,
|
||||
layersIndex,
|
||||
layersVisibility);
|
||||
|
||||
// m_selFrames is not empty if fromFrame/toFrame parameters are
|
||||
|
@ -41,6 +41,8 @@
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "base/log.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
namespace {
|
||||
@ -368,7 +370,6 @@ void Extension::uninstall(const DeletePluginPref delPref)
|
||||
|
||||
// Remove all files inside the extension path
|
||||
uninstallFiles(m_path, delPref);
|
||||
ASSERT(!base::is_directory(m_path) || delPref == DeletePluginPref::kNo);
|
||||
|
||||
m_isEnabled = false;
|
||||
m_isInstalled = false;
|
||||
@ -422,7 +423,13 @@ void Extension::uninstallFiles(const std::string& path,
|
||||
|
||||
for (const auto& dir : installedDirs) {
|
||||
TRACE("EXT: Deleting directory '%s'\n", dir.c_str());
|
||||
base::remove_directory(dir);
|
||||
try {
|
||||
base::remove_directory(dir);
|
||||
}
|
||||
catch (const std::exception& ex) {
|
||||
LOG(ERROR, "RECO: Extension subdirectory cannot be removed, it's not empty.\n"
|
||||
" Error: %s\n", ex.what());
|
||||
}
|
||||
}
|
||||
|
||||
// Delete __info.json file if it does exist (e.g. maybe the
|
||||
@ -435,8 +442,15 @@ void Extension::uninstallFiles(const std::string& path,
|
||||
}
|
||||
|
||||
TRACE("EXT: Deleting extension directory '%s'\n", path.c_str());
|
||||
if (!hasPrefFile)
|
||||
base::remove_directory(path);
|
||||
if (!hasPrefFile) {
|
||||
try {
|
||||
base::remove_directory(path);
|
||||
}
|
||||
catch (const std::exception& ex) {
|
||||
LOG(ERROR, "RECO: Extension directory cannot be removed, it's not empty.\n"
|
||||
" Error: %s\n", ex.what());
|
||||
}
|
||||
}
|
||||
|
||||
#else // The following code delete the whole "path",
|
||||
// we prefer the __info.json approach.
|
||||
|
@ -1213,7 +1213,7 @@ bool BmpFormat::onSave(FileOp *fop)
|
||||
+ biSizeImage); // image data
|
||||
}
|
||||
else {
|
||||
biSizeImage = (w*3 + filler) * h;
|
||||
biSizeImage = (w*bpp/8 + filler) * h;
|
||||
if (withAlpha)
|
||||
bfSize = BV3INFOHEADERSIZE +
|
||||
OS2FILEHEADERSIZE + biSizeImage; // header + image data
|
||||
|
@ -128,12 +128,7 @@ public:
|
||||
|
||||
// Opacity is set to 255 when InkType=Simple in ToolLoopBase()
|
||||
if (loop->getOpacity() == 255 &&
|
||||
// The trace policy is "overlap" when the dynamics has
|
||||
// a gradient between FG <-> BG
|
||||
//
|
||||
// TODO this trace policy is configured in
|
||||
// ToolLoopBase() ctor, is there a better place?
|
||||
loop->getTracePolicy() != TracePolicy::Overlap) {
|
||||
loop->getDynamics().gradient == DynamicSensor::Static) {
|
||||
color_t color = loop->getPrimaryColor();
|
||||
|
||||
switch (loop->sprite()->pixelFormat()) {
|
||||
|
@ -94,8 +94,9 @@ void ButtonSet::Item::onPaint(ui::PaintEvent& ev)
|
||||
bool isLastRow = (info.row+info.vspan >= info.grid_rows);
|
||||
|
||||
if (m_icon || isLastRow) {
|
||||
textRc.y -= 1*guiscale();
|
||||
textRc.y -= 2*guiscale();
|
||||
iconRc.y -= 1*guiscale();
|
||||
if (isLastRow && info.row > 0) iconRc.y -= 2*guiscale();
|
||||
}
|
||||
|
||||
if (!gfx::is_transparent(bgColor()))
|
||||
|
@ -110,7 +110,7 @@ void DrawingState::initToolLoop(Editor* editor,
|
||||
(previewLayer &&
|
||||
previewLayer->isImage() ?
|
||||
static_cast<LayerImage*>(m_toolLoop->getLayer())->blendMode():
|
||||
BlendMode::NEG_BW)); // To preview the selection ink we use the negative black & white blender
|
||||
doc::BlendMode::NEG_BW)); // To preview the selection ink we use the negative black & white blender
|
||||
|
||||
ASSERT(!m_toolLoopManager->isCanceled());
|
||||
|
||||
|
@ -112,15 +112,12 @@ public:
|
||||
m_g->drawLine(color, a, b);
|
||||
}
|
||||
|
||||
void drawRectXor(const gfx::Rect& rc) override {
|
||||
void drawRect(gfx::Color color, const gfx::Rect& rc) override {
|
||||
gfx::Rect rc2 = m_editor->editorToScreen(rc);
|
||||
gfx::Rect bounds = m_editor->bounds();
|
||||
rc2.x -= bounds.x;
|
||||
rc2.y -= bounds.y;
|
||||
|
||||
m_g->setDrawMode(Graphics::DrawMode::Xor);
|
||||
m_g->drawRect(gfx::rgba(255, 255, 255), rc2);
|
||||
m_g->setDrawMode(Graphics::DrawMode::Solid);
|
||||
m_g->drawRect(color, rc2);
|
||||
}
|
||||
|
||||
void fillRect(gfx::Color color, const gfx::Rect& rc) override {
|
||||
@ -1033,12 +1030,11 @@ void Editor::drawMask(Graphics* g)
|
||||
auto& segs = m_document->maskBoundaries();
|
||||
segs.createPathIfNeeeded();
|
||||
|
||||
CheckeredDrawMode checkered(g, m_antsOffset,
|
||||
gfx::rgba(0, 0, 0, 255),
|
||||
gfx::rgba(255, 255, 255, 255));
|
||||
os::Paint paint;
|
||||
paint.style(os::Paint::Stroke);
|
||||
paint.color(gfx::rgba(0, 0, 0));
|
||||
ui::Paint paint;
|
||||
paint.style(ui::Paint::Stroke);
|
||||
set_checkered_paint_mode(paint, m_antsOffset,
|
||||
gfx::rgba(0, 0, 0, 255),
|
||||
gfx::rgba(255, 255, 255, 255));
|
||||
|
||||
// We translate the path instead of applying a matrix to the
|
||||
// ui::Graphics so the "checkered" pattern is not scaled too.
|
||||
@ -1333,12 +1329,14 @@ void Editor::drawCelHGuide(ui::Graphics* g,
|
||||
|
||||
// Vertical guide to touch the horizontal line
|
||||
{
|
||||
CheckeredDrawMode checkered(g, 0, color, gfx::ColorNone);
|
||||
ui::Paint paint;
|
||||
ui::set_checkered_paint_mode(paint, 0, color, gfx::ColorNone);
|
||||
paint.color(color);
|
||||
|
||||
if (scrY < scrCmpBounds.y)
|
||||
g->drawVLine(color, dottedX, scrCelBounds.y, scrCmpBounds.y - scrCelBounds.y);
|
||||
g->drawVLine(dottedX, scrCelBounds.y, scrCmpBounds.y - scrCelBounds.y, paint);
|
||||
else if (scrY > scrCmpBounds.y2())
|
||||
g->drawVLine(color, dottedX, scrCmpBounds.y2(), scrCelBounds.y2() - scrCmpBounds.y2());
|
||||
g->drawVLine(dottedX, scrCmpBounds.y2(), scrCelBounds.y2() - scrCmpBounds.y2(), paint);
|
||||
}
|
||||
|
||||
auto text = fmt::format("{}px", ABS(sprX2 - sprX1));
|
||||
@ -1359,12 +1357,14 @@ void Editor::drawCelVGuide(ui::Graphics* g,
|
||||
|
||||
// Horizontal guide to touch the vertical line
|
||||
{
|
||||
CheckeredDrawMode checkered(g, 0, color, gfx::ColorNone);
|
||||
ui::Paint paint;
|
||||
ui::set_checkered_paint_mode(paint, 0, color, gfx::ColorNone);
|
||||
paint.color(color);
|
||||
|
||||
if (scrX < scrCmpBounds.x)
|
||||
g->drawHLine(color, scrCelBounds.x, dottedY, scrCmpBounds.x - scrCelBounds.x);
|
||||
g->drawHLine(scrCelBounds.x, dottedY, scrCmpBounds.x - scrCelBounds.x, paint);
|
||||
else if (scrX > scrCmpBounds.x2())
|
||||
g->drawHLine(color, scrCmpBounds.x2(), dottedY, scrCelBounds.x2() - scrCmpBounds.x2());
|
||||
g->drawHLine(scrCmpBounds.x2(), dottedY, scrCelBounds.x2() - scrCmpBounds.x2(), paint);
|
||||
}
|
||||
|
||||
auto text = fmt::format("{}px", ABS(sprY2 - sprY1));
|
||||
@ -1409,7 +1409,7 @@ void Editor::flashCurrentLayer()
|
||||
|
||||
ExtraCelRef extraCel(new ExtraCel);
|
||||
extraCel->setType(render::ExtraType::OVER_COMPOSITE);
|
||||
extraCel->setBlendMode(BlendMode::NEG_BW);
|
||||
extraCel->setBlendMode(doc::BlendMode::NEG_BW);
|
||||
|
||||
m_document->setExtraCel(extraCel);
|
||||
m_flashing = Flashing::WithFlashExtraCel;
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2020 Igara Studio S.A.
|
||||
// Copyright (C) 2020-2022 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -39,7 +39,7 @@ namespace app {
|
||||
virtual Editor* getEditor() = 0;
|
||||
virtual ui::Graphics* getGraphics() = 0;
|
||||
virtual void drawLine(gfx::Color color, int x1, int y1, int x2, int y2) = 0;
|
||||
virtual void drawRectXor(const gfx::Rect& rc) = 0;
|
||||
virtual void drawRect(gfx::Color color, const gfx::Rect& rc) = 0;
|
||||
virtual void fillRect(gfx::Color color, const gfx::Rect& rc) = 0;
|
||||
};
|
||||
|
||||
|
@ -566,7 +566,7 @@ void SelectBoxState::postRenderDecorator(EditorPostRender* render)
|
||||
}
|
||||
|
||||
if (hasFlag(Flags::QuickBox)) {
|
||||
render->drawRectXor(rc);
|
||||
render->drawRect(gfx::rgba(255, 255, 255), rc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@ ExportFileWindow::ExportFileWindow(const Doc* doc)
|
||||
// Default export configuration
|
||||
setResizeScale(m_docPref.saveCopy.resizeScale());
|
||||
fill_area_combobox(m_doc->sprite(), area(), m_docPref.saveCopy.area());
|
||||
fill_layers_combobox(m_doc->sprite(), layers(), m_docPref.saveCopy.layer());
|
||||
fill_layers_combobox(m_doc->sprite(), layers(), m_docPref.saveCopy.layer(), m_docPref.saveCopy.layerIndex());
|
||||
fill_frames_combobox(m_doc->sprite(), frames(), m_docPref.saveCopy.frameTag());
|
||||
fill_anidir_combobox(anidir(), m_docPref.saveCopy.aniDir());
|
||||
pixelRatio()->setSelected(m_docPref.saveCopy.applyPixelRatio());
|
||||
@ -100,6 +100,7 @@ void ExportFileWindow::savePref()
|
||||
m_docPref.saveCopy.resizeScale(resizeValue());
|
||||
m_docPref.saveCopy.area(areaValue());
|
||||
m_docPref.saveCopy.layer(layersValue());
|
||||
m_docPref.saveCopy.layerIndex(layersIndex());
|
||||
m_docPref.saveCopy.aniDir(aniDirValue());
|
||||
m_docPref.saveCopy.frameTag(framesValue());
|
||||
m_docPref.saveCopy.applyPixelRatio(applyPixelRatio());
|
||||
@ -128,6 +129,12 @@ std::string ExportFileWindow::layersValue() const
|
||||
return layers()->getValue();
|
||||
}
|
||||
|
||||
int ExportFileWindow::layersIndex() const
|
||||
{
|
||||
int i = layers()->getSelectedItemIndex() - kLayersComboboxExtraInitialItems;
|
||||
return i < 0 ? -1 : i;
|
||||
}
|
||||
|
||||
std::string ExportFileWindow::framesValue() const
|
||||
{
|
||||
return frames()->getValue();
|
||||
|
@ -30,6 +30,7 @@ namespace app {
|
||||
double resizeValue() const;
|
||||
std::string areaValue() const;
|
||||
std::string layersValue() const;
|
||||
int layersIndex() const;
|
||||
std::string framesValue() const;
|
||||
doc::AniDir aniDirValue() const;
|
||||
bool applyPixelRatio() const;
|
||||
|
@ -87,7 +87,7 @@ void fill_area_combobox(const doc::Sprite* sprite, ui::ComboBox* area, const std
|
||||
}
|
||||
}
|
||||
|
||||
void fill_layers_combobox(const doc::Sprite* sprite, ui::ComboBox* layers, const std::string& defLayer)
|
||||
void fill_layers_combobox(const doc::Sprite* sprite, ui::ComboBox* layers, const std::string& defLayer, const int defLayerIndex)
|
||||
{
|
||||
int i = layers->addItem("Visible layers");
|
||||
dynamic_cast<ui::ListItem*>(layers->getItem(i))->setValue(kAllLayers);
|
||||
@ -97,11 +97,16 @@ void fill_layers_combobox(const doc::Sprite* sprite, ui::ComboBox* layers, const
|
||||
if (defLayer == kSelectedLayers)
|
||||
layers->setSelectedItemIndex(i);
|
||||
|
||||
assert(layers->getItemCount() == kLayersComboboxExtraInitialItems);
|
||||
static_assert(kLayersComboboxExtraInitialItems == 2,
|
||||
"Update kLayersComboboxExtraInitialItems value to match the number of initial items in layers combobox");
|
||||
|
||||
doc::LayerList layersList = sprite->allLayers();
|
||||
for (auto it=layersList.rbegin(), end=layersList.rend(); it!=end; ++it) {
|
||||
doc::Layer* layer = *it;
|
||||
i = layers->addItem(new LayerListItem(layer));
|
||||
if (defLayer == layer->name())
|
||||
if (defLayer == layer->name() && defLayerIndex == -1 ||
|
||||
defLayer == layer->name() && defLayerIndex == i-kLayersComboboxExtraInitialItems)
|
||||
layers->setSelectedItemIndex(i);
|
||||
}
|
||||
}
|
||||
@ -142,6 +147,7 @@ void fill_anidir_combobox(ui::ComboBox* anidir, doc::AniDir defAnidir)
|
||||
|
||||
void calculate_visible_layers(const Site& site,
|
||||
const std::string& layersValue,
|
||||
const int layersIndex,
|
||||
RestoreVisibleLayers& layersVisibility)
|
||||
{
|
||||
if (layersValue == kSelectedLayers) {
|
||||
@ -154,10 +160,13 @@ void calculate_visible_layers(const Site& site,
|
||||
layersVisibility.showLayer(const_cast<Layer*>(site.layer()));
|
||||
}
|
||||
}
|
||||
else if (layersValue != kAllFrames) {
|
||||
else if (layersValue != kAllLayers) {
|
||||
int i = site.sprite()->allLayersCount();
|
||||
// TODO add a getLayerByName
|
||||
for (doc::Layer* layer : site.sprite()->allLayers()) {
|
||||
if (layer->name() == layersValue) {
|
||||
i--;
|
||||
if (layer->name() == layersValue && layersIndex == -1 ||
|
||||
layer->name() == layersValue && layersIndex == i) {
|
||||
layersVisibility.showLayer(layer);
|
||||
break;
|
||||
}
|
||||
|
@ -46,6 +46,8 @@ namespace app {
|
||||
doc::Slice* m_slice;
|
||||
};
|
||||
|
||||
constexpr const int kLayersComboboxExtraInitialItems = 2;
|
||||
|
||||
class LayerListItem : public ui::ListItem {
|
||||
public:
|
||||
LayerListItem(doc::Layer* layer);
|
||||
@ -64,12 +66,13 @@ namespace app {
|
||||
};
|
||||
|
||||
void fill_area_combobox(const doc::Sprite* sprite, ui::ComboBox* area, const std::string& defArea);
|
||||
void fill_layers_combobox(const doc::Sprite* sprite, ui::ComboBox* layers, const std::string& defLayer);
|
||||
void fill_layers_combobox(const doc::Sprite* sprite, ui::ComboBox* layers, const std::string& defLayer, const int defLayerIndex);
|
||||
void fill_frames_combobox(const doc::Sprite* sprite, ui::ComboBox* frames, const std::string& defFrame);
|
||||
void fill_anidir_combobox(ui::ComboBox* anidir, doc::AniDir defAnidir);
|
||||
|
||||
void calculate_visible_layers(const Site& site,
|
||||
const std::string& layersValue,
|
||||
const int layersIndex,
|
||||
RestoreVisibleLayers& layersVisibility);
|
||||
|
||||
doc::Tag* calculate_selected_frames(const Site& site,
|
||||
|
@ -974,10 +974,12 @@ void PaletteView::onPaint(ui::PaintEvent& ev)
|
||||
|
||||
IntersectClip clip(g, clipR);
|
||||
if (clip) {
|
||||
CheckeredDrawMode checkered(g, getMarchingAntsOffset(),
|
||||
gfx::rgba(0, 0, 0, 255),
|
||||
gfx::rgba(255, 255, 255, 255));
|
||||
g->drawRect(gfx::rgba(0, 0, 0), box);
|
||||
ui::Paint paint;
|
||||
paint.style(ui::Paint::Stroke);
|
||||
ui::set_checkered_paint_mode(paint, getMarchingAntsOffset(),
|
||||
gfx::rgba(0, 0, 0, 255),
|
||||
gfx::rgba(255, 255, 255, 255));
|
||||
g->drawRect(box, paint);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1310,8 +1312,11 @@ int PaletteView::findExactIndex(const app::Color& color) const
|
||||
{
|
||||
switch (color.getType()) {
|
||||
|
||||
case Color::MaskType:
|
||||
return (current_editor ? current_editor->sprite()->transparentColor(): -1);
|
||||
case Color::MaskType: {
|
||||
if (current_editor && current_editor->sprite()->pixelFormat() == IMAGE_INDEXED)
|
||||
return current_editor->sprite()->transparentColor();
|
||||
return currentPalette()->findMaskColor();
|
||||
}
|
||||
|
||||
case Color::RgbType:
|
||||
case Color::HsvType:
|
||||
|
@ -2069,11 +2069,12 @@ void Timeline::drawClipboardRange(ui::Graphics* g)
|
||||
|
||||
IntersectClip clip(g, getRangeClipBounds(clipboard_range));
|
||||
if (clip) {
|
||||
CheckeredDrawMode checkered(g, m_offset_count,
|
||||
gfx::rgba(0, 0, 0, 255),
|
||||
gfx::rgba(255, 255, 255, 255));
|
||||
g->drawRect(gfx::rgba(0, 0, 0),
|
||||
getRangeBounds(clipboard_range));
|
||||
ui::Paint paint;
|
||||
paint.style(ui::Paint::Stroke);
|
||||
ui::set_checkered_paint_mode(paint, m_offset_count,
|
||||
gfx::rgba(0, 0, 0, 255),
|
||||
gfx::rgba(255, 255, 255, 255));
|
||||
g->drawRect(getRangeBounds(clipboard_range), paint);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -232,7 +232,7 @@ void Clipboard::setData(Image* image,
|
||||
}
|
||||
// Copy non-tilemap images to the native clipboard
|
||||
else {
|
||||
color_t oldMask;
|
||||
color_t oldMask = 0;
|
||||
if (image) {
|
||||
oldMask = image->maskColor();
|
||||
if (!image_source_is_transparent)
|
||||
|
@ -35,6 +35,7 @@ add_library(ui-lib
|
||||
move_region.cpp
|
||||
overlay.cpp
|
||||
overlay_manager.cpp
|
||||
paint.cpp
|
||||
paint_event.cpp
|
||||
panel.cpp
|
||||
popup_window.cpp
|
||||
|
@ -116,23 +116,6 @@ gfx::Matrix Graphics::matrix() const
|
||||
return m_surface->matrix();
|
||||
}
|
||||
|
||||
void Graphics::setDrawMode(DrawMode mode, int param,
|
||||
const gfx::Color a,
|
||||
const gfx::Color b)
|
||||
{
|
||||
switch (mode) {
|
||||
case DrawMode::Solid:
|
||||
m_surface->setDrawMode(os::DrawMode::Solid);
|
||||
break;
|
||||
case DrawMode::Xor:
|
||||
m_surface->setDrawMode(os::DrawMode::Xor);
|
||||
break;
|
||||
case DrawMode::Checkered:
|
||||
m_surface->setDrawMode(os::DrawMode::Checkered, param, a, b);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gfx::Color Graphics::getPixel(int x, int y)
|
||||
{
|
||||
os::SurfaceLock lock(m_surface.get());
|
||||
@ -147,6 +130,14 @@ void Graphics::putPixel(gfx::Color color, int x, int y)
|
||||
m_surface->putPixel(color, m_dx+x, m_dy+y);
|
||||
}
|
||||
|
||||
void Graphics::drawHLine(int x, int y, int w, const Paint& paint)
|
||||
{
|
||||
dirty(gfx::Rect(m_dx+x, m_dy+y, w, 1));
|
||||
|
||||
os::SurfaceLock lock(m_surface.get());
|
||||
m_surface->drawRect(gfx::Rect(m_dx+x, m_dy+y, w, 1), paint);
|
||||
}
|
||||
|
||||
void Graphics::drawHLine(gfx::Color color, int x, int y, int w)
|
||||
{
|
||||
dirty(gfx::Rect(m_dx+x, m_dy+y, w, 1));
|
||||
@ -157,6 +148,14 @@ void Graphics::drawHLine(gfx::Color color, int x, int y, int w)
|
||||
m_surface->drawRect(gfx::Rect(m_dx+x, m_dy+y, w, 1), paint);
|
||||
}
|
||||
|
||||
void Graphics::drawVLine(int x, int y, int h, const Paint& paint)
|
||||
{
|
||||
dirty(gfx::Rect(m_dx+x, m_dy+y, 1, h));
|
||||
|
||||
os::SurfaceLock lock(m_surface.get());
|
||||
m_surface->drawRect(gfx::Rect(m_dx+x, m_dy+y, 1, h), paint);
|
||||
}
|
||||
|
||||
void Graphics::drawVLine(gfx::Color color, int x, int y, int h)
|
||||
{
|
||||
dirty(gfx::Rect(m_dx+x, m_dy+y, 1, h));
|
||||
@ -319,6 +318,7 @@ void Graphics::drawSurfaceNine(os::Surface* surface,
|
||||
const gfx::Rect& src,
|
||||
const gfx::Rect& center,
|
||||
const gfx::Rect& dst,
|
||||
const bool drawCenter,
|
||||
const ui::Paint* paint)
|
||||
{
|
||||
gfx::Rect displacedDst(m_dx+dst.x, m_dy+dst.y, dst.w, dst.h);
|
||||
@ -326,7 +326,7 @@ void Graphics::drawSurfaceNine(os::Surface* surface,
|
||||
|
||||
os::SurfaceLock lockSrc(surface);
|
||||
os::SurfaceLock lockDst(m_surface.get());
|
||||
m_surface->drawSurfaceNine(surface, src, center, displacedDst, paint);
|
||||
m_surface->drawSurfaceNine(surface, src, center, displacedDst, drawCenter, paint);
|
||||
}
|
||||
|
||||
void Graphics::blit(os::Surface* srcSurface, int srcx, int srcy, int dstx, int dsty, int w, int h)
|
||||
|
@ -16,8 +16,8 @@
|
||||
#include "gfx/rect.h"
|
||||
#include "gfx/size.h"
|
||||
#include "os/font.h"
|
||||
#include "os/paint.h"
|
||||
#include "os/surface.h"
|
||||
#include "ui/paint.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@ -34,19 +34,11 @@ namespace os {
|
||||
}
|
||||
|
||||
namespace ui {
|
||||
using os::Paint; // Define ui::Paint = os::Paint
|
||||
|
||||
class Display;
|
||||
|
||||
// Class to render a widget in the screen.
|
||||
class Graphics {
|
||||
public:
|
||||
enum class DrawMode {
|
||||
Solid,
|
||||
Xor,
|
||||
Checkered,
|
||||
};
|
||||
|
||||
Graphics(Display* display, const os::SurfaceRef& surface, int dx, int dy);
|
||||
~Graphics();
|
||||
|
||||
@ -70,14 +62,12 @@ namespace ui {
|
||||
void restore();
|
||||
gfx::Matrix matrix() const;
|
||||
|
||||
void setDrawMode(DrawMode mode, int param = 0,
|
||||
const gfx::Color a = gfx::ColorNone,
|
||||
const gfx::Color b = gfx::ColorNone);
|
||||
|
||||
gfx::Color getPixel(int x, int y);
|
||||
void putPixel(gfx::Color color, int x, int y);
|
||||
|
||||
void drawHLine(int x, int y, int w, const Paint& paint);
|
||||
void drawHLine(gfx::Color color, int x, int y, int w);
|
||||
void drawVLine(int x, int y, int h, const Paint& paint);
|
||||
void drawVLine(gfx::Color color, int x, int y, int h);
|
||||
void drawLine(gfx::Color color, const gfx::Point& a, const gfx::Point& b);
|
||||
void drawPath(gfx::Path& path, const Paint& paint);
|
||||
@ -94,7 +84,7 @@ namespace ui {
|
||||
const gfx::Rect& srcRect,
|
||||
const gfx::Rect& dstRect,
|
||||
const os::Sampling& sampling,
|
||||
const ui::Paint* paint);
|
||||
const Paint* paint);
|
||||
void drawRgbaSurface(os::Surface* surface, int x, int y);
|
||||
void drawRgbaSurface(os::Surface* surface, int srcx, int srcy, int dstx, int dsty, int w, int h);
|
||||
void drawColoredRgbaSurface(os::Surface* surface, gfx::Color color, int x, int y);
|
||||
@ -103,6 +93,7 @@ namespace ui {
|
||||
const gfx::Rect& src,
|
||||
const gfx::Rect& center,
|
||||
const gfx::Rect& dst,
|
||||
const bool drawCenter,
|
||||
const Paint* paint = nullptr);
|
||||
|
||||
void blit(os::Surface* src, int srcx, int srcy, int dstx, int dsty, int w, int h);
|
||||
@ -195,24 +186,6 @@ namespace ui {
|
||||
DISABLE_COPYING(IntersectClip);
|
||||
};
|
||||
|
||||
class CheckeredDrawMode {
|
||||
public:
|
||||
CheckeredDrawMode(Graphics* g, int param,
|
||||
const gfx::Color a,
|
||||
const gfx::Color b) : m_graphics(g) {
|
||||
m_graphics->setDrawMode(Graphics::DrawMode::Checkered, param, a, b);
|
||||
}
|
||||
|
||||
~CheckeredDrawMode() {
|
||||
m_graphics->setDrawMode(Graphics::DrawMode::Solid);
|
||||
}
|
||||
|
||||
private:
|
||||
Graphics* m_graphics;
|
||||
|
||||
DISABLE_COPYING(CheckeredDrawMode);
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<Graphics> GraphicsPtr;
|
||||
|
||||
} // namespace ui
|
||||
|
53
src/ui/paint.cpp
Normal file
53
src/ui/paint.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
// Aseprite UI Library
|
||||
// Copyright (C) 2022 Igara Studio S.A.
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "ui/paint.h"
|
||||
|
||||
#include "base/exception.h"
|
||||
|
||||
#if LAF_SKIA
|
||||
#include "include/core/SkBitmap.h"
|
||||
#endif
|
||||
|
||||
namespace ui {
|
||||
|
||||
void set_checkered_paint_mode(Paint& paint,
|
||||
const int param,
|
||||
const gfx::Color a,
|
||||
const gfx::Color b)
|
||||
{
|
||||
#if LAF_SKIA
|
||||
SkPaint& skPaint = paint.skPaint();
|
||||
skPaint.setBlendMode(SkBlendMode::kSrcOver);
|
||||
|
||||
SkBitmap bitmap;
|
||||
if (!bitmap.tryAllocPixels(
|
||||
SkImageInfo::MakeN32(8, 8, kOpaque_SkAlphaType))) {
|
||||
throw base::Exception("Cannot create temporary Skia surface");
|
||||
}
|
||||
|
||||
{
|
||||
SkPMColor A = SkPreMultiplyARGB(gfx::geta(a), gfx::getr(a), gfx::getg(a), gfx::getb(a));
|
||||
SkPMColor B = SkPreMultiplyARGB(gfx::geta(b), gfx::getr(b), gfx::getg(b), gfx::getb(b));
|
||||
int offset = 7 - (param & 7);
|
||||
for (int y=0; y<8; y++)
|
||||
for (int x=0; x<8; x++)
|
||||
*bitmap.getAddr32(x, y) = (((x+y+offset)&7) < 4 ? B: A);
|
||||
}
|
||||
|
||||
sk_sp<SkShader> shader(
|
||||
bitmap.makeShader(SkTileMode::kRepeat,
|
||||
SkTileMode::kRepeat,
|
||||
SkSamplingOptions()));
|
||||
skPaint.setShader(shader);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace ui
|
27
src/ui/paint.h
Normal file
27
src/ui/paint.h
Normal file
@ -0,0 +1,27 @@
|
||||
// Aseprite UI Library
|
||||
// Copyright (C) 2022 Igara Studio S.A.
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
|
||||
#ifndef UI_PAINT_H_INCLUDED
|
||||
#define UI_PAINT_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "base/disable_copying.h"
|
||||
#include "gfx/color.h"
|
||||
#include "os/paint.h"
|
||||
|
||||
namespace ui {
|
||||
|
||||
using os::Paint;
|
||||
using os::BlendMode;
|
||||
|
||||
void set_checkered_paint_mode(Paint& paint,
|
||||
const int param,
|
||||
const gfx::Color a,
|
||||
const gfx::Color b);
|
||||
|
||||
} // namespace ui
|
||||
|
||||
#endif
|
@ -757,9 +757,7 @@ void Theme::drawSlices(Graphics* g, os::Surface* sheet,
|
||||
{
|
||||
Paint paint;
|
||||
paint.color(color);
|
||||
if (!drawCenter)
|
||||
paint.setFlags(Paint::kNineWithoutCenter);
|
||||
g->drawSurfaceNine(sheet, sprite, slices, rc, &paint);
|
||||
g->drawSurfaceNine(sheet, sprite, slices, rc, drawCenter, &paint);
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -179,6 +179,7 @@ void View::updateView(const bool restoreScrollPos)
|
||||
}
|
||||
|
||||
if (Widget* child = attachedWidget()) {
|
||||
(void)child;
|
||||
updateAttachedWidgetBounds(viewScroll());
|
||||
ASSERT(child->bounds().w >= viewportBounds().w);
|
||||
ASSERT(child->bounds().h >= viewportBounds().h);
|
||||
|
@ -1022,11 +1022,15 @@ void Widget::getTextIconInfo(
|
||||
|
||||
void Widget::setMinSize(const gfx::Size& sz)
|
||||
{
|
||||
ASSERT(sz.w <= m_maxSize.w);
|
||||
ASSERT(sz.h <= m_maxSize.h);
|
||||
m_minSize = sz;
|
||||
}
|
||||
|
||||
void Widget::setMaxSize(const gfx::Size& sz)
|
||||
{
|
||||
ASSERT(sz.w >= m_minSize.w);
|
||||
ASSERT(sz.h >= m_minSize.h);
|
||||
m_maxSize = sz;
|
||||
}
|
||||
|
||||
|
2
third_party/libarchive
vendored
2
third_party/libarchive
vendored
@ -1 +1 @@
|
||||
Subproject commit 1e1a58dfed29f5905fca14391959c04949fc037a
|
||||
Subproject commit fb3d9be28cfd4551de949bb5b8c44b1d6e2aec9b
|
Loading…
x
Reference in New Issue
Block a user