[lua] Add Range.layers/frames setters and Range:clear()

This commit is contained in:
David Capello 2020-04-16 19:19:18 -03:00
parent 48e941cb2f
commit e149f76934
11 changed files with 198 additions and 22 deletions

View File

@ -65,6 +65,7 @@ void ActiveSiteHandler::getActiveSiteForDoc(Doc* doc, Site* site)
site->sprite(doc->sprite());
site->layer(doc::get<doc::Layer>(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<Layer>(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);

View File

@ -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;
};

View File

@ -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)

View File

@ -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);

View File

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

View File

@ -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;

View File

@ -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<color_t> 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<Sprite>(spriteId)); }
@ -133,6 +148,19 @@ int Range_containsColor(lua_State* L)
return 1;
}
int Range_clear(lua_State* L)
{
auto obj = get_obj<RangeObj>(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<RangeObj>(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<RangeObj>(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<Layer>(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<RangeObj>(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<RangeObj>(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 },

View File

@ -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()) {

View File

@ -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;

View File

@ -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);
}

View File

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