mirror of
https://github.com/aseprite/aseprite.git
synced 2025-01-30 15:32:38 +00:00
Add "Import Sprite Sheet" command (part of issue #4).
This commit is contained in:
parent
3cbf3baf75
commit
0bddf2611c
@ -176,6 +176,8 @@
|
|||||||
<item command="CloseFile" text="&Close" />
|
<item command="CloseFile" text="&Close" />
|
||||||
<item command="CloseAllFiles" text="Close All" />
|
<item command="CloseAllFiles" text="Close All" />
|
||||||
<separator />
|
<separator />
|
||||||
|
<item command="ImportSpriteSheet" text="&Import Sprite Sheet" />
|
||||||
|
<separator />
|
||||||
<item command="Exit" text="E&xit" />
|
<item command="Exit" text="E&xit" />
|
||||||
</menu>
|
</menu>
|
||||||
<menu text="&Edit">
|
<menu text="&Edit">
|
||||||
|
@ -146,6 +146,7 @@ add_library(aseprite-library
|
|||||||
commands/cmd_goto_frame.cpp
|
commands/cmd_goto_frame.cpp
|
||||||
commands/cmd_goto_layer.cpp
|
commands/cmd_goto_layer.cpp
|
||||||
commands/cmd_grid.cpp
|
commands/cmd_grid.cpp
|
||||||
|
commands/cmd_import_sprite_sheet.cpp
|
||||||
commands/cmd_invert_mask.cpp
|
commands/cmd_invert_mask.cpp
|
||||||
commands/cmd_launch.cpp
|
commands/cmd_launch.cpp
|
||||||
commands/cmd_layer_from_background.cpp
|
commands/cmd_layer_from_background.cpp
|
||||||
|
329
src/commands/cmd_import_sprite_sheet.cpp
Normal file
329
src/commands/cmd_import_sprite_sheet.cpp
Normal file
@ -0,0 +1,329 @@
|
|||||||
|
/* ASE - Allegro Sprite Editor
|
||||||
|
* Copyright (C) 2001-2011 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "base/bind.h"
|
||||||
|
#include "commands/command.h"
|
||||||
|
#include "commands/commands.h"
|
||||||
|
#include "commands/params.h"
|
||||||
|
#include "dialogs/filesel.h"
|
||||||
|
#include "document_wrappers.h"
|
||||||
|
#include "gui/gui.h"
|
||||||
|
#include "ini_file.h"
|
||||||
|
#include "modules/editors.h"
|
||||||
|
#include "modules/gui.h"
|
||||||
|
#include "modules/palettes.h"
|
||||||
|
#include "raster/cel.h"
|
||||||
|
#include "raster/image.h"
|
||||||
|
#include "raster/layer.h"
|
||||||
|
#include "raster/palette.h"
|
||||||
|
#include "raster/sprite.h"
|
||||||
|
#include "raster/stock.h"
|
||||||
|
#include "undo_transaction.h"
|
||||||
|
#include "widgets/drop_down_button.h"
|
||||||
|
#include "widgets/editor/editor.h"
|
||||||
|
#include "widgets/editor/editor_decorator.h"
|
||||||
|
#include "widgets/editor/select_box_state.h"
|
||||||
|
#include "widgets/editor/standby_state.h"
|
||||||
|
|
||||||
|
#include <allegro/color.h>
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// ImportSpriteSheetFrame
|
||||||
|
|
||||||
|
class ImportSpriteSheetFrame : public Frame,
|
||||||
|
public SelectBoxDelegate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ImportSpriteSheetFrame(Context* context)
|
||||||
|
: Frame(false, "Import Sprite Sheet")
|
||||||
|
, m_context(context)
|
||||||
|
, m_document(NULL)
|
||||||
|
, m_grid(4, false)
|
||||||
|
, m_selectFile("Select File")
|
||||||
|
, m_x(4, "0")
|
||||||
|
, m_y(4, "0")
|
||||||
|
, m_width(4, "16")
|
||||||
|
, m_height(4, "16")
|
||||||
|
, m_import("Import")
|
||||||
|
, m_cancel("Cancel")
|
||||||
|
, m_editor(NULL)
|
||||||
|
, m_fileOpened(false)
|
||||||
|
{
|
||||||
|
addChild(&m_grid);
|
||||||
|
m_grid.addChildInCell(&m_selectFile, 4, 1, 0);
|
||||||
|
m_grid.addChildInCell(new Label("X"), 1, 1, 0);
|
||||||
|
m_grid.addChildInCell(&m_x, 1, 1, 0);
|
||||||
|
m_grid.addChildInCell(new Label("Width"), 1, 1, 0);
|
||||||
|
m_grid.addChildInCell(&m_width, 1, 1, 0);
|
||||||
|
m_grid.addChildInCell(new Label("Y"), 1, 1, 0);
|
||||||
|
m_grid.addChildInCell(&m_y, 1, 1, 0);
|
||||||
|
m_grid.addChildInCell(new Label("Height"), 1, 1, 0);
|
||||||
|
m_grid.addChildInCell(&m_height, 1, 1, 0);
|
||||||
|
m_grid.addChildInCell(&m_import, 4, 1, 0);
|
||||||
|
m_grid.addChildInCell(&m_cancel, 4, 1, 0);
|
||||||
|
|
||||||
|
m_selectFile.Click.connect(&ImportSpriteSheetFrame::onSelectFile, this);
|
||||||
|
m_selectFile.DropDownClick.connect(&ImportSpriteSheetFrame::onDropDown, this);
|
||||||
|
m_import.Click.connect(Bind<void>(&ImportSpriteSheetFrame::onImport, this));
|
||||||
|
m_cancel.Click.connect(Bind<void>(&ImportSpriteSheetFrame::onCancel, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
~ImportSpriteSheetFrame()
|
||||||
|
{
|
||||||
|
releaseEditor();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
void onSelectFile()
|
||||||
|
{
|
||||||
|
Document* oldActiveDocument = m_context->getActiveDocument();
|
||||||
|
Command* openFile = CommandsModule::instance()->getCommandByName(CommandId::OpenFile);
|
||||||
|
Params params;
|
||||||
|
params.set("filename", "");
|
||||||
|
openFile->loadParams(¶ms);
|
||||||
|
openFile->execute(m_context);
|
||||||
|
|
||||||
|
// The user have selected another document.
|
||||||
|
if (oldActiveDocument != m_context->getActiveDocument()) {
|
||||||
|
selectActiveDocument();
|
||||||
|
m_fileOpened = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void onDropDown()
|
||||||
|
{
|
||||||
|
SharedPtr<Menu> menu(new Menu());
|
||||||
|
MenuItem* item = new MenuItem("Use Current Sprite");
|
||||||
|
item->Click.connect(&ImportSpriteSheetFrame::onUseCurrentSprite, this);
|
||||||
|
|
||||||
|
if (m_editor || current_editor->getDocument() == NULL)
|
||||||
|
item->setEnabled(false);
|
||||||
|
|
||||||
|
menu->addChild(item);
|
||||||
|
|
||||||
|
menu->showPopup(m_selectFile.rc->x1, m_selectFile.rc->y2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void onUseCurrentSprite()
|
||||||
|
{
|
||||||
|
selectActiveDocument();
|
||||||
|
m_fileOpened = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onImport()
|
||||||
|
{
|
||||||
|
// The user don't select a sheet yet.
|
||||||
|
if (!m_document) {
|
||||||
|
Alert::show("Import Sprite Sheet<<Select a sprite first.||&Close");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The list of frames imported from the sheet
|
||||||
|
std::vector<Image*> animation;
|
||||||
|
|
||||||
|
try {
|
||||||
|
Sprite* sprite = m_document->getSprite();
|
||||||
|
|
||||||
|
// As first step, we cut each tile and add them into "animation" list.
|
||||||
|
for (int y=m_rect.y; y<sprite->getHeight(); y += m_rect.h) {
|
||||||
|
for (int x=m_rect.x; x<sprite->getWidth(); x += m_rect.w) {
|
||||||
|
UniquePtr<Image> resultImage(image_new(sprite->getImgType(), m_rect.w, m_rect.h));
|
||||||
|
|
||||||
|
// Clear the image with mask color.
|
||||||
|
image_clear(resultImage, 0);
|
||||||
|
|
||||||
|
// Render the portion of sheet.
|
||||||
|
sprite->render(resultImage, -x, -y);
|
||||||
|
animation.push_back(resultImage);
|
||||||
|
resultImage.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (animation.size() == 0) {
|
||||||
|
Alert::show("Import Sprite Sheet"
|
||||||
|
"<<The specified rectangle does not create any tile."
|
||||||
|
"<<Select a rectangle inside the sprite region."
|
||||||
|
"||&OK");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The following steps modify the sprite, so we wrap all
|
||||||
|
// operations in a undo-transaction.
|
||||||
|
UndoTransaction undoTransaction(m_document, "Import Sprite Sheet", undo::ModifyDocument);
|
||||||
|
|
||||||
|
// Add the layer in the sprite.
|
||||||
|
LayerImage* resultLayer = undoTransaction.newLayer();
|
||||||
|
|
||||||
|
// Add all frames+cels to the new layer
|
||||||
|
for (size_t i=0; i<animation.size(); ++i) {
|
||||||
|
int indexInStock;
|
||||||
|
|
||||||
|
// Add the image into the sprite's stock
|
||||||
|
indexInStock = undoTransaction.addImageInStock(animation[i]);
|
||||||
|
animation[i] = NULL;
|
||||||
|
|
||||||
|
// Create the cel.
|
||||||
|
UniquePtr<Cel> resultCel(new Cel(i, indexInStock));
|
||||||
|
|
||||||
|
// Add the cel in the layer.
|
||||||
|
undoTransaction.addCel(resultLayer, resultCel);
|
||||||
|
resultCel.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy the list of layers (because we will modify it in the iteration).
|
||||||
|
LayerList layers = sprite->getFolder()->get_layers_list();
|
||||||
|
|
||||||
|
// Remove all other layers
|
||||||
|
for (LayerIterator it=layers.begin(), end=layers.end(); it!=end; ++it) {
|
||||||
|
if (*it != resultLayer)
|
||||||
|
undoTransaction.removeLayer(*it);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change the number of frames
|
||||||
|
undoTransaction.setNumberOfFrames(animation.size());
|
||||||
|
undoTransaction.setCurrentFrame(0);
|
||||||
|
|
||||||
|
// Set the size of the sprite to the tile size.
|
||||||
|
undoTransaction.setSpriteSize(m_rect.w, m_rect.h);
|
||||||
|
|
||||||
|
undoTransaction.commit();
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
for (size_t i=0; i<animation.size(); ++i)
|
||||||
|
delete animation[i];
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
closeWindow(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void onCancel()
|
||||||
|
{
|
||||||
|
closeWindow(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void onBroadcastMouseMessage(WidgetsList& targets) OVERRIDE
|
||||||
|
{
|
||||||
|
Frame::onBroadcastMouseMessage(targets);
|
||||||
|
|
||||||
|
// Add the editor as receptor of mouse events too.
|
||||||
|
if (m_editor)
|
||||||
|
targets.push_back(View::getView(m_editor));
|
||||||
|
}
|
||||||
|
|
||||||
|
// SelectBoxDelegate impleentation
|
||||||
|
virtual void onChangeRectangle(const gfx::Rect& rect) OVERRIDE
|
||||||
|
{
|
||||||
|
m_rect = rect;
|
||||||
|
|
||||||
|
m_x.setTextf("%d", m_rect.x);
|
||||||
|
m_y.setTextf("%d", m_rect.y);
|
||||||
|
m_width.setTextf("%d", m_rect.w);
|
||||||
|
m_height.setTextf("%d", m_rect.h);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void selectActiveDocument()
|
||||||
|
{
|
||||||
|
Document* oldDocument = m_document;
|
||||||
|
m_document = m_context->getActiveDocument();
|
||||||
|
|
||||||
|
// If the user already have selected a file, we have to close that
|
||||||
|
// file in order to select the new one.
|
||||||
|
if (oldDocument && m_fileOpened) {
|
||||||
|
m_context->setActiveDocument(oldDocument);
|
||||||
|
|
||||||
|
Command* closeFile = CommandsModule::instance()->getCommandByName(CommandId::CloseFile);
|
||||||
|
closeFile->execute(m_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
captureEditor();
|
||||||
|
}
|
||||||
|
|
||||||
|
void captureEditor()
|
||||||
|
{
|
||||||
|
releaseEditor();
|
||||||
|
|
||||||
|
if (m_document && !m_editor) {
|
||||||
|
m_rect = gfx::Rect(0, 0, 16, 16);
|
||||||
|
m_editor = current_editor;
|
||||||
|
m_editor->setDefaultState(EditorStatePtr(new SelectBoxState(this, m_rect,
|
||||||
|
SelectBoxState::PaintRulers |
|
||||||
|
SelectBoxState::PaintGrid)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void releaseEditor()
|
||||||
|
{
|
||||||
|
if (m_editor) {
|
||||||
|
m_editor->setDefaultState(EditorStatePtr(new StandbyState));
|
||||||
|
m_editor = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Context* m_context;
|
||||||
|
Document* m_document;
|
||||||
|
Grid m_grid;
|
||||||
|
DropDownButton m_selectFile;
|
||||||
|
Entry m_x, m_y, m_width, m_height;
|
||||||
|
Button m_import;
|
||||||
|
Button m_cancel;
|
||||||
|
Editor* m_editor;
|
||||||
|
gfx::Rect m_rect;
|
||||||
|
|
||||||
|
// True if the user has been opened the file (instead of selecting
|
||||||
|
// the current document).
|
||||||
|
bool m_fileOpened;
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// ImportSpriteSheetCommand
|
||||||
|
|
||||||
|
class ImportSpriteSheetCommand : public Command
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ImportSpriteSheetCommand();
|
||||||
|
Command* clone() { return new ImportSpriteSheetCommand(*this); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void onExecute(Context* context) OVERRIDE;
|
||||||
|
};
|
||||||
|
|
||||||
|
ImportSpriteSheetCommand::ImportSpriteSheetCommand()
|
||||||
|
: Command("ImportSpriteSheet",
|
||||||
|
"Import Sprite Sheet",
|
||||||
|
CmdRecordableFlag)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImportSpriteSheetCommand::onExecute(Context* context)
|
||||||
|
{
|
||||||
|
FramePtr frame(new ImportSpriteSheetFrame(context));
|
||||||
|
frame->open_window_fg();
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// CommandFactory
|
||||||
|
|
||||||
|
Command* CommandFactory::createImportSpriteSheetCommand()
|
||||||
|
{
|
||||||
|
return new ImportSpriteSheetCommand;
|
||||||
|
}
|
@ -54,6 +54,7 @@ FOR_EACH_COMMAND(GotoNextLayer)
|
|||||||
FOR_EACH_COMMAND(GotoPreviousFrame)
|
FOR_EACH_COMMAND(GotoPreviousFrame)
|
||||||
FOR_EACH_COMMAND(GotoPreviousLayer)
|
FOR_EACH_COMMAND(GotoPreviousLayer)
|
||||||
FOR_EACH_COMMAND(GridSettings)
|
FOR_EACH_COMMAND(GridSettings)
|
||||||
|
FOR_EACH_COMMAND(ImportSpriteSheet)
|
||||||
FOR_EACH_COMMAND(InvertColor)
|
FOR_EACH_COMMAND(InvertColor)
|
||||||
FOR_EACH_COMMAND(InvertMask)
|
FOR_EACH_COMMAND(InvertMask)
|
||||||
FOR_EACH_COMMAND(Launch)
|
FOR_EACH_COMMAND(Launch)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user