mirror of
https://github.com/aseprite/aseprite.git
synced 2024-09-02 13:09:27 +00:00
Lock document in Tx() ctor (part of #2430)
This already fixes a lot of possible problems that can happen when a script is running and modifying some part of a sprite that is being backed up in a background thread. We still need some work to being able to lock a sprite two or more times in the same thread to write it. E.g. an app.transaction() should lock the sprite for write access, but the script transaction function could call a command, and that command could use a ContextWriter to lock the sprite again. At the moment this is not possible because we need a re-entrant RWLock implementation.
This commit is contained in:
parent
e87fdbb3af
commit
8722c8ec16
@ -130,7 +130,7 @@ void AddColorCommand::onExecute(Context* ctx)
|
||||
if (document) {
|
||||
frame_t frame = writer.frame();
|
||||
|
||||
Tx tx(writer.context(), friendlyName(), ModifyDocument);
|
||||
Tx tx(writer, friendlyName(), ModifyDocument);
|
||||
tx(new cmd::SetPalette(sprite, frame, newPalette.get()));
|
||||
tx.commit();
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ void BackgroundFromLayerCommand::onExecute(Context* context)
|
||||
Doc* document(writer.document());
|
||||
|
||||
{
|
||||
Tx tx(writer.context(), friendlyName());
|
||||
Tx tx(writer, friendlyName());
|
||||
tx(new cmd::BackgroundFromLayer(static_cast<LayerImage*>(writer.layer())));
|
||||
tx.commit();
|
||||
}
|
||||
|
@ -385,7 +385,7 @@ void CanvasSizeCommand::onExecute(Context* context)
|
||||
ContextWriter writer(reader);
|
||||
Doc* doc = writer.document();
|
||||
Sprite* sprite = writer.sprite();
|
||||
Tx tx(writer.context(), "Canvas Size");
|
||||
Tx tx(writer, "Canvas Size");
|
||||
DocApi api = doc->getApi(tx);
|
||||
api.cropSprite(sprite, bounds, params.trimOutside());
|
||||
tx.commit();
|
||||
|
@ -73,7 +73,7 @@ void CelOpacityCommand::onExecute(Context* context)
|
||||
return;
|
||||
|
||||
{
|
||||
Tx tx(writer.context(), "Set Cel Opacity");
|
||||
Tx tx(writer, "Set Cel Opacity");
|
||||
|
||||
// TODO the range of selected cels should be in app::Site.
|
||||
DocRange range;
|
||||
|
@ -218,7 +218,7 @@ private:
|
||||
newUserData != m_cel->data()->userData()))) {
|
||||
try {
|
||||
ContextWriter writer(UIContext::instance());
|
||||
Tx tx(writer.context(), "Set Cel Properties");
|
||||
Tx tx(writer, "Set Cel Properties");
|
||||
|
||||
DocRange range;
|
||||
if (m_range.enabled()) {
|
||||
|
@ -48,7 +48,7 @@ void ClearCelCommand::onExecute(Context* context)
|
||||
Doc* document(writer.document());
|
||||
bool nonEditableLayers = false;
|
||||
{
|
||||
Tx tx(writer.context(), "Clear Cel");
|
||||
Tx tx(writer, "Clear Cel");
|
||||
|
||||
const Site* site = writer.site();
|
||||
if (site->inTimeline() &&
|
||||
|
@ -72,7 +72,7 @@ void CropSpriteCommand::onExecute(Context* context)
|
||||
bounds = m_bounds;
|
||||
|
||||
{
|
||||
Tx tx(writer.context(), "Sprite Crop");
|
||||
Tx tx(writer, "Sprite Crop");
|
||||
document->getApi(tx).cropSprite(sprite, bounds);
|
||||
tx.commit();
|
||||
}
|
||||
@ -119,7 +119,7 @@ void AutocropSpriteCommand::onExecute(Context* context)
|
||||
Doc* document(writer.document());
|
||||
Sprite* sprite(writer.sprite());
|
||||
{
|
||||
Tx tx(writer.context(), onGetFriendlyName());
|
||||
Tx tx(writer, onGetFriendlyName());
|
||||
document->getApi(tx).trimSprite(sprite, m_byGrid);
|
||||
tx.commit();
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ void DeselectMaskCommand::onExecute(Context* context)
|
||||
ContextWriter writer(context);
|
||||
Doc* document(writer.document());
|
||||
{
|
||||
Tx tx(writer.context(), "Deselect", DoesntModifyDocument);
|
||||
Tx tx(writer, "Deselect", DoesntModifyDocument);
|
||||
tx(new cmd::DeselectMask(document));
|
||||
tx.commit();
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ void DuplicateLayerCommand::onExecute(Context* context)
|
||||
Doc* document = writer.document();
|
||||
|
||||
{
|
||||
Tx tx(writer.context(), "Layer Duplication");
|
||||
Tx tx(writer, "Layer Duplication");
|
||||
LayerImage* sourceLayer = static_cast<LayerImage*>(writer.layer());
|
||||
DocApi api = document->getApi(tx);
|
||||
api.duplicateLayerAfter(sourceLayer,
|
||||
|
@ -81,7 +81,7 @@ void FillCommand::onExecute(Context* ctx)
|
||||
color = color_utils::color_for_layer(pref.colorBar.fgColor(), layer);
|
||||
|
||||
{
|
||||
Tx tx(writer.context(), "Fill Selection with Foreground Color");
|
||||
Tx tx(writer, "Fill Selection with Foreground Color");
|
||||
{
|
||||
ExpandCelCanvas expand(
|
||||
site, layer,
|
||||
|
@ -57,7 +57,7 @@ void FlattenLayersCommand::onExecute(Context* context)
|
||||
ContextWriter writer(context);
|
||||
Sprite* sprite = writer.sprite();
|
||||
{
|
||||
Tx tx(writer.context(), "Flatten Layers");
|
||||
Tx tx(writer, "Flatten Layers");
|
||||
|
||||
// TODO the range of selected layers should be in app::Site.
|
||||
DocRange range;
|
||||
|
@ -120,7 +120,7 @@ void FlipCommand::onExecute(Context* ctx)
|
||||
ContextWriter writer(ctx);
|
||||
Doc* document = writer.document();
|
||||
Sprite* sprite = writer.sprite();
|
||||
Tx tx(ctx, friendlyName());
|
||||
Tx tx(writer, friendlyName());
|
||||
DocApi api = document->getApi(tx);
|
||||
|
||||
Mask* mask = document->mask();
|
||||
|
@ -127,7 +127,7 @@ void FramePropertiesCommand::onExecute(Context* context)
|
||||
int newMsecs = window.frlen()->textInt();
|
||||
|
||||
ContextWriter writer(reader);
|
||||
Tx tx(writer.context(), "Frame Duration");
|
||||
Tx tx(writer, "Frame Duration");
|
||||
DocApi api = writer.document()->getApi(tx);
|
||||
|
||||
for (frame_t frame : selFrames)
|
||||
|
@ -91,7 +91,7 @@ void FrameTagPropertiesCommand::onExecute(Context* context)
|
||||
return;
|
||||
|
||||
ContextWriter writer(reader);
|
||||
Tx tx(writer.context(), friendlyName());
|
||||
Tx tx(writer, friendlyName());
|
||||
Tag* tag = const_cast<Tag*>(foundTag);
|
||||
|
||||
std::string name = window.nameValue();
|
||||
|
@ -73,7 +73,7 @@ protected:
|
||||
const Mask* mask = doc->mask();
|
||||
gfx::Rect newGrid = mask->bounds();
|
||||
|
||||
Tx tx(writer.context(), friendlyName(), ModifyDocument);
|
||||
Tx tx(writer, friendlyName(), ModifyDocument);
|
||||
tx(new cmd::SetGridBounds(writer.sprite(), newGrid));
|
||||
tx.commit();
|
||||
|
||||
@ -125,7 +125,7 @@ void GridSettingsCommand::onExecute(Context* context)
|
||||
bounds.h = std::max(bounds.h, 1);
|
||||
|
||||
ContextWriter writer(context);
|
||||
Tx tx(context, friendlyName(), ModifyDocument);
|
||||
Tx tx(writer, friendlyName(), ModifyDocument);
|
||||
tx(new cmd::SetGridBounds(site.sprite(), bounds));
|
||||
tx.commit();
|
||||
|
||||
|
@ -512,8 +512,9 @@ void ImportSpriteSheetCommand::onExecute(Context* context)
|
||||
// The following steps modify the sprite, so we wrap all
|
||||
// operations in a undo-transaction.
|
||||
ContextWriter writer(context);
|
||||
Tx tx(
|
||||
writer.context(), Strings::import_sprite_sheet_title(), ModifyDocument);
|
||||
Tx tx(writer,
|
||||
Strings::import_sprite_sheet_title(),
|
||||
ModifyDocument);
|
||||
DocApi api = document->getApi(tx);
|
||||
|
||||
// Add the layer in the sprite.
|
||||
|
@ -93,7 +93,7 @@ void InvertMaskCommand::onExecute(Context* context)
|
||||
mask->intersect(sprite->bounds());
|
||||
|
||||
// Set the new mask
|
||||
Tx tx(writer.context(), "Mask Invert", DoesntModifyDocument);
|
||||
Tx tx(writer, "Mask Invert", DoesntModifyDocument);
|
||||
tx(new cmd::SetMask(document, mask.get()));
|
||||
tx.commit();
|
||||
|
||||
|
@ -51,7 +51,7 @@ void LayerFromBackgroundCommand::onExecute(Context* context)
|
||||
ContextWriter writer(context);
|
||||
Doc* document(writer.document());
|
||||
{
|
||||
Tx tx(writer.context(), friendlyName());
|
||||
Tx tx(writer, friendlyName());
|
||||
tx(new cmd::LayerFromBackground(writer.layer()));
|
||||
tx.commit();
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ void LayerOpacityCommand::onExecute(Context* context)
|
||||
return;
|
||||
|
||||
{
|
||||
Tx tx(writer.context(), "Set Layer Opacity");
|
||||
Tx tx(writer, "Set Layer Opacity");
|
||||
|
||||
// TODO the range of selected frames should be in app::Site.
|
||||
SelectedLayers selLayers;
|
||||
|
@ -265,7 +265,7 @@ private:
|
||||
newBlendMode != static_cast<LayerImage*>(m_layer)->blendMode()))))) {
|
||||
try {
|
||||
ContextWriter writer(UIContext::instance());
|
||||
Tx tx(writer.context(), "Set Layer Properties");
|
||||
Tx tx(writer, "Set Layer Properties");
|
||||
|
||||
DocRange range;
|
||||
if (m_range.enabled())
|
||||
@ -395,7 +395,7 @@ private:
|
||||
tileset->matchFlags() != tilesetInfo.matchFlags ||
|
||||
tilesetInfo.tsi != tilemap->tilesetIndex()) {
|
||||
ContextWriter writer(UIContext::instance());
|
||||
Tx tx(writer.context(), "Set Tileset Properties");
|
||||
Tx tx(writer, "Set Tileset Properties");
|
||||
// User changed tilemap's tileset
|
||||
if (tilesetInfo.tsi != tilemap->tilesetIndex()) {
|
||||
tileset = tilemap->sprite()->tilesets()->get(tilesetInfo.tsi);
|
||||
|
@ -57,7 +57,7 @@ void LinkCelsCommand::onExecute(Context* context)
|
||||
if (!site.inTimeline())
|
||||
return;
|
||||
|
||||
Tx tx(writer.context(), friendlyName());
|
||||
Tx tx(writer, friendlyName());
|
||||
|
||||
for (Layer* layer : site.selectedLayers()) {
|
||||
if (!layer->isImage())
|
||||
|
@ -77,7 +77,7 @@ void LoadMaskCommand::onExecute(Context* context)
|
||||
{
|
||||
ContextWriter writer(reader);
|
||||
Doc* document = writer.document();
|
||||
Tx tx(writer.context(),
|
||||
Tx tx(writer,
|
||||
Strings::load_selection_title(),
|
||||
DoesntModifyDocument);
|
||||
tx(new cmd::SetMask(document, mask.get()));
|
||||
|
@ -49,7 +49,7 @@ void MaskAllCommand::onExecute(Context* context)
|
||||
Mask newMask;
|
||||
newMask.replace(sprite->bounds());
|
||||
|
||||
Tx tx(writer.context(), "Select All", DoesntModifyDocument);
|
||||
Tx tx(writer, "Select All", DoesntModifyDocument);
|
||||
tx(new cmd::SetMask(document, &newMask));
|
||||
document->resetTransformation();
|
||||
tx.commit();
|
||||
|
@ -187,7 +187,7 @@ void MaskByColorCommand::onExecute(Context* context)
|
||||
Doc* document(writer.document());
|
||||
|
||||
if (apply) {
|
||||
Tx tx(writer.context(), "Mask by Color", DoesntModifyDocument);
|
||||
Tx tx(writer, "Mask by Color", DoesntModifyDocument);
|
||||
std::unique_ptr<Mask> mask(generateMask(*document->mask(),
|
||||
sprite, image, xpos, ypos,
|
||||
m_selMode->selectionMode()));
|
||||
|
@ -81,7 +81,7 @@ void MaskContentCommand::onExecute(Context* context)
|
||||
newMask.replace(cel->bounds());
|
||||
}
|
||||
|
||||
Tx tx(writer.context(), "Select Content", DoesntModifyDocument);
|
||||
Tx tx(writer, "Select Content", DoesntModifyDocument);
|
||||
tx(new cmd::SetMask(document, &newMask));
|
||||
document->resetTransformation();
|
||||
tx.commit();
|
||||
|
@ -79,7 +79,7 @@ void MergeDownLayerCommand::onExecute(Context* context)
|
||||
LayerImage* src_layer = static_cast<LayerImage*>(writer.layer());
|
||||
Layer* dst_layer = src_layer->getPrevious();
|
||||
|
||||
Tx tx(writer.context(), friendlyName(), ModifyDocument);
|
||||
Tx tx(writer, friendlyName(), ModifyDocument);
|
||||
|
||||
for (frame_t frpos = 0; frpos<sprite->totalFrames(); ++frpos) {
|
||||
// Get frames
|
||||
|
@ -138,7 +138,7 @@ void ModifySelectionCommand::onExecute(Context* context)
|
||||
}
|
||||
|
||||
// Set the new mask
|
||||
Tx tx(writer.context(),
|
||||
Tx tx(writer,
|
||||
friendlyName(),
|
||||
DoesntModifyDocument);
|
||||
tx(new cmd::SetMask(document, mask.get()));
|
||||
|
@ -87,7 +87,7 @@ void MoveMaskCommand::onExecute(Context* context)
|
||||
ContextWriter writer(context);
|
||||
Doc* document(writer.document());
|
||||
{
|
||||
Tx tx(writer.context(), "Move Selection", DoesntModifyDocument);
|
||||
Tx tx(writer, "Move Selection", DoesntModifyDocument);
|
||||
gfx::Point pt = document->mask()->bounds().origin();
|
||||
document->getApi(tx).setMaskPosition(pt.x+delta.x, pt.y+delta.y);
|
||||
tx.commit();
|
||||
@ -102,7 +102,7 @@ void MoveMaskCommand::onExecute(Context* context)
|
||||
ContextWriter writer(context);
|
||||
if (writer.cel()) {
|
||||
// Rotate content
|
||||
Tx tx(writer.context(), "Shift Pixels");
|
||||
Tx tx(writer, "Shift Pixels");
|
||||
tx(new cmd::ShiftMaskedCel(writer.cel(), delta.x, delta.y));
|
||||
tx.commit();
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ void NewBrushCommand::onQuickboxEnd(Editor* editor, const gfx::Rect& rect, ui::M
|
||||
if (writer.cel()) {
|
||||
gfx::Rect canvasRect = (rect & writer.cel()->bounds());
|
||||
if (!canvasRect.isEmpty()) {
|
||||
Tx tx(writer.context(), "Clear");
|
||||
Tx tx(writer, "Clear");
|
||||
tx(new cmd::ClearRect(writer.cel(), canvasRect));
|
||||
tx.commit();
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ void NewFrameCommand::onExecute(Context* context)
|
||||
#endif
|
||||
|
||||
{
|
||||
Tx tx(writer.context(), friendlyName());
|
||||
Tx tx(writer, friendlyName());
|
||||
DocApi api = document->getApi(tx);
|
||||
|
||||
switch (m_content) {
|
||||
|
@ -74,7 +74,7 @@ void NewFrameTagCommand::onExecute(Context* context)
|
||||
|
||||
{
|
||||
ContextWriter writer(reader);
|
||||
Tx tx(writer.context(), friendlyName());
|
||||
Tx tx(writer, friendlyName());
|
||||
tx(new cmd::AddTag(writer.sprite(), tag.get()));
|
||||
tag.release();
|
||||
tx.commit();
|
||||
|
@ -274,9 +274,8 @@ void NewLayerCommand::onExecute(Context* context)
|
||||
|
||||
Layer* layer = nullptr;
|
||||
{
|
||||
Tx tx(
|
||||
writer.context(),
|
||||
fmt::format(Strings::commands_NewLayer(), layerPrefix()));
|
||||
Tx tx(writer,
|
||||
fmt::format(Strings::commands_NewLayer(), layerPrefix()));
|
||||
DocApi api = document->getApi(tx);
|
||||
bool afterBackground = false;
|
||||
|
||||
@ -428,7 +427,7 @@ void NewLayerCommand::onExecute(Context* context)
|
||||
#ifdef ENABLE_UI
|
||||
// Paste new layer from clipboard
|
||||
else if (params().fromClipboard() && layer->isImage()) {
|
||||
context->clipboard()->paste(context, false);
|
||||
context->clipboard()->paste(writer, false);
|
||||
|
||||
if (layer->isReference()) {
|
||||
if (Cel* cel = layer->cel(site.frame())) {
|
||||
|
@ -782,7 +782,7 @@ public:
|
||||
m_context->activeDocument()->sprite() &&
|
||||
m_context->activeDocument()->sprite()->gridBounds() != gridBounds()) {
|
||||
ContextWriter writer(m_context);
|
||||
Tx tx(m_context, Strings::commands_GridSettings(), ModifyDocument);
|
||||
Tx tx(writer, Strings::commands_GridSettings(), ModifyDocument);
|
||||
tx(new cmd::SetGridBounds(writer.sprite(), gridBounds()));
|
||||
tx.commit();
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ void PaletteSizeCommand::onExecute(Context* context)
|
||||
palette.resize(std::clamp(ncolors, 1, std::numeric_limits<int>::max()));
|
||||
|
||||
ContextWriter writer(reader);
|
||||
Tx tx(context, "Palette Size", ModifyDocument);
|
||||
Tx tx(writer, "Palette Size", ModifyDocument);
|
||||
tx(new cmd::SetPalette(writer.sprite(), frame, &palette));
|
||||
tx.commit();
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ void RemoveFrameCommand::onExecute(Context* context)
|
||||
Doc* document(writer.document());
|
||||
Sprite* sprite(writer.sprite());
|
||||
{
|
||||
Tx tx(writer.context(), "Remove Frame");
|
||||
Tx tx(writer, "Remove Frame");
|
||||
DocApi api = document->getApi(tx);
|
||||
const Site* site = writer.site();
|
||||
if (site->inTimeline() &&
|
||||
|
@ -77,7 +77,7 @@ void RemoveFrameTagCommand::onExecute(Context* context)
|
||||
if (!foundTag)
|
||||
return;
|
||||
|
||||
Tx tx(writer.context(), friendlyName());
|
||||
Tx tx(writer, friendlyName());
|
||||
tx(new cmd::RemoveTag(sprite, foundTag));
|
||||
tx.commit();
|
||||
|
||||
|
@ -139,7 +139,7 @@ void RemoveLayerCommand::onExecute(Context* context)
|
||||
Doc* document(writer.document());
|
||||
Sprite* sprite(writer.sprite());
|
||||
{
|
||||
Tx tx(writer.context(), "Remove Layer");
|
||||
Tx tx(writer, "Remove Layer");
|
||||
DocApi api = document->getApi(tx);
|
||||
// We need to remove all the tilesets after the tilemaps are deleted
|
||||
// and in descending tileset index order, otherwise the tileset indexes
|
||||
|
@ -101,7 +101,7 @@ void RemoveSliceCommand::onExecute(Context* context)
|
||||
ContextWriter writer(reader);
|
||||
Doc* document(writer.document());
|
||||
Sprite* sprite(writer.sprite());
|
||||
Tx tx(writer.context(), "Remove Slice");
|
||||
Tx tx(writer, "Remove Slice");
|
||||
|
||||
for (auto slice : slicesToDelete.iterateAs<Slice>()) {
|
||||
ASSERT(slice);
|
||||
|
@ -53,7 +53,7 @@ void ReselectMaskCommand::onExecute(Context* context)
|
||||
ContextWriter writer(context);
|
||||
Doc* document(writer.document());
|
||||
{
|
||||
Tx tx(writer.context(), "Reselect", DoesntModifyDocument);
|
||||
Tx tx(writer, "Reselect", DoesntModifyDocument);
|
||||
tx(new cmd::ReselectMask(document));
|
||||
tx.commit();
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ void SelectTileCommand::onExecute(Context* ctx)
|
||||
}
|
||||
|
||||
// Set the new mask
|
||||
Tx tx(writer.context(),
|
||||
Tx tx(writer,
|
||||
friendlyName(),
|
||||
DoesntModifyDocument);
|
||||
tx(new cmd::SetMask(doc, mask.get()));
|
||||
|
@ -107,14 +107,14 @@ void SetLoopSectionCommand::onExecute(Context* ctx)
|
||||
loopTag = create_loop_tag(begin, end);
|
||||
|
||||
ContextWriter writer(ctx);
|
||||
Tx tx(writer.context(), "Add Loop");
|
||||
Tx tx(writer, "Add Loop");
|
||||
tx(new cmd::AddTag(sprite, loopTag));
|
||||
tx.commit();
|
||||
}
|
||||
else if (loopTag->fromFrame() != begin ||
|
||||
loopTag->toFrame() != end) {
|
||||
ContextWriter writer(ctx);
|
||||
Tx tx(writer.context(), "Set Loop Range");
|
||||
Tx tx(writer, "Set Loop Range");
|
||||
tx(new cmd::SetTagRange(loopTag, begin, end));
|
||||
tx.commit();
|
||||
}
|
||||
@ -126,7 +126,7 @@ void SetLoopSectionCommand::onExecute(Context* ctx)
|
||||
else {
|
||||
if (loopTag) {
|
||||
ContextWriter writer(ctx);
|
||||
Tx tx(writer.context(), "Remove Loop");
|
||||
Tx tx(writer, "Remove Loop");
|
||||
tx(new cmd::RemoveTag(sprite, loopTag));
|
||||
tx.commit();
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ void SetPaletteCommand::onExecute(Context* context)
|
||||
|
||||
ContextWriter writer(context);
|
||||
if (writer.document()) {
|
||||
Tx tx(writer.context(), "Set Palette");
|
||||
Tx tx(writer, "Set Palette");
|
||||
writer.document()->getApi(tx)
|
||||
.setPalette(writer.sprite(), writer.frame(), m_palette);
|
||||
tx.commit();
|
||||
|
@ -91,7 +91,7 @@ void SlicePropertiesCommand::onExecute(Context* context)
|
||||
{
|
||||
const SliceWindow::Mods mods = window.modifiedFields();
|
||||
ContextWriter writer(reader);
|
||||
Tx tx(writer.context(), "Slice Properties");
|
||||
Tx tx(writer, "Slice Properties");
|
||||
|
||||
for (Slice* slice : slices.iterateAs<Slice>()) {
|
||||
// Change name
|
||||
|
@ -96,10 +96,11 @@ public:
|
||||
private:
|
||||
void onDuplicate(const doc::Tileset* tileset)
|
||||
{
|
||||
auto sprite = tileset->sprite();
|
||||
auto tilesetClone = Tileset::MakeCopyCopyingImages(tileset);
|
||||
|
||||
Tx tx(fmt::format(Strings::commands_TilesetDuplicate()));
|
||||
tx(new cmd::AddTileset(tileset->sprite(), tilesetClone));
|
||||
Tx tx(sprite, fmt::format(Strings::commands_TilesetDuplicate()));
|
||||
tx(new cmd::AddTileset(sprite, tilesetClone));
|
||||
tx.commit();
|
||||
|
||||
TilesetDuplicated(tilesetClone);
|
||||
@ -121,8 +122,9 @@ private:
|
||||
return;
|
||||
}
|
||||
|
||||
Tx tx(fmt::format(Strings::commands_TilesetDelete()));
|
||||
tx(new cmd::RemoveTileset(tileset->sprite(), tsi));
|
||||
auto sprite = tileset->sprite();
|
||||
Tx tx(sprite, fmt::format(Strings::commands_TilesetDelete()));
|
||||
tx(new cmd::RemoveTileset(sprite, tsi));
|
||||
tx.commit();
|
||||
|
||||
TilesetDeleted(this);
|
||||
@ -351,7 +353,7 @@ void SpritePropertiesCommand::onExecute(Context* context)
|
||||
|
||||
ContextWriter writer(context);
|
||||
Sprite* sprite(writer.sprite());
|
||||
Tx tx(writer.context(), Strings::sprite_properties_assign_color_profile());
|
||||
Tx tx(writer, Strings::sprite_properties_assign_color_profile());
|
||||
tx(new cmd::AssignColorProfile(
|
||||
sprite, colorSpaces[selectedColorProfile]->gfxColorSpace()));
|
||||
tx.commit();
|
||||
@ -364,7 +366,7 @@ void SpritePropertiesCommand::onExecute(Context* context)
|
||||
|
||||
ContextWriter writer(context);
|
||||
Sprite* sprite(writer.sprite());
|
||||
Tx tx(writer.context(), Strings::sprite_properties_convert_color_profile());
|
||||
Tx tx(writer, Strings::sprite_properties_convert_color_profile());
|
||||
tx(new cmd::ConvertColorProfile(
|
||||
sprite, colorSpaces[selectedColorProfile]->gfxColorSpace()));
|
||||
tx.commit();
|
||||
@ -394,7 +396,7 @@ void SpritePropertiesCommand::onExecute(Context* context)
|
||||
if (index != sprite->transparentColor() ||
|
||||
pixelRatio != sprite->pixelRatio() ||
|
||||
newUserData != sprite->userData()) {
|
||||
Tx tx(writer.context(), Strings::sprite_properties_change_sprite_props());
|
||||
Tx tx(writer, Strings::sprite_properties_change_sprite_props());
|
||||
DocApi api = writer.document()->getApi(tx);
|
||||
|
||||
if (index != sprite->transparentColor())
|
||||
|
@ -47,7 +47,7 @@ void UnlinkCelCommand::onExecute(Context* context)
|
||||
Doc* document(writer.document());
|
||||
bool nonEditableLayers = false;
|
||||
{
|
||||
Tx tx(writer.context(), "Unlink Cel");
|
||||
Tx tx(writer, "Unlink Cel");
|
||||
|
||||
const Site* site = writer.site();
|
||||
if (site->inTimeline() &&
|
||||
|
@ -180,7 +180,7 @@ void ConvertLayerCommand::onExecute(Context* ctx)
|
||||
ContextWriter writer(ctx);
|
||||
Doc* document(writer.document());
|
||||
{
|
||||
Tx tx(ctx, friendlyName());
|
||||
Tx tx(writer, friendlyName());
|
||||
|
||||
switch (params().to()) {
|
||||
|
||||
|
@ -353,7 +353,7 @@ void FilterManagerImpl::initTransaction()
|
||||
{
|
||||
ASSERT(!m_tx);
|
||||
m_writer.reset(new ContextWriter(m_reader));
|
||||
m_tx.reset(new Tx(m_writer->context(),
|
||||
m_tx.reset(new Tx(*m_writer,
|
||||
m_filter->getName(),
|
||||
ModifyDocument));
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ protected:
|
||||
if (!writer.palette())
|
||||
return;
|
||||
|
||||
Tx tx(writer.context(), friendlyName(), ModifyDocument);
|
||||
Tx tx(writer, friendlyName(), ModifyDocument);
|
||||
const int beforeIndex = params().before();
|
||||
int currentEntry = picks.firstPick();
|
||||
|
||||
|
@ -57,7 +57,7 @@ protected:
|
||||
if (picks.picks() == 0)
|
||||
return;
|
||||
|
||||
Tx tx(writer.context(), onGetFriendlyName(), ModifyDocument);
|
||||
Tx tx(writer, onGetFriendlyName(), ModifyDocument);
|
||||
const int beforeIndex = params().before();
|
||||
int currentEntry = picks.firstPick();
|
||||
|
||||
|
@ -52,7 +52,7 @@ TEST_F(BasicDocApiTest, RestackLayerBefore)
|
||||
{
|
||||
EXPECT_EQ(layer1, root->firstLayer());
|
||||
{
|
||||
Tx tx(&ctx, "");
|
||||
Tx tx(sprite, "");
|
||||
// Do nothing
|
||||
doc->getApi(tx).restackLayerBefore(layer1, layer1->parent(), layer1);
|
||||
EXPECT_EQ(layer1, root->firstLayer());
|
||||
@ -63,7 +63,7 @@ TEST_F(BasicDocApiTest, RestackLayerBefore)
|
||||
|
||||
EXPECT_EQ(layer1, root->firstLayer());
|
||||
{
|
||||
Tx tx(&ctx, "");
|
||||
Tx tx(sprite, "");
|
||||
doc->getApi(tx).restackLayerBefore(layer1, layer3->parent(), layer3);
|
||||
EXPECT_EQ(layer2, root->firstLayer());
|
||||
EXPECT_EQ(layer1, root->firstLayer()->getNext());
|
||||
@ -73,7 +73,7 @@ TEST_F(BasicDocApiTest, RestackLayerBefore)
|
||||
|
||||
EXPECT_EQ(layer1, root->firstLayer());
|
||||
{
|
||||
Tx tx(&ctx, "");
|
||||
Tx tx(sprite, "");
|
||||
doc->getApi(tx).restackLayerBefore(layer1, layer1->parent(), nullptr);
|
||||
EXPECT_EQ(layer2, root->firstLayer());
|
||||
EXPECT_EQ(layer3, root->firstLayer()->getNext());
|
||||
@ -86,7 +86,7 @@ TEST_F(BasicDocApiTest, RestackLayerAfter)
|
||||
{
|
||||
EXPECT_EQ(layer1, root->firstLayer());
|
||||
{
|
||||
Tx tx(&ctx, "");
|
||||
Tx tx(sprite, "");
|
||||
// Do nothing
|
||||
doc->getApi(tx).restackLayerAfter(layer1, layer1->parent(), layer1);
|
||||
EXPECT_EQ(layer1, root->firstLayer());
|
||||
@ -97,7 +97,7 @@ TEST_F(BasicDocApiTest, RestackLayerAfter)
|
||||
|
||||
EXPECT_EQ(layer1, root->firstLayer());
|
||||
{
|
||||
Tx tx(&ctx, "");
|
||||
Tx tx(sprite, "");
|
||||
doc->getApi(tx).restackLayerAfter(layer1, layer3->parent(), layer3);
|
||||
EXPECT_EQ(layer2, root->firstLayer());
|
||||
EXPECT_EQ(layer3, root->firstLayer()->getNext());
|
||||
@ -107,7 +107,7 @@ TEST_F(BasicDocApiTest, RestackLayerAfter)
|
||||
|
||||
EXPECT_EQ(layer1, root->firstLayer());
|
||||
{
|
||||
Tx tx(&ctx, "");
|
||||
Tx tx(sprite, "");
|
||||
doc->getApi(tx).restackLayerAfter(layer3, layer3->parent(), nullptr);
|
||||
EXPECT_EQ(layer3, root->firstLayer());
|
||||
EXPECT_EQ(layer1, root->firstLayer()->getNext());
|
||||
@ -132,7 +132,7 @@ TEST_F(BasicDocApiTest, MoveCel)
|
||||
// Create a copy for later comparison.
|
||||
std::unique_ptr<Image> expectedImage(Image::createCopy(image1));
|
||||
|
||||
Tx tx(&ctx, "");
|
||||
Tx tx(sprite, "");
|
||||
doc->getApi(tx).moveCel(
|
||||
layer1, frame_t(0),
|
||||
layer2, frame_t(1));
|
||||
|
@ -333,7 +333,7 @@ static DocRange drop_range_op(
|
||||
const app::Context* context = static_cast<app::Context*>(doc->context());
|
||||
const ContextReader reader(context);
|
||||
ContextWriter writer(reader);
|
||||
Tx tx(writer.context(), undoLabel, ModifyDocument);
|
||||
Tx tx(writer, undoLabel, ModifyDocument);
|
||||
DocApi api = doc->getApi(tx);
|
||||
|
||||
// TODO Try to add the range with just one call to DocApi
|
||||
@ -490,7 +490,7 @@ void reverse_frames(Doc* doc, const DocRange& range)
|
||||
const app::Context* context = static_cast<app::Context*>(doc->context());
|
||||
const ContextReader reader(context);
|
||||
ContextWriter writer(reader);
|
||||
Tx tx(writer.context(), "Reverse Frames");
|
||||
Tx tx(writer, "Reverse Frames");
|
||||
DocApi api = doc->getApi(tx);
|
||||
Sprite* sprite = doc->sprite();
|
||||
LayerList layers;
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "app/commands/commands.h"
|
||||
#include "app/commands/params.h"
|
||||
#include "app/context.h"
|
||||
#include "app/context_access.h"
|
||||
#include "app/doc.h"
|
||||
#include "app/doc_access.h"
|
||||
#include "app/i18n/strings.h"
|
||||
@ -152,8 +153,22 @@ int App_transaction(lua_State* L)
|
||||
}
|
||||
|
||||
if (lua_isfunction(L, index)) {
|
||||
Tx tx(label); // Create a new transaction so it exists in the whole
|
||||
// duration of the argument function call.
|
||||
app::Context* ctx = App::instance()->context();
|
||||
if (!ctx)
|
||||
return luaL_error(L, "no context");
|
||||
|
||||
// Create a new transaction so it exists in the whole duration of
|
||||
// the argument function call.
|
||||
#if 0
|
||||
// TODO To be able to lock the document in the transaction we have
|
||||
// to create a re-entrant RWLock implementation to allow to call
|
||||
// commands (creating sub-ContextWriters) inside the
|
||||
// app.transaction()
|
||||
ContextWriter writer(ctx);
|
||||
Tx tx(writer, label);
|
||||
#else
|
||||
Tx tx(Tx::DontLockDoc, ctx, ctx->activeDocument(), label);
|
||||
#endif
|
||||
|
||||
lua_pushvalue(L, -1);
|
||||
if (lua_pcall(L, 0, LUA_MULTRET, 0) == LUA_OK)
|
||||
|
@ -110,8 +110,8 @@ int Cel_set_frame(lua_State* L)
|
||||
if (cel->frame() == frame)
|
||||
return 0;
|
||||
|
||||
Tx tx;
|
||||
Doc* doc = static_cast<Doc*>(cel->document());
|
||||
Tx tx(doc);
|
||||
DocApi api = doc->getApi(tx);
|
||||
api.moveCel(cel->layer(), cel->frame(),
|
||||
cel->layer(), frame);
|
||||
@ -125,7 +125,7 @@ int Cel_set_image(lua_State* L)
|
||||
auto srcImage = get_image_from_arg(L, 2);
|
||||
ImageRef newImage(Image::createCopy(srcImage));
|
||||
|
||||
Tx tx;
|
||||
Tx tx(cel->sprite());
|
||||
tx(new cmd::ReplaceImage(cel->sprite(),
|
||||
cel->imageRef(),
|
||||
newImage));
|
||||
@ -137,7 +137,7 @@ int Cel_set_position(lua_State* L)
|
||||
{
|
||||
auto cel = get_docobj<Cel>(L, 1);
|
||||
const gfx::Point pos = convert_args_into_point(L, 2);
|
||||
Tx tx;
|
||||
Tx tx(cel->sprite());
|
||||
tx(new cmd::SetCelPosition(cel, pos.x, pos.y));
|
||||
tx.commit();
|
||||
return 0;
|
||||
@ -146,7 +146,7 @@ int Cel_set_position(lua_State* L)
|
||||
int Cel_set_opacity(lua_State* L)
|
||||
{
|
||||
auto cel = get_docobj<Cel>(L, 1);
|
||||
Tx tx;
|
||||
Tx tx(cel->sprite());
|
||||
tx(new cmd::SetCelOpacity(cel, lua_tointeger(L, 2)));
|
||||
tx.commit();
|
||||
return 0;
|
||||
@ -155,7 +155,7 @@ int Cel_set_opacity(lua_State* L)
|
||||
int Cel_set_zIndex(lua_State* L)
|
||||
{
|
||||
auto cel = get_docobj<Cel>(L, 1);
|
||||
Tx tx;
|
||||
Tx tx(cel->sprite());
|
||||
tx(new cmd::SetCelZIndex(cel, lua_tointeger(L, 2)));
|
||||
tx.commit();
|
||||
return 0;
|
||||
|
@ -104,7 +104,7 @@ int Frame_set_duration(lua_State* L)
|
||||
auto obj = get_obj<FrameObj>(L, 1);
|
||||
auto sprite = obj->sprite(L);
|
||||
double duration = lua_tonumber(L, 2) * 1000.0;
|
||||
Tx tx;
|
||||
Tx tx(sprite);
|
||||
tx(new cmd::SetFrameDuration(sprite, obj->frame, int(duration)));
|
||||
tx.commit();
|
||||
return 1;
|
||||
|
@ -311,14 +311,7 @@ int Image_drawImage(lua_State* L)
|
||||
Image* dst = obj->image(L);
|
||||
const Image* src = sprite->image(L);
|
||||
|
||||
// If the destination image is not related to a sprite, we just draw
|
||||
// the source image without undo information.
|
||||
if (obj->cel(L) == nullptr) {
|
||||
doc::blend_image(dst, src,
|
||||
pos.x, pos.y,
|
||||
opacity, blendMode);
|
||||
}
|
||||
else {
|
||||
if (auto cel = obj->cel(L)) {
|
||||
gfx::Rect bounds(0, 0, src->size().w, src->size().h);
|
||||
buf.reset(new doc::ImageBuffer);
|
||||
ImageRef tmp_src(
|
||||
@ -329,12 +322,19 @@ int Image_drawImage(lua_State* L)
|
||||
// TODO Use something similar to doc::algorithm::shrink_bounds2()
|
||||
// but we need something that does the render and compares
|
||||
// the minimal modified area.
|
||||
Tx tx;
|
||||
Tx tx(cel->sprite());
|
||||
tx(new cmd::CopyRegion(
|
||||
dst, tmp_src.get(), gfx::Region(bounds),
|
||||
gfx::Point(pos.x + bounds.x, pos.y + bounds.y)));
|
||||
tx.commit();
|
||||
}
|
||||
// If the destination image is not related to a sprite, we just draw
|
||||
// the source image without undo information.
|
||||
else {
|
||||
doc::blend_image(dst, src,
|
||||
pos.x, pos.y,
|
||||
opacity, blendMode);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -349,13 +349,8 @@ int Image_drawSprite(lua_State* L)
|
||||
ASSERT(dst);
|
||||
ASSERT(sprite);
|
||||
|
||||
// If the destination image is not related to a sprite, we just draw
|
||||
// the source image without undo information.
|
||||
if (obj->cel(L) == nullptr) {
|
||||
render_sprite(dst, sprite, frame, pos.x, pos.y);
|
||||
}
|
||||
else {
|
||||
Tx tx;
|
||||
if (auto cel = obj->cel(L)) {
|
||||
Tx tx(cel->sprite());
|
||||
|
||||
ImageRef tmp(Image::createCopy(dst));
|
||||
render_sprite(tmp.get(), sprite, frame, pos.x, pos.y);
|
||||
@ -369,6 +364,11 @@ int Image_drawSprite(lua_State* L)
|
||||
|
||||
tx.commit();
|
||||
}
|
||||
// If the destination image is not related to a sprite, we just draw
|
||||
// the source image without undo information.
|
||||
else {
|
||||
render_sprite(dst, sprite, frame, pos.x, pos.y);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -571,7 +571,7 @@ int Image_resize(lua_State* L)
|
||||
// If the destination image is not related to a sprite, we just draw
|
||||
// the source image without undo information.
|
||||
if (cel) {
|
||||
Tx tx;
|
||||
Tx tx(cel->sprite());
|
||||
resize_cel_image(tx, cel, scale, method,
|
||||
gfx::PointF(pivot));
|
||||
tx.commit();
|
||||
@ -627,14 +627,14 @@ int Image_flip(lua_State* L)
|
||||
if (lua_isinteger(L, 2))
|
||||
flipType = (doc::algorithm::FlipType)lua_tointeger(L, 2);
|
||||
|
||||
if (obj->cel(L) == nullptr) {
|
||||
doc::algorithm::flip_image(img, img->bounds(), flipType);
|
||||
}
|
||||
else {
|
||||
Tx tx;
|
||||
if (auto cel = obj->cel(L)) {
|
||||
Tx tx(cel->sprite());
|
||||
tx(new cmd::FlipImage(img, img->bounds(), flipType));
|
||||
tx.commit();
|
||||
}
|
||||
else {
|
||||
doc::algorithm::flip_image(img, img->bounds(), flipType);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -250,7 +250,7 @@ int Layer_set_name(lua_State* L)
|
||||
auto layer = get_docobj<Layer>(L, 1);
|
||||
const char* name = lua_tostring(L, 2);
|
||||
if (name) {
|
||||
Tx tx;
|
||||
Tx tx(layer->sprite());
|
||||
tx(new cmd::SetLayerName(layer, name));
|
||||
tx.commit();
|
||||
}
|
||||
@ -262,7 +262,7 @@ int Layer_set_opacity(lua_State* L)
|
||||
auto layer = get_docobj<Layer>(L, 1);
|
||||
const int opacity = lua_tointeger(L, 2);
|
||||
if (layer->isImage()) {
|
||||
Tx tx;
|
||||
Tx tx(layer->sprite());
|
||||
tx(new cmd::SetLayerOpacity(static_cast<LayerImage*>(layer), opacity));
|
||||
tx.commit();
|
||||
}
|
||||
@ -274,7 +274,7 @@ int Layer_set_blendMode(lua_State* L)
|
||||
auto layer = get_docobj<Layer>(L, 1);
|
||||
auto blendMode = app::script::BlendMode(lua_tointeger(L, 2));
|
||||
if (layer->isImage()) {
|
||||
Tx tx;
|
||||
Tx tx(layer->sprite());
|
||||
tx(new cmd::SetLayerBlendMode(static_cast<LayerImage*>(layer),
|
||||
base::convert_to<doc::BlendMode>(blendMode)));
|
||||
tx.commit();
|
||||
@ -313,7 +313,7 @@ int Layer_set_stackIndex(lua_State* L)
|
||||
return 0;
|
||||
|
||||
Doc* doc = static_cast<Doc*>(layer->sprite()->document());
|
||||
Tx tx;
|
||||
Tx tx(doc);
|
||||
DocApi(doc, tx).restackLayerBefore(layer, parent, beforeThis);
|
||||
tx.commit();
|
||||
return 0;
|
||||
@ -381,7 +381,7 @@ int Layer_set_parent(lua_State* L)
|
||||
|
||||
if (parent) {
|
||||
Doc* doc = static_cast<Doc*>(layer->sprite()->document());
|
||||
Tx tx;
|
||||
Tx tx(doc);
|
||||
DocApi(doc, tx).restackLayerAfter(
|
||||
layer, parent, parent->lastLayer());
|
||||
tx.commit();
|
||||
@ -402,7 +402,7 @@ int Layer_set_tileset(lua_State* L)
|
||||
tsi = lua_tointeger(L, 2);
|
||||
|
||||
if (tsi != tilemap->tilesetIndex()) {
|
||||
Tx tx;
|
||||
Tx tx(layer->sprite());
|
||||
tx(new cmd::SetLayerTileset(tilemap, tsi));
|
||||
tx.commit();
|
||||
}
|
||||
|
@ -165,7 +165,7 @@ int Palette_resize(lua_State* L)
|
||||
newPal.resize(ncolors);
|
||||
|
||||
if (*pal != newPal) {
|
||||
Tx tx;
|
||||
Tx tx(sprite);
|
||||
tx(new cmd::SetPalette(sprite, pal->frame(), &newPal));
|
||||
tx.commit();
|
||||
}
|
||||
@ -212,7 +212,7 @@ int Palette_setColor(lua_State* L)
|
||||
Palette newPal(*pal);
|
||||
newPal.setEntry(i, docColor);
|
||||
|
||||
Tx tx;
|
||||
Tx tx(sprite);
|
||||
tx(new cmd::SetPalette(sprite, pal->frame(), &newPal));
|
||||
tx.commit();
|
||||
}
|
||||
|
@ -126,8 +126,8 @@ int Properties_newindex(lua_State* L)
|
||||
|
||||
// TODO add Object::sprite() member function
|
||||
//if (obj->sprite()) {
|
||||
if (App::instance()->context()->activeDocument()) {
|
||||
Tx tx;
|
||||
if (auto doc = App::instance()->context()->activeDocument()) {
|
||||
Tx tx(doc); // TODO propObj might not be member of "doc"
|
||||
if (propObj->ti != doc::notile) {
|
||||
tx(new cmd::SetTileDataProperty(static_cast<doc::Tileset*>(obj),
|
||||
propObj->ti, propObj->extID, field,
|
||||
@ -165,8 +165,8 @@ int Properties_call(lua_State* L)
|
||||
|
||||
// TODO add Object::sprite() member function
|
||||
//if (obj->sprite()) {
|
||||
if (App::instance()->context()->activeDocument()) {
|
||||
Tx tx;
|
||||
if (auto doc = App::instance()->context()->activeDocument()) {
|
||||
Tx tx(doc); // TODO propObj might not be member of "doc"
|
||||
if (propObj->ti != doc::notile) {
|
||||
tx(new cmd::SetTileDataProperties(static_cast<doc::Tileset*>(obj),
|
||||
propObj->ti, extID, std::move(newProperties)));
|
||||
|
@ -117,7 +117,7 @@ int Selection_deselect(lua_State* L)
|
||||
ASSERT(doc);
|
||||
|
||||
if (doc->isMaskVisible()) {
|
||||
Tx tx;
|
||||
Tx tx(doc);
|
||||
tx(new cmd::DeselectMask(doc));
|
||||
tx.commit();
|
||||
}
|
||||
@ -180,7 +180,7 @@ int Selection_op(lua_State* L, OpMask opMask, OpRect opRect)
|
||||
Mask newMask;
|
||||
opMask(newMask, *mask, *otherMask);
|
||||
|
||||
Tx tx;
|
||||
Tx tx(sprite);
|
||||
tx(new cmd::SetMask(doc, &newMask));
|
||||
tx.commit();
|
||||
}
|
||||
@ -198,7 +198,7 @@ int Selection_op(lua_State* L, OpMask opMask, OpRect opRect)
|
||||
Mask newMask;
|
||||
opRect(newMask, *mask, bounds);
|
||||
|
||||
Tx tx;
|
||||
Tx tx(sprite);
|
||||
tx(new cmd::SetMask(doc, &newMask));
|
||||
tx.commit();
|
||||
}
|
||||
@ -223,7 +223,7 @@ int Selection_selectAll(lua_State* L)
|
||||
Mask newMask;
|
||||
newMask.replace(sprite->bounds());
|
||||
|
||||
Tx tx;
|
||||
Tx tx(doc);
|
||||
tx(new cmd::SetMask(doc, &newMask));
|
||||
tx.commit();
|
||||
}
|
||||
@ -290,7 +290,7 @@ int Selection_set_origin(lua_State* L)
|
||||
if (auto sprite = obj->sprite(L)) {
|
||||
Doc* doc = static_cast<Doc*>(sprite->document());
|
||||
if (doc->isMaskVisible()) {
|
||||
Tx tx;
|
||||
Tx tx(doc);
|
||||
doc->getApi(tx).setMaskPosition(pt.x, pt.y);
|
||||
tx.commit();
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ int Slice_set_name(lua_State* L)
|
||||
auto slice = get_docobj<Slice>(L, 1);
|
||||
const char* name = lua_tostring(L, 2);
|
||||
if (name) {
|
||||
Tx tx;
|
||||
Tx tx(slice->sprite());
|
||||
tx(new cmd::SetSliceName(slice, name));
|
||||
tx.commit();
|
||||
}
|
||||
@ -98,7 +98,7 @@ int Slice_set_bounds(lua_State* L)
|
||||
if (const SliceKey* srcKey = slice->getByFrame(0))
|
||||
key = *srcKey;
|
||||
key.setBounds(bounds);
|
||||
Tx tx;
|
||||
Tx tx(slice->sprite());
|
||||
tx(new cmd::SetSliceKey(slice, 0, key));
|
||||
tx.commit();
|
||||
return 0;
|
||||
@ -112,7 +112,7 @@ int Slice_set_center(lua_State* L)
|
||||
if (const SliceKey* srcKey = slice->getByFrame(0))
|
||||
key = *srcKey;
|
||||
key.setCenter(center);
|
||||
Tx tx;
|
||||
Tx tx(slice->sprite());
|
||||
tx(new cmd::SetSliceKey(slice, 0, key));
|
||||
tx.commit();
|
||||
return 0;
|
||||
@ -126,7 +126,7 @@ int Slice_set_pivot(lua_State* L)
|
||||
if (const SliceKey* srcKey = slice->getByFrame(0))
|
||||
key = *srcKey;
|
||||
key.setPivot(pivot);
|
||||
Tx tx;
|
||||
Tx tx(slice->sprite());
|
||||
tx(new cmd::SetSliceKey(slice, 0, key));
|
||||
tx.commit();
|
||||
return 0;
|
||||
|
@ -201,7 +201,7 @@ int Sprite_crop(lua_State* L)
|
||||
}
|
||||
|
||||
if (!bounds.isEmpty()) {
|
||||
Tx tx;
|
||||
Tx tx(doc);
|
||||
DocApi(doc, tx).cropSprite(sprite, bounds);
|
||||
tx.commit();
|
||||
}
|
||||
@ -285,7 +285,7 @@ int Sprite_loadPalette(lua_State* L)
|
||||
Doc* doc = static_cast<Doc*>(sprite->document());
|
||||
std::unique_ptr<doc::Palette> palette(load_palette(absFn.c_str()));
|
||||
if (palette) {
|
||||
Tx tx;
|
||||
Tx tx(doc);
|
||||
// TODO Merge this with the code in LoadPaletteCommand
|
||||
doc->getApi(tx).setPalette(sprite, 0, palette.get());
|
||||
tx.commit();
|
||||
@ -301,7 +301,7 @@ int Sprite_setPalette(lua_State* L)
|
||||
if (sprite && pal) {
|
||||
Doc* doc = static_cast<Doc*>(sprite->document());
|
||||
|
||||
Tx tx;
|
||||
Tx tx(doc);
|
||||
doc->getApi(tx).setPalette(sprite, 0, pal);
|
||||
tx.commit();
|
||||
}
|
||||
@ -312,7 +312,7 @@ int Sprite_assignColorSpace(lua_State* L)
|
||||
{
|
||||
auto sprite = get_docobj<Sprite>(L, 1);
|
||||
auto cs = get_obj<gfx::ColorSpace>(L, 2);
|
||||
Tx tx;
|
||||
Tx tx(sprite);
|
||||
tx(new cmd::AssignColorProfile(
|
||||
sprite, base::make_ref<gfx::ColorSpace>(*cs)));
|
||||
tx.commit();
|
||||
@ -323,7 +323,7 @@ int Sprite_convertColorSpace(lua_State* L)
|
||||
{
|
||||
auto sprite = get_docobj<Sprite>(L, 1);
|
||||
auto cs = get_obj<gfx::ColorSpace>(L, 2);
|
||||
Tx tx;
|
||||
Tx tx(sprite);
|
||||
tx(new cmd::ConvertColorProfile(
|
||||
sprite, base::make_ref<gfx::ColorSpace>(*cs)));
|
||||
tx.commit();
|
||||
@ -338,7 +338,7 @@ int Sprite_flatten(lua_State* L)
|
||||
for (auto layer : sprite->root()->layers())
|
||||
range.selectLayer(layer);
|
||||
|
||||
Tx tx;
|
||||
Tx tx(sprite);
|
||||
tx(new cmd::FlattenLayers(sprite, range.selectedLayers(), true));
|
||||
tx.commit();
|
||||
return 0;
|
||||
@ -349,7 +349,7 @@ int Sprite_newLayer(lua_State* L)
|
||||
auto sprite = get_docobj<Sprite>(L, 1);
|
||||
doc::Layer* newLayer = new doc::LayerImage(sprite);
|
||||
|
||||
Tx tx;
|
||||
Tx tx(sprite);
|
||||
tx(new cmd::AddLayer(sprite->root(), newLayer, sprite->root()->lastLayer()));
|
||||
tx.commit();
|
||||
|
||||
@ -362,7 +362,7 @@ int Sprite_newGroup(lua_State* L)
|
||||
auto sprite = get_docobj<Sprite>(L, 1);
|
||||
doc::Layer* newGroup = new doc::LayerGroup(sprite);
|
||||
|
||||
Tx tx;
|
||||
Tx tx(sprite);
|
||||
tx(new cmd::AddLayer(sprite->root(), newGroup, sprite->root()->lastLayer()));
|
||||
tx.commit();
|
||||
|
||||
@ -388,7 +388,7 @@ int Sprite_deleteLayer(lua_State* L)
|
||||
if (layer) {
|
||||
if (sprite != layer->sprite())
|
||||
return luaL_error(L, "the layer doesn't belong to the sprite");
|
||||
Tx tx;
|
||||
Tx tx(sprite);
|
||||
tx(new cmd::RemoveLayer(layer));
|
||||
tx.commit();
|
||||
return 0;
|
||||
@ -412,7 +412,7 @@ int Sprite_newFrame(lua_State* L)
|
||||
|
||||
Doc* doc = static_cast<Doc*>(sprite->document());
|
||||
|
||||
Tx tx;
|
||||
Tx tx(doc);
|
||||
doc->getApi(tx).addFrame(sprite, copyThis);
|
||||
tx.commit();
|
||||
|
||||
@ -432,7 +432,7 @@ int Sprite_newEmptyFrame(lua_State* L)
|
||||
|
||||
Doc* doc = static_cast<Doc*>(sprite->document());
|
||||
|
||||
Tx tx;
|
||||
Tx tx(doc);
|
||||
DocApi(doc, tx).addEmptyFrame(sprite, frame);
|
||||
tx.commit();
|
||||
|
||||
@ -449,7 +449,7 @@ int Sprite_deleteFrame(lua_State* L)
|
||||
|
||||
Doc* doc = static_cast<Doc*>(sprite->document());
|
||||
|
||||
Tx tx;
|
||||
Tx tx(doc);
|
||||
doc->getApi(tx).removeFrame(sprite, frame);
|
||||
tx.commit();
|
||||
return 0;
|
||||
@ -479,7 +479,7 @@ int Sprite_newCel(lua_State* L)
|
||||
cel = layer->cel(frame);
|
||||
ASSERT(cel);
|
||||
|
||||
Tx tx;
|
||||
Tx tx(doc);
|
||||
DocApi api = doc->getApi(tx);
|
||||
api.clearCel(layer, frame);
|
||||
if (srcImage) {
|
||||
@ -499,7 +499,7 @@ int Sprite_newCel(lua_State* L)
|
||||
cel = new Cel(frame, image);
|
||||
cel->setPosition(pos);
|
||||
|
||||
Tx tx;
|
||||
Tx tx(doc);
|
||||
DocApi api = doc->getApi(tx);
|
||||
if (layer->cel(frame))
|
||||
api.clearCel(layer, frame);
|
||||
@ -526,7 +526,7 @@ int Sprite_deleteCel(lua_State* L)
|
||||
}
|
||||
|
||||
if (cel) {
|
||||
Tx tx;
|
||||
Tx tx(sprite);
|
||||
tx(new cmd::ClearCel(cel));
|
||||
tx.commit();
|
||||
return 0;
|
||||
@ -543,7 +543,7 @@ int Sprite_newTag(lua_State* L)
|
||||
auto to = get_frame_number_from_arg(L, 3);
|
||||
auto tag = new doc::Tag(from, to);
|
||||
|
||||
Tx tx;
|
||||
Tx tx(sprite);
|
||||
tx(new cmd::AddTag(sprite, tag));
|
||||
tx.commit();
|
||||
|
||||
@ -563,7 +563,7 @@ int Sprite_deleteTag(lua_State* L)
|
||||
if (tag) {
|
||||
if (sprite != tag->owner()->sprite())
|
||||
return luaL_error(L, "the tag doesn't belong to the sprite");
|
||||
Tx tx;
|
||||
Tx tx(sprite);
|
||||
tx(new cmd::RemoveTag(sprite, tag));
|
||||
tx.commit();
|
||||
return 0;
|
||||
@ -582,7 +582,7 @@ int Sprite_newSlice(lua_State* L)
|
||||
if (!bounds.isEmpty())
|
||||
slice->insert(0, doc::SliceKey(bounds));
|
||||
|
||||
Tx tx;
|
||||
Tx tx(sprite);
|
||||
tx(new cmd::AddSlice(sprite, slice));
|
||||
tx.commit();
|
||||
|
||||
@ -602,7 +602,7 @@ int Sprite_deleteSlice(lua_State* L)
|
||||
if (slice) {
|
||||
if (sprite != slice->owner()->sprite())
|
||||
return luaL_error(L, "the slice doesn't belong to the sprite");
|
||||
Tx tx;
|
||||
Tx tx(sprite);
|
||||
tx(new cmd::RemoveSlice(sprite, slice));
|
||||
tx.commit();
|
||||
return 0;
|
||||
@ -663,7 +663,7 @@ int Sprite_newTileset(lua_State* L)
|
||||
tileset = new Tileset(sprite, grid, ntiles);
|
||||
}
|
||||
|
||||
Tx tx;
|
||||
Tx tx(sprite);
|
||||
tx(new cmd::AddTileset(sprite, tileset));
|
||||
tx.commit();
|
||||
|
||||
@ -686,7 +686,7 @@ int Sprite_deleteTileset(lua_State* L)
|
||||
if (tileset && tsi >= 0) {
|
||||
if (sprite != tileset->sprite())
|
||||
return luaL_error(L, "the tileset doesn't belong to the sprite");
|
||||
Tx tx;
|
||||
Tx tx(sprite);
|
||||
|
||||
// Set the tileset from all layers that are using it
|
||||
for (auto layer : sprite->allLayers()) {
|
||||
@ -725,7 +725,7 @@ int Sprite_newTile(lua_State* L)
|
||||
return luaL_error(L, "index must be equal to or greater than 1");
|
||||
}
|
||||
ts->insert(ti, ts->makeEmptyTile());
|
||||
Tx tx;
|
||||
Tx tx(sprite);
|
||||
tx(new cmd::AddTile(ts, ti));
|
||||
tx.commit();
|
||||
push_tile(L, ts, ti);
|
||||
@ -749,7 +749,7 @@ int Sprite_deleteTile(lua_State* L)
|
||||
return luaL_error(L, "tile index = 0 cannot be removed");
|
||||
if (ti < 0 || ti >= ts->size())
|
||||
return luaL_error(L, "index out of bounds");
|
||||
Tx tx;
|
||||
Tx tx(sprite);
|
||||
tx(new cmd::RemoveTile(ts, ti));
|
||||
tx.commit();
|
||||
push_tile(L, ts, ti);
|
||||
@ -902,7 +902,7 @@ int Sprite_set_transparentColor(lua_State* L)
|
||||
{
|
||||
auto sprite = get_docobj<Sprite>(L, 1);
|
||||
const int index = lua_tointeger(L, 2);
|
||||
Tx tx;
|
||||
Tx tx(sprite);
|
||||
tx(new cmd::SetTransparentColor(sprite, index));
|
||||
tx.commit();
|
||||
return 0;
|
||||
@ -920,7 +920,7 @@ int Sprite_set_width(lua_State* L)
|
||||
{
|
||||
auto sprite = get_docobj<Sprite>(L, 1);
|
||||
const int width = lua_tointeger(L, 2);
|
||||
Tx tx;
|
||||
Tx tx(sprite);
|
||||
tx(new cmd::SetSpriteSize(sprite, width, sprite->height()));
|
||||
tx.commit();
|
||||
return 0;
|
||||
@ -930,7 +930,7 @@ int Sprite_set_height(lua_State* L)
|
||||
{
|
||||
auto sprite = get_docobj<Sprite>(L, 1);
|
||||
const int height = lua_tointeger(L, 2);
|
||||
Tx tx;
|
||||
Tx tx(sprite);
|
||||
tx(new cmd::SetSpriteSize(sprite, sprite->width(), height));
|
||||
tx.commit();
|
||||
return 0;
|
||||
@ -941,7 +941,7 @@ int Sprite_set_selection(lua_State* L)
|
||||
auto sprite = get_docobj<Sprite>(L, 1);
|
||||
const auto mask = get_mask_from_arg(L, 2);
|
||||
Doc* doc = static_cast<Doc*>(sprite->document());
|
||||
Tx tx;
|
||||
Tx tx(sprite);
|
||||
tx(new cmd::SetMask(doc, mask));
|
||||
tx.commit();
|
||||
return 0;
|
||||
@ -965,7 +965,7 @@ int Sprite_set_gridBounds(lua_State* L)
|
||||
{
|
||||
auto sprite = get_docobj<Sprite>(L, 1);
|
||||
const gfx::Rect bounds = convert_args_into_rect(L, 2);
|
||||
Tx tx;
|
||||
Tx tx(sprite);
|
||||
tx(new cmd::SetGridBounds(sprite, bounds));
|
||||
tx.commit();
|
||||
return 0;
|
||||
@ -982,7 +982,7 @@ int Sprite_set_pixelRatio(lua_State* L)
|
||||
{
|
||||
auto sprite = get_docobj<Sprite>(L, 1);
|
||||
const gfx::Size pixelRatio = convert_args_into_size(L, 2);
|
||||
Tx tx;
|
||||
Tx tx(sprite);
|
||||
tx(new cmd::SetPixelRatio(sprite, pixelRatio));
|
||||
tx.commit();
|
||||
return 0;
|
||||
@ -1006,7 +1006,7 @@ int Sprite_set_tileManagementPlugin(lua_State* L)
|
||||
value = p;
|
||||
|
||||
if (sprite->tileManagementPlugin() != value) {
|
||||
Tx tx;
|
||||
Tx tx(sprite);
|
||||
tx(new cmd::SetSpriteTileManagementPlugin(sprite, value));
|
||||
tx.commit();
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ int Tag_set_fromFrame(lua_State* L)
|
||||
{
|
||||
auto tag = get_docobj<Tag>(L, 1);
|
||||
const auto fromFrame = get_frame_number_from_arg(L, 2);
|
||||
Tx tx;
|
||||
Tx tx(tag->sprite());
|
||||
tx(new cmd::SetTagRange(tag, fromFrame,
|
||||
std::max(fromFrame, tag->toFrame())));
|
||||
tx.commit();
|
||||
@ -107,7 +107,7 @@ int Tag_set_toFrame(lua_State* L)
|
||||
{
|
||||
auto tag = get_docobj<Tag>(L, 1);
|
||||
const auto toFrame = get_frame_number_from_arg(L, 2);
|
||||
Tx tx;
|
||||
Tx tx(tag->sprite());
|
||||
tx(new cmd::SetTagRange(tag,
|
||||
std::min(tag->fromFrame(), toFrame),
|
||||
toFrame));
|
||||
@ -120,7 +120,7 @@ int Tag_set_name(lua_State* L)
|
||||
auto tag = get_docobj<Tag>(L, 1);
|
||||
const char* name = lua_tostring(L, 2);
|
||||
if (name) {
|
||||
Tx tx;
|
||||
Tx tx(tag->sprite());
|
||||
tx(new cmd::SetTagName(tag, name));
|
||||
tx.commit();
|
||||
}
|
||||
@ -131,7 +131,7 @@ int Tag_set_aniDir(lua_State* L)
|
||||
{
|
||||
auto tag = get_docobj<Tag>(L, 1);
|
||||
const int aniDir = lua_tointeger(L, 2);
|
||||
Tx tx;
|
||||
Tx tx(tag->sprite());
|
||||
tx(new cmd::SetTagAniDir(tag, (doc::AniDir)aniDir));
|
||||
tx.commit();
|
||||
return 0;
|
||||
@ -141,7 +141,7 @@ int Tag_set_repeats(lua_State* L)
|
||||
{
|
||||
auto tag = get_docobj<Tag>(L, 1);
|
||||
const int repeat = lua_tointeger(L, 2);
|
||||
Tx tx;
|
||||
Tx tx(tag->sprite());
|
||||
tx(new cmd::SetTagRepeat(tag, repeat));
|
||||
tx.commit();
|
||||
return 0;
|
||||
|
@ -60,7 +60,7 @@ int Tile_set_image(lua_State* L)
|
||||
ImageRef newImage(Image::createCopy(srcImage));
|
||||
|
||||
if (ts && ts->sprite()) {
|
||||
Tx tx;
|
||||
Tx tx(ts->sprite());
|
||||
tx(new cmd::ReplaceImage(ts->sprite(),
|
||||
ts->get(tile->ti),
|
||||
newImage));
|
||||
@ -125,8 +125,8 @@ int Tile_set_data(lua_State* L)
|
||||
doc::UserData ud = ts->getTileData(tile->ti);
|
||||
ud.setText(text);
|
||||
|
||||
if (ts->sprite()) { // TODO use transaction in this sprite
|
||||
Tx tx;
|
||||
if (ts->sprite()) {
|
||||
Tx tx(ts->sprite());
|
||||
tx(new cmd::SetTileData(ts, tile->ti, ud));
|
||||
tx.commit();
|
||||
}
|
||||
@ -148,8 +148,8 @@ int Tile_set_color(lua_State* L)
|
||||
doc::UserData ud = ts->getTileData(tile->ti);
|
||||
ud.setColor(docColor);
|
||||
|
||||
if (ts->sprite()) { // TODO use transaction in this sprite
|
||||
Tx tx;
|
||||
if (ts->sprite()) {
|
||||
Tx tx(ts->sprite());
|
||||
tx(new cmd::SetTileData(ts, tile->ti, ud));
|
||||
tx.commit();
|
||||
}
|
||||
@ -168,7 +168,7 @@ int Tile_set_properties(lua_State* L)
|
||||
|
||||
auto newProperties = get_value_from_lua<doc::UserData::Properties>(L, 2);
|
||||
if (ts->sprite()) {
|
||||
Tx tx;
|
||||
Tx tx(ts->sprite());
|
||||
tx(new cmd::SetTileDataProperties(ts, tile->ti,
|
||||
std::string(),
|
||||
std::move(newProperties)));
|
||||
|
@ -68,7 +68,7 @@ int Tileset_set_name(lua_State* L)
|
||||
{
|
||||
auto tileset = get_docobj<Tileset>(L, 1);
|
||||
if (const char* newName = lua_tostring(L, 2)) {
|
||||
Tx tx;
|
||||
Tx tx(tileset->sprite());
|
||||
tx(new cmd::SetTilesetName(tileset, newName));
|
||||
tx.commit();
|
||||
}
|
||||
@ -93,7 +93,7 @@ int Tileset_set_baseIndex(lua_State* L)
|
||||
{
|
||||
auto tileset = get_docobj<Tileset>(L, 1);
|
||||
int i = lua_tointeger(L, 2);
|
||||
Tx tx;
|
||||
Tx tx(tileset->sprite());
|
||||
tx(new cmd::SetTilesetBaseIndex(tileset, i));
|
||||
tx.commit();
|
||||
return 0;
|
||||
|
@ -63,13 +63,12 @@ int UserData_get_properties(lua_State* L) {
|
||||
template<typename T>
|
||||
int UserData_set_text(lua_State* L) {
|
||||
auto obj = get_docobj<T>(L, 1);
|
||||
auto spr = obj->sprite();
|
||||
const char* text = lua_tostring(L, 2);
|
||||
auto wud = get_WithUserData<T>(obj);
|
||||
UserData ud = wud->userData();
|
||||
ud.setText(text ? std::string(text): std::string());
|
||||
if (spr) {
|
||||
Tx tx;
|
||||
if (auto spr = obj->sprite()) {
|
||||
Tx tx(spr);
|
||||
tx(new cmd::SetUserData(wud, ud, static_cast<Doc*>(spr->document())));
|
||||
tx.commit();
|
||||
}
|
||||
@ -82,13 +81,12 @@ int UserData_set_text(lua_State* L) {
|
||||
template<typename T>
|
||||
int UserData_set_color(lua_State* L) {
|
||||
auto obj = get_docobj<T>(L, 1);
|
||||
auto spr = obj->sprite();
|
||||
doc::color_t docColor = convert_args_into_pixel_color(L, 2, doc::IMAGE_RGB);
|
||||
auto wud = get_WithUserData<T>(obj);
|
||||
UserData ud = wud->userData();
|
||||
ud.setColor(docColor);
|
||||
if (spr) {
|
||||
Tx tx;
|
||||
if (auto spr = obj->sprite()) {
|
||||
Tx tx(spr);
|
||||
tx(new cmd::SetUserData(wud, ud, static_cast<Doc*>(spr->document())));
|
||||
tx.commit();
|
||||
}
|
||||
@ -103,8 +101,8 @@ int UserData_set_properties(lua_State* L) {
|
||||
auto obj = get_docobj<T>(L, 1);
|
||||
auto wud = get_WithUserData<T>(obj);
|
||||
auto newProperties = get_value_from_lua<doc::UserData::Properties>(L, 2);
|
||||
if (obj->sprite()) {
|
||||
Tx tx;
|
||||
if (auto spr = obj->sprite()) {
|
||||
Tx tx(spr);
|
||||
tx(new cmd::SetUserDataProperties(wud,
|
||||
std::string(),
|
||||
std::move(newProperties)));
|
||||
|
@ -17,7 +17,7 @@ SpriteJob::SpriteJob(const ContextReader& reader, const char* jobName)
|
||||
, m_writer(reader, 500)
|
||||
, m_document(m_writer.document())
|
||||
, m_sprite(m_writer.sprite())
|
||||
, m_tx(m_writer.context(), jobName, ModifyDocument)
|
||||
, m_tx(m_writer, jobName, ModifyDocument)
|
||||
{
|
||||
}
|
||||
|
||||
|
60
src/app/tx.h
60
src/app/tx.h
@ -11,8 +11,11 @@
|
||||
|
||||
#include "app/app.h"
|
||||
#include "app/context.h"
|
||||
#include "app/context_access.h"
|
||||
#include "app/doc.h"
|
||||
#include "app/doc_access.h"
|
||||
#include "app/transaction.h"
|
||||
#include "doc/sprite.h"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
@ -22,36 +25,76 @@ namespace app {
|
||||
// transaction in the context.
|
||||
class Tx {
|
||||
public:
|
||||
enum LockAction {
|
||||
DocIsLocked, // The doc is locked to be written
|
||||
LockDoc, // We have to lock the doc in Tx() ctor to write it
|
||||
DontLockDoc, // In case that we are going for a step-by-step
|
||||
// transaction (e.g. ToolLoop or PixelsMovement)
|
||||
};
|
||||
|
||||
static constexpr const char* kDefaultTransactionName = "Transaction";
|
||||
|
||||
Tx(Context* ctx,
|
||||
Tx() = delete;
|
||||
|
||||
Tx(const LockAction lockAction,
|
||||
Context* ctx,
|
||||
Doc* doc,
|
||||
const std::string& label = kDefaultTransactionName,
|
||||
const Modification mod = ModifyDocument)
|
||||
{
|
||||
m_doc = ctx->activeDocument();
|
||||
m_doc = doc;
|
||||
if (!m_doc)
|
||||
throw std::runtime_error("No active document to execute a transaction");
|
||||
throw std::runtime_error("No document to execute a transaction");
|
||||
|
||||
m_transaction = m_doc->transaction();
|
||||
if (m_transaction)
|
||||
if (m_transaction) {
|
||||
m_owner = false;
|
||||
}
|
||||
else {
|
||||
if (lockAction == LockDoc) {
|
||||
if (!m_doc->writeLock(500))
|
||||
throw CannotWriteDocException();
|
||||
m_locked = true;
|
||||
}
|
||||
|
||||
m_transaction = new Transaction(ctx, m_doc, label, mod);
|
||||
m_doc->setTransaction(m_transaction);
|
||||
m_owner = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Use the default App context
|
||||
Tx(const std::string& label = kDefaultTransactionName,
|
||||
public:
|
||||
Tx(Doc* doc,
|
||||
const std::string& label = kDefaultTransactionName,
|
||||
const Modification mod = ModifyDocument)
|
||||
: Tx(App::instance()->context(), label, mod) {
|
||||
: Tx(LockDoc, doc->context(), doc, label, mod)
|
||||
{
|
||||
}
|
||||
|
||||
Tx(doc::Sprite* spr,
|
||||
const std::string& label = kDefaultTransactionName,
|
||||
const Modification mod = ModifyDocument)
|
||||
: Tx(static_cast<Doc*>(spr->document()), label, mod)
|
||||
{
|
||||
}
|
||||
|
||||
// Use active document of the given context
|
||||
Tx(ContextWriter& writer,
|
||||
const std::string& label = kDefaultTransactionName,
|
||||
const Modification mod = ModifyDocument)
|
||||
: Tx(DocIsLocked,
|
||||
writer.context(),
|
||||
writer.document(), label, mod)
|
||||
{
|
||||
}
|
||||
|
||||
~Tx() {
|
||||
if (m_owner) {
|
||||
m_doc->setTransaction(nullptr);
|
||||
delete m_transaction;
|
||||
|
||||
if (m_locked)
|
||||
m_doc->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,7 +127,8 @@ namespace app {
|
||||
private:
|
||||
Doc* m_doc;
|
||||
Transaction* m_transaction;
|
||||
bool m_owner; // Owner of the transaction
|
||||
bool m_locked = false; // The doc was locked here
|
||||
bool m_owner = false; // Owner of the transaction
|
||||
};
|
||||
|
||||
} // namespace app
|
||||
|
@ -892,7 +892,7 @@ void ColorBar::onRemapPalButtonClick()
|
||||
if (sprite) {
|
||||
ASSERT(sprite->pixelFormat() == IMAGE_INDEXED);
|
||||
|
||||
Tx tx(writer.context(), "Remap Colors", ModifyDocument);
|
||||
Tx tx(writer, "Remap Colors", ModifyDocument);
|
||||
bool remapPixels = true;
|
||||
|
||||
std::vector<ImageRef> images;
|
||||
@ -1003,7 +1003,7 @@ void ColorBar::onRemapTilesButtonClick()
|
||||
return;
|
||||
}
|
||||
|
||||
Tx tx(writer.context(), Strings::color_bar_remap_tiles(), ModifyDocument);
|
||||
Tx tx(writer, Strings::color_bar_remap_tiles(), ModifyDocument);
|
||||
if (!existMapToEmpty &&
|
||||
remap.isInvertible(usedTiles)) {
|
||||
tx(new cmd::RemapTilemaps(tileset, remap));
|
||||
@ -1090,7 +1090,7 @@ void ColorBar::setPalette(const doc::Palette* newPalette, const std::string& act
|
||||
frame_t frame = writer.frame();
|
||||
if (sprite &&
|
||||
newPalette->countDiff(sprite->palette(frame), nullptr, nullptr)) {
|
||||
Tx tx(writer.context(), actionText, ModifyDocument);
|
||||
Tx tx(writer, actionText, ModifyDocument);
|
||||
tx(new cmd::SetPalette(sprite, frame, newPalette));
|
||||
tx.commit();
|
||||
}
|
||||
@ -1110,7 +1110,7 @@ void ColorBar::setTransparentIndex(int index)
|
||||
sprite->pixelFormat() == IMAGE_INDEXED &&
|
||||
int(sprite->transparentColor()) != index) {
|
||||
// TODO merge this code with SpritePropertiesCommand
|
||||
Tx tx(writer.context(), "Set Transparent Color");
|
||||
Tx tx(writer, "Set Transparent Color");
|
||||
DocApi api = writer.document()->getApi(tx);
|
||||
api.setSpriteTransparentColor(sprite, index);
|
||||
tx.commit();
|
||||
@ -1209,7 +1209,7 @@ void ColorBar::onTilesViewClearTiles(const doc::PalettePicks& _picks)
|
||||
if (sprite) {
|
||||
auto tileset = m_tilesView.tileset();
|
||||
|
||||
Tx tx(writer.context(), "Clear Tiles", ModifyDocument);
|
||||
Tx tx(writer, "Clear Tiles", ModifyDocument);
|
||||
for (int ti=int(picks.size())-1; ti>=0; --ti) {
|
||||
if (picks[ti])
|
||||
tx(new cmd::RemoveTile(tileset, ti));
|
||||
@ -1240,7 +1240,7 @@ void ColorBar::onTilesViewResize(const int newSize)
|
||||
if (sprite) {
|
||||
auto tileset = m_tilesView.tileset();
|
||||
|
||||
Tx tx(writer.context(), Strings::color_bar_resize_tiles(), ModifyDocument);
|
||||
Tx tx(writer, Strings::color_bar_resize_tiles(), ModifyDocument);
|
||||
if (tileset->size() < newSize) {
|
||||
for (doc::tile_index ti=tileset->size(); ti<newSize; ++ti) {
|
||||
ImageRef img = tileset->makeEmptyTile();
|
||||
@ -1281,7 +1281,7 @@ void ColorBar::onTilesViewDragAndDrop(doc::Tileset* tileset,
|
||||
Context* ctx = UIContext::instance();
|
||||
InlineCommandExecution inlineCmd(ctx);
|
||||
ContextWriter writer(ctx, 500);
|
||||
Tx tx(writer.context(), Strings::color_bar_drag_and_drop_tiles(), ModifyDocument);
|
||||
Tx tx(writer, Strings::color_bar_drag_and_drop_tiles(), ModifyDocument);
|
||||
if (isCopy)
|
||||
copy_tiles_in_tileset(tx, tileset, picks, currentEntry, beforeIndex);
|
||||
else
|
||||
@ -1880,7 +1880,7 @@ void ColorBar::updateCurrentSpritePalette(const char* operationName)
|
||||
cmd.release()->execute(UIContext::instance());
|
||||
}
|
||||
else {
|
||||
Tx tx(writer.context(), operationName, ModifyDocument);
|
||||
Tx tx(writer, operationName, ModifyDocument);
|
||||
// If tx() fails it will delete the cmd anyway, so we can
|
||||
// release the unique pointer here.
|
||||
tx(cmd.release());
|
||||
|
@ -594,7 +594,8 @@ bool DocView::onPaste(Context* ctx)
|
||||
auto clipboard = ctx->clipboard();
|
||||
if (clipboard->format() == ClipboardFormat::Image ||
|
||||
clipboard->format() == ClipboardFormat::Tilemap) {
|
||||
clipboard->paste(ctx, true);
|
||||
ContextWriter writer(ctx);
|
||||
clipboard->paste(writer, true);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
@ -630,7 +631,7 @@ bool DocView::onClear(Context* ctx)
|
||||
|
||||
// TODO This code is similar to clipboard::cut()
|
||||
{
|
||||
Tx tx(writer.context(), "Clear");
|
||||
Tx tx(writer, "Clear");
|
||||
const bool deselectMask =
|
||||
(visibleMask &&
|
||||
!Preferences::instance().selection.keepSelectionAfterClear());
|
||||
|
@ -153,7 +153,7 @@ bool MovingCelState::onMouseUp(Editor* editor, MouseMessage* msg)
|
||||
if (modified) {
|
||||
{
|
||||
ContextWriter writer(m_reader, 1000);
|
||||
Tx tx(writer.context(), "Cel Movement", ModifyDocument);
|
||||
Tx tx(writer, "Cel Movement", ModifyDocument);
|
||||
DocApi api = document->getApi(tx);
|
||||
gfx::Point intOffset = intCelOffset();
|
||||
|
||||
|
@ -82,7 +82,7 @@ EditorState::LeaveAction MovingSelectionState::onLeaveState(Editor* editor, Edit
|
||||
else {
|
||||
{
|
||||
ContextWriter writer(UIContext::instance(), 1000);
|
||||
Tx tx(writer.context(), "Move Selection Edges", DoesntModifyDocument);
|
||||
Tx tx(writer, "Move Selection Edges", DoesntModifyDocument);
|
||||
tx(new cmd::SetMaskPosition(doc, newOrigin));
|
||||
tx.commit();
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ bool MovingSliceState::onMouseUp(Editor* editor, MouseMessage* msg)
|
||||
{
|
||||
{
|
||||
ContextWriter writer(UIContext::instance(), 1000);
|
||||
Tx tx(writer.context(), "Slice Movement", ModifyDocument);
|
||||
Tx tx(writer, "Slice Movement", ModifyDocument);
|
||||
|
||||
for (const auto& item : m_items) {
|
||||
item.slice->insert(m_frame, item.oldKey);
|
||||
|
@ -119,7 +119,8 @@ PixelsMovement::PixelsMovement(
|
||||
: m_reader(context)
|
||||
, m_site(site)
|
||||
, m_document(site.document())
|
||||
, m_tx(context, operationName)
|
||||
, m_tx(Tx::DontLockDoc, context,
|
||||
context->activeDocument(), operationName)
|
||||
, m_isDragging(false)
|
||||
, m_adjustPivot(false)
|
||||
, m_handle(NoHandle)
|
||||
|
@ -477,7 +477,9 @@ public:
|
||||
const bool saveLastPoint)
|
||||
: ToolLoopBase(editor, site, grid, params)
|
||||
, m_context(context)
|
||||
, m_tx(m_context,
|
||||
, m_tx(Tx::DontLockDoc,
|
||||
m_context,
|
||||
m_context->activeDocument(),
|
||||
m_tool->getText().c_str(),
|
||||
((m_ink->isSelection() ||
|
||||
m_ink->isEyedropper() ||
|
||||
|
@ -1387,7 +1387,8 @@ bool Timeline::onProcessMessage(Message* msg)
|
||||
if (tag) {
|
||||
if ((m_state == STATE_RESIZING_TAG_LEFT && tag->fromFrame() != m_resizeTagData.from) ||
|
||||
(m_state == STATE_RESIZING_TAG_RIGHT && tag->toFrame() != m_resizeTagData.to)) {
|
||||
Tx tx(UIContext::instance(), Strings::commands_FrameTagProperties());
|
||||
ContextWriter writer(UIContext::instance());
|
||||
Tx tx(writer, Strings::commands_FrameTagProperties());
|
||||
tx(new cmd::SetTagRange(
|
||||
tag,
|
||||
(m_state == STATE_RESIZING_TAG_LEFT ? m_resizeTagData.from: tag->fromFrame()),
|
||||
@ -4389,7 +4390,9 @@ bool Timeline::onPaste(Context* ctx)
|
||||
m_redrawMarchingAntsOnly = false;
|
||||
invalidate();
|
||||
}
|
||||
clipboard->paste(ctx, true);
|
||||
|
||||
ContextWriter writer(ctx);
|
||||
clipboard->paste(writer, true);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
@ -362,7 +362,7 @@ void Clipboard::cut(ContextWriter& writer)
|
||||
else {
|
||||
// TODO This code is similar to DocView::onClear()
|
||||
{
|
||||
Tx tx(writer.context(), "Cut");
|
||||
Tx tx(writer, "Cut");
|
||||
Site site = writer.context()->activeSite();
|
||||
CelList cels;
|
||||
if (site.range().enabled()) {
|
||||
@ -461,10 +461,10 @@ void Clipboard::copyPalette(const Palette* palette,
|
||||
m_data->picks = picks;
|
||||
}
|
||||
|
||||
void Clipboard::paste(Context* ctx,
|
||||
void Clipboard::paste(ContextWriter& writer,
|
||||
const bool interactive)
|
||||
{
|
||||
Site site = ctx->activeSite();
|
||||
const Site site = *writer.site();
|
||||
Doc* dstDoc = site.document();
|
||||
if (!dstDoc)
|
||||
return;
|
||||
@ -531,7 +531,7 @@ void Clipboard::paste(Context* ctx,
|
||||
if (!dstLayer || !dstLayer->isImage())
|
||||
return;
|
||||
|
||||
Tx tx(ctx, "Paste Image");
|
||||
Tx tx(writer, "Paste Image");
|
||||
DocApi api = dstDoc->getApi(tx);
|
||||
Cel* dstCel = api.addCel(
|
||||
static_cast<LayerImage*>(dstLayer), site.frame(),
|
||||
@ -611,7 +611,7 @@ void Clipboard::paste(Context* ctx,
|
||||
break;
|
||||
}
|
||||
|
||||
Tx tx(ctx, "Paste Cels");
|
||||
Tx tx(writer, "Paste Cels");
|
||||
DocApi api = dstDoc->getApi(tx);
|
||||
|
||||
// Add extra frames if needed
|
||||
@ -671,7 +671,7 @@ void Clipboard::paste(Context* ctx,
|
||||
break;
|
||||
}
|
||||
|
||||
Tx tx(ctx, "Paste Frames");
|
||||
Tx tx(writer, "Paste Frames");
|
||||
DocApi api = dstDoc->getApi(tx);
|
||||
|
||||
auto srcLayers = srcSpr->allBrowsableLayers();
|
||||
@ -714,7 +714,7 @@ void Clipboard::paste(Context* ctx,
|
||||
if (srcDoc->colorMode() != dstDoc->colorMode())
|
||||
throw std::runtime_error("You cannot copy layers of document with different color modes");
|
||||
|
||||
Tx tx(ctx, "Paste Layers");
|
||||
Tx tx(writer, "Paste Layers");
|
||||
DocApi api = dstDoc->getApi(tx);
|
||||
|
||||
// Remove children if their parent is selected so we only
|
||||
|
@ -74,7 +74,8 @@ namespace app {
|
||||
const doc::Tileset* tileset);
|
||||
void copyPalette(const doc::Palette* palette,
|
||||
const doc::PalettePicks& picks);
|
||||
void paste(Context* ctx, const bool interactive);
|
||||
void paste(ContextWriter& writer,
|
||||
const bool interactive);
|
||||
|
||||
doc::ImageRef getImage(doc::Palette* palette);
|
||||
|
||||
|
@ -121,7 +121,7 @@ void select_layer_boundaries(Layer* layer,
|
||||
}
|
||||
}
|
||||
|
||||
Tx tx(writer.context(), "Select Layer Boundaries", DoesntModifyDocument);
|
||||
Tx tx(writer, "Select Layer Boundaries", DoesntModifyDocument);
|
||||
tx(new cmd::SetMask(doc, &newMask));
|
||||
tx.commit();
|
||||
|
||||
|
@ -105,7 +105,7 @@ namespace doc {
|
||||
void setColorSpace(const gfx::ColorSpaceRef& colorSpace);
|
||||
|
||||
// This method is only required/used for the template functions app::script::UserData_set_text/color.
|
||||
const Sprite* sprite() const { return this; }
|
||||
Sprite* sprite() const { return const_cast<Sprite*>(this); }
|
||||
|
||||
// Returns true if the sprite has a background layer and it's visible
|
||||
bool isOpaque() const;
|
||||
|
Loading…
Reference in New Issue
Block a user