mirror of
https://github.com/aseprite/aseprite.git
synced 2025-02-20 18:40:57 +00:00
Implement issue #265 - command/keyboard shortcut for "last export" operation
- Add doc::ExportData with information about the last export operation. - Add RepeatLastExport command. - Add SaveFileBaseCommand as base Command class, to accept "filename" param. - Add parameters to ExportSpriteSheet so we can call it without UI from "repeat last export".
This commit is contained in:
parent
395be62b03
commit
b16bf981d0
@ -14,6 +14,7 @@
|
|||||||
<key command="SaveFileCopyAs" shortcut="Ctrl+Shift+C" />
|
<key command="SaveFileCopyAs" shortcut="Ctrl+Shift+C" />
|
||||||
<key command="CloseFile" shortcut="Ctrl+W" />
|
<key command="CloseFile" shortcut="Ctrl+W" />
|
||||||
<key command="CloseAllFiles" shortcut="Ctrl+Shift+W" />
|
<key command="CloseAllFiles" shortcut="Ctrl+Shift+W" />
|
||||||
|
<key command="RepeatLastExport" shortcut="Ctrl+Shift+X" />
|
||||||
<key command="AdvancedMode" shortcut="F11" />
|
<key command="AdvancedMode" shortcut="F11" />
|
||||||
<key command="DeveloperConsole" shortcut="F12" />
|
<key command="DeveloperConsole" shortcut="F12" />
|
||||||
<key command="Exit" shortcut="Alt+F4" />
|
<key command="Exit" shortcut="Alt+F4" />
|
||||||
@ -229,6 +230,7 @@
|
|||||||
<separator />
|
<separator />
|
||||||
<item command="ImportSpriteSheet" text="&Import Sprite Sheet" />
|
<item command="ImportSpriteSheet" text="&Import Sprite Sheet" />
|
||||||
<item command="ExportSpriteSheet" text="&Export Sprite Sheet" />
|
<item command="ExportSpriteSheet" text="&Export Sprite Sheet" />
|
||||||
|
<item command="RepeatLastExport" text="Repeat &Last Export" />
|
||||||
<separator />
|
<separator />
|
||||||
<item command="Exit" text="E&xit" />
|
<item command="Exit" text="E&xit" />
|
||||||
</menu>
|
</menu>
|
||||||
|
@ -68,6 +68,7 @@ add_library(app-lib
|
|||||||
commands/cmd_remove_cel.cpp
|
commands/cmd_remove_cel.cpp
|
||||||
commands/cmd_remove_frame.cpp
|
commands/cmd_remove_frame.cpp
|
||||||
commands/cmd_remove_layer.cpp
|
commands/cmd_remove_layer.cpp
|
||||||
|
commands/cmd_repeat_last_export.cpp
|
||||||
commands/cmd_reselect_mask.cpp
|
commands/cmd_reselect_mask.cpp
|
||||||
commands/cmd_rotate_canvas.cpp
|
commands/cmd_rotate_canvas.cpp
|
||||||
commands/cmd_save_file.cpp
|
commands/cmd_save_file.cpp
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Aseprite
|
/* Aseprite
|
||||||
* Copyright (C) 2001-2013 David Capello
|
* Copyright (C) 2001-2014 David Capello
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -20,8 +20,12 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "app/commands/cmd_export_sprite_sheet.h"
|
||||||
|
|
||||||
|
#include "app/commands/cmd_save_file.h"
|
||||||
#include "app/commands/command.h"
|
#include "app/commands/command.h"
|
||||||
#include "app/commands/commands.h"
|
#include "app/commands/commands.h"
|
||||||
|
#include "app/commands/params.h"
|
||||||
#include "app/context.h"
|
#include "app/context.h"
|
||||||
#include "app/context_access.h"
|
#include "app/context_access.h"
|
||||||
#include "app/document.h"
|
#include "app/document.h"
|
||||||
@ -50,20 +54,19 @@ namespace app {
|
|||||||
using namespace ui;
|
using namespace ui;
|
||||||
|
|
||||||
class ExportSpriteSheetWindow : public Window {
|
class ExportSpriteSheetWindow : public Window {
|
||||||
enum SpriteSheetType { HorizontalStrip, VerticalStrip, Matrix };
|
|
||||||
enum ExportAction { SaveCopyAs, SaveAs, Save, DoNotSave };
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
typedef ExportSpriteSheetCommand::SpriteSheetType SpriteSheetType;
|
||||||
|
typedef ExportSpriteSheetCommand::ExportAction ExportAction;
|
||||||
|
|
||||||
ExportSpriteSheetWindow(Context* context)
|
ExportSpriteSheetWindow(Context* context)
|
||||||
: Window(WithTitleBar, "Export Sprite Sheet")
|
: Window(WithTitleBar, "Export Sprite Sheet")
|
||||||
, m_context(context)
|
|
||||||
, m_document(context->getActiveDocument())
|
|
||||||
, m_grid(4, false)
|
, m_grid(4, false)
|
||||||
, m_columnsLabel("Columns:")
|
, m_columnsLabel("Columns:")
|
||||||
, m_columns(4, "4")
|
, m_columns(4, "4")
|
||||||
, m_exportActionLabel("Export Action:")
|
, m_exportActionLabel("Export Action:")
|
||||||
, m_export("Export")
|
, m_export("&Export")
|
||||||
, m_cancel("Cancel")
|
, m_cancel("&Cancel")
|
||||||
|
, m_ok(false)
|
||||||
{
|
{
|
||||||
m_sheetType.addItem("Horizontal Strip");
|
m_sheetType.addItem("Horizontal Strip");
|
||||||
m_sheetType.addItem("Vertical Strip");
|
m_sheetType.addItem("Vertical Strip");
|
||||||
@ -100,8 +103,20 @@ public:
|
|||||||
onSheetTypeChange();
|
onSheetTypeChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
~ExportSpriteSheetWindow()
|
bool ok() const {
|
||||||
{
|
return m_ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
SpriteSheetType spriteSheetType() const {
|
||||||
|
return (SpriteSheetType)m_sheetType.getSelectedItemIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
ExportAction exportAction() const {
|
||||||
|
return (ExportAction)m_exportAction.getSelectedItemIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
int columns() const {
|
||||||
|
return m_columns.getTextInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -110,7 +125,7 @@ protected:
|
|||||||
{
|
{
|
||||||
bool state = false;
|
bool state = false;
|
||||||
switch (m_sheetType.getSelectedItemIndex()) {
|
switch (m_sheetType.getSelectedItemIndex()) {
|
||||||
case Matrix:
|
case ExportSpriteSheetCommand::Matrix:
|
||||||
state = true;
|
state = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -125,170 +140,7 @@ protected:
|
|||||||
|
|
||||||
void onExport()
|
void onExport()
|
||||||
{
|
{
|
||||||
Sprite* sprite = m_document->getSprite();
|
m_ok = true;
|
||||||
FrameNumber nframes = sprite->getTotalFrames();
|
|
||||||
int columns;
|
|
||||||
|
|
||||||
switch (m_sheetType.getSelectedItemIndex()) {
|
|
||||||
case HorizontalStrip:
|
|
||||||
columns = nframes;
|
|
||||||
break;
|
|
||||||
case VerticalStrip:
|
|
||||||
columns = 1;
|
|
||||||
break;
|
|
||||||
case Matrix:
|
|
||||||
columns = m_columns.getTextInt();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
columns = MID(1, columns, nframes);
|
|
||||||
|
|
||||||
int sheet_w = sprite->getWidth()*columns;
|
|
||||||
int sheet_h = sprite->getHeight()*((nframes/columns)+((nframes%columns)>0?1:0));
|
|
||||||
base::UniquePtr<Image> resultImage(Image::create(sprite->getPixelFormat(), sheet_w, sheet_h));
|
|
||||||
base::UniquePtr<Image> tempImage(Image::create(sprite->getPixelFormat(), sprite->getWidth(), sprite->getHeight()));
|
|
||||||
raster::clear_image(resultImage, 0);
|
|
||||||
|
|
||||||
int column = 0, row = 0;
|
|
||||||
for (FrameNumber frame(0); frame<nframes; ++frame) {
|
|
||||||
// TODO "tempImage" could not be necessary if we could specify
|
|
||||||
// destination clipping bounds in Sprite::render() function.
|
|
||||||
tempImage->clear(0);
|
|
||||||
sprite->render(tempImage, 0, 0, frame);
|
|
||||||
resultImage->copy(tempImage, column*sprite->getWidth(), row*sprite->getHeight());
|
|
||||||
|
|
||||||
if (++column >= columns) {
|
|
||||||
column = 0;
|
|
||||||
++row;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store the frame in the current editor so we can restore it
|
|
||||||
// after change and restore the setTotalFrames() number.
|
|
||||||
FrameNumber oldSelectedFrame = (current_editor ? current_editor->getFrame():
|
|
||||||
FrameNumber(0));
|
|
||||||
|
|
||||||
{
|
|
||||||
// The following steps modify the sprite, so we wrap all
|
|
||||||
// operations in a undo-transaction.
|
|
||||||
ContextWriter writer(m_context);
|
|
||||||
UndoTransaction undoTransaction(writer.context(), "Export Sprite Sheet", undo::ModifyDocument);
|
|
||||||
DocumentApi api = m_document->getApi();
|
|
||||||
|
|
||||||
// Add the layer in the sprite.
|
|
||||||
LayerImage* resultLayer = api.newLayer(sprite);
|
|
||||||
|
|
||||||
// Add the image into the sprite's stock
|
|
||||||
int indexInStock = api.addImageInStock(sprite, resultImage);
|
|
||||||
resultImage.release();
|
|
||||||
|
|
||||||
// Create the cel.
|
|
||||||
base::UniquePtr<Cel> resultCel(new Cel(FrameNumber(0), indexInStock));
|
|
||||||
|
|
||||||
// Add the cel in the layer.
|
|
||||||
api.addCel(resultLayer, resultCel);
|
|
||||||
resultCel.release();
|
|
||||||
|
|
||||||
// Copy the list of layers (because we will modify it in the iteration).
|
|
||||||
LayerList layers = sprite->getFolder()->getLayersList();
|
|
||||||
|
|
||||||
// Remove all other layers
|
|
||||||
for (LayerIterator it=layers.begin(), end=layers.end(); it!=end; ++it) {
|
|
||||||
if (*it != resultLayer)
|
|
||||||
api.removeLayer(*it);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Change the number of frames (just one, the sprite sheet). As
|
|
||||||
// we are using the observable API, all DocumentView will change
|
|
||||||
// its current frame to frame 1. We'll try to restore the
|
|
||||||
// selected frame for the current_editor later.
|
|
||||||
api.setTotalFrames(sprite, FrameNumber(1));
|
|
||||||
|
|
||||||
// Set the size of the sprite to the tile size.
|
|
||||||
api.setSpriteSize(sprite, sheet_w, sheet_h);
|
|
||||||
|
|
||||||
undoTransaction.commit();
|
|
||||||
|
|
||||||
// Draw the document with the new dimensions in the screen.
|
|
||||||
update_screen_for_document(m_document);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This flag indicates if we've to undo the last action (so we
|
|
||||||
// back to the original sprite dimensions).
|
|
||||||
bool undo = false;
|
|
||||||
|
|
||||||
// Do the "Export Action"
|
|
||||||
switch (m_exportAction.getSelectedItemIndex()) {
|
|
||||||
|
|
||||||
case SaveCopyAs:
|
|
||||||
{
|
|
||||||
Command* command = CommandsModule::instance()
|
|
||||||
->getCommandByName(CommandId::SaveFileCopyAs);
|
|
||||||
|
|
||||||
m_context->executeCommand(command);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Always go back, as we are using "Save Copy As", so the user
|
|
||||||
// wants to continue editing the original sprite.
|
|
||||||
undo = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SaveAs:
|
|
||||||
{
|
|
||||||
Command* command = CommandsModule::instance()
|
|
||||||
->getCommandByName(CommandId::SaveFileAs);
|
|
||||||
|
|
||||||
m_context->executeCommand(command);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the command was cancelled, we go back to the original
|
|
||||||
// state, if the sprite sheet was saved then we don't undo
|
|
||||||
// because the user wants to edit the sprite sheet.
|
|
||||||
undo = (m_document->isModified());
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Save:
|
|
||||||
{
|
|
||||||
Command* command = CommandsModule::instance()
|
|
||||||
->getCommandByName(CommandId::SaveFile);
|
|
||||||
|
|
||||||
m_context->executeCommand(command);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Same case as "Save As"
|
|
||||||
undo = (m_document->isModified());
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DoNotSave:
|
|
||||||
// Do not undo as the user wants to edit the sprite sheet
|
|
||||||
// before to save the file.
|
|
||||||
undo = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Undo the sprite sheet conversion
|
|
||||||
if (undo) {
|
|
||||||
if (m_document->getUndo()->canUndo()) {
|
|
||||||
m_document->getUndo()->doUndo();
|
|
||||||
|
|
||||||
// We've to restore the previously selected frame. As we've
|
|
||||||
// called setTotalFrames(), all document observers
|
|
||||||
// (current_editor included) have changed its current frame to
|
|
||||||
// the first one (to a visible/editable frame). The "undo"
|
|
||||||
// action doesn't restore the previously selected frame in
|
|
||||||
// observers, so at least we can restore the current_editor's
|
|
||||||
// frame.
|
|
||||||
if (current_editor)
|
|
||||||
current_editor->setFrame(oldSelectedFrame);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_document->generateMaskBoundaries();
|
|
||||||
m_document->destroyExtraCel(); // Regenerate extras
|
|
||||||
|
|
||||||
// Redraw the sprite.
|
|
||||||
update_screen_for_document(m_document);
|
|
||||||
}
|
|
||||||
|
|
||||||
closeWindow(NULL);
|
closeWindow(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -298,8 +150,6 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Context* m_context;
|
|
||||||
Document* m_document;
|
|
||||||
Grid m_grid;
|
Grid m_grid;
|
||||||
ComboBox m_sheetType;
|
ComboBox m_sheetType;
|
||||||
Label m_columnsLabel;
|
Label m_columnsLabel;
|
||||||
@ -308,22 +158,14 @@ private:
|
|||||||
ComboBox m_exportAction;
|
ComboBox m_exportAction;
|
||||||
Button m_export;
|
Button m_export;
|
||||||
Button m_cancel;
|
Button m_cancel;
|
||||||
};
|
bool m_ok;
|
||||||
|
|
||||||
class ExportSpriteSheetCommand : public Command {
|
|
||||||
public:
|
|
||||||
ExportSpriteSheetCommand();
|
|
||||||
Command* clone() { return new ExportSpriteSheetCommand(*this); }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual bool onEnabled(Context* context) OVERRIDE;
|
|
||||||
virtual void onExecute(Context* context) OVERRIDE;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ExportSpriteSheetCommand::ExportSpriteSheetCommand()
|
ExportSpriteSheetCommand::ExportSpriteSheetCommand()
|
||||||
: Command("ExportSpriteSheet",
|
: Command("ExportSpriteSheet",
|
||||||
"Export Sprite Sheet",
|
"Export Sprite Sheet",
|
||||||
CmdRecordableFlag)
|
CmdRecordableFlag)
|
||||||
|
, m_useUI(true)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -334,8 +176,203 @@ bool ExportSpriteSheetCommand::onEnabled(Context* context)
|
|||||||
|
|
||||||
void ExportSpriteSheetCommand::onExecute(Context* context)
|
void ExportSpriteSheetCommand::onExecute(Context* context)
|
||||||
{
|
{
|
||||||
base::UniquePtr<Window> window(new ExportSpriteSheetWindow(context));
|
if (m_useUI) {
|
||||||
window->openWindowInForeground();
|
base::UniquePtr<ExportSpriteSheetWindow> window(new ExportSpriteSheetWindow(context));
|
||||||
|
window->openWindowInForeground();
|
||||||
|
|
||||||
|
if (!window->ok())
|
||||||
|
return;
|
||||||
|
|
||||||
|
setType(window->spriteSheetType());
|
||||||
|
setAction(window->exportAction());
|
||||||
|
setColumns(window->columns());
|
||||||
|
}
|
||||||
|
|
||||||
|
Document* document(context->getActiveDocument());
|
||||||
|
Sprite* sprite = document->getSprite();
|
||||||
|
FrameNumber nframes = sprite->getTotalFrames();
|
||||||
|
int columns;
|
||||||
|
|
||||||
|
switch (m_type) {
|
||||||
|
case HorizontalStrip:
|
||||||
|
columns = nframes;
|
||||||
|
break;
|
||||||
|
case VerticalStrip:
|
||||||
|
columns = 1;
|
||||||
|
break;
|
||||||
|
case Matrix:
|
||||||
|
columns = m_columns;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
columns = MID(1, columns, nframes);
|
||||||
|
|
||||||
|
int sheet_w = sprite->getWidth()*columns;
|
||||||
|
int sheet_h = sprite->getHeight()*((nframes/columns)+((nframes%columns)>0?1:0));
|
||||||
|
base::UniquePtr<Image> resultImage(Image::create(sprite->getPixelFormat(), sheet_w, sheet_h));
|
||||||
|
base::UniquePtr<Image> tempImage(Image::create(sprite->getPixelFormat(), sprite->getWidth(), sprite->getHeight()));
|
||||||
|
raster::clear_image(resultImage, 0);
|
||||||
|
|
||||||
|
int column = 0, row = 0;
|
||||||
|
for (FrameNumber frame(0); frame<nframes; ++frame) {
|
||||||
|
// TODO "tempImage" could not be necessary if we could specify
|
||||||
|
// destination clipping bounds in Sprite::render() function.
|
||||||
|
tempImage->clear(0);
|
||||||
|
sprite->render(tempImage, 0, 0, frame);
|
||||||
|
resultImage->copy(tempImage, column*sprite->getWidth(), row*sprite->getHeight());
|
||||||
|
|
||||||
|
if (++column >= columns) {
|
||||||
|
column = 0;
|
||||||
|
++row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store the frame in the current editor so we can restore it
|
||||||
|
// after change and restore the setTotalFrames() number.
|
||||||
|
FrameNumber oldSelectedFrame = (current_editor ? current_editor->getFrame():
|
||||||
|
FrameNumber(0));
|
||||||
|
|
||||||
|
{
|
||||||
|
// The following steps modify the sprite, so we wrap all
|
||||||
|
// operations in a undo-transaction.
|
||||||
|
ContextWriter writer(context);
|
||||||
|
UndoTransaction undoTransaction(writer.context(), "Export Sprite Sheet", undo::ModifyDocument);
|
||||||
|
DocumentApi api = document->getApi();
|
||||||
|
|
||||||
|
// Add the layer in the sprite.
|
||||||
|
LayerImage* resultLayer = api.newLayer(sprite);
|
||||||
|
|
||||||
|
// Add the image into the sprite's stock
|
||||||
|
int indexInStock = api.addImageInStock(sprite, resultImage);
|
||||||
|
resultImage.release();
|
||||||
|
|
||||||
|
// Create the cel.
|
||||||
|
base::UniquePtr<Cel> resultCel(new Cel(FrameNumber(0), indexInStock));
|
||||||
|
|
||||||
|
// Add the cel in the layer.
|
||||||
|
api.addCel(resultLayer, resultCel);
|
||||||
|
resultCel.release();
|
||||||
|
|
||||||
|
// Copy the list of layers (because we will modify it in the iteration).
|
||||||
|
LayerList layers = sprite->getFolder()->getLayersList();
|
||||||
|
|
||||||
|
// Remove all other layers
|
||||||
|
for (LayerIterator it=layers.begin(), end=layers.end(); it!=end; ++it) {
|
||||||
|
if (*it != resultLayer)
|
||||||
|
api.removeLayer(*it);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change the number of frames (just one, the sprite sheet). As
|
||||||
|
// we are using the observable API, all DocumentView will change
|
||||||
|
// its current frame to frame 1. We'll try to restore the
|
||||||
|
// selected frame for the current_editor later.
|
||||||
|
api.setTotalFrames(sprite, FrameNumber(1));
|
||||||
|
|
||||||
|
// Set the size of the sprite to the tile size.
|
||||||
|
api.setSpriteSize(sprite, sheet_w, sheet_h);
|
||||||
|
|
||||||
|
undoTransaction.commit();
|
||||||
|
|
||||||
|
// Draw the document with the new dimensions in the screen.
|
||||||
|
update_screen_for_document(document);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This flag indicates if we've to undo the last action (so we
|
||||||
|
// back to the original sprite dimensions).
|
||||||
|
bool undo = false;
|
||||||
|
|
||||||
|
Params params;
|
||||||
|
if (!m_filename.empty())
|
||||||
|
params.set("filename", m_filename.c_str());
|
||||||
|
|
||||||
|
SaveFileBaseCommand* command = NULL;
|
||||||
|
|
||||||
|
// Do the "Export Action"
|
||||||
|
switch (m_action) {
|
||||||
|
|
||||||
|
case SaveCopyAs:
|
||||||
|
command = static_cast<SaveFileBaseCommand*>(CommandsModule::instance()
|
||||||
|
->getCommandByName(CommandId::SaveFileCopyAs));
|
||||||
|
|
||||||
|
context->executeCommand(command, ¶ms);
|
||||||
|
|
||||||
|
// Always go back, as we are using "Save Copy As", so the user
|
||||||
|
// wants to continue editing the original sprite.
|
||||||
|
undo = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SaveAs:
|
||||||
|
command = static_cast<SaveFileBaseCommand*>(CommandsModule::instance()
|
||||||
|
->getCommandByName(CommandId::SaveFileAs));
|
||||||
|
|
||||||
|
context->executeCommand(command, ¶ms);
|
||||||
|
|
||||||
|
// If the command was cancelled, we go back to the original
|
||||||
|
// state, if the sprite sheet was saved then we don't undo
|
||||||
|
// because the user wants to edit the sprite sheet.
|
||||||
|
undo = (document->isModified());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Save:
|
||||||
|
command = static_cast<SaveFileBaseCommand*>(CommandsModule::instance()
|
||||||
|
->getCommandByName(CommandId::SaveFile));
|
||||||
|
|
||||||
|
context->executeCommand(command, ¶ms);
|
||||||
|
|
||||||
|
// Same case as "Save As"
|
||||||
|
undo = (document->isModified());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DoNotSave:
|
||||||
|
// Do not undo as the user wants to edit the sprite sheet
|
||||||
|
// before to save the file.
|
||||||
|
undo = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set export data
|
||||||
|
if (command != NULL) {
|
||||||
|
doc::ExportData::Type type;
|
||||||
|
switch (m_type) {
|
||||||
|
case ExportSpriteSheetCommand::HorizontalStrip:
|
||||||
|
type = doc::ExportData::HorizontalStrip;
|
||||||
|
break;
|
||||||
|
case ExportSpriteSheetCommand::VerticalStrip:
|
||||||
|
type = doc::ExportData::VerticalStrip;
|
||||||
|
break;
|
||||||
|
case ExportSpriteSheetCommand::Matrix:
|
||||||
|
type = doc::ExportData::Matrix;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
doc::ExportDataPtr data(new doc::ExportData);
|
||||||
|
data->setType(type);
|
||||||
|
data->setColumns(columns);
|
||||||
|
data->setFilename(command->selectedFilename());
|
||||||
|
document->setExportData(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Undo the sprite sheet conversion
|
||||||
|
if (undo) {
|
||||||
|
if (document->getUndo()->canUndo()) {
|
||||||
|
document->getUndo()->doUndo();
|
||||||
|
|
||||||
|
// We've to restore the previously selected frame. As we've
|
||||||
|
// called setTotalFrames(), all document observers
|
||||||
|
// (current_editor included) have changed its current frame to
|
||||||
|
// the first one (to a visible/editable frame). The "undo"
|
||||||
|
// action doesn't restore the previously selected frame in
|
||||||
|
// observers, so at least we can restore the current_editor's
|
||||||
|
// frame.
|
||||||
|
if (current_editor)
|
||||||
|
current_editor->setFrame(oldSelectedFrame);
|
||||||
|
}
|
||||||
|
|
||||||
|
document->generateMaskBoundaries();
|
||||||
|
document->destroyExtraCel(); // Regenerate extras
|
||||||
|
|
||||||
|
// Redraw the sprite.
|
||||||
|
update_screen_for_document(document);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Command* CommandFactory::createExportSpriteSheetCommand()
|
Command* CommandFactory::createExportSpriteSheetCommand()
|
||||||
|
60
src/app/commands/cmd_export_sprite_sheet.h
Normal file
60
src/app/commands/cmd_export_sprite_sheet.h
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/* Aseprite
|
||||||
|
* Copyright (C) 2001-2014 David Capello
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef APP_COMMANDS_CMD_EXPORT_SPRITE_SHEET_H_INCLUDED
|
||||||
|
#define APP_COMMANDS_CMD_EXPORT_SPRITE_SHEET_H_INCLUDED
|
||||||
|
|
||||||
|
#include "app/commands/command.h"
|
||||||
|
#include "base/compiler_specific.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace app {
|
||||||
|
|
||||||
|
class ExportSpriteSheetCommand : public Command {
|
||||||
|
public:
|
||||||
|
enum SpriteSheetType { HorizontalStrip, VerticalStrip, Matrix };
|
||||||
|
enum ExportAction { SaveCopyAs, SaveAs, Save, DoNotSave };
|
||||||
|
|
||||||
|
ExportSpriteSheetCommand();
|
||||||
|
Command* clone() const OVERRIDE { return new ExportSpriteSheetCommand(*this); }
|
||||||
|
|
||||||
|
SpriteSheetType type() const { return m_type; }
|
||||||
|
ExportAction action() const { return m_action; }
|
||||||
|
|
||||||
|
void setUseUI(bool useUI) { m_useUI = useUI; }
|
||||||
|
void setType(SpriteSheetType type) { m_type = type; }
|
||||||
|
void setAction(ExportAction action) { m_action = action; }
|
||||||
|
void setColumns(int columns) { m_columns = columns; }
|
||||||
|
void setFileName(const std::string& filename) { m_filename = filename; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual bool onEnabled(Context* context) OVERRIDE;
|
||||||
|
virtual void onExecute(Context* context) OVERRIDE;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_useUI;
|
||||||
|
SpriteSheetType m_type;
|
||||||
|
ExportAction m_action;
|
||||||
|
int m_columns;
|
||||||
|
std::string m_filename;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace app
|
||||||
|
|
||||||
|
#endif
|
98
src/app/commands/cmd_repeat_last_export.cpp
Normal file
98
src/app/commands/cmd_repeat_last_export.cpp
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
/* Aseprite
|
||||||
|
* Copyright (C) 2001-2013 David Capello
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "app/commands/cmd_export_sprite_sheet.h"
|
||||||
|
#include "app/commands/command.h"
|
||||||
|
#include "app/commands/commands.h"
|
||||||
|
#include "app/commands/params.h"
|
||||||
|
#include "app/context.h"
|
||||||
|
#include "app/context_access.h"
|
||||||
|
#include "base/compiler_specific.h"
|
||||||
|
|
||||||
|
namespace app {
|
||||||
|
|
||||||
|
class RepeatLastExportCommand : public Command {
|
||||||
|
public:
|
||||||
|
RepeatLastExportCommand();
|
||||||
|
Command* clone() { return new RepeatLastExportCommand(*this); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual bool onEnabled(Context* context) OVERRIDE;
|
||||||
|
virtual void onExecute(Context* context) OVERRIDE;
|
||||||
|
};
|
||||||
|
|
||||||
|
RepeatLastExportCommand::RepeatLastExportCommand()
|
||||||
|
: Command("RepeatLastExport",
|
||||||
|
"Repeat Last Export",
|
||||||
|
CmdRecordableFlag)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RepeatLastExportCommand::onEnabled(Context* context)
|
||||||
|
{
|
||||||
|
return context->checkFlags(ContextFlags::ActiveDocumentIsWritable);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatLastExportCommand::onExecute(Context* context)
|
||||||
|
{
|
||||||
|
base::UniquePtr<ExportSpriteSheetCommand> command(
|
||||||
|
static_cast<ExportSpriteSheetCommand*>(
|
||||||
|
CommandsModule::instance()->getCommandByName(CommandId::ExportSpriteSheet)->clone()));
|
||||||
|
|
||||||
|
{
|
||||||
|
const ContextReader reader(context);
|
||||||
|
const Document* document(reader.document());
|
||||||
|
doc::ExportDataPtr data = document->exportData();
|
||||||
|
|
||||||
|
if (data != NULL) {
|
||||||
|
command->setUseUI(false);
|
||||||
|
|
||||||
|
ExportSpriteSheetCommand::SpriteSheetType type;
|
||||||
|
switch (data->type()) {
|
||||||
|
case doc::ExportData::None: return;
|
||||||
|
case doc::ExportData::HorizontalStrip:
|
||||||
|
type = ExportSpriteSheetCommand::HorizontalStrip;
|
||||||
|
break;
|
||||||
|
case doc::ExportData::VerticalStrip:
|
||||||
|
type = ExportSpriteSheetCommand::VerticalStrip;
|
||||||
|
break;
|
||||||
|
case doc::ExportData::Matrix:
|
||||||
|
type = ExportSpriteSheetCommand::Matrix;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
command->setType(type);
|
||||||
|
command->setAction(ExportSpriteSheetCommand::SaveCopyAs);
|
||||||
|
command->setColumns(data->columns());
|
||||||
|
command->setFileName(data->filename());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context->executeCommand(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
Command* CommandFactory::createRepeatLastExportCommand()
|
||||||
|
{
|
||||||
|
return new RepeatLastExportCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace app
|
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include "app/app.h"
|
#include "app/app.h"
|
||||||
#include "app/commands/command.h"
|
#include "app/commands/command.h"
|
||||||
|
#include "app/commands/params.h"
|
||||||
#include "app/console.h"
|
#include "app/console.h"
|
||||||
#include "app/context_access.h"
|
#include "app/context_access.h"
|
||||||
#include "app/file/file.h"
|
#include "app/file/file.h"
|
||||||
@ -101,105 +102,122 @@ static void save_document_in_background(Document* document, bool mark_as_saved)
|
|||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static bool confirm_readonly(const base::string& filename)
|
class SaveFileBaseCommand : public Command {
|
||||||
{
|
public:
|
||||||
if (!base::has_readonly_attr(filename))
|
SaveFileBaseCommand(const char* short_name, const char* friendly_name, CommandFlags flags)
|
||||||
return true;
|
: Command(short_name, friendly_name, flags) {
|
||||||
|
|
||||||
int ret = ui::Alert::show("Warning<<The file is read-only, do you really want to overwrite it?<<%s||&Yes||&No",
|
|
||||||
base::get_file_name(filename).c_str());
|
|
||||||
|
|
||||||
if (ret == 1) {
|
|
||||||
base::remove_readonly_attr(filename);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void save_as_dialog(const ContextReader& reader, const char* dlg_title, bool mark_as_saved)
|
protected:
|
||||||
{
|
void onLoadParams(Params* params) OVERRIDE {
|
||||||
const Document* document = reader.document();
|
m_filename = params->get("filename");
|
||||||
char exts[4096];
|
}
|
||||||
base::string filename;
|
|
||||||
base::string newfilename;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
filename = document->getFilename();
|
// Returns true if there is a current sprite to save.
|
||||||
get_writable_extensions(exts, sizeof(exts));
|
// [main thread]
|
||||||
|
bool onEnabled(Context* context) OVERRIDE {
|
||||||
|
return context->checkFlags(ContextFlags::ActiveDocumentIsWritable);
|
||||||
|
}
|
||||||
|
|
||||||
for (;;) {
|
void saveAsDialog(const ContextReader& reader, const char* dlgTitle, bool markAsSaved)
|
||||||
newfilename = app::show_file_selector(dlg_title, filename, exts);
|
{
|
||||||
if (newfilename.empty())
|
const Document* document = reader.document();
|
||||||
return;
|
base::string filename;
|
||||||
|
|
||||||
filename = newfilename;
|
if (!m_filename.empty()) {
|
||||||
|
filename = m_filename;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
filename = document->getFilename();
|
||||||
|
|
||||||
// Ask if the user wants overwrite the existent file.
|
char exts[4096];
|
||||||
if (base::file_exists(filename)) {
|
get_writable_extensions(exts, sizeof(exts));
|
||||||
ret = ui::Alert::show("Warning<<The file already exists, overwrite it?<<%s||&Yes||&No||&Cancel",
|
|
||||||
base::get_file_name(filename).c_str());
|
|
||||||
|
|
||||||
// Check for read-only attribute.
|
for (;;) {
|
||||||
if (ret == 1) {
|
base::string newfilename = app::show_file_selector(dlgTitle, filename, exts);
|
||||||
if (!confirm_readonly(filename))
|
if (newfilename.empty())
|
||||||
ret = 2; // Select file again.
|
return;
|
||||||
|
|
||||||
|
filename = newfilename;
|
||||||
|
|
||||||
|
// Ask if the user wants overwrite the existent file.
|
||||||
|
int ret = 0;
|
||||||
|
if (base::file_exists(filename)) {
|
||||||
|
ret = ui::Alert::show("Warning<<The file already exists, overwrite it?<<%s||&Yes||&No||&Cancel",
|
||||||
|
base::get_file_name(filename).c_str());
|
||||||
|
|
||||||
|
// Check for read-only attribute.
|
||||||
|
if (ret == 1) {
|
||||||
|
if (!confirmReadonly(filename))
|
||||||
|
ret = 2; // Select file again.
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// "yes": we must continue with the operation...
|
||||||
|
if (ret == 1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// "cancel" or <esc> per example: we back doing nothing
|
||||||
|
else if (ret != 2)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// "no": we must back to select other file-name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
break;
|
|
||||||
|
|
||||||
// "yes": we must continue with the operation...
|
{
|
||||||
if (ret == 1) {
|
ContextWriter writer(reader);
|
||||||
break;
|
Document* documentWriter = writer.document();
|
||||||
|
|
||||||
|
// Change the document file name
|
||||||
|
documentWriter->setFilename(filename.c_str());
|
||||||
|
m_selectedFilename = filename;
|
||||||
|
|
||||||
|
// Save the document
|
||||||
|
save_document_in_background(documentWriter, markAsSaved);
|
||||||
|
|
||||||
|
update_screen_for_document(documentWriter);
|
||||||
}
|
}
|
||||||
// "cancel" or <esc> per example: we back doing nothing
|
|
||||||
else if (ret != 2)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// "no": we must back to select other file-name
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool confirmReadonly(const std::string& filename)
|
||||||
{
|
{
|
||||||
ContextWriter writer(reader);
|
if (!base::has_readonly_attr(filename))
|
||||||
Document* documentWriter = writer.document();
|
return true;
|
||||||
|
|
||||||
// Change the document file name
|
int ret = ui::Alert::show("Warning<<The file is read-only, do you really want to overwrite it?<<%s||&Yes||&No",
|
||||||
documentWriter->setFilename(filename.c_str());
|
base::get_file_name(filename).c_str());
|
||||||
|
|
||||||
// Save the document
|
if (ret == 1) {
|
||||||
save_document_in_background(documentWriter, mark_as_saved);
|
base::remove_readonly_attr(filename);
|
||||||
|
return true;
|
||||||
update_screen_for_document(documentWriter);
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
class SaveFileCommand : public Command {
|
std::string m_filename;
|
||||||
|
std::string m_selectedFilename;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SaveFileCommand : public SaveFileBaseCommand {
|
||||||
public:
|
public:
|
||||||
SaveFileCommand();
|
SaveFileCommand();
|
||||||
Command* clone() { return new SaveFileCommand(*this); }
|
Command* clone() { return new SaveFileCommand(*this); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool onEnabled(Context* context);
|
|
||||||
void onExecute(Context* context);
|
void onExecute(Context* context);
|
||||||
};
|
};
|
||||||
|
|
||||||
SaveFileCommand::SaveFileCommand()
|
SaveFileCommand::SaveFileCommand()
|
||||||
: Command("SaveFile",
|
: SaveFileBaseCommand("SaveFile", "Save File", CmdRecordableFlag)
|
||||||
"Save File",
|
|
||||||
CmdRecordableFlag)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if there is a current sprite to save.
|
|
||||||
// [main thread]
|
|
||||||
bool SaveFileCommand::onEnabled(Context* context)
|
|
||||||
{
|
|
||||||
return context->checkFlags(ContextFlags::ActiveDocumentIsWritable);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Saves the active document in a file.
|
// Saves the active document in a file.
|
||||||
// [main thread]
|
// [main thread]
|
||||||
void SaveFileCommand::onExecute(Context* context)
|
void SaveFileCommand::onExecute(Context* context)
|
||||||
@ -213,7 +231,7 @@ void SaveFileCommand::onExecute(Context* context)
|
|||||||
ContextWriter writer(reader);
|
ContextWriter writer(reader);
|
||||||
Document* documentWriter = writer.document();
|
Document* documentWriter = writer.document();
|
||||||
|
|
||||||
if (!confirm_readonly(documentWriter->getFilename()))
|
if (!confirmReadonly(documentWriter->getFilename()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
save_document_in_background(documentWriter, true);
|
save_document_in_background(documentWriter, true);
|
||||||
@ -223,60 +241,44 @@ void SaveFileCommand::onExecute(Context* context)
|
|||||||
// save-as dialog to the user to select for first time the file-name
|
// save-as dialog to the user to select for first time the file-name
|
||||||
// for this document.
|
// for this document.
|
||||||
else {
|
else {
|
||||||
save_as_dialog(reader, "Save File", true);
|
saveAsDialog(reader, "Save File", true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SaveFileAsCommand : public Command {
|
class SaveFileAsCommand : public SaveFileBaseCommand {
|
||||||
public:
|
public:
|
||||||
SaveFileAsCommand();
|
SaveFileAsCommand();
|
||||||
Command* clone() { return new SaveFileAsCommand(*this); }
|
Command* clone() { return new SaveFileAsCommand(*this); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool onEnabled(Context* context);
|
|
||||||
void onExecute(Context* context);
|
void onExecute(Context* context);
|
||||||
};
|
};
|
||||||
|
|
||||||
SaveFileAsCommand::SaveFileAsCommand()
|
SaveFileAsCommand::SaveFileAsCommand()
|
||||||
: Command("SaveFileAs",
|
: SaveFileBaseCommand("SaveFileAs", "Save File As", CmdRecordableFlag)
|
||||||
"Save File As",
|
|
||||||
CmdRecordableFlag)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SaveFileAsCommand::onEnabled(Context* context)
|
|
||||||
{
|
|
||||||
return context->checkFlags(ContextFlags::ActiveDocumentIsWritable);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SaveFileAsCommand::onExecute(Context* context)
|
void SaveFileAsCommand::onExecute(Context* context)
|
||||||
{
|
{
|
||||||
const ContextReader reader(context);
|
const ContextReader reader(context);
|
||||||
save_as_dialog(reader, "Save As", true);
|
saveAsDialog(reader, "Save As", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
class SaveFileCopyAsCommand : public Command {
|
class SaveFileCopyAsCommand : public SaveFileBaseCommand {
|
||||||
public:
|
public:
|
||||||
SaveFileCopyAsCommand();
|
SaveFileCopyAsCommand();
|
||||||
Command* clone() { return new SaveFileCopyAsCommand(*this); }
|
Command* clone() { return new SaveFileCopyAsCommand(*this); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool onEnabled(Context* context);
|
|
||||||
void onExecute(Context* context);
|
void onExecute(Context* context);
|
||||||
};
|
};
|
||||||
|
|
||||||
SaveFileCopyAsCommand::SaveFileCopyAsCommand()
|
SaveFileCopyAsCommand::SaveFileCopyAsCommand()
|
||||||
: Command("SaveFileCopyAs",
|
: SaveFileBaseCommand("SaveFileCopyAs", "Save File Copy As", CmdRecordableFlag)
|
||||||
"Save File Copy As",
|
|
||||||
CmdRecordableFlag)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SaveFileCopyAsCommand::onEnabled(Context* context)
|
|
||||||
{
|
|
||||||
return context->checkFlags(ContextFlags::ActiveDocumentIsWritable);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SaveFileCopyAsCommand::onExecute(Context* context)
|
void SaveFileCopyAsCommand::onExecute(Context* context)
|
||||||
{
|
{
|
||||||
const ContextReader reader(context);
|
const ContextReader reader(context);
|
||||||
@ -284,7 +286,7 @@ void SaveFileCopyAsCommand::onExecute(Context* context)
|
|||||||
base::string old_filename = document->getFilename();
|
base::string old_filename = document->getFilename();
|
||||||
|
|
||||||
// show "Save As" dialog
|
// show "Save As" dialog
|
||||||
save_as_dialog(reader, "Save Copy As", false);
|
saveAsDialog(reader, "Save Copy As", false);
|
||||||
|
|
||||||
// Restore the file name.
|
// Restore the file name.
|
||||||
{
|
{
|
||||||
|
52
src/app/commands/cmd_save_file.h
Normal file
52
src/app/commands/cmd_save_file.h
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/* Aseprite
|
||||||
|
* Copyright (C) 2001-2014 David Capello
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef APP_COMMANDS_CMD_SAVE_FILE_H_INCLUDED
|
||||||
|
#define APP_COMMANDS_CMD_SAVE_FILE_H_INCLUDED
|
||||||
|
|
||||||
|
#include "app/commands/command.h"
|
||||||
|
#include "base/compiler_specific.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace app {
|
||||||
|
class ContextReader;
|
||||||
|
|
||||||
|
class SaveFileBaseCommand : public Command {
|
||||||
|
public:
|
||||||
|
SaveFileBaseCommand(const char* shortName, const char* friendlyName, CommandFlags flags);
|
||||||
|
|
||||||
|
std::string selectedFilename() const {
|
||||||
|
return m_selectedFilename;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void onLoadParams(Params* params) OVERRIDE;
|
||||||
|
bool onEnabled(Context* context) OVERRIDE;
|
||||||
|
|
||||||
|
void saveAsDialog(const ContextReader& reader, const char* dlgTitle, bool markAsSaved);
|
||||||
|
|
||||||
|
static bool confirmReadonly(const std::string& filename);
|
||||||
|
|
||||||
|
std::string m_filename;
|
||||||
|
std::string m_selectedFilename;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace app
|
||||||
|
|
||||||
|
#endif
|
@ -87,6 +87,7 @@ FOR_EACH_COMMAND(Refresh)
|
|||||||
FOR_EACH_COMMAND(RemoveCel)
|
FOR_EACH_COMMAND(RemoveCel)
|
||||||
FOR_EACH_COMMAND(RemoveFrame)
|
FOR_EACH_COMMAND(RemoveFrame)
|
||||||
FOR_EACH_COMMAND(RemoveLayer)
|
FOR_EACH_COMMAND(RemoveLayer)
|
||||||
|
FOR_EACH_COMMAND(RepeatLastExport)
|
||||||
FOR_EACH_COMMAND(ReplaceColor)
|
FOR_EACH_COMMAND(ReplaceColor)
|
||||||
FOR_EACH_COMMAND(ReselectMask)
|
FOR_EACH_COMMAND(ReselectMask)
|
||||||
FOR_EACH_COMMAND(RotateCanvas)
|
FOR_EACH_COMMAND(RotateCanvas)
|
||||||
|
@ -98,6 +98,17 @@ namespace app {
|
|||||||
|
|
||||||
void addSprite(Sprite* sprite);
|
void addSprite(Sprite* sprite);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// Export data
|
||||||
|
|
||||||
|
doc::ExportDataPtr exportData() const {
|
||||||
|
return m_document.exportData();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setExportData(const doc::ExportDataPtr& data) {
|
||||||
|
return m_document.setExportData(data);
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// Notifications
|
// Notifications
|
||||||
|
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
|
|
||||||
#include "doc/document.h"
|
#include "doc/document.h"
|
||||||
|
|
||||||
|
#include "doc/export_data.h"
|
||||||
|
|
||||||
namespace doc {
|
namespace doc {
|
||||||
|
|
||||||
Document::Document()
|
Document::Document()
|
||||||
@ -21,4 +23,9 @@ void Document::setFilename(const std::string& filename)
|
|||||||
m_filename = filename;
|
m_filename = filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Document::setExportData(const ExportDataPtr& data)
|
||||||
|
{
|
||||||
|
m_exportData = data;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace doc
|
} // namespace doc
|
||||||
|
@ -10,21 +10,28 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "doc/object.h"
|
#include "doc/object.h"
|
||||||
|
#include "doc/export_data.h"
|
||||||
|
|
||||||
namespace doc {
|
namespace doc {
|
||||||
|
|
||||||
|
class ExportData;
|
||||||
|
|
||||||
class Document : public Object {
|
class Document : public Object {
|
||||||
public:
|
public:
|
||||||
Document();
|
Document();
|
||||||
|
|
||||||
const std::string& filename() const { return m_filename; }
|
const std::string& filename() const { return m_filename; }
|
||||||
|
ExportDataPtr exportData() const { return m_exportData; }
|
||||||
|
|
||||||
void setFilename(const std::string& filename);
|
void setFilename(const std::string& filename);
|
||||||
|
void setExportData(const ExportDataPtr& data);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Document's file name. From where it was loaded, where it is
|
// Document's file name. From where it was loaded, where it is
|
||||||
// saved.
|
// saved.
|
||||||
std::string m_filename;
|
std::string m_filename;
|
||||||
|
|
||||||
|
ExportDataPtr m_exportData;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace doc
|
} // namespace doc
|
||||||
|
48
src/doc/export_data.h
Normal file
48
src/doc/export_data.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
// Aseprite Document Library
|
||||||
|
// Copyright (c) 2014 David Capello
|
||||||
|
//
|
||||||
|
// This source file is distributed under the terms of the MIT license,
|
||||||
|
// please read LICENSE.txt for more information.
|
||||||
|
|
||||||
|
#ifndef DOC_EXPORT_DATA_H_INCLUDED
|
||||||
|
#define DOC_EXPORT_DATA_H_INCLUDED
|
||||||
|
|
||||||
|
#include "base/shared_ptr.h"
|
||||||
|
#include "gfx/rect.h"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace doc {
|
||||||
|
|
||||||
|
class ExportData {
|
||||||
|
public:
|
||||||
|
enum Type {
|
||||||
|
None,
|
||||||
|
HorizontalStrip,
|
||||||
|
VerticalStrip,
|
||||||
|
Matrix
|
||||||
|
};
|
||||||
|
|
||||||
|
ExportData() : m_type(None) {
|
||||||
|
}
|
||||||
|
|
||||||
|
Type type() const { return m_type; }
|
||||||
|
int columns() const { return m_columns; }
|
||||||
|
const std::string& filename() const { return m_filename; }
|
||||||
|
|
||||||
|
void setType(Type type) { m_type = type; }
|
||||||
|
void setColumns(int columns) { m_columns = columns; }
|
||||||
|
void setFilename(const std::string& filename) {
|
||||||
|
m_filename = filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Type m_type;
|
||||||
|
int m_columns;
|
||||||
|
std::string m_filename;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef SharedPtr<ExportData> ExportDataPtr;
|
||||||
|
|
||||||
|
} // namespace doc
|
||||||
|
|
||||||
|
#endif
|
Loading…
x
Reference in New Issue
Block a user