Skip to content

Commit

Permalink
Add snap to grid preferences (fix aseprite#723)
Browse files Browse the repository at this point in the history
This commit adds fields on Preferences > Grid about:
 - Snap To Grid (on/off)
 - Snap To <geometric location in a box grid>
Also added PreferSnapTo::BoxCenter calculation in snap_to_grid.cpp.
  • Loading branch information
Gasparoken committed Sep 22, 2023
1 parent dd7e27a commit 8c69881
Show file tree
Hide file tree
Showing 11 changed files with 166 additions and 29 deletions.
5 changes: 5 additions & 0 deletions data/pref.xml
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,10 @@
<option id="painting_cursor_type" type="PaintingCursorType" default="PaintingCursorType::CROSSHAIR_ON_SPRITE" />
<option id="brush_preview" type="BrushPreview" default="BrushPreview::FULL" />
</section>
<section id="grid">
<option id="snap" type="bool" default="false" />
<option id="snap_to" type="app::PreferSnapTo" default="app::PreferSnapTo::ClosestGridVertex" />
</section>
<section id="preview" text="Preview">
<option id="play_once" type="bool" default="false" />
<option id="play_all" type="bool" default="false" />
Expand Down Expand Up @@ -495,6 +499,7 @@
</section>
<section id="grid" canforce="true">
<option id="snap" type="bool" default="false" />
<option id="snap_to" type="app::PreferSnapTo" default="app::PreferSnapTo::ClosestGridVertex" />
<option id="bounds" type="gfx::Rect" default="doc::Sprite::DefaultGridBounds()" />
<option id="color" type="app::Color" default="app::Color::fromRgb(0, 0, 255)" />
<option id="opacity" type="int" default="160" />
Expand Down
6 changes: 6 additions & 0 deletions data/strings/en.ini
Original file line number Diff line number Diff line change
Expand Up @@ -1465,6 +1465,11 @@ default = Default (Octree)
rgb5a3 = Table RGB 5 bits + Alpha 3 bits
octree = Octree
[snap_to_selector]
label = Snap To:
default = Box Vertex
box_center = Box Center
[open_file]
title = Open
loading = Loading file
Expand Down Expand Up @@ -1699,6 +1704,7 @@ grid_auto = Auto
grid_pixel_grid_visible = Visible Pixel Grid
grid_pixel_grid_color = Color:
grid_pixel_grid_opacity = Opacity:
grid_snap_to_grid = Snap To Grid
guides = Guides
slices = Slices
layer_edges_color = Layer Edges Color:
Expand Down
62 changes: 38 additions & 24 deletions data/widgets/options.xml
Original file line number Diff line number Diff line change
Expand Up @@ -358,51 +358,65 @@
<!-- Grid -->
<vbox id="section_grid">
<combobox id="grid_scope" />
<hbox>

<hbox>
<check id="grid_visible" text="@.grid_visible" />
<separator horizontal="true" expansive="true" />
</hbox>
</hbox>

<grid columns="5">
<label text="@.grid_x" />
<expr id="grid_x" text="" />
<label text="@.grid_y" />
<expr id="grid_y" text="" />
<hbox />
<grid columns="5">
<label text="@.grid_x" />
<expr id="grid_x" text="" />
<label text="@.grid_y" />
<expr id="grid_y" text="" />
<hbox />

<label text="@.grid_width" />
<expr id="grid_w" text="" />
<label text="@.grid_height" />
<expr id="grid_h" text="" />
<hbox />
<label text="@.grid_width" />
<expr id="grid_w" text="" />
<label text="@.grid_height" />
<expr id="grid_h" text="" />
<hbox />

<label text="@.grid_color" />
<colorpicker id="grid_color" rgba="true" cell_hspan="3" />
<hbox />
<hbox />

<label text="@.grid_opacity" />
<label text="@.grid_opacity" />
<slider id="grid_opacity" cell_hspan="3" min="1" max="255" width="128" />
<check id="grid_auto_opacity" text="@.grid_auto" />
</grid>
</grid>

<hbox>
<hbox>
<check id="pixel_grid_visible" text="@.grid_pixel_grid_visible" />
<separator horizontal="true" expansive="true" />
</hbox>
</hbox>

<grid columns="3">
<label text="@.grid_color" />
<colorpicker id="pixel_grid_color" rgba="true" />
<hbox />
<hbox />

<label text="@.grid_opacity" />
<label text="@.grid_opacity" />
<slider id="pixel_grid_opacity" min="1" max="255" width="128" />
<check id="pixel_grid_auto_opacity" text="@.grid_auto" />
</grid>

<hbox>
<hbox expansive="true" />
<button id="reset_grid" text="@general.reset" width="60" />
</hbox>
<hbox>
<check id="snap_to_grid" text="@.grid_snap_to_grid" />
<separator horizontal="true" expansive="true" />
</hbox>

<grid columns="3">
<label text="@snap_to_selector.label" />
<hbox id="snap_to_placeholder" />
<hbox />

</grid>

<hbox>
<hbox expansive="true" />
<button id="reset_grid" text="@general.reset" width="60" />
</hbox>
</vbox>

<!-- Guides -->
Expand Down
1 change: 1 addition & 0 deletions src/app/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,7 @@ if(ENABLE_UI)
ui/skin/skin_theme.cpp
ui/slice_window.cpp
ui/slider2.cpp
ui/snap_to_selector.cpp
ui/status_bar.cpp
ui/tabs.cpp
ui/tag_window.cpp
Expand Down
36 changes: 34 additions & 2 deletions src/app/commands/cmd_options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
#include "app/ui/sampling_selector.h"
#include "app/ui/separator_in_view.h"
#include "app/ui/skin/skin_theme.h"
#include "app/ui/snap_to_selector.h"
#include "app/ui/status_bar.h"
#include "base/convert_to.h"
#include "base/fs.h"
#include "base/string.h"
Expand Down Expand Up @@ -472,6 +474,10 @@ class OptionsWindow : public app::gen::Options {
m_rgbmapAlgorithmSelector.setExpansive(true);
m_rgbmapAlgorithmSelector.algorithm(m_pref.quantization.rgbmapAlgorithm());

snapToPlaceholder()->addChild(&m_snapToSelector);
m_snapToSelector.setExpansive(true);
m_snapToSelector.snapTo(app::PreferSnapTo::ClosestGridVertex);

if (m_pref.editor.showScrollbars())
showScrollbars()->setSelected(true);

Expand Down Expand Up @@ -789,6 +795,12 @@ class OptionsWindow : public app::gen::Options {
m_curPref->pixelGrid.opacity(pixelGridOpacity()->getValue());
m_curPref->pixelGrid.autoOpacity(pixelGridAutoOpacity()->isSelected());

m_curPref->grid.snapTo(
(app::PreferSnapTo)m_snapToSelector.getSelectedItemIndex());
m_curPref->grid.snap(snapToGrid()->isSelected());
StatusBar::instance()->showSnapToGridWarning(
m_docPref.grid.snap());

m_curPref->bg.type(app::gen::BgType(checkeredBgSize()->getSelectedItemIndex()));
if (m_curPref->bg.type() == app::gen::BgType::CHECKERED_CUSTOM) {
m_curPref->bg.size(gfx::Size(
Expand Down Expand Up @@ -1189,8 +1201,16 @@ class OptionsWindow : public app::gen::Options {
int item = gridScope()->getSelectedItemIndex();

switch (item) {
case 0: m_curPref = &m_globPref; break;
case 1: m_curPref = &m_docPref; break;
case 0:
m_curPref = &m_globPref;
snapToGrid()->setSelected(false);
snapToGrid()->setEnabled(false);
break;
case 1:
m_curPref = &m_docPref;
snapToGrid()->setEnabled(true);
snapToGrid()->setSelected(m_curPref->grid.snap());
break;
}

gridVisible()->setSelected(m_curPref->show.grid());
Expand All @@ -1207,6 +1227,9 @@ class OptionsWindow : public app::gen::Options {
pixelGridColor()->setColor(m_curPref->pixelGrid.color());
pixelGridOpacity()->setValue(m_curPref->pixelGrid.opacity());
pixelGridAutoOpacity()->setSelected(m_curPref->pixelGrid.autoOpacity());

m_snapToSelector.setSelectedItemIndex(
(int)m_curPref->grid.snapTo());
}

void onResetBg() {
Expand Down Expand Up @@ -1249,6 +1272,10 @@ class OptionsWindow : public app::gen::Options {
pixelGridColor()->setColor(pref.pixelGrid.color.defaultValue());
pixelGridOpacity()->setValue(pref.pixelGrid.opacity.defaultValue());
pixelGridAutoOpacity()->setSelected(pref.pixelGrid.autoOpacity.defaultValue());

snapToGrid()->setSelected(pref.grid.snap.defaultValue());
m_snapToSelector.setSelectedItemIndex(
(int)pref.grid.snapTo.defaultValue());
}
// Reset document preferences with global settings
else {
Expand All @@ -1266,6 +1293,10 @@ class OptionsWindow : public app::gen::Options {
pixelGridColor()->setColor(pref.pixelGrid.color());
pixelGridOpacity()->setValue(pref.pixelGrid.opacity());
pixelGridAutoOpacity()->setSelected(pref.pixelGrid.autoOpacity());

snapToGrid()->setSelected(pref.grid.snap());
m_snapToSelector.setSelectedItemIndex(
(int)pref.grid.snapTo());
}
}

Expand Down Expand Up @@ -1784,6 +1815,7 @@ class OptionsWindow : public app::gen::Options {
RgbMapAlgorithmSelector m_rgbmapAlgorithmSelector;
ButtonSet* m_themeVars = nullptr;
SamplingSelector* m_samplingSelector = nullptr;
SnapToSelector m_snapToSelector;
};

class OptionsCommand : public Command {
Expand Down
1 change: 1 addition & 0 deletions src/app/pref/preferences.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "app/commands/filters/cels_target.h"
#include "app/docs_observer.h"
#include "app/pref/option.h"
#include "app/snap_to_grid.h"
#include "app/sprite_sheet_data_format.h"
#include "app/sprite_sheet_type.h"
#include "app/tools/dynamics.h"
Expand Down
1 change: 1 addition & 0 deletions src/app/script/values.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ doc::tile_t get_value_from_lua(lua_State* L, int index) {

FOR_ENUM(app::CelsTarget)
FOR_ENUM(app::ColorBar::ColorSelector)
FOR_ENUM(app::PreferSnapTo)
FOR_ENUM(app::SpriteSheetDataFormat)
FOR_ENUM(app::SpriteSheetType)
FOR_ENUM(app::TilesetMode)
Expand Down
12 changes: 11 additions & 1 deletion src/app/snap_to_grid.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2019-2020 Igara Studio S.A.
// Copyright (C) 2019-2023 Igara Studio S.A.
// Copyright (C) 2001-2016 David Capello
//
// This program is distributed under the terms of
Expand Down Expand Up @@ -70,6 +70,16 @@ gfx::Point snap_to_grid(const gfx::Rect& grid,
d = std::div(newPoint.y, grid.h);
newPoint.y = dy.rem + (d.quot+1)*grid.h;
break;

case PreferSnapTo::BoxCenter:
d = std::div(newPoint.x, grid.w);
bool nextBox = newPoint.x >= d.quot * grid.w;
newPoint.x = d.quot * grid.w + grid.w / (nextBox ? 2 : -2);

d = std::div(newPoint.y, grid.h);
nextBox = newPoint.y >= d.quot * grid.h;
newPoint.y = d.quot * grid.h + grid.h / (nextBox ? 2 : -2);
break;
}

return newPoint;
Expand Down
5 changes: 3 additions & 2 deletions src/app/snap_to_grid.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2020 Igara Studio S.A.
// Copyright (C) 2020-2023 Igara Studio S.A.
// Copyright (C) 2001-2016 David Capello
//
// This program is distributed under the terms of
Expand All @@ -15,8 +15,9 @@ namespace app {

enum class PreferSnapTo {
ClosestGridVertex,
BoxCenter,
BoxOrigin, BoxEnd,
FloorGrid, CeilGrid,
FloorGrid, CeilGrid
};

gfx::Point snap_to_grid(const gfx::Rect& grid,
Expand Down
40 changes: 40 additions & 0 deletions src/app/ui/snap_to_selector.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Aseprite
// Copyright (C) 2023 Igara Studio S.A.
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "app/snap_to_grid.h"
#include "app/ui/snap_to_selector.h"

#include "app/i18n/strings.h"

namespace app {

SnapToSelector::SnapToSelector()
{
// addItem() must match the PreferSnapTo enum
static_assert(int(PreferSnapTo::ClosestGridVertex) == 0 &&
int(PreferSnapTo::BoxCenter) == 1,
"Unexpected app::PreferSnapTo values");

addItem(Strings::snap_to_selector_default());
addItem(Strings::snap_to_selector_box_center());
snapTo(app::PreferSnapTo::ClosestGridVertex);
}

PreferSnapTo SnapToSelector::snapTo()
{
return (PreferSnapTo)getSelectedItemIndex();
}

void SnapToSelector::snapTo(const PreferSnapTo snapTo)
{
setSelectedItemIndex((int)snapTo);
}

} // namespace app
26 changes: 26 additions & 0 deletions src/app/ui/snap_to_selector.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Aseprite
// Copyright (C) 2023 Igara Studio S.A.
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.

#ifndef APP_UI_SNAP_TO_SELECTOR_H_INCLUDED
#define APP_UI_SNAP_TO_SELECTOR_H_INCLUDED
#pragma once

#include "app/snap_to_grid.h"
#include "ui/combobox.h"

namespace app {

class SnapToSelector : public ui::ComboBox {
public:
SnapToSelector();

PreferSnapTo snapTo();
void snapTo(PreferSnapTo snapTo);
};

} // namespace app

#endif

0 comments on commit 8c69881

Please sign in to comment.