[aseprite] 33/308: Add possibility to import/export sprite sheet matrices by columns

Tobias Hansen thansen at moszumanska.debian.org
Tue Mar 8 02:44:49 UTC 2016


This is an automated email from the git hooks/post-receive script.

thansen pushed a commit to branch master
in repository aseprite.

commit 4dbee127891a4931a90ddb50731b2a5530ec4009
Author: David Capello <davidcapello at gmail.com>
Date:   Thu Dec 3 11:38:59 2015 -0300

    Add possibility to import/export sprite sheet matrices by columns
    
    Fix #872
---
 data/pref.xml                                |  10 +-
 data/skins/default/skin.xml                  |   2 +
 data/widgets/export_sprite_sheet.xml         |   6 +-
 data/widgets/import_sprite_sheet.xml         |   3 +
 src/app/app.cpp                              |  20 +++-
 src/app/app_options.cpp                      |   3 +-
 src/app/app_options.h                        |   2 +
 src/app/commands/cmd_canvas_size.cpp         |   9 +-
 src/app/commands/cmd_export_sprite_sheet.cpp | 152 ++++++++++++++++++---------
 src/app/commands/cmd_import_sprite_sheet.cpp | 122 +++++++++++++++++----
 src/app/commands/cmd_new_brush.cpp           |   5 +-
 src/app/commands/cmd_repeat_last_export.cpp  |   2 +-
 src/app/document_exporter.cpp                |  89 +++++++++++-----
 src/app/document_exporter.h                  |   5 +-
 src/app/pref/preferences.h                   |   1 +
 src/app/sprite_sheet_type.h                  |  25 +++++
 src/app/ui/editor/select_box_state.cpp       |  72 ++++++++-----
 src/app/ui/editor/select_box_state.h         |  26 ++++-
 18 files changed, 410 insertions(+), 144 deletions(-)

diff --git a/data/pref.xml b/data/pref.xml
index aaff328..c15dade 100644
--- a/data/pref.xml
+++ b/data/pref.xml
@@ -26,12 +26,6 @@
       <value id="CHECKED_4x4" value="2" />
       <value id="CHECKED_2x2" value="3" />
     </enum>
-    <enum id="SpriteSheetType">
-      <value id="NONE" value="0" />
-      <value id="HORIZONTAL_STRIP" value="1" />
-      <value id="VERTICAL_STRIP" value="2" />
-      <value id="MATRIX" value="3" />
-    </enum>
     <enum id="StopAtGrid">
       <value id="NEVER" value="0" />
       <value id="IF_VISIBLE" value="1" />
@@ -241,8 +235,9 @@
       <option id="resize_scale" type="double" default="1" />
     </section>
     <section id="sprite_sheet">
-      <option id="type" type="SpriteSheetType" default="SpriteSheetType::NONE" />
+      <option id="type" type="app::SpriteSheetType" default="app::SpriteSheetType::None" />
       <option id="columns" type="int" default="0" />
+      <option id="rows" type="int" default="0" />
       <option id="width" type="int" default="0" />
       <option id="height" type="int" default="0" />
       <option id="best_fit" type="bool" default="false" />
@@ -256,6 +251,7 @@
       <option id="frame_tag" type="std::string" />
     </section>
     <section id="import_sprite_sheet">
+      <option id="type" type="app::SpriteSheetType" default="app::SpriteSheetType::Rows" />
       <option id="bounds" type="gfx::Rect" default="gfx::Rect(0, 0, 16, 16)" />
     </section>
   </document>
diff --git a/data/skins/default/skin.xml b/data/skins/default/skin.xml
index 63a5576..203fe57 100644
--- a/data/skins/default/skin.xml
+++ b/data/skins/default/skin.xml
@@ -101,6 +101,8 @@
     <color id="flag_normal" value="#d3cbbe" />
     <color id="flag_active" value="#ff0000" />
     <color id="flag_clicked" value="#7d929e" />
+    <color id="select_box_ruler" value="#0000ff" />
+    <color id="select_box_grid" value="#64c864" />
   </colors>
 
   <cursors>
diff --git a/data/widgets/export_sprite_sheet.xml b/data/widgets/export_sprite_sheet.xml
index 2b8aca9..a3a4ffb 100644
--- a/data/widgets/export_sprite_sheet.xml
+++ b/data/widgets/export_sprite_sheet.xml
@@ -6,10 +6,14 @@
     <label text="Sheet Type:" />
     <combobox id="sheet_type" cell_hspan="3" />
 
-    <label id="columns_label" text="Columns:" />
+    <label id="columns_label" text="# of Columns:" />
     <entry id="columns" text="" maxsize="4" />
     <boxfiller cell_hspan="2" />
 
+    <label id="rows_label" text="# of Rows:" />
+    <entry id="rows" text="" maxsize="4" />
+    <boxfiller cell_hspan="2" />
+
     <hbox />
     <vbox>
       <check id="padding_enabled" text="Padding" />
diff --git a/data/widgets/import_sprite_sheet.xml b/data/widgets/import_sprite_sheet.xml
index 12f219d..a6854e6 100644
--- a/data/widgets/import_sprite_sheet.xml
+++ b/data/widgets/import_sprite_sheet.xml
@@ -5,6 +5,9 @@
   <grid columns="4">
     <button id="select_file" text="Select File" cell_hspan="4" />
 
+    <label text="Type:" />
+    <combobox id="sheet_type" cell_hspan="3" />
+
     <label text="X" />
     <entry id="x" text="0" maxsize="4" />
     <label text="Width" />
diff --git a/src/app/app.cpp b/src/app/app.cpp
index 7155a02..55d72f2 100644
--- a/src/app/app.cpp
+++ b/src/app/app.cpp
@@ -218,6 +218,7 @@ void App::initialize(const AppOptions& options)
   bool ignoreEmpty = false;
   bool trim = false;
   Params cropParams;
+  SpriteSheetType sheetType = SpriteSheetType::None;
 
   // Open file specified in the command line
   if (!options.values().empty()) {
@@ -271,9 +272,21 @@ void App::initialize(const AppOptions& options)
             m_exporter->setTextureHeight(strtol(value.value().c_str(), NULL, 0));
         }
         // --sheet-pack
+        else if (opt == &options.sheetType()) {
+          if (value.value() == "horizontal")
+            sheetType = SpriteSheetType::Horizontal;
+          else if (value.value() == "vertical")
+            sheetType = SpriteSheetType::Vertical;
+          else if (value.value() == "rows")
+            sheetType = SpriteSheetType::Rows;
+          else if (value.value() == "columns")
+            sheetType = SpriteSheetType::Columns;
+          else if (value.value() == "packed")
+            sheetType = SpriteSheetType::Packed;
+        }
+        // --sheet-pack
         else if (opt == &options.sheetPack()) {
-          if (m_exporter)
-            m_exporter->setTexturePack(true);
+          sheetType = SpriteSheetType::Packed;
         }
         // --split-layers
         else if (opt == &options.splitLayers()) {
@@ -564,6 +577,9 @@ void App::initialize(const AppOptions& options)
   if (m_exporter) {
     LOG("Exporting sheet...\n");
 
+    if (sheetType != SpriteSheetType::None)
+      m_exporter->setSpriteSheetType(sheetType);
+
     if (ignoreEmpty)
       m_exporter->setIgnoreEmptyCels(true);
 
diff --git a/src/app/app_options.cpp b/src/app/app_options.cpp
index 8bf3b77..b9abab6 100644
--- a/src/app/app_options.cpp
+++ b/src/app/app_options.cpp
@@ -35,7 +35,8 @@ AppOptions::AppOptions(int argc, const char* argv[])
   , m_sheet(m_po.add("sheet").requiresValue("<filename.png>").description("Image file to save the texture"))
   , m_sheetWidth(m_po.add("sheet-width").requiresValue("<pixels>").description("Sprite sheet width"))
   , m_sheetHeight(m_po.add("sheet-height").requiresValue("<pixels>").description("Sprite sheet height"))
-  , m_sheetPack(m_po.add("sheet-pack").description("Use a packing algorithm to avoid waste of space\nin the texture"))
+  , m_sheetType(m_po.add("sheet-type").requiresValue("<type>").description("Algorithm to create the sprite sheet:\n  horizontal\n  vertical\n  rows\n  columns\n  packed"))
+  , m_sheetPack(m_po.add("sheet-pack").description("Same as --sheet-type packed"))
   , m_splitLayers(m_po.add("split-layers").description("Import each layer of the next given sprite as\na separated image in the sheet"))
   , m_layer(m_po.add("layer").alias("import-layer").requiresValue("<name>").description("Include just the given layer in the sheet"))
   , m_allLayers(m_po.add("all-layers").description("Make all layers visible\nBy default hidden layers will be ignored"))
diff --git a/src/app/app_options.h b/src/app/app_options.h
index 61fd560..dc3df68 100644
--- a/src/app/app_options.h
+++ b/src/app/app_options.h
@@ -43,6 +43,7 @@ public:
   const Option& sheet() const { return m_sheet; }
   const Option& sheetWidth() const { return m_sheetWidth; }
   const Option& sheetHeight() const { return m_sheetHeight; }
+  const Option& sheetType() const { return m_sheetType; }
   const Option& sheetPack() const { return m_sheetPack; }
   const Option& splitLayers() const { return m_splitLayers; }
   const Option& layer() const { return m_layer; }
@@ -82,6 +83,7 @@ private:
   Option& m_sheet;
   Option& m_sheetWidth;
   Option& m_sheetHeight;
+  Option& m_sheetType;
   Option& m_sheetPack;
   Option& m_splitLayers;
   Option& m_layer;
diff --git a/src/app/commands/cmd_canvas_size.cpp b/src/app/commands/cmd_canvas_size.cpp
index ad3307e..45fc8ad 100644
--- a/src/app/commands/cmd_canvas_size.cpp
+++ b/src/app/commands/cmd_canvas_size.cpp
@@ -49,9 +49,12 @@ public:
   CanvasSizeWindow()
     : m_editor(current_editor)
     , m_rect(0, 0, current_editor->sprite()->width(), current_editor->sprite()->height())
-    , m_selectBoxState(new SelectBoxState(this, m_rect,
-        SelectBoxState::RULERS |
-        SelectBoxState::DARKOUTSIDE)) {
+    , m_selectBoxState(
+      new SelectBoxState(
+        this, m_rect,
+        SelectBoxState::Flags(
+          int(SelectBoxState::Flags::Rulers) |
+          int(SelectBoxState::Flags::DarkOutside)))) {
     setWidth(m_rect.w);
     setHeight(m_rect.h);
     setLeft(0);
diff --git a/src/app/commands/cmd_export_sprite_sheet.cpp b/src/app/commands/cmd_export_sprite_sheet.cpp
index 8711066..580e686 100644
--- a/src/app/commands/cmd_export_sprite_sheet.cpp
+++ b/src/app/commands/cmd_export_sprite_sheet.cpp
@@ -54,11 +54,12 @@ namespace {
     int width;
     int height;
     int columns;
+    int rows;
     int freearea;
-    Fit() : width(0), height(0), columns(0), freearea(0) {
+    Fit() : width(0), height(0), columns(0), rows(0), freearea(0) {
     }
-    Fit(int width, int height, int columns, int freearea) :
-      width(width), height(height), columns(columns), freearea(freearea) {
+    Fit(int width, int height, int columns, int rows, int freearea) :
+      width(width), height(height), columns(columns), rows(rows), freearea(freearea) {
     }
   };
 
@@ -67,7 +68,7 @@ namespace {
   Fit best_fit(Sprite* sprite, int nframes, int borderPadding, int shapePadding, int innerPadding) {
     int framew = sprite->width()+2*innerPadding;
     int frameh = sprite->height()+2*innerPadding;
-    Fit result(framew*nframes, frameh, nframes, std::numeric_limits<int>::max());
+    Fit result(framew*nframes, frameh, nframes, 1, std::numeric_limits<int>::max());
     int w, h;
 
     for (w=2; w < framew; w*=2)
@@ -103,7 +104,7 @@ namespace {
         for (const gfx::Rect& rgnRect : rgn)
           freearea += rgnRect.w * rgnRect.h;
 
-        Fit fit(w, h, (w / framew), freearea);
+        Fit fit(w, h, (w / framew), (h / frameh), freearea);
         if (fit.freearea < result.freearea)
           result = fit;
       }
@@ -115,15 +116,22 @@ namespace {
     return result;
   }
 
-  Fit calculate_sheet_size(Sprite* sprite, int nframes, int columns,
+  Fit calculate_sheet_size(Sprite* sprite, int nframes,
+                           int columns, int rows,
                            int borderPadding, int shapePadding, int innerPadding) {
-    columns = MID(1, columns, nframes);
-    int rows = ((nframes/columns) + ((nframes%columns) > 0 ? 1: 0));
+    if (columns == 0) {
+      rows = MID(1, rows, nframes);
+      columns = ((nframes/rows) + ((nframes%rows) > 0 ? 1: 0));
+    }
+    else {
+      columns = MID(1, columns, nframes);
+      rows = ((nframes/columns) + ((nframes%columns) > 0 ? 1: 0));
+    }
 
     return Fit(
       2*borderPadding + (sprite->width()+2*innerPadding)*columns + (columns-1)*shapePadding,
       2*borderPadding + (sprite->height()+2*innerPadding)*rows + (rows-1)*shapePadding,
-      columns, 0);
+      columns, rows, 0);
   }
 
   bool ask_overwrite(bool askFilename, std::string filename,
@@ -270,16 +278,18 @@ public:
     , m_dataFilenameAskOverwrite(true)
   {
     static_assert(
-      (int)app::gen::SpriteSheetType::NONE == 0 &&
-      (int)app::gen::SpriteSheetType::HORIZONTAL_STRIP == 1 &&
-      (int)app::gen::SpriteSheetType::VERTICAL_STRIP == 2 &&
-      (int)app::gen::SpriteSheetType::MATRIX == 3,
-      "ExportType enum changed");
+      (int)app::SpriteSheetType::None == 0 &&
+      (int)app::SpriteSheetType::Horizontal == 1 &&
+      (int)app::SpriteSheetType::Vertical == 2 &&
+      (int)app::SpriteSheetType::Rows == 3 &&
+      (int)app::SpriteSheetType::Columns == 4,
+      "SpriteSheetType enum changed");
 
     sheetType()->addItem("Horizontal Strip");
     sheetType()->addItem("Vertical Strip");
-    sheetType()->addItem("Matrix");
-    if (m_docPref.spriteSheet.type() != app::gen::SpriteSheetType::NONE)
+    sheetType()->addItem("By Rows");
+    sheetType()->addItem("By Columns");
+    if (m_docPref.spriteSheet.type() != app::SpriteSheetType::None)
       sheetType()->setSelectedItemIndex((int)m_docPref.spriteSheet.type()-1);
 
     layers()->addItem("Visible layers");
@@ -329,6 +339,7 @@ public:
     }
     else {
       columns()->setTextf("%d", m_docPref.spriteSheet.columns());
+      rows()->setTextf("%d", m_docPref.spriteSheet.rows());
       onColumnsChange();
 
       if (m_docPref.spriteSheet.width() > 0 || m_docPref.spriteSheet.height() > 0) {
@@ -368,6 +379,7 @@ public:
     exportButton()->Click.connect(Bind<void>(&ExportSpriteSheetWindow::onExport, this));
     sheetType()->Change.connect(&ExportSpriteSheetWindow::onSheetTypeChange, this);
     columns()->Change.connect(Bind<void>(&ExportSpriteSheetWindow::onColumnsChange, this));
+    rows()->Change.connect(Bind<void>(&ExportSpriteSheetWindow::onRowsChange, this));
     fitWidth()->Change.connect(Bind<void>(&ExportSpriteSheetWindow::onSizeChange, this));
     fitHeight()->Change.connect(Bind<void>(&ExportSpriteSheetWindow::onSizeChange, this));
     bestFit()->Click.connect(Bind<void>(&ExportSpriteSheetWindow::onBestFit, this));
@@ -391,41 +403,51 @@ public:
     return getKiller() == exportButton();
   }
 
-  app::gen::SpriteSheetType spriteSheetTypeValue() {
-    return (app::gen::SpriteSheetType)(sheetType()->getSelectedItemIndex()+1);
+  app::SpriteSheetType spriteSheetTypeValue() const {
+    return (app::SpriteSheetType)(sheetType()->getSelectedItemIndex()+1);
   }
 
-  int columnsValue() {
-    return columns()->getTextInt();
+  int columnsValue() const {
+    if (spriteSheetTypeValue() != SpriteSheetType::Columns)
+      return columns()->getTextInt();
+    else
+      return 0;
+  }
+
+  int rowsValue() const {
+    if (spriteSheetTypeValue() == SpriteSheetType::Columns)
+      return rows()->getTextInt();
+    else
+      return 0;
   }
 
-  int fitWidthValue() {
+  int fitWidthValue() const {
     return fitWidth()->getEntryWidget()->getTextInt();
   }
 
-  int fitHeightValue() {
+  int fitHeightValue() const {
     return fitHeight()->getEntryWidget()->getTextInt();
   }
 
-  bool bestFitValue() {
+  bool bestFitValue() const {
     return bestFit()->isSelected();
   }
 
-  std::string filenameValue() {
+  std::string filenameValue() const {
     if (imageEnabled()->isSelected())
       return m_filename;
     else
       return std::string();
   }
 
-  std::string dataFilenameValue() {
+  std::string dataFilenameValue() const {
     if (dataEnabled()->isSelected())
       return m_dataFilename;
     else
       return std::string();
   }
 
-  int borderPaddingValue() {
+  int borderPaddingValue() const {
     if (paddingEnabled()->isSelected()) {
       int value = borderPadding()->getTextInt();
       return MID(0, value, 100);
@@ -434,7 +456,7 @@ public:
       return 0;
   }
 
-  int shapePaddingValue() {
+  int shapePaddingValue() const {
     if (paddingEnabled()->isSelected()) {
       int value = shapePadding()->getTextInt();
       return MID(0, value, 100);
@@ -443,7 +465,7 @@ public:
       return 0;
   }
 
-  int innerPaddingValue() {
+  int innerPaddingValue() const {
     if (paddingEnabled()->isSelected()) {
       int value = innerPadding()->getTextInt();
       return MID(0, value, 100);
@@ -452,11 +474,11 @@ public:
       return 0;
   }
 
-  bool openGeneratedValue() {
+  bool openGeneratedValue() const {
     return openGenerated()->isSelected();
   }
 
-  std::string layerValue() {
+  std::string layerValue() const {
     if (LayerItem* item = dynamic_cast<LayerItem*>(layers()->getSelectedItem()))
       return item->layer()->name();
     else if (layers()->getSelectedItemIndex() == 1)
@@ -465,7 +487,7 @@ public:
       return kAllLayers;
   }
 
-  std::string frameTagValue() {
+  std::string frameTagValue() const {
     if (TagItem* item = dynamic_cast<TagItem*>(frames()->getSelectedItem()))
       return item->tag()->name();
     else if (frames()->getSelectedItemIndex() == 1)
@@ -485,21 +507,33 @@ private:
   }
 
   void onSheetTypeChange() {
-    bool state = false;
+    bool rowsState = false;
+    bool colsState = false;
+    bool matrixState = false;
     switch (spriteSheetTypeValue()) {
-      case app::gen::SpriteSheetType::MATRIX:
-        state = true;
+      case app::SpriteSheetType::Rows:
+        colsState = true;
+        matrixState = true;
+        break;
+      case app::SpriteSheetType::Columns:
+        rowsState = true;
+        matrixState = true;
         break;
     }
 
-    columnsLabel()->setVisible(state);
-    columns()->setVisible(state);
-    fitWidthLabel()->setVisible(state);
-    fitWidth()->setVisible(state);
-    fitHeightLabel()->setVisible(state);
-    fitHeight()->setVisible(state);
-    bestFitFiller()->setVisible(state);
-    bestFit()->setVisible(state);
+    columnsLabel()->setVisible(colsState);
+    columns()->setVisible(colsState);
+
+    rowsLabel()->setVisible(rowsState);
+    rows()->setVisible(rowsState);
+
+    fitWidthLabel()->setVisible(matrixState);
+    fitWidth()->setVisible(matrixState);
+    fitHeightLabel()->setVisible(matrixState);
+    fitHeight()->setVisible(matrixState);
+    bestFitFiller()->setVisible(matrixState);
+    bestFit()->setVisible(matrixState);
+
     resize();
   }
 
@@ -514,8 +548,14 @@ private:
     updateSizeFields();
   }
 
+  void onRowsChange() {
+    bestFit()->setSelected(false);
+    updateSizeFields();
+  }
+
   void onSizeChange() {
     columns()->setTextf("%d", fitWidthValue() / m_sprite->width());
+    rows()->setTextf("%d", fitHeightValue() / m_sprite->height());
     bestFit()->setSelected(false);
   }
 
@@ -585,6 +625,7 @@ private:
   void resize() {
     gfx::Size reqSize = getPreferredSize();
     moveWindow(gfx::Rect(getOrigin(), reqSize));
+    layout();
     invalidate();
   }
 
@@ -614,13 +655,16 @@ private:
     }
     else {
       fit = calculate_sheet_size(
-        m_sprite, nframes, columnsValue(),
+        m_sprite, nframes,
+        columnsValue(),
+        rowsValue(),
         borderPaddingValue(),
         shapePaddingValue(),
         innerPaddingValue());
     }
 
     columns()->setTextf("%d", fit.columns);
+    rows()->setTextf("%d", fit.rows);
     fitWidth()->getEntryWidget()->setTextf("%d", fit.width);
     fitHeight()->getEntryWidget()->setTextf("%d", fit.height);
   }
@@ -692,6 +736,7 @@ void ExportSpriteSheetCommand::onExecute(Context* context)
 
     docPref.spriteSheet.type(window.spriteSheetTypeValue());
     docPref.spriteSheet.columns(window.columnsValue());
+    docPref.spriteSheet.rows(window.rowsValue());
     docPref.spriteSheet.width(window.fitWidthValue());
     docPref.spriteSheet.height(window.fitHeightValue());
     docPref.spriteSheet.bestFit(window.bestFitValue());
@@ -716,8 +761,9 @@ void ExportSpriteSheetCommand::onExecute(Context* context)
     askOverwrite = false; // Already asked in the ExportSpriteSheetWindow
   }
 
-  app::gen::SpriteSheetType type = docPref.spriteSheet.type();
+  app::SpriteSheetType type = docPref.spriteSheet.type();
   int columns = docPref.spriteSheet.columns();
+  int rows = docPref.spriteSheet.rows();
   int width = docPref.spriteSheet.width();
   int height = docPref.spriteSheet.height();
   bool bestFit = docPref.spriteSheet.bestFit();
@@ -777,6 +823,7 @@ void ExportSpriteSheetCommand::onExecute(Context* context)
   if (bestFit) {
     Fit fit = best_fit(sprite, nframes, borderPadding, shapePadding, innerPadding);
     columns = fit.columns;
+    rows = fit.rows;
     width = fit.width;
     height = fit.height;
   }
@@ -785,24 +832,25 @@ void ExportSpriteSheetCommand::onExecute(Context* context)
   int sheet_h = 0;
 
   switch (type) {
-    case app::gen::SpriteSheetType::HORIZONTAL_STRIP:
+    case app::SpriteSheetType::Horizontal:
       columns = sprite->totalFrames();
+      rows = 1;
       break;
-    case app::gen::SpriteSheetType::VERTICAL_STRIP:
+    case app::SpriteSheetType::Vertical:
       columns = 1;
+      rows = nframes;
       break;
-    case app::gen::SpriteSheetType::MATRIX:
+    case app::SpriteSheetType::Rows:
+    case app::SpriteSheetType::Columns:
       if (width > 0) sheet_w = width;
       if (height > 0) sheet_h = height;
       break;
   }
 
   Fit fit = calculate_sheet_size(
-    sprite,
-    nframes,
-    columns,
+    sprite, nframes,
+    columns, rows,
     borderPadding, shapePadding, innerPadding);
-  columns = fit.columns;
   if (sheet_w == 0) sheet_w = fit.width;
   if (sheet_h == 0) sheet_h = fit.height;
 
@@ -813,7 +861,7 @@ void ExportSpriteSheetCommand::onExecute(Context* context)
     exporter.setDataFilename(dataFilename);
   exporter.setTextureWidth(sheet_w);
   exporter.setTextureHeight(sheet_h);
-  exporter.setTexturePack(false);
+  exporter.setSpriteSheetType(type);
   exporter.setBorderPadding(borderPadding);
   exporter.setShapePadding(shapePadding);
   exporter.setInnerPadding(innerPadding);
diff --git a/src/app/commands/cmd_import_sprite_sheet.cpp b/src/app/commands/cmd_import_sprite_sheet.cpp
index fa5572b..c49cc48 100644
--- a/src/app/commands/cmd_import_sprite_sheet.cpp
+++ b/src/app/commands/cmd_import_sprite_sheet.cpp
@@ -54,6 +54,20 @@ public:
     , m_docPref(nullptr) {
     import()->setEnabled(false);
 
+    static_assert(
+      (int)app::SpriteSheetType::Horizontal == 1 &&
+      (int)app::SpriteSheetType::Vertical == 2 &&
+      (int)app::SpriteSheetType::Rows == 3 &&
+      (int)app::SpriteSheetType::Columns == 4,
+      "SpriteSheetType enum changed");
+
+    sheetType()->addItem("Horizontal Strip");
+    sheetType()->addItem("Vertical Strip");
+    sheetType()->addItem("By Rows");
+    sheetType()->addItem("By Columns");
+    sheetType()->setSelectedItemIndex((int)app::SpriteSheetType::Rows-1);
+
+    sheetType()->Change.connect(Bind<void>(&ImportSpriteSheetWindow::onSheetTypeChange, this));
     x()->Change.connect(Bind<void>(&ImportSpriteSheetWindow::onEntriesChange, this));
     y()->Change.connect(Bind<void>(&ImportSpriteSheetWindow::onEntriesChange, this));
     width()->Change.connect(Bind<void>(&ImportSpriteSheetWindow::onEntriesChange, this));
@@ -74,6 +88,10 @@ public:
     releaseEditor();
   }
 
+  SpriteSheetType sheetTypeValue() const {
+    return (app::SpriteSheetType)(sheetType()->getSelectedItemIndex()+1);
+  }
+
   bool ok() const {
     return getKiller() == import();
   }
@@ -92,6 +110,10 @@ public:
 
 protected:
 
+  void onSheetTypeChange() {
+    updateGridState();
+  }
+
   void onSelectFile() {
     Document* oldActiveDocument = m_context->activeDocument();
     Command* openFile = CommandsModule::instance()->getCommandByName(CommandId::OpenFile);
@@ -107,8 +129,7 @@ protected:
     }
   }
 
-  gfx::Rect getRectFromEntries()
-  {
+  gfx::Rect getRectFromEntries() {
     int w = width()->getTextInt();
     int h = height()->getTextInt();
 
@@ -119,8 +140,7 @@ protected:
       std::max<int>(1, h));
   }
 
-  void onEntriesChange()
-  {
+  void onEntriesChange() {
     m_rect = getRectFromEntries();
 
     // Redraw new rulers position
@@ -187,6 +207,12 @@ private:
     if (m_document) {
       m_docPref = &Preferences::instance().document(m_document);
 
+      if (m_docPref->importSpriteSheet.type() >= app::SpriteSheetType::Horizontal &&
+          m_docPref->importSpriteSheet.type() <= app::SpriteSheetType::Columns)
+        sheetType()->setSelectedItemIndex((int)m_docPref->importSpriteSheet.type()-1);
+      else
+        sheetType()->setSelectedItemIndex((int)app::SpriteSheetType::Rows-1);
+
       onChangeRectangle(m_docPref->importSpriteSheet.bounds());
       onEntriesChange();
     }
@@ -198,12 +224,38 @@ private:
     if (m_document && !m_editor) {
       m_rect = getRectFromEntries();
       m_editor = current_editor;
+      m_editorState.reset(
+        new SelectBoxState(
+          this, m_rect,
+          SelectBoxState::Flags(
+            int(SelectBoxState::Flags::Rulers) |
+            int(SelectBoxState::Flags::Grid))));
+
+      m_editor->setState(m_editorState);
+      updateGridState();
+    }
+  }
+
+  void updateGridState() {
+    if (!m_editorState)
+      return;
 
-      EditorStatePtr newState(new SelectBoxState(this, m_rect,
-                                                 SelectBoxState::RULERS |
-                                                 SelectBoxState::GRID));
-      m_editor->setState(newState);
+    int flags = int(SelectBoxState::Flags::Rulers);
+    switch (sheetTypeValue()) {
+      case SpriteSheetType::Horizontal:
+        flags |= int(SelectBoxState::Flags::HGrid);
+        break;
+      case SpriteSheetType::Vertical:
+        flags |= int(SelectBoxState::Flags::VGrid);
+        break;
+      case SpriteSheetType::Rows:
+      case SpriteSheetType::Columns:
+        flags |= int(SelectBoxState::Flags::Grid);
+        break;
     }
+
+    static_cast<SelectBoxState*>(m_editorState.get())->setFlags(SelectBoxState::Flags(flags));
+    m_editor->invalidate();
   }
 
   void releaseEditor() {
@@ -216,6 +268,7 @@ private:
   Context* m_context;
   Document* m_document;
   Editor* m_editor;
+  EditorStatePtr m_editorState;
   gfx::Rect m_rect;
 
   // True if the user has been opened the file (instead of selecting
@@ -252,6 +305,7 @@ void ImportSpriteSheetCommand::onExecute(Context* context)
   Document* document = window.document();
   DocumentPreferences* docPref = window.docPref();
   gfx::Rect frameBounds = window.frameBounds();
+  auto sheetType = window.sheetTypeValue();
 
   ASSERT(document);
   if (!document)
@@ -265,18 +319,48 @@ void ImportSpriteSheetCommand::onExecute(Context* context)
     frame_t currentFrame = context->activeSite().frame();
     render::Render render;
 
+    // Each sprite in the sheet
+    std::vector<gfx::Rect> tileRects;
+
+    switch (sheetType) {
+      case app::SpriteSheetType::Horizontal:
+        for (int x=frameBounds.x; x+frameBounds.w<=sprite->width(); x += frameBounds.w) {
+          tileRects.push_back(gfx::Rect(x, frameBounds.y, frameBounds.w, frameBounds.h));
+        }
+        break;
+      case app::SpriteSheetType::Vertical:
+        for (int y=frameBounds.y; y+frameBounds.h<=sprite->height(); y += frameBounds.h) {
+          tileRects.push_back(gfx::Rect(frameBounds.x, y, frameBounds.w, frameBounds.h));
+        }
+        break;
+      case app::SpriteSheetType::Rows:
+        for (int y=frameBounds.y; y+frameBounds.h<=sprite->height(); y += frameBounds.h) {
+          for (int x=frameBounds.x; x+frameBounds.w<=sprite->width(); x += frameBounds.w) {
+            tileRects.push_back(gfx::Rect(x, y, frameBounds.w, frameBounds.h));
+          }
+        }
+        break;
+      case app::SpriteSheetType::Columns:
+        for (int x=frameBounds.x; x+frameBounds.w<=sprite->width(); x += frameBounds.w) {
+          for (int y=frameBounds.y; y+frameBounds.h<=sprite->height(); y += frameBounds.h) {
+            tileRects.push_back(gfx::Rect(x, y, frameBounds.w, frameBounds.h));
+          }
+        }
+        break;
+    }
+
     // As first step, we cut each tile and add them into "animation" list.
-    for (int y=frameBounds.y; y<sprite->height(); y += frameBounds.h) {
-      for (int x=frameBounds.x; x<sprite->width(); x += frameBounds.w) {
-        ImageRef resultImage(
-          Image::create(sprite->pixelFormat(), frameBounds.w, frameBounds.h));
+    for (const auto& tileRect : tileRects) {
+      ImageRef resultImage(
+        Image::create(
+          sprite->pixelFormat(), tileRect.w, tileRect.h));
 
-        // Render the portion of sheet.
-        render.renderSprite(resultImage.get(), sprite, currentFrame,
-          gfx::Clip(0, 0, x, y, frameBounds.w, frameBounds.h));
+      // Render the portion of sheet.
+      render.renderSprite(
+        resultImage.get(), sprite, currentFrame,
+        gfx::Clip(0, 0, tileRect));
 
-        animation.push_back(resultImage);
-      }
+      animation.push_back(resultImage);
     }
 
     if (animation.size() == 0) {
@@ -324,8 +408,10 @@ void ImportSpriteSheetCommand::onExecute(Context* context)
     transaction.commit();
 
     ASSERT(docPref);
-    if (docPref)
+    if (docPref) {
+      docPref->importSpriteSheet.type(sheetType);
       docPref->importSpriteSheet.bounds(frameBounds);
+    }
   }
   catch (...) {
     throw;
diff --git a/src/app/commands/cmd_new_brush.cpp b/src/app/commands/cmd_new_brush.cpp
index 4f1811e..06509a5 100644
--- a/src/app/commands/cmd_new_brush.cpp
+++ b/src/app/commands/cmd_new_brush.cpp
@@ -87,8 +87,9 @@ void NewBrushCommand::onExecute(Context* context)
       EditorStatePtr(
         new SelectBoxState(
           this, current_editor->sprite()->bounds(),
-          SelectBoxState::DARKOUTSIDE |
-          SelectBoxState::QUICKBOX)));
+          SelectBoxState::Flags(
+            int(SelectBoxState::Flags::DarkOutside) |
+            int(SelectBoxState::Flags::QuickBox)))));
   }
   // Create a brush from the active selection
   else {
diff --git a/src/app/commands/cmd_repeat_last_export.cpp b/src/app/commands/cmd_repeat_last_export.cpp
index 874cb6d..5b8c13e 100644
--- a/src/app/commands/cmd_repeat_last_export.cpp
+++ b/src/app/commands/cmd_repeat_last_export.cpp
@@ -53,7 +53,7 @@ void RepeatLastExportCommand::onExecute(Context* context)
       Preferences::instance().document(document);
 
     params.set("ui",
-      (docPref.spriteSheet.type() == app::gen::SpriteSheetType::NONE ? "1": "0"));
+      (docPref.spriteSheet.type() == app::SpriteSheetType::None ? "1": "0"));
   }
 
   context->executeCommand(cmd, params);
diff --git a/src/app/document_exporter.cpp b/src/app/document_exporter.cpp
index 8627297..1aaf4eb 100644
--- a/src/app/document_exporter.cpp
+++ b/src/app/document_exporter.cpp
@@ -202,6 +202,10 @@ public:
 class DocumentExporter::SimpleLayoutSamples :
     public DocumentExporter::LayoutSamples {
 public:
+  SimpleLayoutSamples(SpriteSheetType type)
+    : m_type(type) {
+  }
+
   void layoutSamples(Samples& samples, int borderPadding, int shapePadding, int& width, int& height) override {
     const Sprite* oldSprite = NULL;
     const Layer* oldLayer = NULL;
@@ -218,36 +222,67 @@ public:
       gfx::Size size = sample.requiredSize();
 
       if (oldSprite) {
-        // If the user didn't specify a width for the texture, we put
-        // each sprite/layer in a different row.
-        if (width == 0) {
-          // New sprite or layer, go to next row.
-          if (oldSprite != sprite || oldLayer != layer) {
+        if (m_type == SpriteSheetType::Columns) {
+          // If the user didn't specify a height for the texture, we
+          // put each sprite/layer in a different column.
+          if (height == 0) {
+            // New sprite or layer, go to next column.
+            if (oldSprite != sprite || oldLayer != layer) {
+              framePt.x += rowSize.w + shapePadding;
+              framePt.y = borderPadding;
+              rowSize = size;
+            }
+          }
+          // When a texture height is specified, we can put different
+          // sprites/layers in each column until we reach the texture
+          // bottom-border.
+          else if (framePt.y+size.h > height-borderPadding) {
+            framePt.x += rowSize.w + shapePadding;
+            framePt.y = borderPadding;
+            rowSize = size;
+          }
+        }
+        else {
+          // If the user didn't specify a width for the texture, we put
+          // each sprite/layer in a different row.
+          if (width == 0) {
+            // New sprite or layer, go to next row.
+            if (oldSprite != sprite || oldLayer != layer) {
+              framePt.x = borderPadding;
+              framePt.y += rowSize.h + shapePadding;
+              rowSize = size;
+            }
+          }
+          // When a texture width is specified, we can put different
+          // sprites/layers in each row until we reach the texture
+          // right-border.
+          else if (framePt.x+size.w > width-borderPadding) {
             framePt.x = borderPadding;
             framePt.y += rowSize.h + shapePadding;
             rowSize = size;
           }
         }
-        // When a texture width is specified, we can put different
-        // sprites/layers in each row until we reach the texture
-        // right-border.
-        else if (framePt.x+size.w > width-borderPadding) {
-          framePt.x = borderPadding;
-          framePt.y += rowSize.h + shapePadding;
-          rowSize = size;
-        }
       }
 
       sample.setInTextureBounds(gfx::Rect(framePt, size));
 
       // Next frame position.
-      framePt.x += size.w + shapePadding;
+      if (m_type == SpriteSheetType::Columns) {
+        framePt.y += size.h + shapePadding;
+      }
+      else {
+        framePt.x += size.w + shapePadding;
+      }
+
       rowSize = rowSize.createUnion(size);
 
       oldSprite = sprite;
       oldLayer = layer;
     }
   }
+
+private:
+  SpriteSheetType m_type;
 };
 
 class DocumentExporter::BestFitLayoutSamples :
@@ -290,7 +325,7 @@ DocumentExporter::DocumentExporter()
  , m_textureFormat(DefaultTextureFormat)
  , m_textureWidth(0)
  , m_textureHeight(0)
- , m_texturePack(false)
+ , m_sheetType(SpriteSheetType::None)
  , m_scale(1.0)
  , m_scaleMode(DefaultScaleMode)
  , m_ignoreEmptyCels(false)
@@ -327,15 +362,21 @@ Document* DocumentExporter::exportSheet()
   }
 
   // 2) Layout those samples in a texture field.
-  if (m_texturePack) {
-    BestFitLayoutSamples layout;
-    layout.layoutSamples(samples,
-      m_borderPadding, m_shapePadding, m_textureWidth, m_textureHeight);
-  }
-  else {
-    SimpleLayoutSamples layout;
-    layout.layoutSamples(samples,
-      m_borderPadding, m_shapePadding, m_textureWidth, m_textureHeight);
+  switch (m_sheetType) {
+    case SpriteSheetType::Packed: {
+      BestFitLayoutSamples layout;
+      layout.layoutSamples(
+        samples, m_borderPadding, m_shapePadding,
+        m_textureWidth, m_textureHeight);
+      break;
+    }
+    default: {
+      SimpleLayoutSamples layout(m_sheetType);
+      layout.layoutSamples(
+        samples, m_borderPadding, m_shapePadding,
+        m_textureWidth, m_textureHeight);
+      break;
+    }
   }
 
   // 3) Create and render the texture.
diff --git a/src/app/document_exporter.h b/src/app/document_exporter.h
index 692e1e2..8a3ca2a 100644
--- a/src/app/document_exporter.h
+++ b/src/app/document_exporter.h
@@ -9,6 +9,7 @@
 #define APP_DOCUMENT_EXPORTER_H_INCLUDED
 #pragma once
 
+#include "app/sprite_sheet_type.h"
 #include "base/disable_copying.h"
 #include "doc/image_buffer.h"
 #include "gfx/fwd.h"
@@ -51,7 +52,7 @@ namespace app {
     void setTextureFilename(const std::string& filename) { m_textureFilename = filename; }
     void setTextureWidth(int width) { m_textureWidth = width; }
     void setTextureHeight(int height) { m_textureHeight = height; }
-    void setTexturePack(bool state) { m_texturePack = state; }
+    void setSpriteSheetType(SpriteSheetType type) { m_sheetType = type; }
     void setScale(double scale) { m_scale = scale; }
     void setScaleMode(ScaleMode mode) { m_scaleMode = mode; }
     void setIgnoreEmptyCels(bool ignore) { m_ignoreEmptyCels = ignore; }
@@ -112,7 +113,7 @@ namespace app {
     std::string m_textureFilename;
     int m_textureWidth;
     int m_textureHeight;
-    bool m_texturePack;
+    SpriteSheetType m_sheetType;
     double m_scale;
     ScaleMode m_scaleMode;
     bool m_ignoreEmptyCels;
diff --git a/src/app/pref/preferences.h b/src/app/pref/preferences.h
index 2c559f7..692b69c 100644
--- a/src/app/pref/preferences.h
+++ b/src/app/pref/preferences.h
@@ -11,6 +11,7 @@
 
 #include "app/color.h"
 #include "app/pref/option.h"
+#include "app/sprite_sheet_type.h"
 #include "app/tools/freehand_algorithm.h"
 #include "app/tools/ink_type.h"
 #include "app/tools/rotation_algorithm.h"
diff --git a/src/app/sprite_sheet_type.h b/src/app/sprite_sheet_type.h
new file mode 100644
index 0000000..5788932
--- /dev/null
+++ b/src/app/sprite_sheet_type.h
@@ -0,0 +1,25 @@
+// Aseprite
+// Copyright (C) 2001-2015  David Capello
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+
+#ifndef APP_SPRITE_SHEET_TYPE_H_INCLUDED
+#define APP_SPRITE_SHEET_TYPE_H_INCLUDED
+#pragma once
+
+namespace app {
+
+  enum class SpriteSheetType {
+    None,
+    Horizontal,
+    Vertical,
+    Rows,
+    Columns,
+    Packed
+  };
+
+} // namespace app
+
+#endif
diff --git a/src/app/ui/editor/select_box_state.cpp b/src/app/ui/editor/select_box_state.cpp
index 2865683..ea5fd74 100644
--- a/src/app/ui/editor/select_box_state.cpp
+++ b/src/app/ui/editor/select_box_state.cpp
@@ -12,10 +12,11 @@
 #include "app/ui/editor/select_box_state.h"
 
 #include "app/app.h"
-#include "app/ui/main_window.h"
-#include "app/ui/context_bar.h"
 #include "app/tools/tool_box.h"
+#include "app/ui/context_bar.h"
 #include "app/ui/editor/editor.h"
+#include "app/ui/main_window.h"
+#include "app/ui/skin/skin_theme.h"
 #include "doc/image.h"
 #include "doc/sprite.h"
 #include "gfx/rect.h"
@@ -43,6 +44,11 @@ SelectBoxState::~SelectBoxState()
   contextBar->updateForCurrentTool();
 }
 
+void SelectBoxState::setFlags(Flags flags)
+{
+  m_flags = flags;
+}
+
 gfx::Rect SelectBoxState::getBoxBounds() const
 {
   int x1 = std::min(m_rulers[V1].getPosition(), m_rulers[V2].getPosition());
@@ -79,7 +85,7 @@ bool SelectBoxState::onMouseDown(Editor* editor, MouseMessage* msg)
   if (msg->left() || msg->right()) {
     m_movingRuler = -1;
 
-    if (hasFlag(RULERS)) {
+    if (hasFlag(Flags::Rulers)) {
       for (int i=0; i<(int)m_rulers.size(); ++i) {
         if (touchRuler(editor, m_rulers[i], msg->position().x, msg->position().y)) {
           m_movingRuler = i;
@@ -88,7 +94,7 @@ bool SelectBoxState::onMouseDown(Editor* editor, MouseMessage* msg)
       }
     }
 
-    if (hasFlag(QUICKBOX) && m_movingRuler == -1) {
+    if (hasFlag(Flags::QuickBox) && m_movingRuler == -1) {
       m_selectingBox = true;
       m_selectingButtons = msg->buttons();
       m_startingPos = editor->screenToEditor(msg->position());
@@ -125,7 +131,7 @@ bool SelectBoxState::onMouseMove(Editor* editor, MouseMessage* msg)
 
   updateContextBar();
 
-  if (hasFlag(RULERS) && m_movingRuler >= 0) {
+  if (hasFlag(Flags::Rulers) && m_movingRuler >= 0) {
     gfx::Point pt = editor->screenToEditor(msg->position());
 
     switch (m_rulers[m_movingRuler].getOrientation()) {
@@ -141,7 +147,7 @@ bool SelectBoxState::onMouseMove(Editor* editor, MouseMessage* msg)
     used = true;
   }
 
-  if (hasFlag(QUICKBOX) && m_selectingBox) {
+  if (hasFlag(Flags::QuickBox) && m_selectingBox) {
     gfx::Point p1 = m_startingPos;
     gfx::Point p2 = editor->screenToEditor(msg->position());
 
@@ -167,7 +173,7 @@ bool SelectBoxState::onMouseMove(Editor* editor, MouseMessage* msg)
 
 bool SelectBoxState::onSetCursor(Editor* editor, const gfx::Point& mouseScreenPos)
 {
-  if (hasFlag(RULERS)) {
+  if (hasFlag(Flags::Rulers)) {
     if (m_movingRuler >= 0) {
       switch (m_rulers[m_movingRuler].getOrientation()) {
 
@@ -210,7 +216,7 @@ bool SelectBoxState::acceptQuickTool(tools::Tool* tool)
 
 bool SelectBoxState::requireBrushPreview()
 {
-  if (hasFlag(QUICKBOX))
+  if (hasFlag(Flags::QuickBox))
     return true;
 
   // Returns false as it overrides default standby state behavior &
@@ -220,7 +226,7 @@ bool SelectBoxState::requireBrushPreview()
 
 tools::Ink* SelectBoxState::getStateInk()
 {
-  if (hasFlag(QUICKBOX))
+  if (hasFlag(Flags::QuickBox))
     return App::instance()->getToolBox()->getInkById(
       tools::WellKnownInks::Selection);
   else
@@ -230,7 +236,7 @@ tools::Ink* SelectBoxState::getStateInk()
 void SelectBoxState::preRenderDecorator(EditorPreRender* render)
 {
   // Without black shadow?
-  if (!hasFlag(DARKOUTSIDE))
+  if (!hasFlag(Flags::DarkOutside))
     return;
 
   gfx::Rect rc = getBoxBounds();
@@ -259,29 +265,43 @@ void SelectBoxState::postRenderDecorator(EditorPostRender* render)
 {
   Editor* editor = render->getEditor();
   render::Zoom zoom = editor->zoom();
+  gfx::Rect sp = editor->sprite()->bounds();
   gfx::Rect vp = View::getView(editor)->getViewportBounds();
   vp.w += zoom.apply(1);
   vp.h += zoom.apply(1);
   vp = editor->screenToEditor(vp);
 
   // Paint a grid generated by the box
-  if (hasFlag(GRID)) {
-    gfx::Color gridColor = gfx::rgba(100, 200, 100);
-    gfx::Rect boxBounds = getBoxBounds();
-
-    if (boxBounds.w > 0)
-      for (int x=boxBounds.x+boxBounds.w*2; x<vp.x+vp.w; x+=boxBounds.w)
-        render->drawLine(x, boxBounds.y, x, vp.y+vp.h-1, gridColor);
+  gfx::Color rulerColor = skin::SkinTheme::instance()->colors.selectBoxRuler();
+  gfx::Color gridColor = skin::SkinTheme::instance()->colors.selectBoxGrid();
+  gfx::Rect boxBounds = getBoxBounds();
+
+  if (hasFlag(Flags::Grid)) {
+    if (boxBounds.w > 0) {
+      for (int x=boxBounds.x+boxBounds.w*2; x<=sp.x+sp.w; x+=boxBounds.w)
+        render->drawLine(x, boxBounds.y, x, sp.y+sp.h, gridColor);
+    }
 
-    if (boxBounds.h > 0)
-      for (int y=boxBounds.y+boxBounds.h*2; y<vp.y+vp.h; y+=boxBounds.h)
-        render->drawLine(boxBounds.x, y, vp.x+vp.w-1, y, gridColor);
+    if (boxBounds.h > 0) {
+      for (int y=boxBounds.y+boxBounds.h*2; y<=sp.y+sp.h; y+=boxBounds.h)
+        render->drawLine(boxBounds.x, y, sp.x+sp.w, y, gridColor);
+    }
+  }
+  else if (hasFlag(Flags::HGrid)) {
+    if (boxBounds.w > 0) {
+      for (int x=boxBounds.x+boxBounds.w*2; x<=sp.x+sp.w; x+=boxBounds.w)
+        render->drawLine(x, boxBounds.y, x, boxBounds.y+boxBounds.h, gridColor);
+    }
+  }
+  else if (hasFlag(Flags::VGrid)) {
+    if (boxBounds.h > 0) {
+      for (int y=boxBounds.y+boxBounds.h*2; y<=sp.y+sp.h; y+=boxBounds.h)
+        render->drawLine(boxBounds.x, y, boxBounds.x+boxBounds.w, y, gridColor);
+    }
   }
 
   // Draw the rulers enclosing the box
-  if (hasFlag(RULERS)) {
-    gfx::Color rulerColor = gfx::rgba(0, 0, 255);
-
+  if (hasFlag(Flags::Rulers)) {
     for (Rulers::iterator it = m_rulers.begin(), end = m_rulers.end(); it != end; ++it) {
       switch (it->getOrientation()) {
 
@@ -296,8 +316,8 @@ void SelectBoxState::postRenderDecorator(EditorPostRender* render)
     }
   }
 
-  if (hasFlag(QUICKBOX)) {
-    render->drawRectXor(getBoxBounds());
+  if (hasFlag(Flags::QuickBox)) {
+    render->drawRectXor(boxBounds);
   }
 }
 
@@ -322,7 +342,7 @@ bool SelectBoxState::touchRuler(Editor* editor, Ruler& ruler, int x, int y)
 
 bool SelectBoxState::hasFlag(Flags flag) const
 {
-  return ((m_flags & flag) == flag);
+  return (int(m_flags) & int(flag)) == int(flag);
 }
 
 } // namespace app
diff --git a/src/app/ui/editor/select_box_state.h b/src/app/ui/editor/select_box_state.h
index c632dd4..15bb0f4 100644
--- a/src/app/ui/editor/select_box_state.h
+++ b/src/app/ui/editor/select_box_state.h
@@ -41,17 +41,33 @@ namespace app {
     enum { H1, H2, V1, V2 };
 
   public:
-    typedef int Flags;
-    static const int RULERS = 1;      // Draw rulers at each edge of the current box
-    static const int DARKOUTSIDE = 2; // The outside of the box must be darker
-    static const int GRID = 4;        // Draw a grid
-    static const int QUICKBOX = 8;    // Select the box as in selection tool, drawing a boxu
+    enum class Flags {
+      // Draw rulers at each edge of the current box
+      Rulers = 1,
+
+      // The outside of the current box must be darker (used in "Canvas Size" command)
+      DarkOutside = 2,
+
+      // Show a horizontal array of boxes starting from the current box
+      HGrid = 4,
+
+      // Show a vertical array of boxes starting from the current box
+      VGrid = 8,
+
+      // Show a grid starting from the current box
+      Grid = (HGrid | VGrid),
+
+      // Select the box as in selection tool, drawing a boxu
+      QuickBox = 16,
+    };
 
     SelectBoxState(SelectBoxDelegate* delegate,
                    const gfx::Rect& rc,
                    Flags flags);
     ~SelectBoxState();
 
+    void setFlags(Flags flags);
+
     // Returns the bounding box arranged by the rulers.
     gfx::Rect getBoxBounds() const;
     void setBoxBounds(const gfx::Rect& rc);

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/aseprite.git



More information about the Pkg-games-commits mailing list