Add Import Sprite Sheet padding (fix #78)

This commit is contained in:
Gaspar Capello 2019-01-21 15:16:32 -03:00 committed by David Capello
parent 67e0da478d
commit d4607e889b
6 changed files with 364 additions and 71 deletions

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Aseprite -->
<!-- Copyright (C) 2018 Igara Studio S.A. -->
<!-- Copyright (C) 2018-2019 Igara Studio S.A. -->
<!-- Copyright (C) 2014-2018 David Capello -->
<preferences>
@ -436,6 +436,7 @@
<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, 0, 0)" />
<option id="padding_bounds" type="gfx::Size" default="gfx::Size(0, 0)" />
<option id="partial_tiles" type="bool" default="false" />
</section>
<section id="preview" text="Preview">

View File

@ -1,5 +1,5 @@
# Aseprite
# Copyright (C) 2018 Igara Studio S.A.
# Copyright (C) 2018-2019 Igara Studio S.A.
# Copyright (C) 2016-2018 David Capello
[advanced_mode]
@ -624,6 +624,8 @@ x = X:
y = Y:
width = Width:
height = Height:
horizontal_padding = Horizontal:
vertical_padding = Vertical:
partial_tiles = Include partial tiles at bottom/right edges
import = &Import
cancel = &Cancel

View File

@ -1,34 +1,49 @@
<!-- Aseprite -->
<!-- Copyright (C) 2019 by Igara Studio S.A. -->
<!-- Copyright (C) 2001-2018 by David Capello -->
<gui>
<window id="import_sprite_sheet" text="@.title">
<grid columns="4">
<button id="select_file" text="@.select_file" cell_hspan="4" />
<vbox>
<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="@.type" />
<combobox id="sheet_type" cell_hspan="3" />
<label text="@.x" />
<expr id="x" text="0" />
<separator text="Tiles:" horizontal="true" cell_hspan="4" />
<label text="@.y" />
<expr id="y" text="0" />
<label text="@.x" />
<expr id="x" text="0" />
<label text="@.width" />
<expr id="width" text="16" />
<label text="@.y" />
<expr id="y" text="0" />
<label text="@.height" />
<expr id="height" text="16" />
<label text="@.width" />
<expr id="width" text="16" />
<check id="partial_tiles" text="@.partial_tiles" cell_hspan="4" />
<label text="@.height" />
<expr id="height" text="16" />
<hbox cell_hspan="4">
<boxfiller />
<hbox>
</hbox>
<button id="import" text="@.import" minwidth="60" magnet="true" cell_align="center" closewindow="true" />
<button id="cancel" text="@.cancel" minwidth="60" cell_align="center" closewindow="true" />
</hbox>
</grid>
<separator text="Padding:" horizontal="true" cell_hspan="4" />
<label text="@.horizontal_padding" />
<expr id="horizontal_padding" text="0" />
<label text="" cell_hspan="2" />
<label text="@.vertical_padding" />
<expr id="vertical_padding" text="0" />
<label text="" cell_hspan="2" />
<check id="partial_tiles" text="@.partial_tiles" cell_hspan="4" />
<hbox cell_hspan="4">
<boxfiller />
<hbox>
</hbox>
<button id="import" text="@.import" minwidth="60" magnet="true" cell_align="center" closewindow="true" />
<button id="cancel" text="@.cancel" minwidth="60" cell_align="center" closewindow="true" />
</hbox>
</grid>
</vbox>
</window>
</gui>

View File

@ -1,4 +1,5 @@
// Aseprite
// Copyright (C) 2019 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
@ -73,6 +74,9 @@ public:
y()->Change.connect(base::Bind<void>(&ImportSpriteSheetWindow::onEntriesChange, this));
width()->Change.connect(base::Bind<void>(&ImportSpriteSheetWindow::onEntriesChange, this));
height()->Change.connect(base::Bind<void>(&ImportSpriteSheetWindow::onEntriesChange, this));
horizontalPadding()->Change.connect(base::Bind<void>(&ImportSpriteSheetWindow::onEntriesChange, this));
verticalPadding()->Change.connect(base::Bind<void>(&ImportSpriteSheetWindow::onEntriesChange, this));
partialTiles()->Click.connect(base::Bind<void>(&ImportSpriteSheetWindow::onEntriesChange, this));
selectFile()->Click.connect(base::Bind<void>(&ImportSpriteSheetWindow::onSelectFile, this));
remapWindow();
@ -113,6 +117,10 @@ public:
return m_rect;
}
gfx::Size paddingThickness() const {
return m_padding;
}
protected:
void onSheetTypeChange() {
@ -144,16 +152,31 @@ protected:
std::max<int>(1, h));
}
gfx::Size getPaddingFromEntries() {
int padW = horizontalPadding()->textInt();
int padH = verticalPadding()->textInt();
if (padW < 0)
padW = 0;
if (padH < 0)
padH = 0;
return gfx::Size(padW, padH);
}
void onEntriesChange() {
m_rect = getRectFromEntries();
m_padding = getPaddingFromEntries();
// Redraw new rulers position
if (m_editor) {
EditorStatePtr state = m_editor->getState();
if (SelectBoxState* boxState = dynamic_cast<SelectBoxState*>(state.get())) {
boxState->setBoxBounds(m_rect);
m_editor->invalidate();
}
SelectBoxState* boxState = dynamic_cast<SelectBoxState*>(state.get());
boxState->setBoxBounds(m_rect);
boxState->setPaddingBounds(m_padding);
if (partialTilesValue())
boxState->setFlag(SelectBoxState::Flags::IncludePartialTiles);
else
boxState->clearFlag(SelectBoxState::Flags::IncludePartialTiles);
m_editor->invalidate();
}
}
@ -184,6 +207,16 @@ protected:
height()->setTextf("%d", m_rect.h);
}
void onChangePadding(const gfx::Size& padding) override {
m_padding = padding;
if (padding.w < 0)
m_padding.w = 0;
if (padding.h < 0)
m_padding.h = 0;
horizontalPadding()->setTextf("%d", m_padding.w);
verticalPadding()->setTextf("%d", m_padding.h);
}
std::string onGetContextBarHelp() override {
return "Select bounds to identify sprite frames";
}
@ -218,9 +251,11 @@ private:
sheetType()->setSelectedItemIndex((int)app::SpriteSheetType::Rows-1);
gfx::Rect defBounds = m_docPref->importSpriteSheet.bounds();
gfx::Size defPaddingBounds = m_docPref->importSpriteSheet.paddingBounds();
if (defBounds.isEmpty())
defBounds = m_docPref->grid.bounds();
onChangeRectangle(defBounds);
onChangePadding(defPaddingBounds);
partialTiles()->setSelected(m_docPref->importSpriteSheet.partialTiles());
onEntriesChange();
@ -232,13 +267,17 @@ private:
if (m_document && !m_editor) {
m_rect = getRectFromEntries();
m_padding = getPaddingFromEntries();
m_editor = current_editor;
m_editorState.reset(
new SelectBoxState(
this, m_rect,
SelectBoxState::Flags(
int(SelectBoxState::Flags::Rulers) |
int(SelectBoxState::Flags::Grid))));
int(SelectBoxState::Flags::Grid) |
int(SelectBoxState::Flags::DarkOutside) |
int(SelectBoxState::Flags::PaddingRulers)
)));
m_editor->setState(m_editorState);
updateGridState();
@ -249,7 +288,8 @@ private:
if (!m_editorState)
return;
int flags = int(SelectBoxState::Flags::Rulers);
int flags = (int)static_cast<SelectBoxState*>(m_editorState.get())->getFlags();
flags = flags & ~((int)SelectBoxState::Flags::HGrid | (int)SelectBoxState::Flags::VGrid);
switch (sheetTypeValue()) {
case SpriteSheetType::Horizontal:
flags |= int(SelectBoxState::Flags::HGrid);
@ -279,6 +319,7 @@ private:
Editor* m_editor;
EditorStatePtr m_editorState;
gfx::Rect m_rect;
gfx::Size m_padding;
// True if the user has been opened the file (instead of selecting
// the current document).
@ -311,6 +352,7 @@ void ImportSpriteSheetCommand::onExecute(Context* context)
Doc* document = window.document();
DocumentPreferences* docPref = window.docPref();
gfx::Rect frameBounds = window.frameBounds();
gfx::Size padThickness = window.paddingThickness();
bool partialTiles = window.partialTilesValue();
auto sheetType = window.sheetTypeValue();
@ -337,25 +379,25 @@ void ImportSpriteSheetCommand::onExecute(Context* context)
switch (sheetType) {
case app::SpriteSheetType::Horizontal:
for (int x=frameBounds.x; x+frameBounds.w<=widthStop; x += frameBounds.w) {
for (int x=frameBounds.x; x+frameBounds.w<=widthStop; x+=frameBounds.w+padThickness.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<=heightStop; y += frameBounds.h) {
for (int y=frameBounds.y; y+frameBounds.h<=heightStop; y+=frameBounds.h+padThickness.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<=heightStop; y += frameBounds.h) {
for (int x=frameBounds.x; x+frameBounds.w<=widthStop; x += frameBounds.w) {
for (int y=frameBounds.y; y+frameBounds.h<=heightStop; y+=frameBounds.h+padThickness.h) {
for (int x=frameBounds.x; x+frameBounds.w<=widthStop; x+=frameBounds.w+padThickness.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) {
for (int x=frameBounds.x; x+frameBounds.w<=widthStop; x+=frameBounds.w+padThickness.w) {
for (int y=frameBounds.y; y+frameBounds.h<=heightStop; y+=frameBounds.h+padThickness.h) {
tileRects.push_back(gfx::Rect(x, y, frameBounds.w, frameBounds.h));
}
}
@ -422,6 +464,7 @@ void ImportSpriteSheetCommand::onExecute(Context* context)
docPref->importSpriteSheet.type(sheetType);
docPref->importSpriteSheet.bounds(frameBounds);
docPref->importSpriteSheet.partialTiles(partialTiles);
docPref->importSpriteSheet.paddingBounds(padThickness);
}
}
catch (...) {

View File

@ -1,4 +1,5 @@
// Aseprite
// Copyright (C) 2019 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
@ -29,12 +30,16 @@ using namespace ui;
SelectBoxState::SelectBoxState(SelectBoxDelegate* delegate, const gfx::Rect& rc, Flags flags)
: m_delegate(delegate)
, m_rulers(4)
, m_rulers((int(flags) & int(Flags::PaddingRulers))? 6: 4)
, m_rulersDragAlign(0)
, m_selectingBox(false)
, m_flags(flags)
{
setBoxBounds(rc);
if (hasFlag(Flags::PaddingRulers)) {
gfx::Size padding(0, 0);
setPaddingBounds(padding);
}
}
SelectBoxState::~SelectBoxState()
@ -43,18 +48,33 @@ SelectBoxState::~SelectBoxState()
contextBar->updateForActiveTool();
}
SelectBoxState::Flags SelectBoxState::getFlags()
{
return m_flags;
}
void SelectBoxState::setFlags(Flags flags)
{
m_flags = flags;
}
void SelectBoxState::setFlag(Flags flag)
{
m_flags = Flags(int(flag) | int(m_flags));
}
void SelectBoxState::clearFlag(Flags flag)
{
m_flags = Flags(~(int(flag)) & int(m_flags));
}
gfx::Rect SelectBoxState::getBoxBounds() const
{
int x1 = std::min(m_rulers[V1].position(), m_rulers[V2].position());
int y1 = std::min(m_rulers[H1].position(), m_rulers[H2].position());
int x2 = std::max(m_rulers[V1].position(), m_rulers[V2].position());
int y2 = std::max(m_rulers[H1].position(), m_rulers[H2].position());
return gfx::Rect(x1, y1, x2 - x1, y2 - y1);
return gfx::Rect(x1, y1, x2-x1, y2-y1);
}
void SelectBoxState::setBoxBounds(const gfx::Rect& box)
@ -65,6 +85,26 @@ void SelectBoxState::setBoxBounds(const gfx::Rect& box)
m_rulers[V2] = Ruler(Ruler::Vertical, box.x+box.w);
}
// Get and Set Padding for Import Sprite Sheet box state
gfx::Size SelectBoxState::getPaddingBounds() const
{
ASSERT(hasFlag(Flags::PaddingRulers));
int w = m_rulers[PV].position() - m_rulers[V2].position();
int h = m_rulers[PH].position() - m_rulers[H2].position();
if (w < 0)
w = 0;
if (h < 0)
h = 0;
return gfx::Size(w, h);
}
void SelectBoxState::setPaddingBounds(const gfx::Size& padding)
{
ASSERT(hasFlag(Flags::PaddingRulers));
m_rulers[PH] = Ruler(Ruler::Horizontal, m_rulers[H2].position() + padding.h);
m_rulers[PV] = Ruler(Ruler::Vertical, m_rulers[V2].position() + padding.w);
}
void SelectBoxState::onEnterState(Editor* editor)
{
StandbyState::onEnterState(editor);
@ -178,8 +218,11 @@ bool SelectBoxState::onMouseMove(Editor* editor, MouseMessage* msg)
}
if (used) {
if (m_delegate)
if (m_delegate) {
m_delegate->onChangeRectangle(getBoxBounds());
if (hasFlag(Flags::PaddingRulers))
m_delegate->onChangePadding(getPaddingBounds());
}
editor->invalidate();
return true;
@ -250,47 +293,220 @@ void SelectBoxState::postRenderDecorator(EditorPostRender* render)
const gfx::Color gridColor = skin::SkinTheme::instance()->colors.selectBoxGrid();
const gfx::Point mainOffset = editor->mainTilePosition();
gfx::Rect rc = getBoxBounds();
gfx::Size padding;
if (hasFlag(Flags::PaddingRulers))
padding = getPaddingBounds();
rc.offset(mainOffset);
sp.offset(mainOffset);
// With black shadow?
if (hasFlag(Flags::DarkOutside)) {
const gfx::Color dark = doc::rgba(0, 0, 0, 128);
// Top band
if (rc.y > vp.y)
render->fillRect(dark, gfx::Rect(vp.x, vp.y, vp.w, rc.y-vp.y));
// Bottom band
if (rc.y2() < vp.y2())
render->fillRect(dark, gfx::Rect(vp.x, rc.y2(), vp.w, vp.y2()-rc.y2()));
// Left band
if (rc.x > vp.x)
render->fillRect(dark, gfx::Rect(vp.x, rc.y, rc.x-vp.x, rc.h));
// Right band
if (rc.x2() < vp.x2())
render->fillRect(dark, gfx::Rect(rc.x2(), rc.y, vp.x2()-rc.x2(), rc.h));
}
if (hasFlag(Flags::PaddingRulers)) {
const gfx::Color dark = doc::rgba(0, 0, 0, 128);
// Top band
if (rc.y > vp.y)
render->fillRect(dark, gfx::Rect(vp.x, vp.y, vp.w, rc.y-vp.y));
// Left band
if (rc.x > vp.x)
render->fillRect(dark, gfx::Rect(vp.x, rc.y, rc.x-vp.x, vp.y2()-rc.y));
if (hasFlag(Flags::VGrid)) {
// Bottom band
if (sp.y2() < vp.y2())
render->fillRect(dark, gfx::Rect(rc.x, sp.y2(), vp.x2()-rc.x, vp.y2()-sp.y2()));
// Right band
if (hasFlag(Flags::HGrid)) {
// VGrid Active, HGrid Active:
if (sp.x2() < vp.x2())
render->fillRect(dark, gfx::Rect(sp.x2(), rc.y, vp.x2()-sp.x2(), sp.y2()-rc.y));
}
else {
// Just VGrid Active, HGrid disabled:
if (rc.x2() < vp.x2())
render->fillRect(dark, gfx::Rect(rc.x2(), rc.y, vp.x2()-rc.x2(), sp.y2()-rc.y));
}
}
else {
if (hasFlag(Flags::HGrid)) {
// Just HGrid Active, VGrid disabled
// Bottom band
if (rc.y2() < vp.y2())
render->fillRect(dark, gfx::Rect(rc.x, rc.y2(), vp.x2()-rc.x, vp.y2()-rc.y2()));
// Right band
if (sp.x2() < vp.x2())
render->fillRect(dark, gfx::Rect(sp.x2(), rc.y, vp.x2()-sp.x2(), rc.h));
}
}
if (hasFlag(Flags::Grid)) {
if (rc.w > 0) {
for (int x=rc.x+rc.w*2; x<=sp.x+sp.w; x+=rc.w)
render->drawLine(gridColor, x, rc.y, x, sp.y+sp.h);
// Draw vertical dark padding big bands
if (hasFlag(Flags::VGrid) && hasFlag(Flags::HGrid)) {
std::vector<int> padXTips;
std::vector<int> padYTips;
if (rc.w > 0) {
for (int x=rc.x+rc.w; x<=sp.x+sp.w; x+=(rc.w+padding.w)) {
if (x + padding.w > sp.x2())
render->fillRect(dark, gfx::Rect(x, rc.y, sp.x2()-x, sp.h-rc.y));
else
render->fillRect(dark, gfx::Rect(x, rc.y, padding.w, sp.h-rc.y));
padXTips.push_back(x);
}
}
if (rc.h > 0) {
// Draw horizontal dark chopped padding bands (to complete the dark grid)
for (int y=rc.y+rc.h; y<=sp.y+sp.h; y+=(rc.h+padding.h)) {
for (const int& padXTip : padXTips) {
if (y+padding.h > sp.y2())
render->fillRect(dark, gfx::Rect(padXTip-rc.w, y, rc.w, sp.y2()-y));
else
render->fillRect(dark, gfx::Rect(padXTip-rc.w, y, rc.w, padding.h));
}
if (!padXTips.empty()) {
if (padXTips.back() + padding.w < sp.x2()) {
if (y + padding.h > sp.y2())
render->fillRect(dark, gfx::Rect(padXTips.back() + padding.w, y,
sp.x2() - padXTips.back() - padding.w,
sp.y2() - y));
else
render->fillRect(dark, gfx::Rect(padXTips.back() + padding.w, y,
sp.x2() - padXTips.back() - padding.w,
padding.h));
}
}
padYTips.push_back(y);
}
}
// Draw chopped dark rectangles to ban partial tiles
if (!hasFlag(Flags::IncludePartialTiles)) {
if (!padXTips.empty() && !padYTips.empty()) {
if (padXTips.back() + padding.w < sp.x2()) {
for (const int& padYTip : padYTips)
render->fillRect(dark, gfx::Rect(padXTips.back() + padding.w, padYTip - rc.h,
sp.x2() - padXTips.back() - padding.w, rc.h));
if (padYTips.back() + padding.h < sp.y2()) {
render->fillRect(dark, gfx::Rect(padXTips.back() + padding.w,
padYTips.back() + padding.h,
sp.x2() - padXTips.back() - padding.w,
sp.y2() - padYTips.back() - padding.h));
}
}
if (padYTips.back() + padding.h < sp.y2()) {
for (const int& padXTip : padXTips)
render->fillRect(dark, gfx::Rect(padXTip - rc.w, padYTips.back() + padding.h,
rc.w, sp.y2() - padYTips.back() - padding.h));
}
}
}
}
else if (hasFlag(Flags::HGrid)) {
if (rc.w > 0) {
int lastX = 0;
for (int x=rc.x+rc.w; x<=sp.x+sp.w; x+=rc.w+padding.w) {
if (x + padding.w > sp.x2())
render->fillRect(dark, gfx::Rect(x, rc.y, sp.x2()-x, rc.h));
else
render->fillRect(dark, gfx::Rect(x, rc.y, padding.w, rc.h));
lastX = x;
}
if (!hasFlag(Flags::IncludePartialTiles) && (lastX > 0)) {
if (lastX + padding.w < sp.x2())
render->fillRect(dark, gfx::Rect(lastX + padding.w, rc.y,
sp.x2() - lastX - padding.w, rc.h));
}
}
}
else if (hasFlag(Flags::VGrid)) {
if (rc.h > 0) {
int lastY = 0;
for (int y=rc.y+rc.h; y<=sp.y+sp.h; y+=rc.h+padding.h) {
if (y + padding.h > sp.y2())
render->fillRect(dark, gfx::Rect(rc.x, y, rc.w, sp.y2()-y));
else
render->fillRect(dark, gfx::Rect(rc.x, y, rc.w, padding.h));
lastY = y;
}
if (!hasFlag(Flags::IncludePartialTiles) && (lastY > 0)) {
if (lastY + padding.h < sp.y2())
render->fillRect(dark, gfx::Rect(rc.x, lastY + padding.h,
rc.w, sp.y2() - lastY - padding.h));
}
}
}
}
else {
// Draw dark zones when SelectBoxState is a simple box
const gfx::Color dark = doc::rgba(0, 0, 0, 128);
// Top band
if (rc.y > vp.y)
render->fillRect(dark, gfx::Rect(vp.x, vp.y, vp.w, rc.y-vp.y));
// Bottom band
if (rc.y2() < vp.y2())
render->fillRect(dark, gfx::Rect(vp.x, rc.y2(), vp.w, vp.y2()-rc.y2()));
// Left band
if (rc.x > vp.x)
render->fillRect(dark, gfx::Rect(vp.x, rc.y, rc.x-vp.x, rc.h));
// Right band
if (rc.x2() < vp.x2())
render->fillRect(dark, gfx::Rect(rc.x2(), rc.y, vp.x2()-rc.x2(), rc.h));
}
}
// Draw the grid rulers when padding is posible (i.e. Flag::PaddingRulers=true)
if (hasFlag(Flags::PaddingRulers)) {
if (hasFlag(Flags::HGrid) && hasFlag(Flags::VGrid)) {
if (rc.w > 0 && padding.w == 0) {
for (int x=rc.x+rc.w*2+padding.w; x<=sp.x+sp.w; x+=rc.w+padding.w)
render->drawLine(gridColor, x, rc.y, x, sp.y2());
for (int x=rc.x+rc.w+padding.w; x<=sp.x+sp.w; x+=rc.w+padding.w)
render->drawLine(gridColor, x, rc.y, x, sp.y2());
}
if (rc.h > 0) {
for (int y=rc.y+rc.h*2; y<=sp.y+sp.h; y+=rc.h)
render->drawLine(gridColor, rc.x, y, sp.x+sp.w, y);
if (rc.h > 0 && padding.h == 0) {
for (int y=rc.y+rc.h*2+padding.h; y<=sp.y+sp.h; y+=rc.h+padding.h)
render->drawLine(gridColor, rc.x, y, sp.x2(), y);
for (int y=rc.y+rc.h+padding.h; y<=sp.y+sp.h; y+=rc.h+padding.h)
render->drawLine(gridColor, rc.x, y, sp.x2(), y);
}
}
else if (hasFlag(Flags::HGrid)) {
if (rc.w > 0 && padding.w == 0) {
for (int x=rc.x+rc.w*2+padding.w; x<=sp.x+sp.w; x+=rc.w+padding.w)
render->drawLine(gridColor, x, rc.y, x, rc.y2());
for (int x=rc.x+rc.w+padding.w; x<=sp.x+sp.w; x+=rc.w+padding.w)
render->drawLine(gridColor, x, rc.y, x, rc.y2());
}
}
else if (hasFlag(Flags::VGrid)) {
if (rc.h > 0 && padding.h == 0) {
for (int y=rc.y+rc.h*2+padding.h; y<=sp.y+sp.h; y+=rc.h+padding.h)
render->drawLine(gridColor, rc.x, y, rc.x2(), y);
for (int y=rc.y+rc.h+padding.h; y<=sp.y+sp.h; y+=rc.h+padding.h)
render->drawLine(gridColor, rc.x, y, rc.x2(), y);
}
}
}
else if (hasFlag(Flags::HGrid)) {
if (rc.w > 0) {
for (int x=rc.x+rc.w*2; x<=sp.x+sp.w; x+=rc.w)
render->drawLine(gridColor, x, rc.y, x, rc.y+rc.h);
else {
// Draw the grid rulers when padding is not posible (i.e. Flag::PaddingRulers=false)
if (hasFlag(Flags::Grid)) {
if (rc.w > 0) {
for (int x=rc.x+rc.w*2; x<=sp.x+sp.w; x+=rc.w)
render->drawLine(gridColor, x, rc.y, x, sp.y+sp.h);
}
if (rc.h > 0) {
for (int y=rc.y+rc.h*2; y<=sp.y+sp.h; y+=rc.h)
render->drawLine(gridColor, rc.x, y, sp.x+sp.w, y);
}
}
}
else if (hasFlag(Flags::VGrid)) {
if (rc.h > 0) {
for (int y=rc.y+rc.h*2; y<=sp.y+sp.h; y+=rc.h)
render->drawLine(gridColor, rc.x, y, rc.x+rc.w, y);
else if (hasFlag(Flags::HGrid)) {
if (rc.w > 0) {
for (int x=rc.x+rc.w*2; x<=sp.x+sp.w; x+=rc.w)
render->drawLine(gridColor, x, rc.y, x, rc.y+rc.h);
}
}
else if (hasFlag(Flags::VGrid)) {
if (rc.h > 0) {
for (int y=rc.y+rc.h*2; y<=sp.y+sp.h; y+=rc.h)
render->drawLine(gridColor, rc.x, y, rc.x+rc.w, y);
}
}
}
@ -338,7 +554,7 @@ int SelectBoxState::hitTestRulers(Editor* editor,
ASSERT(H2 == 1);
ASSERT(V1 == 2);
ASSERT(V2 == 3);
int aligns[] = { TOP, BOTTOM, LEFT, RIGHT };
int aligns[] = { TOP, BOTTOM, LEFT, RIGHT, BOTTOM, RIGHT };
int align = 0;
if (updateMovingRulers)
@ -360,7 +576,7 @@ int SelectBoxState::hitTestRulers(Editor* editor,
align = LEFT | TOP | RIGHT | BOTTOM;
if (updateMovingRulers) {
// Add all rulers
for (int i=0; i<4; ++i)
for (int i=0; i<m_rulers.size(); ++i)
m_movingRulers.push_back(i);
}
}

View File

@ -1,4 +1,5 @@
// Aseprite
// Copyright (C) 2019 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
@ -11,6 +12,7 @@
#include "app/ui/editor/editor_decorator.h"
#include "app/ui/editor/ruler.h"
#include "app/ui/editor/standby_state.h"
#include "gfx/fwd.h"
#include "ui/cursor_type.h"
#include "ui/mouse_buttons.h"
@ -26,6 +28,7 @@ namespace app {
// Called each time the selected box is modified (e.g. rulers are
// moved).
virtual void onChangeRectangle(const gfx::Rect& rect) { }
virtual void onChangePadding(const gfx::Size& padding) { }
// Called only in QUICKBOX mode, when the user released the mouse
// button.
@ -38,7 +41,7 @@ namespace app {
class SelectBoxState : public StandbyState
, public EditorDecorator {
enum { H1, H2, V1, V2 };
enum { H1, H2, V1, V2, PH, PV };
public:
enum class Flags {
@ -59,6 +62,12 @@ namespace app {
// Select the box as in selection tool, drawing a boxu
QuickBox = 16,
// Adding 2 rules more for padding. Used in Import Sprite Sheet render
PaddingRulers = 32,
// Include Partial Tiles at the end of the sprite? Used in Import Sprite Sheet render
IncludePartialTiles = 64
};
SelectBoxState(SelectBoxDelegate* delegate,
@ -66,12 +75,19 @@ namespace app {
Flags flags);
~SelectBoxState();
Flags getFlags();
void setFlags(Flags flags);
void setFlag(Flags flag);
void clearFlag(Flags flag);
// Returns the bounding box arranged by the rulers.
gfx::Rect getBoxBounds() const;
void setBoxBounds(const gfx::Rect& rc);
// Get & Set the size of the padding rulers during Import Sprite Sheet Dialog
gfx::Size getPaddingBounds() const;
void setPaddingBounds(const gfx::Size& padding);
// EditorState overrides
virtual void onEnterState(Editor* editor) override;
virtual void onBeforePopState(Editor* editor) override;