diff --git a/data/gui.xml b/data/gui.xml index 057429355..1c6cc4a4e 100644 --- a/data/gui.xml +++ b/data/gui.xml @@ -39,9 +39,6 @@ - - - @@ -78,6 +75,15 @@ + + + + + + + + + @@ -770,10 +776,31 @@ - - - - + + + + + + + + + + + + + + + + + + + + + + + + + @@ -784,11 +811,6 @@ - - - - - diff --git a/data/strings/en.ini b/data/strings/en.ini index a3e4d2560..f8a9dccf5 100644 --- a/data/strings/en.ini +++ b/data/strings/en.ini @@ -211,7 +211,7 @@ AddColor_Specific = Specific AdvancedMode = Advanced Mode AutocropSprite = Trim Sprite AutocropSprite_ByGrid = Trim Sprite by Grid -BackgroundFromLayer = Background From Layer +BackgroundFromLayer = Background from Layer BrightnessContrast = Adjust Brightness/Contrast Cancel = Cancel Current Operation CanvasSize = Canvas Size @@ -295,7 +295,7 @@ InvertColor = Invert Color InvertMask = Invert Selection KeyboardShortcuts = Keyboard Shortcuts Launch = Launch -LayerFromBackground = Layer From Background +LayerFromBackground = Layer from Background LayerLock = Lock Layers LayerOpacity = Set Layer Opacity to {0} ({1}%) LayerProperties = Layer Properties @@ -332,7 +332,7 @@ MoveMask_Boundaries = Selection Boundaries MoveMask_Content = Selection Content NewBrush = New Brush NewFile = New File -NewFile_FromClipboard = New File (From Clipboard) +NewFile_FromClipboard = New File from Clipboard NewFrame = New Frame NewFrame_NewEmptyFrame = New Empty Frame NewFrame_DuplicateCels = Duplicate Linked Cels @@ -343,8 +343,10 @@ NewLayer_BeforeActiveLayer = New {} Below NewLayer_Layer = Layer NewLayer_Group = Group NewLayer_ReferenceLayer = Reference Layer -NewLayer_FromClipboard = {} (From Clipboard) -NewSpriteFromSelection = New Sprite From Selection +NewLayer_FromClipboard = {} from Clipboard +NewLayer_ViaCopy = {} via Copy +NewLayer_ViaCut = {} via Cut +NewSpriteFromSelection = New Sprite from Selection OpenBrowser = Open Browser OpenFile = Open Sprite OpenGroup = Open/Close Group @@ -739,7 +741,7 @@ edit_shift_right = &Right edit_shift_up = &Up edit_shift_down = &Down edit_new_brush = New &Brush -edit_new_sprite_from_selection = &New Sprite from Selection +edit_new_sprite_from_selection = &New Sprite From Selection edit_replace_color = R&eplace Color... edit_invert_color = &Invert... edit_adjustments = Ad&justments @@ -777,8 +779,14 @@ layer_properties = &Properties... layer_visible = &Visible layer_lock_layers = Loc&k Layers layer_open_group = &Open Group +layer_new = &New... layer_new_layer = &New Layer layer_new_group = New &Group +layer_new_layer_from_clipboard = New Layer from Clip&board +layer_new_layer_via_copy = New Layer via &Copy +layer_new_layer_via_cut = New Layer via Cu&t +layer_new_reference_layer_from_file = New &Reference Layer from File +layer_new_reference_layer_from_clipboard = New R&eference Layer from Clipboard layer_delete_layer = Delete Laye&r layer_background_from_layer = &Background from Layer layer_layer_from_background = &Layer from Background @@ -786,7 +794,6 @@ layer_duplicate = &Duplicate layer_merge_down = &Merge Down layer_flatten = &Flatten layer_flatten_visible = Flatten Vi&sible -layer_add_reference_layer = Add R&eference Layer frame = F&rame frame_properties = Frame &Properties... frame_cel_properties = &Cel Properties... diff --git a/src/app/commands/cmd_new_layer.cpp b/src/app/commands/cmd_new_layer.cpp index e1c874bbb..06cae48f7 100644 --- a/src/app/commands/cmd_new_layer.cpp +++ b/src/app/commands/cmd_new_layer.cpp @@ -10,7 +10,9 @@ #endif #include "app/app.h" +#include "app/cmd/clear_mask.h" #include "app/cmd/move_layer.h" +#include "app/cmd/trim_cel.h" #include "app/commands/command.h" #include "app/commands/commands.h" #include "app/commands/new_params.h" @@ -26,6 +28,7 @@ #include "app/ui/status_bar.h" #include "app/ui_context.h" #include "app/util/clipboard.h" +#include "app/util/new_image_from_mask.h" #include "doc/layer.h" #include "doc/primitives.h" #include "doc/sprite.h" @@ -52,6 +55,8 @@ struct NewLayerParams : public NewParams { Param ask { this, false, "ask" }; Param fromFile { this, false, { "fromFile", "from-file" } }; Param fromClipboard { this, false, "fromClipboard" }; + Param viaCut { this, false, "viaCut" }; + Param viaCopy { this, false, "viaCopy" }; Param top { this, false, "top" }; Param before { this, false, "before" }; }; @@ -70,6 +75,7 @@ protected: std::string onGetFriendlyName() const override; private: + void adjustRefCelBounds(Cel* cel, gfx::RectF bounds); std::string getUniqueLayerName(const Sprite* sprite) const; int getMaxLayerNum(const Layer* layer) const; std::string layerPrefix() const; @@ -102,13 +108,22 @@ void NewLayerCommand::onLoadParams(const Params& commandParams) bool NewLayerCommand::onEnabled(Context* context) { - return context->checkFlags(ContextFlags::ActiveDocumentIsWritable | - ContextFlags::HasActiveSprite) - && (!params().fromClipboard() + if (!context->checkFlags(ContextFlags::ActiveDocumentIsWritable | + ContextFlags::HasActiveSprite)) + return false; + #ifdef ENABLE_UI - || (clipboard::get_current_format() == clipboard::ClipboardImage) + if (params().fromClipboard() && + clipboard::get_current_format() != clipboard::ClipboardImage) + return false; #endif - ); + + if ((params().viaCut() || + params().viaCopy()) && + !context->checkFlags(ContextFlags::HasVisibleMask)) + return false; + + return true; } namespace { @@ -124,6 +139,7 @@ private: void NewLayerCommand::onExecute(Context* context) { ContextWriter writer(context); + Site site = context->activeSite(); Doc* document(writer.document()); Sprite* sprite(writer.sprite()); std::string name; @@ -180,7 +196,7 @@ void NewLayerCommand::onExecute(Context* context) LayerGroup* parent = sprite->root(); Layer* activeLayer = writer.layer(); - SelectedLayers selLayers = writer.site()->selectedLayers(); + SelectedLayers selLayers = site.selectedLayers(); if (activeLayer) { if (activeLayer->isGroup() && activeLayer->isExpanded() && @@ -243,7 +259,7 @@ void NewLayerCommand::onExecute(Context* context) } // Put all selected layers inside the group - if (m_type == Type::Group && writer.site()->inTimeline()) { + if (m_type == Type::Group && site.inTimeline()) { LayerGroup* commonParent = nullptr; layer_t sameParents = 0; for (Layer* l : selLayers) { @@ -314,14 +330,8 @@ void NewLayerCommand::onExecute(Context* context) if (cel) { if (layer->isReference()) { - gfx::RectF bounds(0, 0, pasteSpr->width(), pasteSpr->height()); - double scale = MIN(double(sprite->width()) / bounds.w, - double(sprite->height()) / bounds.h); - bounds.w *= scale; - bounds.h *= scale; - bounds.x = sprite->width()/2 - bounds.w/2; - bounds.y = sprite->height()/2 - bounds.h/2; - cel->setBoundsF(bounds); + adjustRefCelBounds( + cel, gfx::RectF(0, 0, pasteSpr->width(), pasteSpr->height())); } else { cel->setPosition(sprite->width()/2 - pasteSpr->width()/2, @@ -334,8 +344,43 @@ void NewLayerCommand::onExecute(Context* context) // Paste new layer from clipboard else if (params().fromClipboard() && layer->isImage()) { clipboard::paste(context, false); + + if (layer->isReference()) { + if (Cel* cel = layer->cel(site.frame())) { + adjustRefCelBounds( + cel, cel->boundsF()); + } + } } #endif // ENABLE_UI + // Paste new layer from selection + else if ((params().viaCut() || params().viaCopy()) + && layer->isImage() + && document->isMaskVisible()) { + const doc::Mask* mask = document->mask(); + ASSERT(mask); + ImageRef image(new_image_from_mask(site, mask, true)); + if (image) { + Cel* cel = api.addCel(static_cast(layer), + site.frame(), image); + if (cel) { + gfx::Point pos = mask->bounds().origin(); + cel->setPosition(pos.x, pos.y); + } + + if (params().viaCut() && + site.cel() && site.layer()) { + tx(new cmd::ClearMask(site.cel())); + + if (site.layer()->isTransparent()) { + // If the cel wasn't deleted by cmd::ClearMask, we trim it. + cel = site.layer()->cel(site.frame()); + if (cel) + tx(new cmd::TrimCel(cel)); + } + } + } + } tx.commit(); } @@ -364,9 +409,25 @@ std::string NewLayerCommand::onGetFriendlyName() const text = fmt::format(Strings::commands_NewLayer(), layerPrefix()); if (params().fromClipboard()) text = fmt::format(Strings::commands_NewLayer_FromClipboard(), text); + if (params().viaCopy()) + text = fmt::format(Strings::commands_NewLayer_ViaCopy(), text); + if (params().viaCut()) + text = fmt::format(Strings::commands_NewLayer_ViaCut(), text); return text; } +void NewLayerCommand::adjustRefCelBounds(Cel* cel, gfx::RectF bounds) +{ + Sprite* sprite = cel->sprite(); + double scale = MIN(double(sprite->width()) / bounds.w, + double(sprite->height()) / bounds.h); + bounds.w *= scale; + bounds.h *= scale; + bounds.x = sprite->width()/2 - bounds.w/2; + bounds.y = sprite->height()/2 - bounds.h/2; + cel->setBoundsF(bounds); +} + std::string NewLayerCommand::getUniqueLayerName(const Sprite* sprite) const { return fmt::format("{} {}",