mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-30 04:20:23 +00:00
Initial refactor to create the view module (#3904)
* 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 commit is contained in:
parent
37f55fb635
commit
b2c6240a7e
@ -51,6 +51,7 @@ add_subdirectory(undo)
|
||||
|
||||
add_subdirectory(cfg)
|
||||
add_subdirectory(doc)
|
||||
add_subdirectory(view)
|
||||
add_subdirectory(filters)
|
||||
add_subdirectory(fixmath)
|
||||
add_subdirectory(flic)
|
||||
@ -208,6 +209,7 @@ if(ENABLE_TESTS)
|
||||
include(FindTests)
|
||||
find_tests(doc doc-lib)
|
||||
find_tests(doc/algorithm doc-lib)
|
||||
find_tests(view view-lib)
|
||||
find_tests(render render-lib)
|
||||
find_tests(ui ui-lib)
|
||||
find_tests(app/cli app-lib)
|
||||
|
@ -41,10 +41,11 @@ because they don't depend on any other component.
|
||||
* [dio](dio/) (base, doc, fixmath, flic): Load/save sprites/documents.
|
||||
* [filters](filters/) (base, doc, gfx): Effects for images.
|
||||
* [render](render/) (base, doc, gfx): Library to render documents.
|
||||
* [view](view/) (base, doc): Abstract timeline/range view/helpers.
|
||||
|
||||
## Level 4
|
||||
|
||||
* [app](app/) (base, doc, dio, filters, fixmath, flic, gfx, pen, render, scripting, os, ui, undo, updater)
|
||||
* [app](app/) (base, doc, dio, filters, fixmath, flic, gfx, pen, render, scripting, os, ui, undo, updater, view)
|
||||
* [desktop](desktop/) (base, doc, dio, render): Integration with the desktop (Windows Explorer, Finder, GNOME, KDE, etc.)
|
||||
|
||||
## Level 5
|
||||
|
@ -527,7 +527,6 @@ target_sources(app-lib PRIVATE
|
||||
doc_api.cpp
|
||||
doc_diff.cpp
|
||||
doc_exporter.cpp
|
||||
doc_range.cpp
|
||||
doc_range_ops.cpp
|
||||
doc_undo.cpp
|
||||
docs.cpp
|
||||
@ -707,7 +706,6 @@ target_sources(app-lib PRIVATE
|
||||
util/pal_ops.cpp
|
||||
util/pic_file.cpp
|
||||
util/pixel_ratio.cpp
|
||||
util/range_utils.cpp
|
||||
util/readable_time.cpp
|
||||
util/render_text.cpp
|
||||
util/resize_image.cpp
|
||||
@ -745,6 +743,7 @@ target_link_libraries(app-lib
|
||||
cfg-lib
|
||||
clip
|
||||
doc-lib
|
||||
view-lib
|
||||
dio-lib
|
||||
filters-lib
|
||||
fixmath-lib
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019-2021 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2023 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -12,8 +12,8 @@
|
||||
#include "app/doc.h"
|
||||
#include "app/doc_event.h"
|
||||
#include "app/site.h"
|
||||
#include "app/util/layer_utils.h"
|
||||
#include "doc/layer.h"
|
||||
#include "view/layers.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
@ -143,7 +143,8 @@ void ActiveSiteHandler::onBeforeRemoveLayer(DocEvent& ev)
|
||||
data.range.eraseAndAdjust(ev.layer());
|
||||
|
||||
// Select other layer as active
|
||||
doc::Layer* layerToSelect = candidate_if_layer_is_deleted(selectedLayer, ev.layer());
|
||||
doc::Layer* layerToSelect =
|
||||
view::candidate_if_layer_is_deleted(selectedLayer, ev.layer());
|
||||
if (selectedLayer != layerToSelect) {
|
||||
data.layer = (layerToSelect ? layerToSelect->id():
|
||||
doc::NullId);
|
||||
|
@ -63,8 +63,9 @@ bool CelOpacityCommand::onEnabled(Context* context)
|
||||
void CelOpacityCommand::onExecute(Context* context)
|
||||
{
|
||||
ContextWriter writer(context);
|
||||
Layer* layer = writer.layer();
|
||||
Cel* cel = writer.cel();
|
||||
const Site& site = writer.site();
|
||||
Layer* layer = site.layer();
|
||||
Cel* cel = site.cel();
|
||||
if (!cel ||
|
||||
layer->isBackground() ||
|
||||
!layer->isEditable() ||
|
||||
@ -74,24 +75,11 @@ void CelOpacityCommand::onExecute(Context* context)
|
||||
{
|
||||
Tx tx(writer, "Set Cel Opacity");
|
||||
|
||||
// TODO the range of selected cels should be in app::Site.
|
||||
DocRange range;
|
||||
|
||||
if (context->isUIAvailable())
|
||||
range = App::instance()->timeline()->range();
|
||||
|
||||
if (!range.enabled()) {
|
||||
range.startRange(layer, cel->frame(), DocRange::kCels);
|
||||
range.endRange(layer, cel->frame());
|
||||
}
|
||||
|
||||
for (Cel* c : cel->sprite()->uniqueCels(range.selectedFrames())) {
|
||||
if (range.contains(c->layer())) {
|
||||
if (!c->layer()->isBackground() &&
|
||||
c->layer()->isEditable() &&
|
||||
m_opacity != c->opacity()) {
|
||||
tx(new cmd::SetCelOpacity(c, m_opacity));
|
||||
}
|
||||
for (Cel* c : site.selectedUniqueCels()) {
|
||||
if (!c->layer()->isBackground() &&
|
||||
c->layer()->isEditable() &&
|
||||
m_opacity != c->opacity()) {
|
||||
tx(new cmd::SetCelOpacity(c, m_opacity));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2023 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -50,11 +50,11 @@ void ClearCelCommand::onExecute(Context* context)
|
||||
{
|
||||
Tx tx(writer, "Clear Cel");
|
||||
|
||||
const Site* site = writer.site();
|
||||
if (site->inTimeline() &&
|
||||
!site->selectedLayers().empty() &&
|
||||
!site->selectedFrames().empty()) {
|
||||
for (Layer* layer : site->selectedLayers()) {
|
||||
const Site& site = writer.site();
|
||||
if (site.inTimeline() &&
|
||||
!site.selectedLayers().empty() &&
|
||||
!site.selectedFrames().empty()) {
|
||||
for (Layer* layer : site.selectedLayers()) {
|
||||
if (!layer->isImage())
|
||||
continue;
|
||||
|
||||
@ -63,7 +63,7 @@ void ClearCelCommand::onExecute(Context* context)
|
||||
continue;
|
||||
}
|
||||
|
||||
for (frame_t frame : site->selectedFrames().reversed()) {
|
||||
for (frame_t frame : site.selectedFrames().reversed()) {
|
||||
if (Cel* cel = layer->cel(frame))
|
||||
document->getApi(tx).clearCel(cel);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019-2022 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2023 Igara Studio S.A.
|
||||
// Copyright (C) 2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -61,7 +61,7 @@ bool FillCommand::onEnabled(Context* ctx)
|
||||
void FillCommand::onExecute(Context* ctx)
|
||||
{
|
||||
ContextWriter writer(ctx);
|
||||
Site site = *writer.site();
|
||||
const Site& site = writer.site();
|
||||
Doc* doc = site.document();
|
||||
Sprite* sprite = site.sprite();
|
||||
Layer* layer = site.layer();
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2023 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -15,9 +15,9 @@
|
||||
#include "app/doc_range.h"
|
||||
#include "app/i18n/strings.h"
|
||||
#include "app/modules/gui.h"
|
||||
#include "app/pref/preferences.h"
|
||||
#include "app/tx.h"
|
||||
#include "app/ui/color_bar.h"
|
||||
#include "app/ui/timeline/timeline.h"
|
||||
#include "doc/layer.h"
|
||||
#include "doc/sprite.h"
|
||||
|
||||
@ -55,12 +55,12 @@ bool FlattenLayersCommand::onEnabled(Context* context)
|
||||
void FlattenLayersCommand::onExecute(Context* context)
|
||||
{
|
||||
ContextWriter writer(context);
|
||||
Sprite* sprite = writer.sprite();
|
||||
const Site& site = writer.site();
|
||||
Sprite* sprite = site.sprite();
|
||||
{
|
||||
Tx tx(writer, "Flatten Layers");
|
||||
|
||||
// TODO the range of selected layers should be in app::Site.
|
||||
DocRange range;
|
||||
view::Range range;
|
||||
|
||||
if (m_visibleOnly) {
|
||||
for (auto layer : sprite->root()->layers())
|
||||
@ -68,8 +68,7 @@ void FlattenLayersCommand::onExecute(Context* context)
|
||||
range.selectLayer(layer);
|
||||
}
|
||||
else {
|
||||
if (context->isUIAvailable())
|
||||
range = App::instance()->timeline()->range();
|
||||
range = site.range();
|
||||
|
||||
// If the range is not selected or we have only one image layer
|
||||
// selected, we'll flatten all layers.
|
||||
|
@ -31,7 +31,6 @@
|
||||
#include "app/ui/timeline/timeline.h"
|
||||
#include "app/ui/toolbar.h"
|
||||
#include "app/util/expand_cel_canvas.h"
|
||||
#include "app/util/range_utils.h"
|
||||
#include "doc/algorithm/flip_image.h"
|
||||
#include "doc/cel.h"
|
||||
#include "doc/cels_range.h"
|
||||
@ -41,7 +40,6 @@
|
||||
#include "doc/sprite.h"
|
||||
#include "gfx/size.h"
|
||||
|
||||
|
||||
namespace app {
|
||||
|
||||
FlipCommand::FlipCommand()
|
||||
@ -88,16 +86,7 @@ void FlipCommand::onExecute(Context* ctx)
|
||||
}
|
||||
}
|
||||
|
||||
auto range = site.range();
|
||||
if (range.enabled()) {
|
||||
cels = get_unique_cels_to_edit_pixels(site.sprite(), range);
|
||||
}
|
||||
else if (site.cel() &&
|
||||
site.layer() &&
|
||||
site.layer()->canEditPixels()) {
|
||||
cels.push_back(site.cel());
|
||||
}
|
||||
|
||||
cels = site.selectedUniqueCelsToEditPixels();
|
||||
if (cels.empty()) {
|
||||
if (ctx->isUIAvailable()) {
|
||||
StatusBar::instance()->showTip(
|
||||
@ -108,8 +97,7 @@ void FlipCommand::onExecute(Context* ctx)
|
||||
}
|
||||
// Flip the whole sprite (even locked layers)
|
||||
else {
|
||||
for (Cel* cel : site.sprite()->uniqueCels())
|
||||
cels.push_back(cel);
|
||||
cels = site.sprite()->uniqueCels().toList();
|
||||
}
|
||||
|
||||
ContextWriter writer(ctx);
|
||||
@ -120,7 +108,7 @@ void FlipCommand::onExecute(Context* ctx)
|
||||
|
||||
Mask* mask = document->mask();
|
||||
if (m_flipMask && document->isMaskVisible()) {
|
||||
Site site = *writer.site();
|
||||
Site site = writer.site();
|
||||
|
||||
for (Cel* cel : cels) {
|
||||
// TODO add support to flip masked part of a reference layer
|
||||
|
@ -70,9 +70,9 @@ void LayerOpacityCommand::onExecute(Context* context)
|
||||
{
|
||||
Tx tx(writer, "Set Layer Opacity");
|
||||
|
||||
// TODO the range of selected frames should be in app::Site.
|
||||
Site site = writer.site();
|
||||
SelectedLayers selLayers;
|
||||
auto range = App::instance()->timeline()->range();
|
||||
auto range = site.range();
|
||||
if (range.enabled()) {
|
||||
selLayers = range.selectedLayers();
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019-2022 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2023 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -63,7 +63,7 @@ void MaskContentCommand::onExecute(Context* context)
|
||||
gfx::Color color;
|
||||
if (writer.layer()->isBackground()) {
|
||||
ColorPicker picker;
|
||||
picker.pickColor(*writer.site(),
|
||||
picker.pickColor(writer.site(),
|
||||
gfx::PointF(0.0, 0.0),
|
||||
Editor::activeEditor()->projection(),
|
||||
ColorPicker::FromComposition);
|
||||
|
@ -121,29 +121,31 @@ void NewFrameCommand::onExecute(Context* context)
|
||||
case Content::DUPLICATE_CELS_LINKED: continuous.reset(new bool(true)); break;
|
||||
}
|
||||
|
||||
const Site* site = writer.site();
|
||||
if (site->inTimeline() &&
|
||||
!site->selectedLayers().empty() &&
|
||||
!site->selectedFrames().empty()) {
|
||||
auto timeline = App::instance()->timeline();
|
||||
timeline->prepareToMoveRange();
|
||||
DocRange range = timeline->range();
|
||||
const Site& site = writer.site();
|
||||
if (site.inTimeline() &&
|
||||
!site.selectedLayers().empty() &&
|
||||
!site.selectedFrames().empty()) {
|
||||
auto* timeline = App::instance()->timeline();
|
||||
if (timeline)
|
||||
timeline->prepareToMoveRange();
|
||||
|
||||
DocRange range = site.range();
|
||||
|
||||
SelectedLayers selLayers;
|
||||
if (site->inFrames())
|
||||
if (site.inFrames())
|
||||
selLayers.selectAllLayers(writer.sprite()->root());
|
||||
else {
|
||||
selLayers = site->selectedLayers();
|
||||
selLayers = site.selectedLayers();
|
||||
selLayers.expandCollapsedGroups();
|
||||
}
|
||||
|
||||
frame_t frameRange =
|
||||
(site->selectedFrames().lastFrame() -
|
||||
site->selectedFrames().firstFrame() + 1);
|
||||
(site.selectedFrames().lastFrame() -
|
||||
site.selectedFrames().firstFrame() + 1);
|
||||
|
||||
for (Layer* layer : selLayers) {
|
||||
if (layer->isImage()) {
|
||||
for (frame_t srcFrame : site->selectedFrames().reversed()) {
|
||||
for (frame_t srcFrame : site.selectedFrames().reversed()) {
|
||||
frame_t dstFrame = srcFrame+frameRange;
|
||||
api.copyCel(
|
||||
static_cast<LayerImage*>(layer), srcFrame,
|
||||
@ -153,7 +155,8 @@ void NewFrameCommand::onExecute(Context* context)
|
||||
}
|
||||
|
||||
range.displace(0, frameRange);
|
||||
timeline->moveRange(range);
|
||||
if (timeline)
|
||||
timeline->moveRange(range);
|
||||
}
|
||||
else if (auto layer = static_cast<LayerImage*>(writer.layer())) {
|
||||
api.copyCel(
|
||||
|
@ -34,7 +34,6 @@
|
||||
#include "app/ui_context.h"
|
||||
#include "app/util/clipboard.h"
|
||||
#include "app/util/new_image_from_mask.h"
|
||||
#include "app/util/range_utils.h"
|
||||
#include "doc/layer.h"
|
||||
#include "doc/layer_tilemap.h"
|
||||
#include "doc/primitives.h"
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2020 Igara Studio S.A.
|
||||
// Copyright (C) 2020-2023 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -55,10 +55,10 @@ void RemoveFrameCommand::onExecute(Context* context)
|
||||
{
|
||||
Tx tx(writer, "Remove Frame");
|
||||
DocApi api = document->getApi(tx);
|
||||
const Site* site = writer.site();
|
||||
if (site->inTimeline() &&
|
||||
!site->selectedFrames().empty()) {
|
||||
for (frame_t frame : site->selectedFrames().reversed()) {
|
||||
const Site& site = writer.site();
|
||||
if (site.inTimeline() &&
|
||||
!site.selectedFrames().empty()) {
|
||||
for (frame_t frame : site.selectedFrames().reversed()) {
|
||||
api.removeFrame(sprite, frame);
|
||||
}
|
||||
}
|
||||
|
@ -140,10 +140,10 @@ void RemoveLayerCommand::onExecute(Context* context)
|
||||
// the std::greater Compare.
|
||||
std::set<tileset_index, std::greater<tileset_index>> tsiToDelete;
|
||||
|
||||
const Site* site = writer.site();
|
||||
if (site->inTimeline() &&
|
||||
!site->selectedLayers().empty()) {
|
||||
SelectedLayers selLayers = site->selectedLayers();
|
||||
const Site& site = writer.site();
|
||||
if (site.inTimeline() &&
|
||||
!site.selectedLayers().empty()) {
|
||||
SelectedLayers selLayers = site.selectedLayers();
|
||||
selLayers.removeChildrenIfParentIsSelected();
|
||||
|
||||
layer_t deletedTopLevelLayers = 0;
|
||||
|
@ -82,7 +82,7 @@ void RemoveSliceCommand::onExecute(Context* context)
|
||||
if (slice)
|
||||
slicesToDelete.insert(slice->id());
|
||||
else
|
||||
slicesToDelete = reader.site()->selectedSlices();
|
||||
slicesToDelete = reader.site().selectedSlices();
|
||||
}
|
||||
|
||||
// Nothing to delete
|
||||
|
@ -25,7 +25,6 @@
|
||||
#include "app/ui/status_bar.h"
|
||||
#include "app/ui/timeline/timeline.h"
|
||||
#include "app/ui/toolbar.h"
|
||||
#include "app/util/range_utils.h"
|
||||
#include "base/convert_to.h"
|
||||
#include "doc/cel.h"
|
||||
#include "doc/cels_range.h"
|
||||
@ -221,15 +220,7 @@ void RotateCommand::onExecute(Context* context)
|
||||
}
|
||||
}
|
||||
|
||||
auto range = App::instance()->timeline()->range();
|
||||
if (range.enabled())
|
||||
cels = get_unique_cels_to_edit_pixels(site.sprite(), range);
|
||||
else if (site.cel() &&
|
||||
site.layer() &&
|
||||
site.layer()->canEditPixels()) {
|
||||
cels.push_back(site.cel());
|
||||
}
|
||||
|
||||
cels = site.selectedUniqueCelsToEditPixels();
|
||||
if (cels.empty()) {
|
||||
StatusBar::instance()->showTip(
|
||||
1000, Strings::statusbar_tips_all_layers_are_locked());
|
||||
@ -238,9 +229,7 @@ void RotateCommand::onExecute(Context* context)
|
||||
}
|
||||
// Flip the whole sprite (even locked layers)
|
||||
else if (site.sprite()) {
|
||||
for (Cel* cel : site.sprite()->uniqueCels())
|
||||
cels.push_back(cel);
|
||||
|
||||
cels = site.sprite()->uniqueCels().toList();
|
||||
rotateSprite = true;
|
||||
}
|
||||
|
||||
|
@ -80,7 +80,7 @@ void SelectTileCommand::onExecute(Context* ctx)
|
||||
mask->copyFrom(doc->mask());
|
||||
|
||||
{
|
||||
gfx::Rect gridBounds = writer.site()->gridBounds();
|
||||
gfx::Rect gridBounds = writer.site().gridBounds();
|
||||
gfx::Point pos = editor->screenToEditor(editor->mousePosInDisplay());
|
||||
pos = snap_to_grid(gridBounds, pos, PreferSnapTo::BoxOrigin);
|
||||
gridBounds.setOrigin(pos);
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2023 Igara Studio S.A.
|
||||
// Copyright (C) 2017-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -77,7 +77,7 @@ void SlicePropertiesCommand::onExecute(Context* context)
|
||||
if (slice)
|
||||
slices.insert(slice->id());
|
||||
else
|
||||
slices = reader.site()->selectedSlices();
|
||||
slices = reader.site().selectedSlices();
|
||||
}
|
||||
|
||||
// Nothing to delete
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2020-2022 Igara Studio S.A.
|
||||
// Copyright (C) 2020-2023 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -71,8 +71,8 @@ void UndoCommand::onExecute(Context* context)
|
||||
(Preferences::instance().undo.gotoModified() &&
|
||||
context->isUIAvailable() && editor);
|
||||
if (gotoModified) {
|
||||
SpritePosition currentPosition(writer.site()->layer(),
|
||||
writer.site()->frame());
|
||||
SpritePosition currentPosition(writer.site().layer(),
|
||||
writer.site().frame());
|
||||
|
||||
if (m_type == Undo)
|
||||
spritePosition = undo->nextUndoSpritePosition();
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2023 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -49,10 +50,10 @@ void UnlinkCelCommand::onExecute(Context* context)
|
||||
{
|
||||
Tx tx(writer, "Unlink Cel");
|
||||
|
||||
const Site* site = writer.site();
|
||||
if (site->inTimeline() &&
|
||||
!site->selectedLayers().empty()) {
|
||||
for (Layer* layer : site->selectedLayers()) {
|
||||
const Site& site = writer.site();
|
||||
if (site.inTimeline() &&
|
||||
!site.selectedLayers().empty()) {
|
||||
for (Layer* layer : site.selectedLayers()) {
|
||||
if (!layer->isImage())
|
||||
continue;
|
||||
|
||||
@ -63,7 +64,7 @@ void UnlinkCelCommand::onExecute(Context* context)
|
||||
|
||||
LayerImage* layerImage = static_cast<LayerImage*>(layer);
|
||||
|
||||
for (frame_t frame : site->selectedFrames().reversed()) {
|
||||
for (frame_t frame : site.selectedFrames().reversed()) {
|
||||
Cel* cel = layerImage->cel(frame);
|
||||
if (cel && cel->links())
|
||||
tx(new cmd::UnlinkCel(cel));
|
||||
|
@ -28,7 +28,6 @@
|
||||
#include "app/ui/timeline/timeline.h"
|
||||
#include "app/ui_context.h"
|
||||
#include "app/util/cel_ops.h"
|
||||
#include "app/util/range_utils.h"
|
||||
#include "doc/algorithm/shrink_bounds.h"
|
||||
#include "doc/cel.h"
|
||||
#include "doc/cels_range.h"
|
||||
@ -40,6 +39,7 @@
|
||||
#include "ui/manager.h"
|
||||
#include "ui/view.h"
|
||||
#include "ui/widget.h"
|
||||
#include "view/cels.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
@ -52,7 +52,7 @@ using namespace ui;
|
||||
|
||||
FilterManagerImpl::FilterManagerImpl(Context* context, Filter* filter)
|
||||
: m_reader(context)
|
||||
, m_site(*const_cast<Site*>(m_reader.site()))
|
||||
, m_site(const_cast<Site&>(m_reader.site()))
|
||||
, m_filter(filter)
|
||||
, m_cel(nullptr)
|
||||
, m_src(nullptr)
|
||||
@ -279,16 +279,7 @@ void FilterManagerImpl::applyToTarget()
|
||||
switch (m_celsTarget) {
|
||||
|
||||
case CelsTarget::Selected: {
|
||||
auto range = m_site.range();
|
||||
if (range.enabled()) {
|
||||
for (Cel* cel : get_unique_cels_to_edit_pixels(m_site.sprite(), range))
|
||||
cels.push_back(cel);
|
||||
}
|
||||
else if (m_site.cel() &&
|
||||
m_site.layer() &&
|
||||
m_site.layer()->canEditPixels()) {
|
||||
cels.push_back(m_site.cel());
|
||||
}
|
||||
cels = m_site.selectedUniqueCelsToEditPixels();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (c) 2019 Igara Studio S.A.
|
||||
// Copyright (c) 2019-2023 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -53,7 +53,7 @@ protected:
|
||||
if (!tileset)
|
||||
return;
|
||||
|
||||
PalettePicks picks = writer.site()->selectedTiles();
|
||||
PalettePicks picks = writer.site().selectedTiles();
|
||||
if (picks.picks() == 0)
|
||||
return;
|
||||
|
||||
|
@ -31,12 +31,15 @@ namespace doc {
|
||||
class PalettePicks;
|
||||
}
|
||||
|
||||
namespace view {
|
||||
class Range;
|
||||
}
|
||||
|
||||
namespace app {
|
||||
class ActiveSiteHandler;
|
||||
class Clipboard;
|
||||
class Command;
|
||||
class Doc;
|
||||
class DocRange;
|
||||
class DocView;
|
||||
class Preferences;
|
||||
|
||||
@ -134,7 +137,7 @@ namespace app {
|
||||
void setActiveDocument(Doc* document);
|
||||
void setActiveLayer(doc::Layer* layer);
|
||||
void setActiveFrame(doc::frame_t frame);
|
||||
void setRange(const DocRange& range);
|
||||
void setRange(const view::Range& range);
|
||||
void setSelectedColors(const doc::PalettePicks& picks);
|
||||
void setSelectedTiles(const doc::PalettePicks& picks);
|
||||
bool hasModifiedDocuments() const;
|
||||
@ -167,7 +170,7 @@ namespace app {
|
||||
virtual void onSetActiveDocument(Doc* doc, bool notify);
|
||||
virtual void onSetActiveLayer(doc::Layer* layer);
|
||||
virtual void onSetActiveFrame(const doc::frame_t frame);
|
||||
virtual void onSetRange(const DocRange& range);
|
||||
virtual void onSetRange(const view::Range& range);
|
||||
virtual void onSetSelectedColors(const doc::PalettePicks& picks);
|
||||
virtual void onSetSelectedTiles(const doc::PalettePicks& picks);
|
||||
virtual void onCloseDocument(Doc* doc);
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2020 Igara Studio S.A.
|
||||
// Copyright (C) 2020-2023 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -20,16 +20,13 @@ namespace app {
|
||||
class ContextAccess {
|
||||
public:
|
||||
const Context* context() const { return m_context; }
|
||||
const Site* site() const { return &m_site; }
|
||||
const Site& site() const { return m_site; }
|
||||
const DocumentAccessT& document() const { return m_document; }
|
||||
const Sprite* sprite() const { return m_site.sprite(); }
|
||||
const Layer* layer() const { return m_site.layer(); }
|
||||
frame_t frame() const { return m_site.frame(); }
|
||||
const Cel* cel() const { return m_site.cel(); }
|
||||
|
||||
// You cannot change the site directly from a writable ContextAccess anyway.
|
||||
const Site* site() { return &m_site; }
|
||||
|
||||
Context* context() { return const_cast<Context*>(m_context); }
|
||||
DocumentAccessT& document() { return m_document; }
|
||||
Sprite* sprite() { return m_site.sprite(); }
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2020 Igara Studio S.A.
|
||||
// Copyright (C) 2020-2023 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -9,90 +9,14 @@
|
||||
#define APP_DOC_RANGE_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "doc/frame.h"
|
||||
#include "doc/selected_frames.h"
|
||||
#include "doc/selected_layers.h"
|
||||
|
||||
#include <iosfwd>
|
||||
|
||||
namespace doc {
|
||||
class Cel;
|
||||
class Sprite;
|
||||
}
|
||||
#include "view/range.h"
|
||||
|
||||
namespace app {
|
||||
using namespace doc;
|
||||
|
||||
class DocRange {
|
||||
public:
|
||||
enum Type { kNone = 0,
|
||||
kCels = 1,
|
||||
kFrames = 2,
|
||||
kLayers = 4 };
|
||||
|
||||
DocRange();
|
||||
DocRange(Cel* cel);
|
||||
DocRange(const DocRange&) = default;
|
||||
DocRange& operator=(const DocRange&) = default;
|
||||
|
||||
Type type() const { return m_type; }
|
||||
bool enabled() const { return m_type != kNone; }
|
||||
layer_t layers() const { return int(m_selectedLayers.size()); }
|
||||
frame_t frames() const { return int(m_selectedFrames.size()); }
|
||||
const SelectedLayers& selectedLayers() const { return m_selectedLayers; }
|
||||
const SelectedFrames& selectedFrames() const { return m_selectedFrames; }
|
||||
|
||||
void setType(const Type type);
|
||||
void setSelectedLayers(const SelectedLayers& layers);
|
||||
void setSelectedFrames(const SelectedFrames& frames);
|
||||
|
||||
void displace(layer_t layerDelta, frame_t frameDelta);
|
||||
|
||||
bool contains(const Layer* layer) const;
|
||||
bool contains(const frame_t frame) const {
|
||||
return m_selectedFrames.contains(frame);
|
||||
}
|
||||
bool contains(const Layer* layer,
|
||||
const frame_t frame) const;
|
||||
|
||||
// If the range includes the given layer, it will be erased from
|
||||
// the selection and other candidates might be selected (e.g. a
|
||||
// sibling, parent, etc.) using the
|
||||
// candidate_if_layer_is_deleted() function.
|
||||
void eraseAndAdjust(const Layer* layer);
|
||||
|
||||
void clearRange();
|
||||
void startRange(Layer* fromLayer, frame_t fromFrame, Type type);
|
||||
void endRange(Layer* toLayer, frame_t toFrame);
|
||||
|
||||
void selectLayer(Layer* layer);
|
||||
void selectLayers(const SelectedLayers& selLayers);
|
||||
|
||||
frame_t firstFrame() const { return m_selectedFrames.firstFrame(); }
|
||||
frame_t lastFrame() const { return m_selectedFrames.lastFrame(); }
|
||||
|
||||
bool operator==(const DocRange& o) const {
|
||||
return (m_type == o.m_type &&
|
||||
m_selectedLayers == o.m_selectedLayers &&
|
||||
m_selectedFrames == o.m_selectedFrames);
|
||||
}
|
||||
|
||||
bool convertToCels(const Sprite* sprite);
|
||||
|
||||
bool write(std::ostream& os) const;
|
||||
bool read(std::istream& is);
|
||||
|
||||
private:
|
||||
void selectLayerRange(Layer* fromLayer, Layer* toLayer);
|
||||
void selectFrameRange(frame_t fromFrame, frame_t toFrame);
|
||||
|
||||
Type m_type; // Last used type of the range
|
||||
int m_flags; // All used types in startRange()
|
||||
SelectedLayers m_selectedLayers;
|
||||
SelectedFrames m_selectedFrames;
|
||||
Layer* m_selectingFromLayer;
|
||||
frame_t m_selectingFromFrame;
|
||||
};
|
||||
// Now DocRange is just an alias for view::Range
|
||||
//
|
||||
// TODO replace DocRange with view::Range in the future
|
||||
using DocRange = view::Range;
|
||||
|
||||
} // namespace app
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2023 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -8,13 +9,13 @@
|
||||
#define APP_DOC_RANGE_OPS_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "app/doc_range.h"
|
||||
#include "app/tags_handling.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace app {
|
||||
class Doc;
|
||||
class DocRange;
|
||||
|
||||
enum DocRangePlace {
|
||||
kDocRangeBefore,
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2018-2022 Igara Studio S.A.
|
||||
// Copyright (C) 2018-2023 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -16,7 +16,6 @@
|
||||
#include "app/script/luacpp.h"
|
||||
#include "app/site.h"
|
||||
#include "app/ui/editor/editor.h"
|
||||
#include "app/util/range_utils.h"
|
||||
#include "doc/cel.h"
|
||||
#include "doc/layer.h"
|
||||
#include "doc/object_ids.h"
|
||||
@ -24,6 +23,7 @@
|
||||
#include "doc/slices.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "doc/tile.h"
|
||||
#include "view/cels.h"
|
||||
|
||||
#include <set>
|
||||
#include <vector>
|
||||
@ -77,7 +77,7 @@ struct RangeObj { // This is like DocRange but referencing objects with IDs
|
||||
// it might not be possible because we have to save the IDs of the
|
||||
// objects (and we cannot store the DocRange because it contains
|
||||
// pointers instead of IDs).
|
||||
for (const Cel* cel : get_cels(site.sprite(), range))
|
||||
for (const Cel* cel : view::get_cels(site.sprite(), range))
|
||||
cels.insert(cel->id());
|
||||
}
|
||||
else {
|
||||
|
@ -19,6 +19,8 @@
|
||||
#include "doc/sprite.h"
|
||||
#include "doc/tileset.h"
|
||||
#include "ui/system.h"
|
||||
#include "view/cels.h"
|
||||
#include "view/range.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
@ -135,4 +137,29 @@ bool Site::shouldTrimCel(Cel* cel) const
|
||||
cel->layer()->isTilemap()));
|
||||
}
|
||||
|
||||
CelList Site::selectedUniqueCels() const
|
||||
{
|
||||
if (m_range.enabled()) {
|
||||
return view::get_unique_cels(m_sprite, m_range);
|
||||
}
|
||||
else if (auto c = cel()) {
|
||||
return CelList{ c };
|
||||
}
|
||||
else
|
||||
return CelList();
|
||||
}
|
||||
|
||||
CelList Site::selectedUniqueCelsToEditPixels() const
|
||||
{
|
||||
if (m_range.enabled()) {
|
||||
return view::get_unique_cels_to_edit_pixels(m_sprite, m_range);
|
||||
}
|
||||
else if (auto c = cel()) {
|
||||
if (m_layer &&
|
||||
m_layer->canEditPixels())
|
||||
return CelList{ c };
|
||||
}
|
||||
return CelList();
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019-2021 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2023 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -12,13 +12,13 @@
|
||||
#include "app/doc_range.h"
|
||||
#include "app/tilemap_mode.h"
|
||||
#include "app/tileset_mode.h"
|
||||
#include "doc/cel_list.h"
|
||||
#include "doc/frame.h"
|
||||
#include "doc/palette_picks.h"
|
||||
#include "doc/selected_objects.h"
|
||||
#include "gfx/fwd.h"
|
||||
|
||||
namespace doc {
|
||||
class Cel;
|
||||
class Grid;
|
||||
class Image;
|
||||
class Layer;
|
||||
@ -116,7 +116,15 @@ namespace app {
|
||||
TilemapMode tilemapMode() const { return m_tilemapMode; }
|
||||
TilesetMode tilesetMode() const { return m_tilesetMode; }
|
||||
|
||||
bool shouldTrimCel(Cel* cel) const;
|
||||
bool shouldTrimCel(doc::Cel* cel) const;
|
||||
|
||||
// Returns the list of selected "unique" cels (to avoid iterating
|
||||
// two or more times through linked cels), or just a list of the
|
||||
// active cel if there is no range in the given site.
|
||||
doc::CelList selectedUniqueCels() const;
|
||||
|
||||
// Same as uniqueCels() with cels from non-locked/editable layers.
|
||||
doc::CelList selectedUniqueCelsToEditPixels() const;
|
||||
|
||||
private:
|
||||
Focus m_focus;
|
||||
|
@ -15,11 +15,14 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace view {
|
||||
class Range;
|
||||
}
|
||||
|
||||
namespace app {
|
||||
|
||||
class Cmd;
|
||||
class Context;
|
||||
class DocRange;
|
||||
class DocUndo;
|
||||
|
||||
enum Modification {
|
||||
@ -69,7 +72,7 @@ namespace app {
|
||||
// Can be used to change the new document range resulting from
|
||||
// executing this transaction. This range can be used then in
|
||||
// undo/redo operations to restore the Timeline selection/range.
|
||||
void setNewDocRange(const DocRange& range);
|
||||
void setNewDocRange(const view::Range& range);
|
||||
|
||||
// This must be called to commit all the changes, so the undo will
|
||||
// be finally added in the sprite.
|
||||
|
@ -36,7 +36,6 @@
|
||||
#include "app/ui/workspace.h"
|
||||
#include "app/ui_context.h"
|
||||
#include "app/util/clipboard.h"
|
||||
#include "app/util/range_utils.h"
|
||||
#include "base/fs.h"
|
||||
#include "doc/color.h"
|
||||
#include "doc/layer.h"
|
||||
@ -579,9 +578,9 @@ bool DocView::onCut(Context* ctx)
|
||||
bool DocView::onCopy(Context* ctx)
|
||||
{
|
||||
const ContextReader reader(ctx);
|
||||
if (reader.site()->document() &&
|
||||
static_cast<const Doc*>(reader.site()->document())->isMaskVisible() &&
|
||||
reader.site()->image()) {
|
||||
if (reader.site().document() &&
|
||||
static_cast<const Doc*>(reader.site().document())->isMaskVisible() &&
|
||||
reader.site().image()) {
|
||||
ctx->clipboard()->copy(reader);
|
||||
return true;
|
||||
}
|
||||
@ -618,14 +617,7 @@ bool DocView::onClear(Context* ctx)
|
||||
Doc* document = site.document();
|
||||
bool visibleMask = document->isMaskVisible();
|
||||
|
||||
CelList cels;
|
||||
if (site.range().enabled()) {
|
||||
cels = get_unique_cels_to_edit_pixels(site.sprite(), site.range());
|
||||
}
|
||||
else if (site.cel()) {
|
||||
cels.push_back(site.cel());
|
||||
}
|
||||
|
||||
CelList cels = site.selectedUniqueCelsToEditPixels();
|
||||
if (cels.empty()) // No cels to modify
|
||||
return false;
|
||||
|
||||
|
@ -67,6 +67,7 @@
|
||||
#include "os/system.h"
|
||||
#include "render/rasterize.h"
|
||||
#include "ui/ui.h"
|
||||
#include "view/layers.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
@ -2472,7 +2473,8 @@ void Editor::onBeforeRemoveLayer(DocEvent& ev)
|
||||
|
||||
// If the layer that was removed is the selected one in the editor,
|
||||
// or is an ancestor of the selected one.
|
||||
Layer* layerToSelect = candidate_if_layer_is_deleted(layer(), ev.layer());
|
||||
Layer* layerToSelect =
|
||||
view::candidate_if_layer_is_deleted(layer(), ev.layer());
|
||||
if (layer() != layerToSelect)
|
||||
setLayer(layerToSelect);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2020-2022 Igara Studio S.A.
|
||||
// Copyright (C) 2020-2023 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -25,13 +25,13 @@
|
||||
#include "app/ui/status_bar.h"
|
||||
#include "app/ui/timeline/timeline.h"
|
||||
#include "app/ui_context.h"
|
||||
#include "app/util/range_utils.h"
|
||||
#include "doc/cel.h"
|
||||
#include "doc/layer.h"
|
||||
#include "doc/mask.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "fmt/format.h"
|
||||
#include "ui/message.h"
|
||||
#include "view/cels.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
@ -71,7 +71,7 @@ MovingCelCollect::MovingCelCollect(Editor* editor, Layer* layer)
|
||||
}
|
||||
|
||||
// Record start positions of all cels in selected range
|
||||
for (Cel* cel : get_unique_cels_to_move_cel(editor->sprite(), range2)) {
|
||||
for (Cel* cel : view::get_unique_cels_to_move_cel(editor->sprite(), range2)) {
|
||||
Layer* layer = cel->layer();
|
||||
ASSERT(layer);
|
||||
|
||||
|
@ -31,7 +31,6 @@
|
||||
#include "app/util/cel_ops.h"
|
||||
#include "app/util/expand_cel_canvas.h"
|
||||
#include "app/util/new_image_from_mask.h"
|
||||
#include "app/util/range_utils.h"
|
||||
#include "base/pi.h"
|
||||
#include "doc/algorithm/flip_image.h"
|
||||
#include "doc/algorithm/rotate.h"
|
||||
@ -1455,8 +1454,7 @@ CelList PixelsMovement::getEditableCels()
|
||||
CelList cels;
|
||||
|
||||
if (editMultipleCels()) {
|
||||
cels = get_unique_cels_to_edit_pixels(m_site.sprite(),
|
||||
m_site.range());
|
||||
cels = m_site.selectedUniqueCelsToEditPixels();
|
||||
}
|
||||
else {
|
||||
// TODO This case is used in paste too, where the cel() can be
|
||||
|
@ -165,11 +165,11 @@ void calculate_visible_layers(const Site& site,
|
||||
if (layersValue == kSelectedLayers) {
|
||||
if (!site.selectedLayers().empty()) {
|
||||
layersVisibility.showSelectedLayers(
|
||||
const_cast<Sprite*>(site.sprite()),
|
||||
const_cast<doc::Sprite*>(site.sprite()),
|
||||
site.selectedLayers());
|
||||
}
|
||||
else {
|
||||
layersVisibility.showLayer(const_cast<Layer*>(site.layer()));
|
||||
layersVisibility.showLayer(const_cast<doc::Layer*>(site.layer()));
|
||||
}
|
||||
}
|
||||
else if (layersValue != kAllLayers) {
|
||||
|
@ -35,7 +35,6 @@
|
||||
#include "app/ui/toolbar.h"
|
||||
#include "app/ui/zoom_entry.h"
|
||||
#include "app/ui_context.h"
|
||||
#include "app/util/range_utils.h"
|
||||
#include "app/util/tile_flags_utils.h"
|
||||
#include "base/fs.h"
|
||||
#include "base/string.h"
|
||||
|
@ -46,7 +46,6 @@
|
||||
#include "app/ui_context.h"
|
||||
#include "app/util/clipboard.h"
|
||||
#include "app/util/layer_boundaries.h"
|
||||
#include "app/util/layer_utils.h"
|
||||
#include "app/util/readable_time.h"
|
||||
#include "base/convert_to.h"
|
||||
#include "base/memory.h"
|
||||
@ -62,6 +61,7 @@
|
||||
#include "os/system.h"
|
||||
#include "text/font.h"
|
||||
#include "ui/ui.h"
|
||||
#include "view/layers.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
@ -1934,7 +1934,7 @@ void Timeline::onAddLayer(DocEvent& ev)
|
||||
// TODO similar to ActiveSiteHandler::onBeforeRemoveLayer() and Editor::onBeforeRemoveLayer()
|
||||
void Timeline::onBeforeRemoveLayer(DocEvent& ev)
|
||||
{
|
||||
Layer* layerToSelect = candidate_if_layer_is_deleted(m_layer, ev.layer());
|
||||
Layer* layerToSelect = view::candidate_if_layer_is_deleted(m_layer, ev.layer());
|
||||
if (m_layer != layerToSelect)
|
||||
setLayer(layerToSelect);
|
||||
|
||||
|
@ -73,7 +73,7 @@ namespace app {
|
||||
void onSetActiveDocument(Doc* doc, bool notify) override;
|
||||
void onSetActiveLayer(doc::Layer* layer) override;
|
||||
void onSetActiveFrame(const doc::frame_t frame) override;
|
||||
void onSetRange(const DocRange& range) override;
|
||||
void onSetRange(const view::Range& range) override;
|
||||
void onSetSelectedColors(const doc::PalettePicks& picks) override;
|
||||
void onSetSelectedTiles(const doc::PalettePicks& picks) override;
|
||||
void onCloseDocument(Doc* doc) override;
|
||||
|
@ -32,7 +32,6 @@
|
||||
#include "app/util/cel_ops.h"
|
||||
#include "app/util/clipboard.h"
|
||||
#include "app/util/new_image_from_mask.h"
|
||||
#include "app/util/range_utils.h"
|
||||
#include "clip/clip.h"
|
||||
#include "doc/algorithm/shrink_bounds.h"
|
||||
#include "doc/blend_image.h"
|
||||
@ -40,6 +39,7 @@
|
||||
#include "render/dithering.h"
|
||||
#include "render/ordered_dither.h"
|
||||
#include "render/quantization.h"
|
||||
#include "view/cels.h"
|
||||
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
@ -345,7 +345,7 @@ void Clipboard::cut(ContextWriter& writer)
|
||||
ASSERT(writer.sprite() != NULL);
|
||||
ASSERT(writer.layer() != NULL);
|
||||
|
||||
if (!copyFromDocument(*writer.site())) {
|
||||
if (!copyFromDocument(writer.site())) {
|
||||
Console console;
|
||||
console.printf("Can't copying an image portion from the current layer\n");
|
||||
}
|
||||
@ -354,13 +354,7 @@ void Clipboard::cut(ContextWriter& writer)
|
||||
{
|
||||
Tx tx(writer, "Cut");
|
||||
Site site = writer.context()->activeSite();
|
||||
CelList cels;
|
||||
if (site.range().enabled()) {
|
||||
cels = get_unique_cels_to_edit_pixels(site.sprite(), site.range());
|
||||
}
|
||||
else if (site.cel()) {
|
||||
cels.push_back(site.cel());
|
||||
}
|
||||
CelList cels = site.selectedUniqueCelsToEditPixels();
|
||||
clearMaskFromCels(tx,
|
||||
writer.document(),
|
||||
site,
|
||||
@ -377,7 +371,7 @@ void Clipboard::copy(const ContextReader& reader)
|
||||
{
|
||||
ASSERT(reader.document() != NULL);
|
||||
|
||||
if (!copyFromDocument(*reader.site())) {
|
||||
if (!copyFromDocument(reader.site())) {
|
||||
Console console;
|
||||
console.printf("Can't copying an image portion from the current layer\n");
|
||||
return;
|
||||
@ -388,7 +382,7 @@ void Clipboard::copyMerged(const ContextReader& reader)
|
||||
{
|
||||
ASSERT(reader.document() != NULL);
|
||||
|
||||
copyFromDocument(*reader.site(), true);
|
||||
copyFromDocument(reader.site(), true);
|
||||
}
|
||||
|
||||
void Clipboard::copyRange(const ContextReader& reader, const DocRange& range)
|
||||
|
@ -26,12 +26,15 @@ namespace doc {
|
||||
class Tileset;
|
||||
}
|
||||
|
||||
namespace view {
|
||||
class Range;
|
||||
}
|
||||
|
||||
namespace app {
|
||||
class Context;
|
||||
class ContextReader;
|
||||
class ContextWriter;
|
||||
class Doc;
|
||||
class DocRange;
|
||||
class Site;
|
||||
class Tx;
|
||||
|
||||
@ -52,7 +55,7 @@ namespace app {
|
||||
~Clipboard();
|
||||
|
||||
ClipboardFormat format() const;
|
||||
void getDocumentRangeInfo(Doc** document, DocRange* range);
|
||||
void getDocumentRangeInfo(Doc** document, view::Range* range);
|
||||
|
||||
void clearMaskFromCels(Tx& tx,
|
||||
Doc* doc,
|
||||
@ -64,7 +67,7 @@ namespace app {
|
||||
void cut(ContextWriter& context);
|
||||
void copy(const ContextReader& context);
|
||||
void copyMerged(const ContextReader& context);
|
||||
void copyRange(const ContextReader& context, const DocRange& range);
|
||||
void copyRange(const ContextReader& context, const view::Range& range);
|
||||
void copyImage(const doc::Image* image,
|
||||
const doc::Mask* mask,
|
||||
const doc::Palette* palette);
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019-2022 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2023 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -23,7 +23,6 @@
|
||||
#include "app/doc.h"
|
||||
#include "app/site.h"
|
||||
#include "app/util/cel_ops.h"
|
||||
#include "app/util/range_utils.h"
|
||||
#include "base/debug.h"
|
||||
#include "doc/algorithm/shrink_bounds.h"
|
||||
#include "doc/cel.h"
|
||||
|
@ -18,36 +18,9 @@
|
||||
|
||||
namespace app {
|
||||
|
||||
using namespace doc;
|
||||
|
||||
Layer* candidate_if_layer_is_deleted(
|
||||
const Layer* selectedLayer,
|
||||
const Layer* layerToDelete)
|
||||
{
|
||||
const Layer* layerToSelect = selectedLayer;
|
||||
|
||||
if ((selectedLayer == layerToDelete) ||
|
||||
(selectedLayer &&
|
||||
selectedLayer->hasAncestor(layerToDelete))) {
|
||||
Sprite* sprite = selectedLayer->sprite();
|
||||
LayerGroup* parent = layerToDelete->parent();
|
||||
|
||||
// Select previous layer, or next layer, or the parent (if it is
|
||||
// not the main layer of sprite set).
|
||||
if (layerToDelete->getPrevious())
|
||||
layerToSelect = layerToDelete->getPrevious();
|
||||
else if (layerToDelete->getNext())
|
||||
layerToSelect = layerToDelete->getNext();
|
||||
else if (parent != sprite->root())
|
||||
layerToSelect = parent;
|
||||
}
|
||||
|
||||
return const_cast<Layer*>(layerToSelect);
|
||||
}
|
||||
|
||||
bool layer_is_locked(Editor* editor)
|
||||
{
|
||||
Layer* layer = editor->layer();
|
||||
doc::Layer* layer = editor->layer();
|
||||
if (!layer)
|
||||
return false;
|
||||
|
||||
|
@ -19,13 +19,6 @@ namespace app {
|
||||
|
||||
class Editor;
|
||||
|
||||
// Calculates a possible candidate to be selected in case that we
|
||||
// have a specific "selectedLayer" and are going to delete the given
|
||||
// "layerToDelete".
|
||||
doc::Layer* candidate_if_layer_is_deleted(
|
||||
const doc::Layer* selectedLayer,
|
||||
const doc::Layer* layerToDelete);
|
||||
|
||||
// True if the active layer is locked (itself or its hierarchy),
|
||||
// also, it sends a tip to the user 'Layer ... is locked'
|
||||
bool layer_is_locked(Editor* editor);
|
||||
|
@ -1,32 +0,0 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2020-2021 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
|
||||
#ifndef APP_UTIL_RANGE_UTILS_H_INCLUDED
|
||||
#define APP_UTIL_RANGE_UTILS_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "doc/cel_list.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace doc {
|
||||
class Sprite;
|
||||
}
|
||||
|
||||
namespace app {
|
||||
using namespace doc;
|
||||
|
||||
class DocRange;
|
||||
|
||||
doc::CelList get_cels(const doc::Sprite* sprite, const DocRange& range);
|
||||
doc::CelList get_unique_cels(const doc::Sprite* sprite, const DocRange& range);
|
||||
doc::CelList get_unique_cels_to_edit_pixels(const doc::Sprite* sprite, const DocRange& range);
|
||||
doc::CelList get_unique_cels_to_move_cel(const doc::Sprite* sprite, const DocRange& range);
|
||||
|
||||
} // namespace app
|
||||
|
||||
#endif
|
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2018-2022 Igara Studio S.A.
|
||||
Copyright (c) 2018-2023 Igara Studio S.A.
|
||||
Copyright (c) 2001-2018 David Capello
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite Document Library
|
||||
// Copyright (c) 2019 Igara Studio S.A.
|
||||
// Copyright (c) 2019-2023 Igara Studio S.A.
|
||||
// Copyright (c) 2001-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
@ -100,4 +100,16 @@ CelsRange::iterator& CelsRange::iterator::operator++()
|
||||
return *this;
|
||||
}
|
||||
|
||||
CelList CelsRange::toList()
|
||||
{
|
||||
CelList list;
|
||||
int n = size();
|
||||
if (n > 0) {
|
||||
list.reserve(n);
|
||||
for (Cel* cel : *this)
|
||||
list.push_back(cel);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
} // namespace doc
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite Document Library
|
||||
// Copyright (c) 2023 Igara Studio S.A.
|
||||
// Copyright (c) 2001-2017 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
@ -8,6 +9,7 @@
|
||||
#define DOC_CELS_RANGE_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "doc/cel_list.h"
|
||||
#include "doc/frame.h"
|
||||
#include "doc/object_id.h"
|
||||
#include "doc/selected_frames.h"
|
||||
@ -77,6 +79,10 @@ namespace doc {
|
||||
return count;
|
||||
}
|
||||
|
||||
// Converts the CelsRange into a CelList (which indeed it's an
|
||||
// array).
|
||||
CelList toList();
|
||||
|
||||
private:
|
||||
SelectedFrames m_selFrames;
|
||||
iterator m_begin, m_end;
|
||||
|
11
src/view/CMakeLists.txt
Normal file
11
src/view/CMakeLists.txt
Normal file
@ -0,0 +1,11 @@
|
||||
# Aseprite View Library
|
||||
# Copyright (c) 2023 Igara Studio S.A.
|
||||
|
||||
add_library(view-lib
|
||||
cels.cpp
|
||||
layers.cpp
|
||||
range.cpp)
|
||||
|
||||
target_link_libraries(view-lib
|
||||
doc-lib
|
||||
laf-base)
|
6
src/view/README.md
Normal file
6
src/view/README.md
Normal file
@ -0,0 +1,6 @@
|
||||
# Aseprite View Library
|
||||
|
||||
> Distributed under the terms of the [End-User License Agreement for Aseprite](../../EULA.txt)
|
||||
|
||||
Library to represent an abstract view (and concepts) of the timeline
|
||||
like the range of selected frames/layers.
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2020-2021 Igara Studio S.A.
|
||||
// Aseprite View Library
|
||||
// Copyright (C) 2020-2023 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -9,18 +9,14 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "app/util/range_utils.h"
|
||||
#include "view/cels.h"
|
||||
|
||||
#include "app/context_access.h"
|
||||
#include "app/doc.h"
|
||||
#include "app/doc_range.h"
|
||||
#include "doc/cel.h"
|
||||
#include "doc/layer.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "view/range.h"
|
||||
|
||||
#include <set>
|
||||
|
||||
namespace app {
|
||||
namespace view {
|
||||
|
||||
using namespace doc;
|
||||
|
||||
@ -31,10 +27,10 @@ enum class Target {
|
||||
kUniqueCanEditPixelsCels,
|
||||
};
|
||||
|
||||
// TODO the DocRange should be "iteratable" to replace this function
|
||||
// TODO the view::Range should be "iteratable" to replace this function
|
||||
// or we can wait to C++20 coroutines and co_yield
|
||||
static CelList get_cels_templ(const Sprite* sprite,
|
||||
DocRange range,
|
||||
Range range,
|
||||
const Target target)
|
||||
{
|
||||
CelList cels;
|
||||
@ -71,24 +67,24 @@ static CelList get_cels_templ(const Sprite* sprite,
|
||||
return cels;
|
||||
}
|
||||
|
||||
CelList get_cels(const doc::Sprite* sprite, const DocRange& range)
|
||||
CelList get_cels(const Sprite* sprite, const Range& range)
|
||||
{
|
||||
return get_cels_templ(sprite, range, Target::kAllCels);
|
||||
}
|
||||
|
||||
CelList get_unique_cels(const Sprite* sprite, const DocRange& range)
|
||||
CelList get_unique_cels(const Sprite* sprite, const Range& range)
|
||||
{
|
||||
return get_cels_templ(sprite, range, Target::kUniqueCels);
|
||||
}
|
||||
|
||||
CelList get_unique_cels_to_move_cel(const Sprite* sprite, const DocRange& range)
|
||||
CelList get_unique_cels_to_move_cel(const Sprite* sprite, const Range& range)
|
||||
{
|
||||
return get_cels_templ(sprite, range, Target::kUniqueCanMoveCels);
|
||||
}
|
||||
|
||||
CelList get_unique_cels_to_edit_pixels(const Sprite* sprite, const DocRange& range)
|
||||
CelList get_unique_cels_to_edit_pixels(const Sprite* sprite, const Range& range)
|
||||
{
|
||||
return get_cels_templ(sprite, range, Target::kUniqueCanEditPixelsCels);
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
} // namespace view
|
28
src/view/cels.h
Normal file
28
src/view/cels.h
Normal file
@ -0,0 +1,28 @@
|
||||
// Aseprite View Library
|
||||
// Copyright (C) 2020-2023 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
|
||||
#ifndef VIEW_CELS_H_INCLUDED
|
||||
#define VIEW_CELS_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "doc/cel_list.h"
|
||||
|
||||
namespace doc {
|
||||
class Sprite;
|
||||
}
|
||||
|
||||
namespace view {
|
||||
class Range;
|
||||
|
||||
doc::CelList get_cels(const doc::Sprite* sprite, const Range& range);
|
||||
doc::CelList get_unique_cels(const doc::Sprite* sprite, const Range& range);
|
||||
doc::CelList get_unique_cels_to_edit_pixels(const doc::Sprite* sprite, const Range& range);
|
||||
doc::CelList get_unique_cels_to_move_cel(const doc::Sprite* sprite, const Range& range);
|
||||
|
||||
} // namespace view
|
||||
|
||||
#endif // VIEW_CELS_H_INCLUDED
|
45
src/view/layers.cpp
Normal file
45
src/view/layers.cpp
Normal file
@ -0,0 +1,45 @@
|
||||
// Aseprite View Library
|
||||
// Copyright (c) 2020-2023 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 "view/layers.h"
|
||||
|
||||
#include "doc/layer.h"
|
||||
#include "doc/sprite.h"
|
||||
|
||||
namespace view {
|
||||
|
||||
using namespace doc;
|
||||
|
||||
Layer* candidate_if_layer_is_deleted(
|
||||
const Layer* selectedLayer,
|
||||
const Layer* layerToDelete)
|
||||
{
|
||||
const Layer* layerToSelect = selectedLayer;
|
||||
|
||||
if ((selectedLayer == layerToDelete) ||
|
||||
(selectedLayer &&
|
||||
selectedLayer->hasAncestor(layerToDelete))) {
|
||||
Sprite* sprite = selectedLayer->sprite();
|
||||
LayerGroup* parent = layerToDelete->parent();
|
||||
|
||||
// Select previous layer, or next layer, or the parent (if it is
|
||||
// not the main layer of sprite set).
|
||||
if (layerToDelete->getPrevious())
|
||||
layerToSelect = layerToDelete->getPrevious();
|
||||
else if (layerToDelete->getNext())
|
||||
layerToSelect = layerToDelete->getNext();
|
||||
else if (parent != sprite->root())
|
||||
layerToSelect = parent;
|
||||
}
|
||||
|
||||
return const_cast<Layer*>(layerToSelect);
|
||||
}
|
||||
|
||||
} // namespace view
|
26
src/view/layers.h
Normal file
26
src/view/layers.h
Normal file
@ -0,0 +1,26 @@
|
||||
// Aseprite View Library
|
||||
// Copyright (c) 2020-2023 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
|
||||
#ifndef VIEW_LAYERS_H_INCLUDED
|
||||
#define VIEW_LAYERS_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
namespace doc {
|
||||
class Layer;
|
||||
}
|
||||
|
||||
namespace view {
|
||||
|
||||
// Calculates a possible candidate to be selected in case that we
|
||||
// have a specific "selectedLayer" and are going to delete the given
|
||||
// "layerToDelete".
|
||||
doc::Layer* candidate_if_layer_is_deleted(
|
||||
const doc::Layer* selectedLayer,
|
||||
const doc::Layer* layerToDelete);
|
||||
|
||||
} // namespace view
|
||||
|
||||
#endif // VIEW_LAYERS_H_INCLUDED
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2020 Igara Studio S.A.
|
||||
// Aseprite View Library
|
||||
// Copyright (C) 2020-2023 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -9,24 +9,24 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "app/doc_range.h"
|
||||
#include "view/range.h"
|
||||
|
||||
#include "app/util/layer_utils.h"
|
||||
#include "base/serialization.h"
|
||||
#include "doc/cel.h"
|
||||
#include "doc/image.h"
|
||||
#include "doc/layer.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "view/layers.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace app {
|
||||
namespace view {
|
||||
|
||||
using namespace base::serialization;
|
||||
using namespace base::serialization::little_endian;
|
||||
using namespace doc;
|
||||
|
||||
DocRange::DocRange()
|
||||
Range::Range()
|
||||
: m_type(kNone)
|
||||
, m_flags(m_type)
|
||||
, m_selectingFromLayer(nullptr)
|
||||
@ -34,7 +34,7 @@ DocRange::DocRange()
|
||||
{
|
||||
}
|
||||
|
||||
DocRange::DocRange(Cel* cel)
|
||||
Range::Range(Cel* cel)
|
||||
: m_type(kCels)
|
||||
, m_flags(m_type)
|
||||
, m_selectingFromLayer(nullptr)
|
||||
@ -44,7 +44,7 @@ DocRange::DocRange(Cel* cel)
|
||||
m_selectedFrames.insert(cel->frame());
|
||||
}
|
||||
|
||||
void DocRange::clearRange()
|
||||
void Range::clearRange()
|
||||
{
|
||||
m_type = kNone;
|
||||
m_flags = kNone;
|
||||
@ -58,7 +58,7 @@ void DocRange::clearRange()
|
||||
m_selectingFromFrame = -1;
|
||||
}
|
||||
|
||||
void DocRange::startRange(Layer* fromLayer, frame_t fromFrame, Type type)
|
||||
void Range::startRange(Layer* fromLayer, frame_t fromFrame, Type type)
|
||||
{
|
||||
m_type = type;
|
||||
m_flags |= type;
|
||||
@ -71,7 +71,7 @@ void DocRange::startRange(Layer* fromLayer, frame_t fromFrame, Type type)
|
||||
m_selectedFrames.insert(fromFrame);
|
||||
}
|
||||
|
||||
void DocRange::endRange(Layer* toLayer, frame_t toFrame)
|
||||
void Range::endRange(Layer* toLayer, frame_t toFrame)
|
||||
{
|
||||
ASSERT(enabled());
|
||||
|
||||
@ -82,7 +82,7 @@ void DocRange::endRange(Layer* toLayer, frame_t toFrame)
|
||||
selectFrameRange(m_selectingFromFrame, toFrame);
|
||||
}
|
||||
|
||||
void DocRange::selectLayer(Layer* layer)
|
||||
void Range::selectLayer(Layer* layer)
|
||||
{
|
||||
if (m_type == kNone)
|
||||
m_type = kLayers;
|
||||
@ -91,7 +91,7 @@ void DocRange::selectLayer(Layer* layer)
|
||||
m_selectedLayers.insert(layer);
|
||||
}
|
||||
|
||||
void DocRange::selectLayers(const SelectedLayers& selLayers)
|
||||
void Range::selectLayers(const SelectedLayers& selLayers)
|
||||
{
|
||||
if (m_type == kNone)
|
||||
m_type = kLayers;
|
||||
@ -101,7 +101,7 @@ void DocRange::selectLayers(const SelectedLayers& selLayers)
|
||||
m_selectedLayers.insert(layer);
|
||||
}
|
||||
|
||||
void DocRange::eraseAndAdjust(const Layer* layer)
|
||||
void Range::eraseAndAdjust(const Layer* layer)
|
||||
{
|
||||
if (!enabled())
|
||||
return;
|
||||
@ -126,7 +126,7 @@ void DocRange::eraseAndAdjust(const Layer* layer)
|
||||
}
|
||||
}
|
||||
|
||||
bool DocRange::contains(const Layer* layer) const
|
||||
bool Range::contains(const Layer* layer) const
|
||||
{
|
||||
if (enabled())
|
||||
return m_selectedLayers.contains(const_cast<Layer*>(layer));
|
||||
@ -134,15 +134,15 @@ bool DocRange::contains(const Layer* layer) const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DocRange::contains(const Layer* layer,
|
||||
bool Range::contains(const Layer* layer,
|
||||
const frame_t frame) const
|
||||
{
|
||||
switch (m_type) {
|
||||
case DocRange::kNone:
|
||||
case Range::kNone:
|
||||
return false;
|
||||
case DocRange::kCels:
|
||||
case Range::kCels:
|
||||
return contains(layer) && contains(frame);
|
||||
case DocRange::kFrames:
|
||||
case Range::kFrames:
|
||||
if (contains(frame)) {
|
||||
if ((m_flags & (kCels | kLayers)) != 0)
|
||||
return contains(layer);
|
||||
@ -150,7 +150,7 @@ bool DocRange::contains(const Layer* layer,
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case DocRange::kLayers:
|
||||
case Range::kLayers:
|
||||
if (contains(layer)) {
|
||||
if ((m_flags & (kCels | kFrames)) != 0)
|
||||
return contains(frame);
|
||||
@ -162,37 +162,38 @@ bool DocRange::contains(const Layer* layer,
|
||||
return false;
|
||||
}
|
||||
|
||||
void DocRange::displace(layer_t layerDelta, frame_t frameDelta)
|
||||
void Range::displace(const layer_t layerDelta,
|
||||
const frame_t frameDelta)
|
||||
{
|
||||
m_selectedLayers.displace(layerDelta);
|
||||
m_selectedFrames.displace(frameDelta);
|
||||
}
|
||||
|
||||
bool DocRange::convertToCels(const Sprite* sprite)
|
||||
bool Range::convertToCels(const Sprite* sprite)
|
||||
{
|
||||
switch (m_type) {
|
||||
case DocRange::kNone:
|
||||
case Range::kNone:
|
||||
return false;
|
||||
case DocRange::kCels:
|
||||
case Range::kCels:
|
||||
break;
|
||||
case DocRange::kFrames: {
|
||||
case Range::kFrames: {
|
||||
if ((m_flags & (kCels | kLayers)) == 0) {
|
||||
for (auto layer : sprite->allBrowsableLayers())
|
||||
m_selectedLayers.insert(layer);
|
||||
}
|
||||
m_type = DocRange::kCels;
|
||||
m_type = Range::kCels;
|
||||
break;
|
||||
}
|
||||
case DocRange::kLayers:
|
||||
case Range::kLayers:
|
||||
if ((m_flags & (kCels | kFrames)) == 0)
|
||||
selectFrameRange(0, sprite->lastFrame());
|
||||
m_type = DocRange::kCels;
|
||||
m_type = Range::kCels;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DocRange::write(std::ostream& os) const
|
||||
bool Range::write(std::ostream& os) const
|
||||
{
|
||||
write32(os, m_type);
|
||||
write32(os, m_flags);
|
||||
@ -205,7 +206,7 @@ bool DocRange::write(std::ostream& os) const
|
||||
return os.good();
|
||||
}
|
||||
|
||||
bool DocRange::read(std::istream& is)
|
||||
bool Range::read(std::istream& is)
|
||||
{
|
||||
clearRange();
|
||||
|
||||
@ -221,7 +222,7 @@ bool DocRange::read(std::istream& is)
|
||||
return is.good();
|
||||
}
|
||||
|
||||
void DocRange::selectLayerRange(Layer* fromLayer, Layer* toLayer)
|
||||
void Range::selectLayerRange(Layer* fromLayer, Layer* toLayer)
|
||||
{
|
||||
ASSERT(fromLayer);
|
||||
ASSERT(toLayer);
|
||||
@ -267,12 +268,12 @@ void DocRange::selectLayerRange(Layer* fromLayer, Layer* toLayer)
|
||||
} while (it);
|
||||
}
|
||||
|
||||
void DocRange::selectFrameRange(frame_t fromFrame, frame_t toFrame)
|
||||
void Range::selectFrameRange(frame_t fromFrame, frame_t toFrame)
|
||||
{
|
||||
m_selectedFrames.insert(fromFrame, toFrame);
|
||||
}
|
||||
|
||||
void DocRange::setType(const Type type)
|
||||
void Range::setType(const Type type)
|
||||
{
|
||||
if (type != kNone) {
|
||||
m_type = type;
|
||||
@ -284,7 +285,7 @@ void DocRange::setType(const Type type)
|
||||
}
|
||||
}
|
||||
|
||||
void DocRange::setSelectedLayers(const SelectedLayers& layers)
|
||||
void Range::setSelectedLayers(const SelectedLayers& layers)
|
||||
{
|
||||
if (layers.empty()) {
|
||||
m_type = kNone;
|
||||
@ -297,7 +298,7 @@ void DocRange::setSelectedLayers(const SelectedLayers& layers)
|
||||
m_selectedLayers = layers;
|
||||
}
|
||||
|
||||
void DocRange::setSelectedFrames(const SelectedFrames& frames)
|
||||
void Range::setSelectedFrames(const SelectedFrames& frames)
|
||||
{
|
||||
if (frames.empty()) {
|
||||
m_type = kNone;
|
||||
@ -310,4 +311,4 @@ void DocRange::setSelectedFrames(const SelectedFrames& frames)
|
||||
m_selectedFrames = frames;
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
} // namespace view
|
100
src/view/range.h
Normal file
100
src/view/range.h
Normal file
@ -0,0 +1,100 @@
|
||||
// Aseprite View Library
|
||||
// Copyright (C) 2020-2023 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
|
||||
#ifndef VIEW_RANGE_H_INCLUDED
|
||||
#define VIEW_RANGE_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "doc/cel_list.h"
|
||||
#include "doc/frame.h"
|
||||
#include "doc/selected_frames.h"
|
||||
#include "doc/selected_layers.h"
|
||||
|
||||
#include <iosfwd>
|
||||
|
||||
namespace doc {
|
||||
class Cel;
|
||||
class Sprite;
|
||||
}
|
||||
|
||||
namespace view {
|
||||
|
||||
class Range {
|
||||
public:
|
||||
enum Type { kNone = 0,
|
||||
kCels = 1,
|
||||
kFrames = 2,
|
||||
kLayers = 4 };
|
||||
|
||||
Range();
|
||||
Range(doc::Cel* cel);
|
||||
Range(const Range&) = default;
|
||||
Range& operator=(const Range&) = default;
|
||||
|
||||
Type type() const { return m_type; }
|
||||
bool enabled() const { return m_type != kNone; }
|
||||
doc::layer_t layers() const { return int(m_selectedLayers.size()); }
|
||||
doc::frame_t frames() const { return int(m_selectedFrames.size()); }
|
||||
const doc::SelectedLayers& selectedLayers() const { return m_selectedLayers; }
|
||||
const doc::SelectedFrames& selectedFrames() const { return m_selectedFrames; }
|
||||
|
||||
void setType(const Type type);
|
||||
void setSelectedLayers(const doc::SelectedLayers& layers);
|
||||
void setSelectedFrames(const doc::SelectedFrames& frames);
|
||||
|
||||
void displace(const doc::layer_t layerDelta,
|
||||
const doc::frame_t frameDelta);
|
||||
|
||||
bool contains(const doc::Layer* layer) const;
|
||||
bool contains(const doc::frame_t frame) const {
|
||||
return m_selectedFrames.contains(frame);
|
||||
}
|
||||
bool contains(const doc::Layer* layer,
|
||||
const doc::frame_t frame) const;
|
||||
|
||||
// If the range includes the given layer, it will be erased from
|
||||
// the selection and other candidates might be selected (e.g. a
|
||||
// sibling, parent, etc.) using the
|
||||
// candidate_if_layer_is_deleted() function.
|
||||
void eraseAndAdjust(const doc::Layer* layer);
|
||||
|
||||
void clearRange();
|
||||
void startRange(doc::Layer* fromLayer, doc::frame_t fromFrame, Type type);
|
||||
void endRange(doc::Layer* toLayer, doc::frame_t toFrame);
|
||||
|
||||
void selectLayer(doc::Layer* layer);
|
||||
void selectLayers(const doc::SelectedLayers& selLayers);
|
||||
|
||||
doc::frame_t firstFrame() const { return m_selectedFrames.firstFrame(); }
|
||||
doc::frame_t lastFrame() const { return m_selectedFrames.lastFrame(); }
|
||||
|
||||
bool operator==(const Range& o) const {
|
||||
return (m_type == o.m_type &&
|
||||
m_selectedLayers == o.m_selectedLayers &&
|
||||
m_selectedFrames == o.m_selectedFrames);
|
||||
}
|
||||
|
||||
bool convertToCels(const doc::Sprite* sprite);
|
||||
|
||||
bool write(std::ostream& os) const;
|
||||
bool read(std::istream& is);
|
||||
|
||||
private:
|
||||
void selectLayerRange(doc::Layer* fromLayer, doc::Layer* toLayer);
|
||||
void selectFrameRange(doc::frame_t fromFrame, doc::frame_t toFrame);
|
||||
|
||||
Type m_type; // Last used type of the range
|
||||
int m_flags; // All used types in startRange()
|
||||
doc::SelectedLayers m_selectedLayers;
|
||||
doc::SelectedFrames m_selectedFrames;
|
||||
doc::Layer* m_selectingFromLayer;
|
||||
doc::frame_t m_selectingFromFrame;
|
||||
};
|
||||
|
||||
} // namespace view
|
||||
|
||||
#endif // VIEW_RANGE_H_INCLUDED
|
Loading…
x
Reference in New Issue
Block a user