From e149f769343f27be6fee7dfc116180a4c232db45 Mon Sep 17 00:00:00 2001 From: David Capello Date: Thu, 16 Apr 2020 19:19:18 -0300 Subject: [PATCH] [lua] Add Range.layers/frames setters and Range:clear() --- src/app/active_site_handler.cpp | 23 ++++++++ src/app/active_site_handler.h | 5 +- src/app/context.cpp | 13 ++++- src/app/context.h | 5 +- src/app/doc_range.cpp | 38 +++++++++++++ src/app/doc_range.h | 6 ++ src/app/script/range_class.cpp | 98 +++++++++++++++++++++++++++++---- src/app/ui_context.cpp | 13 +++++ src/app/ui_context.h | 3 +- src/app/util/range_utils.cpp | 9 +-- src/app/util/range_utils.h | 7 ++- 11 files changed, 198 insertions(+), 22 deletions(-) diff --git a/src/app/active_site_handler.cpp b/src/app/active_site_handler.cpp index eefdabb6a..bf213407f 100644 --- a/src/app/active_site_handler.cpp +++ b/src/app/active_site_handler.cpp @@ -65,6 +65,7 @@ void ActiveSiteHandler::getActiveSiteForDoc(Doc* doc, Site* site) site->sprite(doc->sprite()); site->layer(doc::get(data.layer)); site->frame(data.frame); + site->range(data.range); site->selectedColors(data.selectedColors); } @@ -80,6 +81,28 @@ void ActiveSiteHandler::setActiveFrameInDoc(Doc* doc, doc::frame_t frame) data.frame = frame; } +void ActiveSiteHandler::setRangeInDoc(Doc* doc, const DocRange& range) +{ + Data& data = getData(doc); + data.range = range; + + // Select at least the active layer + if (data.range.selectedLayers().empty()) { + if (auto layer = doc::get(data.layer)) { + data.range.selectLayer(layer); + } + } + + // Select at least the active frame + if (data.range.selectedFrames().empty()) { + SelectedFrames frames; + frames.insert(data.frame); + data.range.setSelectedFrames(frames); + } + + data.range.setType(range.type()); +} + void ActiveSiteHandler::setSelectedColorsInDoc(Doc* doc, const doc::PalettePicks& picks) { Data& data = getData(doc); diff --git a/src/app/active_site_handler.h b/src/app/active_site_handler.h index 01216827a..32136ba26 100644 --- a/src/app/active_site_handler.h +++ b/src/app/active_site_handler.h @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2019 Igara Studio S.A. +// Copyright (C) 2019-2020 Igara Studio S.A. // // This program is distributed under the terms of // the End-User License Agreement for Aseprite. @@ -9,6 +9,7 @@ #pragma once #include "app/doc_observer.h" +#include "app/doc_range.h" #include "doc/frame.h" #include "doc/object_id.h" #include "doc/palette_picks.h" @@ -38,6 +39,7 @@ namespace app { void getActiveSiteForDoc(Doc* doc, Site* site); void setActiveLayerInDoc(Doc* doc, doc::Layer* layer); void setActiveFrameInDoc(Doc* doc, doc::frame_t frame); + void setRangeInDoc(Doc* doc, const DocRange& range); void setSelectedColorsInDoc(Doc* doc, const doc::PalettePicks& picks); private: @@ -51,6 +53,7 @@ namespace app { struct Data { doc::ObjectId layer; doc::frame_t frame; + DocRange range; doc::PalettePicks selectedColors; }; diff --git a/src/app/context.cpp b/src/app/context.cpp index 6850ea320..3a62da3e7 100644 --- a/src/app/context.cpp +++ b/src/app/context.cpp @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2018-2019 Igara Studio S.A. +// Copyright (C) 2018-2020 Igara Studio S.A. // Copyright (C) 2001-2018 David Capello // // This program is distributed under the terms of @@ -94,6 +94,11 @@ void Context::setActiveFrame(const doc::frame_t frame) onSetActiveFrame(frame); } +void Context::setRange(const DocRange& range) +{ + onSetRange(range); +} + void Context::setSelectedColors(const doc::PalettePicks& picks) { onSetSelectedColors(picks); @@ -235,6 +240,12 @@ void Context::onSetActiveFrame(const doc::frame_t frame) activeSiteHandler()->setActiveFrameInDoc(m_lastSelectedDoc, frame); } +void Context::onSetRange(const DocRange& range) +{ + if (m_lastSelectedDoc) + activeSiteHandler()->setRangeInDoc(m_lastSelectedDoc, range); +} + void Context::onSetSelectedColors(const doc::PalettePicks& picks) { if (m_lastSelectedDoc) diff --git a/src/app/context.h b/src/app/context.h index 7328e499e..e9fe64e48 100644 --- a/src/app/context.h +++ b/src/app/context.h @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2018-2019 Igara Studio S.A. +// Copyright (C) 2018-2020 Igara Studio S.A. // Copyright (C) 2001-2018 David Capello // // This program is distributed under the terms of @@ -32,6 +32,7 @@ namespace app { class ActiveSiteHandler; class Command; class Doc; + class DocRange; class DocView; class Preferences; @@ -88,6 +89,7 @@ namespace app { void setActiveDocument(Doc* document); void setActiveLayer(doc::Layer* layer); void setActiveFrame(doc::frame_t frame); + void setRange(const DocRange& range); void setSelectedColors(const doc::PalettePicks& picks); bool hasModifiedDocuments() const; void notifyActiveSiteChanged(); @@ -111,6 +113,7 @@ namespace app { virtual void onSetActiveDocument(Doc* doc); virtual void onSetActiveLayer(doc::Layer* layer); virtual void onSetActiveFrame(const doc::frame_t frame); + virtual void onSetRange(const DocRange& range); virtual void onSetSelectedColors(const doc::PalettePicks& picks); virtual void onCloseDocument(Doc* doc); diff --git a/src/app/doc_range.cpp b/src/app/doc_range.cpp index 5a605151d..d0d59cfd9 100644 --- a/src/app/doc_range.cpp +++ b/src/app/doc_range.cpp @@ -258,4 +258,42 @@ void DocRange::selectFrameRange(frame_t fromFrame, frame_t toFrame) m_selectedFrames.insert(fromFrame, toFrame); } +void DocRange::setType(const Type type) +{ + if (type != kNone) { + m_type = type; + m_flags |= type; + } + else { + m_type = kNone; + m_flags = kNone; + } +} + +void DocRange::setSelectedLayers(const SelectedLayers& layers) +{ + if (layers.empty()) { + m_type = kNone; + m_selectedLayers.clear(); + return; + } + + m_type = kLayers; + m_flags |= kLayers; + m_selectedLayers = layers; +} + +void DocRange::setSelectedFrames(const SelectedFrames& frames) +{ + if (frames.empty()) { + m_type = kNone; + m_selectedFrames.clear(); + return; + } + + m_type = kFrames; + m_flags |= kFrames; + m_selectedFrames = frames; +} + } // namespace app diff --git a/src/app/doc_range.h b/src/app/doc_range.h index 3f3cc836b..125bcb8c0 100644 --- a/src/app/doc_range.h +++ b/src/app/doc_range.h @@ -32,6 +32,8 @@ namespace app { 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; } @@ -40,6 +42,10 @@ namespace app { 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; diff --git a/src/app/script/range_class.cpp b/src/app/script/range_class.cpp index ec17246e2..3d719ff6b 100644 --- a/src/app/script/range_class.cpp +++ b/src/app/script/range_class.cpp @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2018-2019 Igara Studio S.A. +// Copyright (C) 2018-2020 Igara Studio S.A. // // This program is distributed under the terms of // the End-User License Agreement for Aseprite. @@ -39,15 +39,32 @@ struct RangeObj { // This is like DocRange but referencing objects with IDs std::vector colors; RangeObj(Site& site) { - const DocRange& docRange = site.range(); + updateFromSite(site); + } + RangeObj(const RangeObj&) = delete; + RangeObj& operator=(const RangeObj&) = delete; + + void updateFromSite(const Site& site) { + if (!site.sprite()) { + type = DocRange::kNone; + spriteId = NullId; + return; + } + + const DocRange& range = site.range(); spriteId = site.sprite()->id(); - type = docRange.type(); + type = range.type(); - if (docRange.enabled()) { - for (const Layer* layer : docRange.selectedLayers()) + layers.clear(); + frames.clear(); + cels.clear(); + colors.clear(); + + if (range.enabled()) { + for (const Layer* layer : range.selectedLayers()) layers.insert(layer->id()); - for (const frame_t frame : docRange.selectedFrames()) + for (const frame_t frame : range.selectedFrames()) frames.push_back(frame); // TODO improve this, in the best case we should defer layers, @@ -55,7 +72,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 (Cel* cel : get_cels(site.sprite(), docRange)) + for (const Cel* cel : get_cels(site.sprite(), range)) cels.insert(cel->id()); } else { @@ -68,8 +85,6 @@ struct RangeObj { // This is like DocRange but referencing objects with IDs if (site.selectedColors().picks() > 0) colors = site.selectedColors().toVectorOfIndexes(); } - RangeObj(const RangeObj&) = delete; - RangeObj& operator=(const RangeObj&) = delete; Sprite* sprite(lua_State* L) { return check_docobj(L, doc::get(spriteId)); } @@ -133,6 +148,19 @@ int Range_containsColor(lua_State* L) return 1; } +int Range_clear(lua_State* L) +{ + auto obj = get_obj(L, 1); + auto ctx = App::instance()->context(); + + // Set an empty range + DocRange range; + ctx->setRange(range); + obj->updateFromSite(ctx->activeSite()); + + return 0; +} + int Range_get_isEmpty(lua_State* L) { auto obj = get_obj(L, 1); @@ -212,8 +240,53 @@ int Range_get_colors(lua_State* L) return 1; } +int Range_set_layers(lua_State* L) +{ + auto obj = get_obj(L, 1); + app::Context* ctx = App::instance()->context(); + DocRange range = ctx->activeSite().range(); + + doc::SelectedLayers layers; + if (lua_istable(L, 2)) { + lua_pushnil(L); + while (lua_next(L, 2) != 0) { + if (Layer* layer = may_get_docobj(L, -1)) + layers.insert(layer); + lua_pop(L, 1); + } + } + range.setSelectedLayers(layers); + + ctx->setRange(range); + obj->updateFromSite(ctx->activeSite()); + return 0; +} + +int Range_set_frames(lua_State* L) +{ + auto obj = get_obj(L, 1); + app::Context* ctx = App::instance()->context(); + DocRange range = ctx->activeSite().range(); + + doc::SelectedFrames frames; + if (lua_istable(L, 2)) { + lua_pushnil(L); + while (lua_next(L, 2) != 0) { + doc::frame_t f = get_frame_number_from_arg(L, -1); + frames.insert(f); + lua_pop(L, 1); + } + } + range.setSelectedFrames(frames); + + ctx->setRange(range); + obj->updateFromSite(ctx->activeSite()); + return 0; +} + int Range_set_colors(lua_State* L) { + auto obj = get_obj(L, 1); app::Context* ctx = App::instance()->context(); doc::PalettePicks picks; if (lua_istable(L, 2)) { @@ -226,7 +299,9 @@ int Range_set_colors(lua_State* L) lua_pop(L, 1); } } + ctx->setSelectedColors(picks); + obj->updateFromSite(ctx->activeSite()); return 0; } @@ -234,6 +309,7 @@ const luaL_Reg Range_methods[] = { { "__gc", Range_gc }, { "contains", Range_contains }, { "containsColor", Range_containsColor }, + { "clear", Range_clear }, { nullptr, nullptr } }; @@ -241,8 +317,8 @@ const Property Range_properties[] = { { "sprite", Range_get_sprite, nullptr }, { "type", Range_get_type, nullptr }, { "isEmpty", Range_get_isEmpty, nullptr }, - { "layers", Range_get_layers, nullptr }, - { "frames", Range_get_frames, nullptr }, + { "layers", Range_get_layers, Range_set_layers }, + { "frames", Range_get_frames, Range_set_frames }, { "cels", Range_get_cels, nullptr }, { "images", Range_get_images, nullptr }, { "editableImages", Range_get_editableImages, nullptr }, diff --git a/src/app/ui_context.cpp b/src/app/ui_context.cpp index 0d392a686..915d6f235 100644 --- a/src/app/ui_context.cpp +++ b/src/app/ui_context.cpp @@ -168,6 +168,19 @@ void UIContext::onSetActiveFrame(const doc::frame_t frame) Context::onSetActiveFrame(frame); } +void UIContext::onSetRange(const DocRange& range) +{ + Timeline* timeline = + (App::instance()->mainWindow() ? + App::instance()->mainWindow()->getTimeline(): nullptr); + if (timeline) { + timeline->setRange(range); + } + else if (!isUIAvailable()) { + Context::onSetRange(range); + } +} + void UIContext::onSetSelectedColors(const doc::PalettePicks& picks) { if (activeView()) { diff --git a/src/app/ui_context.h b/src/app/ui_context.h index 8a2060fe7..35472d908 100644 --- a/src/app/ui_context.h +++ b/src/app/ui_context.h @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2019 Igara Studio S.A. +// Copyright (C) 2019-2020 Igara Studio S.A. // Copyright (C) 2001-2018 David Capello // // This program is distributed under the terms of @@ -56,6 +56,7 @@ namespace app { void onSetActiveDocument(Doc* doc) override; void onSetActiveLayer(doc::Layer* layer) override; void onSetActiveFrame(const doc::frame_t frame) override; + void onSetRange(const DocRange& range) override; void onSetSelectedColors(const doc::PalettePicks& picks) override; void onCloseDocument(Doc* doc) override; diff --git a/src/app/util/range_utils.cpp b/src/app/util/range_utils.cpp index 49b1e28ac..f31c9f02a 100644 --- a/src/app/util/range_utils.cpp +++ b/src/app/util/range_utils.cpp @@ -1,4 +1,5 @@ // Aseprite +// Copyright (C) 2020 Igara Studio S.A. // Copyright (C) 2001-2018 David Capello // // This program is distributed under the terms of @@ -24,7 +25,7 @@ namespace app { using namespace doc; // TODO the DocRange should be "iteratable" to replace this function -static CelList get_cels_templ(Sprite* sprite, +static CelList get_cels_templ(const Sprite* sprite, DocRange range, const bool onlyUniqueCels, const bool onlyUnlockedCel) @@ -59,17 +60,17 @@ static CelList get_cels_templ(Sprite* sprite, return cels; } -CelList get_cels(doc::Sprite* sprite, const DocRange& range) +CelList get_cels(const doc::Sprite* sprite, const DocRange& range) { return get_cels_templ(sprite, range, false, false); } -CelList get_unique_cels(Sprite* sprite, const DocRange& range) +CelList get_unique_cels(const Sprite* sprite, const DocRange& range) { return get_cels_templ(sprite, range, true, false); } -CelList get_unlocked_unique_cels(Sprite* sprite, const DocRange& range) +CelList get_unlocked_unique_cels(const Sprite* sprite, const DocRange& range) { return get_cels_templ(sprite, range, true, true); } diff --git a/src/app/util/range_utils.h b/src/app/util/range_utils.h index 71d42d259..8fbc0c753 100644 --- a/src/app/util/range_utils.h +++ b/src/app/util/range_utils.h @@ -1,4 +1,5 @@ // Aseprite +// Copyright (C) 2020 Igara Studio S.A. // Copyright (C) 2001-2018 David Capello // // This program is distributed under the terms of @@ -21,9 +22,9 @@ namespace app { class DocRange; - doc::CelList get_cels(doc::Sprite* sprite, const DocRange& range); - doc::CelList get_unique_cels(doc::Sprite* sprite, const DocRange& range); - doc::CelList get_unlocked_unique_cels(doc::Sprite* sprite, const DocRange& range); + 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_unlocked_unique_cels(const doc::Sprite* sprite, const DocRange& range); } // namespace app