mirror of
https://github.com/aseprite/aseprite.git
synced 2025-01-29 21:33:12 +00:00
Save grid bounds inside .aseprite files and doc::Sprite (fix #688)
This commit is contained in:
parent
86ef6979e2
commit
30b2585037
@ -394,7 +394,7 @@
|
||||
</section>
|
||||
<section id="grid">
|
||||
<option id="snap" type="bool" default="false" />
|
||||
<option id="bounds" type="gfx::Rect" default="gfx::Rect(0, 0, 16, 16)" />
|
||||
<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" />
|
||||
<option id="auto_opacity" type="bool" default="true" />
|
||||
|
@ -71,7 +71,12 @@ A 128-byte header (same as FLC/FLI header, but with other magic number):
|
||||
BYTE Pixel width (pixel ratio is "pixel width/pixel height").
|
||||
If this or pixel height field is zero, pixel ratio is 1:1
|
||||
BYTE Pixel height
|
||||
BYTE[92] For future (set to zero)
|
||||
SHORT X position of the grid
|
||||
SHORT Y position of the grid
|
||||
WORD Grid width (zero if there is no grid, grid size
|
||||
is 16x16 on Aseprite by default)
|
||||
WORD Grid height (zero if there is no grid)
|
||||
BYTE[84] For future (set to zero)
|
||||
|
||||
## Frames
|
||||
|
||||
|
@ -452,6 +452,7 @@ add_library(app-lib
|
||||
cmd/set_cel_opacity.cpp
|
||||
cmd/set_cel_position.cpp
|
||||
cmd/set_frame_duration.cpp
|
||||
cmd/set_grid_bounds.cpp
|
||||
cmd/set_last_point.cpp
|
||||
cmd/set_layer_blend_mode.cpp
|
||||
cmd/set_layer_flags.cpp
|
||||
|
54
src/app/cmd/set_grid_bounds.cpp
Normal file
54
src/app/cmd/set_grid_bounds.cpp
Normal file
@ -0,0 +1,54 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 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/cmd/set_grid_bounds.h"
|
||||
|
||||
#include "app/doc.h"
|
||||
#include "app/doc_event.h"
|
||||
#include "app/doc_observer.h"
|
||||
#include "doc/sprite.h"
|
||||
|
||||
namespace app {
|
||||
namespace cmd {
|
||||
|
||||
using namespace doc;
|
||||
|
||||
SetGridBounds::SetGridBounds(Sprite* sprite, const gfx::Rect& bounds)
|
||||
: WithSprite(sprite)
|
||||
, m_oldBounds(sprite->gridBounds())
|
||||
, m_newBounds(bounds)
|
||||
{
|
||||
}
|
||||
|
||||
void SetGridBounds::onExecute()
|
||||
{
|
||||
Sprite* spr = sprite();
|
||||
spr->setGridBounds(m_newBounds);
|
||||
spr->incrementVersion();
|
||||
}
|
||||
|
||||
void SetGridBounds::onUndo()
|
||||
{
|
||||
Sprite* spr = sprite();
|
||||
spr->setGridBounds(m_oldBounds);
|
||||
spr->incrementVersion();
|
||||
}
|
||||
|
||||
void SetGridBounds::onFireNotifications()
|
||||
{
|
||||
Sprite* sprite = this->sprite();
|
||||
Doc* doc = static_cast<Doc*>(sprite->document());
|
||||
DocEvent ev(doc);
|
||||
ev.sprite(sprite);
|
||||
doc->notify_observers<DocEvent&>(&DocObserver::onSpriteGridBoundsChanged, ev);
|
||||
}
|
||||
|
||||
} // namespace cmd
|
||||
} // namespace app
|
43
src/app/cmd/set_grid_bounds.h
Normal file
43
src/app/cmd/set_grid_bounds.h
Normal file
@ -0,0 +1,43 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
|
||||
#ifndef APP_CMD_SET_GRID_BOUNDS_H_INCLUDED
|
||||
#define APP_CMD_SET_GRID_BOUNDS_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "app/cmd.h"
|
||||
#include "app/cmd/with_sprite.h"
|
||||
#include "gfx/rect.h"
|
||||
|
||||
namespace doc {
|
||||
class Sprite;
|
||||
}
|
||||
|
||||
namespace app {
|
||||
namespace cmd {
|
||||
|
||||
class SetGridBounds : public Cmd
|
||||
, public WithSprite {
|
||||
public:
|
||||
SetGridBounds(doc::Sprite* sprite, const gfx::Rect& bounds);
|
||||
|
||||
protected:
|
||||
void onExecute() override;
|
||||
void onUndo() override;
|
||||
void onFireNotifications() override;
|
||||
size_t onMemSize() const override {
|
||||
return sizeof(*this);
|
||||
}
|
||||
|
||||
private:
|
||||
gfx::Rect m_oldBounds;
|
||||
gfx::Rect m_newBounds;
|
||||
};
|
||||
|
||||
} // namespace cmd
|
||||
} // namespace app
|
||||
|
||||
#endif
|
@ -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
|
||||
@ -9,6 +10,7 @@
|
||||
#endif
|
||||
|
||||
#include "app/app.h"
|
||||
#include "app/cmd/set_grid_bounds.h"
|
||||
#include "app/commands/command.h"
|
||||
#include "app/context.h"
|
||||
#include "app/context_access.h"
|
||||
@ -17,6 +19,7 @@
|
||||
#include "app/load_widget.h"
|
||||
#include "app/modules/editors.h"
|
||||
#include "app/pref/preferences.h"
|
||||
#include "app/tx.h"
|
||||
#include "app/ui/status_bar.h"
|
||||
#include "app/ui_context.h"
|
||||
#include "doc/document.h"
|
||||
@ -25,6 +28,8 @@
|
||||
|
||||
#include "grid_settings.xml.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace app {
|
||||
|
||||
using namespace ui;
|
||||
@ -38,12 +43,12 @@ public:
|
||||
|
||||
protected:
|
||||
bool onChecked(Context* ctx) override {
|
||||
DocumentPreferences& docPref = Preferences::instance().document(ctx->activeDocument());
|
||||
auto& docPref = Preferences::instance().document(ctx->activeDocument());
|
||||
return docPref.grid.snap();
|
||||
}
|
||||
|
||||
void onExecute(Context* ctx) override {
|
||||
DocumentPreferences& docPref = Preferences::instance().document(ctx->activeDocument());
|
||||
auto& docPref = Preferences::instance().document(ctx->activeDocument());
|
||||
bool newValue = !docPref.grid.snap();
|
||||
docPref.grid.snap(newValue);
|
||||
|
||||
@ -59,21 +64,23 @@ public:
|
||||
|
||||
protected:
|
||||
bool onEnabled(Context* ctx) override {
|
||||
return (ctx->activeDocument() &&
|
||||
ctx->activeDocument()->isMaskVisible());
|
||||
return ctx->checkFlags(ContextFlags::ActiveDocumentIsWritable |
|
||||
ContextFlags::HasVisibleMask);
|
||||
}
|
||||
|
||||
void onExecute(Context* ctx) override {
|
||||
const ContextReader reader(ctx);
|
||||
const Doc* document = reader.document();
|
||||
const Mask* mask(document->mask());
|
||||
DocumentPreferences& docPref =
|
||||
Preferences::instance().document(ctx->activeDocument());
|
||||
ContextWriter writer(ctx, 500);
|
||||
Doc* doc = writer.document();
|
||||
const Mask* mask = doc->mask();
|
||||
gfx::Rect newGrid = mask->bounds();
|
||||
|
||||
docPref.grid.bounds(mask->bounds());
|
||||
Tx tx(writer.context(), friendlyName(), ModifyDocument);
|
||||
tx(new cmd::SetGridBounds(writer.sprite(), newGrid));
|
||||
tx.commit();
|
||||
|
||||
// Make grid visible
|
||||
if (!docPref.show.grid())
|
||||
auto& docPref = Preferences::instance().document(doc);
|
||||
docPref.grid.bounds(newGrid);
|
||||
if (!docPref.show.grid()) // Make grid visible
|
||||
docPref.show.grid(true);
|
||||
}
|
||||
};
|
||||
@ -101,8 +108,8 @@ void GridSettingsCommand::onExecute(Context* context)
|
||||
{
|
||||
gen::GridSettings window;
|
||||
|
||||
DocumentPreferences& docPref = Preferences::instance().document(context->activeDocument());
|
||||
Rect bounds = docPref.grid.bounds();
|
||||
Site site = context->activeSite();
|
||||
Rect bounds = site.gridBounds();
|
||||
|
||||
window.gridX()->setTextf("%d", bounds.x);
|
||||
window.gridY()->setTextf("%d", bounds.y);
|
||||
@ -115,13 +122,17 @@ void GridSettingsCommand::onExecute(Context* context)
|
||||
bounds.y = window.gridY()->textInt();
|
||||
bounds.w = window.gridW()->textInt();
|
||||
bounds.h = window.gridH()->textInt();
|
||||
bounds.w = MAX(bounds.w, 1);
|
||||
bounds.h = MAX(bounds.h, 1);
|
||||
bounds.w = std::max(bounds.w, 1);
|
||||
bounds.h = std::max(bounds.h, 1);
|
||||
|
||||
ContextWriter writer(context, 500);
|
||||
Tx tx(context, friendlyName(), ModifyDocument);
|
||||
tx(new cmd::SetGridBounds(site.sprite(), bounds));
|
||||
tx.commit();
|
||||
|
||||
auto& docPref = Preferences::instance().document(site.document());
|
||||
docPref.grid.bounds(bounds);
|
||||
|
||||
// Make grid visible
|
||||
if (!docPref.show.grid())
|
||||
if (!docPref.show.grid()) // Make grid visible
|
||||
docPref.show.grid(true);
|
||||
}
|
||||
}
|
||||
|
@ -266,7 +266,7 @@ private:
|
||||
|
||||
gfx::Rect defBounds = m_docPref->importSpriteSheet.bounds();
|
||||
if (defBounds.isEmpty())
|
||||
defBounds = m_docPref->grid.bounds();
|
||||
defBounds = m_document->sprite()->gridBounds();
|
||||
onChangeRectangle(defBounds);
|
||||
|
||||
gfx::Size defPaddingBounds = m_docPref->importSpriteSheet.paddingBounds();
|
||||
|
@ -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
|
||||
@ -20,6 +21,7 @@
|
||||
#include "app/job.h"
|
||||
#include "app/modules/editors.h"
|
||||
#include "app/modules/gui.h"
|
||||
#include "app/pref/preferences.h"
|
||||
#include "app/recent_files.h"
|
||||
#include "app/ui/status_bar.h"
|
||||
#include "app/ui_context.h"
|
||||
@ -191,12 +193,27 @@ void OpenFileCommand::onExecute(Context* context)
|
||||
if (fop->hasError() && !fop->isStop())
|
||||
console.printf(fop->error().c_str());
|
||||
|
||||
Doc* document = fop->document();
|
||||
if (document) {
|
||||
if (context->isUIAvailable())
|
||||
Doc* doc = fop->document();
|
||||
if (doc) {
|
||||
if (context->isUIAvailable()) {
|
||||
App::instance()->recentFiles()->addRecentFile(fop->filename().c_str());
|
||||
auto& docPref = Preferences::instance().document(doc);
|
||||
|
||||
document->setContext(context);
|
||||
if (fop->hasEmbeddedGridBounds() &&
|
||||
!doc->sprite()->gridBounds().isEmpty()) {
|
||||
// If the sprite contains the grid bounds inside, we put
|
||||
// those grid bounds into the settings (e.g. useful to
|
||||
// interact with old versions of Aseprite saving the grid
|
||||
// bounds in the aseprite.ini file)
|
||||
docPref.grid.bounds(doc->sprite()->gridBounds());
|
||||
}
|
||||
else {
|
||||
// Get grid bounds from preferences
|
||||
doc->sprite()->setGridBounds(docPref.grid.bounds());
|
||||
}
|
||||
}
|
||||
|
||||
doc->setContext(context);
|
||||
}
|
||||
else if (!fop->isStop())
|
||||
unrecent = true;
|
||||
|
@ -10,9 +10,11 @@
|
||||
#endif
|
||||
|
||||
#include "app/app.h"
|
||||
#include "app/cmd/set_grid_bounds.h"
|
||||
#include "app/commands/command.h"
|
||||
#include "app/console.h"
|
||||
#include "app/context.h"
|
||||
#include "app/context_access.h"
|
||||
#include "app/extensions.h"
|
||||
#include "app/file/file.h"
|
||||
#include "app/file_selector.h"
|
||||
@ -23,6 +25,7 @@
|
||||
#include "app/pref/preferences.h"
|
||||
#include "app/recent_files.h"
|
||||
#include "app/resource_finder.h"
|
||||
#include "app/tx.h"
|
||||
#include "app/ui/color_button.h"
|
||||
#include "app/ui/pref_widget.h"
|
||||
#include "app/ui/separator_in_view.h"
|
||||
@ -163,7 +166,8 @@ class OptionsWindow : public app::gen::Options {
|
||||
|
||||
public:
|
||||
OptionsWindow(Context* context, int& curSection)
|
||||
: m_pref(Preferences::instance())
|
||||
: m_context(context)
|
||||
, m_pref(Preferences::instance())
|
||||
, m_globPref(m_pref.document(nullptr))
|
||||
, m_docPref(m_pref.document(context->activeDocument()))
|
||||
, m_curPref(&m_docPref)
|
||||
@ -586,6 +590,14 @@ public:
|
||||
}
|
||||
update_displays_color_profile_from_preferences();
|
||||
|
||||
// Change sprite grid bounds
|
||||
if (m_context && m_context->activeDocument()) {
|
||||
ContextWriter writer(m_context, 500);
|
||||
Tx tx(m_context, Strings::commands_GridSettings(), ModifyDocument);
|
||||
tx(new cmd::SetGridBounds(writer.sprite(), gridBounds()));
|
||||
tx.commit();
|
||||
}
|
||||
|
||||
m_curPref->show.grid(gridVisible()->isSelected());
|
||||
m_curPref->grid.bounds(gridBounds());
|
||||
m_curPref->grid.color(gridColor()->getColor());
|
||||
@ -1390,6 +1402,7 @@ private:
|
||||
return paths;
|
||||
}
|
||||
|
||||
Context* m_context;
|
||||
Preferences& m_pref;
|
||||
DocumentPreferences& m_globPref;
|
||||
DocumentPreferences& m_docPref;
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include "app/i18n/strings.h"
|
||||
#include "app/modules/editors.h"
|
||||
#include "app/modules/gui.h"
|
||||
#include "app/pref/preferences.h"
|
||||
#include "app/snap_to_grid.h"
|
||||
#include "app/tx.h"
|
||||
#include "app/ui/editor/editor.h"
|
||||
@ -75,7 +74,6 @@ void SelectTileCommand::onExecute(Context* ctx)
|
||||
// Lock sprite
|
||||
ContextWriter writer(ctx);
|
||||
Doc* doc(writer.document());
|
||||
auto& docPref = Preferences::instance().document(doc);
|
||||
|
||||
std::unique_ptr<Mask> mask(new Mask());
|
||||
|
||||
@ -83,7 +81,7 @@ void SelectTileCommand::onExecute(Context* ctx)
|
||||
mask->copyFrom(doc->mask());
|
||||
|
||||
{
|
||||
gfx::Rect gridBounds = docPref.grid.bounds();
|
||||
gfx::Rect gridBounds = doc->sprite()->gridBounds();
|
||||
gfx::Point pos = current_editor->screenToEditor(ui::get_mouse_position());
|
||||
pos = snap_to_grid(gridBounds, pos, PreferSnapTo::BoxOrigin);
|
||||
gridBounds.setOrigin(pos);
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2017 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -12,7 +13,6 @@
|
||||
|
||||
#include "app/commands/params.h"
|
||||
#include "app/i18n/strings.h"
|
||||
#include "app/pref/preferences.h"
|
||||
#include "app/ui/doc_view.h"
|
||||
#include "app/ui/editor/editor.h"
|
||||
#include "app/ui_context.h"
|
||||
@ -78,10 +78,9 @@ gfx::Point MoveThing::getDelta(Context* context) const
|
||||
if (!view)
|
||||
return delta;
|
||||
|
||||
DocumentPreferences& docPref = Preferences::instance().document(view->document());
|
||||
Editor* editor = view->editor();
|
||||
gfx::Rect vp = view->viewWidget()->viewportBounds();
|
||||
gfx::Rect gridBounds = docPref.grid.bounds();
|
||||
gfx::Rect gridBounds = view->document()->sprite()->gridBounds();
|
||||
int pixels = 0;
|
||||
|
||||
switch (units) {
|
||||
|
@ -183,16 +183,17 @@ bool BackupObserver::saveDocData(Doc* doc)
|
||||
m_session->restoreBackupDocById(doc->id(), nullptr));
|
||||
DocDiff diff = compare_docs(doc, copy.get());
|
||||
if (diff.anything) {
|
||||
TRACE("RECO: Differences (%s/%s/%s/%s/%s/%s/%s)\n",
|
||||
diff.canvas ? "canvas": "",
|
||||
diff.totalFrames ? "totalFrames": "",
|
||||
diff.frameDuration ? "frameDuration": "",
|
||||
diff.frameTags ? "frameTags": "",
|
||||
diff.palettes ? "palettes": "",
|
||||
diff.layers ? "layers": "",
|
||||
diff.cels ? "cels": "",
|
||||
diff.images ? "images": "",
|
||||
diff.colorProfiles ? "colorProfiles": "");
|
||||
TRACEARGS("RECO: Differences:",
|
||||
diff.canvas ? "canvas": "",
|
||||
diff.totalFrames ? "totalFrames": "",
|
||||
diff.frameDuration ? "frameDuration": "",
|
||||
diff.tags ? "tags": "",
|
||||
diff.palettes ? "palettes": "",
|
||||
diff.layers ? "layers": "",
|
||||
diff.cels ? "cels": "",
|
||||
diff.images ? "images": "",
|
||||
diff.colorProfiles ? "colorProfiles": "",
|
||||
diff.gridBounds ? "gridBounds": "");
|
||||
|
||||
Doc* copyDoc = copy.release();
|
||||
ui::execute_from_ui_thread(
|
||||
|
@ -345,6 +345,11 @@ private:
|
||||
if (colorSpace)
|
||||
spr->setColorSpace(colorSpace);
|
||||
|
||||
// Read grid bounds
|
||||
gfx::Rect gridBounds = readGridBounds(s);
|
||||
if (!gridBounds.isEmpty())
|
||||
spr->setGridBounds(gridBounds);
|
||||
|
||||
return spr.release();
|
||||
}
|
||||
|
||||
@ -364,6 +369,15 @@ private:
|
||||
return colorSpace;
|
||||
}
|
||||
|
||||
gfx::Rect readGridBounds(std::ifstream& s) {
|
||||
gfx::Rect grid;
|
||||
grid.x = (int16_t)read16(s);
|
||||
grid.y = (int16_t)read16(s);
|
||||
grid.w = read16(s);
|
||||
grid.h = read16(s);
|
||||
return grid;
|
||||
}
|
||||
|
||||
// TODO could we use doc::read_layer() here?
|
||||
Layer* readLayer(std::ifstream& s) {
|
||||
LayerFlags flags = (LayerFlags)read32(s);
|
||||
|
@ -170,6 +170,17 @@ private:
|
||||
// Color Space
|
||||
writeColorSpace(s, spr->colorSpace());
|
||||
|
||||
// Grid bounds
|
||||
writeGridBounds(s, spr->gridBounds());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool writeGridBounds(std::ofstream& s, const gfx::Rect& grid) {
|
||||
write16(s, (int16_t)grid.x);
|
||||
write16(s, (int16_t)grid.y);
|
||||
write16(s, grid.w);
|
||||
write16(s, grid.h);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -334,13 +334,13 @@ void DocApi::trimSprite(Sprite* sprite, const bool byGrid)
|
||||
// TODO merge this code with the code in DocExporter::captureSamples()
|
||||
if (byGrid) {
|
||||
Doc* doc = m_document;
|
||||
auto& docPref = Preferences::instance().document(doc);
|
||||
const gfx::Rect& gridBounds = doc->sprite()->gridBounds();
|
||||
gfx::Point posTopLeft =
|
||||
snap_to_grid(docPref.grid.bounds(),
|
||||
snap_to_grid(gridBounds,
|
||||
bounds.origin(),
|
||||
PreferSnapTo::FloorGrid);
|
||||
gfx::Point posBottomRight =
|
||||
snap_to_grid(docPref.grid.bounds(),
|
||||
snap_to_grid(gridBounds,
|
||||
bounds.point2(),
|
||||
PreferSnapTo::CeilGrid);
|
||||
bounds = gfx::Rect(posTopLeft, posBottomRight);
|
||||
|
@ -144,6 +144,11 @@ DocDiff compare_docs(const Doc* a,
|
||||
diff.anything = diff.colorProfiles = true;
|
||||
}
|
||||
|
||||
// Compare grid bounds
|
||||
if (a->sprite()->gridBounds() != b->sprite()->gridBounds()) {
|
||||
diff.anything = diff.gridBounds = true;
|
||||
}
|
||||
|
||||
return diff;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -22,6 +23,7 @@ namespace app {
|
||||
bool cels : 1;
|
||||
bool images : 1;
|
||||
bool colorProfiles : 1;
|
||||
bool gridBounds : 1;
|
||||
|
||||
DocDiff() :
|
||||
anything(false),
|
||||
@ -33,7 +35,8 @@ namespace app {
|
||||
layers(false),
|
||||
cels(false),
|
||||
images(false),
|
||||
colorProfiles(false) {
|
||||
colorProfiles(false),
|
||||
gridBounds(false) {
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -698,13 +698,13 @@ void DocExporter::captureSamples(Samples& samples)
|
||||
if (m_trimCels) {
|
||||
// TODO merge this code with the code in DocApi::trimSprite()
|
||||
if (m_trimByGrid) {
|
||||
auto& docPref = Preferences::instance().document(doc);
|
||||
const gfx::Rect& gridBounds = doc->sprite()->gridBounds();
|
||||
gfx::Point posTopLeft =
|
||||
snap_to_grid(docPref.grid.bounds(),
|
||||
snap_to_grid(gridBounds,
|
||||
frameBounds.origin(),
|
||||
PreferSnapTo::FloorGrid);
|
||||
gfx::Point posBottomRight =
|
||||
snap_to_grid(docPref.grid.bounds(),
|
||||
snap_to_grid(gridBounds,
|
||||
frameBounds.point2(),
|
||||
PreferSnapTo::CeilGrid);
|
||||
frameBounds = gfx::Rect(posTopLeft, posBottomRight);
|
||||
|
@ -46,6 +46,7 @@ namespace app {
|
||||
virtual void onSpriteSizeChanged(DocEvent& ev) { }
|
||||
virtual void onSpriteTransparentColorChanged(DocEvent& ev) { }
|
||||
virtual void onSpritePixelRatioChanged(DocEvent& ev) { }
|
||||
virtual void onSpriteGridBoundsChanged(DocEvent& ev) { }
|
||||
|
||||
virtual void onLayerNameChange(DocEvent& ev) { }
|
||||
virtual void onLayerOpacityChange(DocEvent& ev) { }
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2018 Igara Studio S.A.
|
||||
// Copyright (C) 2018-2019 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -208,6 +208,12 @@ bool AseFormat::onLoad(FileOp* fop)
|
||||
fop->setEmbeddedColorProfile();
|
||||
}
|
||||
|
||||
// Sprite grid bounds will be set to empty (instead of
|
||||
// doc::Sprite::DefaultGridBounds()) if the file doesn't contain an
|
||||
// embedded grid bounds.
|
||||
if (!sprite->gridBounds().isEmpty())
|
||||
fop->setEmbeddedGridBounds();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -371,6 +377,10 @@ static void ase_file_prepare_header(FILE* f, dio::AsepriteHeader* header, const
|
||||
header->ncolors = sprite->palette(firstFrame)->size();
|
||||
header->pixel_width = sprite->pixelRatio().w;
|
||||
header->pixel_height = sprite->pixelRatio().h;
|
||||
header->grid_x = sprite->gridBounds().x;
|
||||
header->grid_y = sprite->gridBounds().y;
|
||||
header->grid_width = sprite->gridBounds().w;
|
||||
header->grid_height = sprite->gridBounds().h;
|
||||
}
|
||||
|
||||
static void ase_file_write_header(FILE* f, dio::AsepriteHeader* header)
|
||||
@ -394,6 +404,10 @@ static void ase_file_write_header(FILE* f, dio::AsepriteHeader* header)
|
||||
fputw(header->ncolors, f);
|
||||
fputc(header->pixel_width, f);
|
||||
fputc(header->pixel_height, f);
|
||||
fputw(header->grid_x, f);
|
||||
fputw(header->grid_y, f);
|
||||
fputw(header->grid_width, f);
|
||||
fputw(header->grid_height, f);
|
||||
|
||||
fseek(f, header->pos+128, SEEK_SET);
|
||||
}
|
||||
|
@ -1190,6 +1190,7 @@ FileOp::FileOp(FileOpType type,
|
||||
, m_createPaletteFromRgba(false)
|
||||
, m_ignoreEmpty(false)
|
||||
, m_embeddedColorProfile(false)
|
||||
, m_embeddedGridBounds(false)
|
||||
{
|
||||
if (config)
|
||||
m_config = *config;
|
||||
|
@ -209,6 +209,9 @@ namespace app {
|
||||
void setEmbeddedColorProfile() { m_embeddedColorProfile = true; }
|
||||
bool hasEmbeddedColorProfile() const { return m_embeddedColorProfile; }
|
||||
|
||||
void setEmbeddedGridBounds() { m_embeddedGridBounds = true; }
|
||||
bool hasEmbeddedGridBounds() const { return m_embeddedGridBounds; }
|
||||
|
||||
bool newBlend() const { return m_config.newBlend; }
|
||||
|
||||
private:
|
||||
@ -243,6 +246,9 @@ namespace app {
|
||||
// True if the file contained a color profile when it was loaded.
|
||||
bool m_embeddedColorProfile;
|
||||
|
||||
// True if the file contained a the grid bounds inside.
|
||||
bool m_embeddedGridBounds;
|
||||
|
||||
FileOpConfig m_config;
|
||||
|
||||
// Options
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "doc/color_mode.h"
|
||||
#include "doc/frame.h"
|
||||
#include "doc/layer_list.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "filters/tiled_mode.h"
|
||||
#include "gfx/rect.h"
|
||||
#include "render/onionskin_position.h"
|
||||
|
@ -10,6 +10,6 @@
|
||||
|
||||
// Increment this value if the scripting API is modified between two
|
||||
// released Aseprite versions.
|
||||
#define API_VERSION 6
|
||||
#define API_VERSION 7
|
||||
|
||||
#endif
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "app/cmd/remove_layer.h"
|
||||
#include "app/cmd/remove_slice.h"
|
||||
#include "app/cmd/remove_tag.h"
|
||||
#include "app/cmd/set_grid_bounds.h"
|
||||
#include "app/cmd/set_mask.h"
|
||||
#include "app/cmd/set_sprite_size.h"
|
||||
#include "app/cmd/set_transparent_color.h"
|
||||
@ -735,6 +736,23 @@ int Sprite_get_bounds(lua_State* L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Sprite_get_gridBounds(lua_State* L)
|
||||
{
|
||||
const auto sprite = get_docobj<Sprite>(L, 1);
|
||||
push_obj<gfx::Rect>(L, sprite->gridBounds());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Sprite_set_gridBounds(lua_State* L)
|
||||
{
|
||||
auto sprite = get_docobj<Sprite>(L, 1);
|
||||
const gfx::Rect bounds = convert_args_into_rect(L, 2);
|
||||
Tx tx;
|
||||
tx(new cmd::SetGridBounds(sprite, bounds));
|
||||
tx.commit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
const luaL_Reg Sprite_methods[] = {
|
||||
{ "__eq", Sprite_eq },
|
||||
{ "resize", Sprite_resize },
|
||||
@ -784,6 +802,7 @@ const Property Sprite_properties[] = {
|
||||
{ "backgroundLayer", Sprite_get_backgroundLayer, nullptr },
|
||||
{ "transparentColor", Sprite_get_transparentColor, Sprite_set_transparentColor },
|
||||
{ "bounds", Sprite_get_bounds, nullptr },
|
||||
{ "gridBounds", Sprite_get_gridBounds, Sprite_set_gridBounds },
|
||||
{ nullptr, nullptr, nullptr }
|
||||
};
|
||||
|
||||
|
@ -11,10 +11,12 @@
|
||||
|
||||
#include "app/site.h"
|
||||
|
||||
#include "app/pref/preferences.h"
|
||||
#include "base/base.h"
|
||||
#include "doc/cel.h"
|
||||
#include "doc/layer.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "ui/system.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
@ -77,4 +79,20 @@ void Site::range(const DocRange& range)
|
||||
}
|
||||
}
|
||||
|
||||
gfx::Rect Site::gridBounds() const
|
||||
{
|
||||
gfx::Rect bounds;
|
||||
if (m_sprite) {
|
||||
bounds = m_sprite->gridBounds();
|
||||
if (!bounds.isEmpty())
|
||||
return bounds;
|
||||
}
|
||||
if (ui::is_ui_thread()) {
|
||||
bounds = Preferences::instance().document(m_document).grid.bounds();
|
||||
if (!bounds.isEmpty())
|
||||
return bounds;
|
||||
}
|
||||
return doc::Sprite::DefaultGridBounds();
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "doc/frame.h"
|
||||
#include "doc/palette_picks.h"
|
||||
#include "doc/selected_objects.h"
|
||||
#include "gfx/fwd.h"
|
||||
|
||||
namespace doc {
|
||||
class Cel;
|
||||
@ -98,6 +99,8 @@ namespace app {
|
||||
doc::Palette* palette() const;
|
||||
doc::RgbMap* rgbMap() const;
|
||||
|
||||
gfx::Rect gridBounds() const;
|
||||
|
||||
private:
|
||||
Focus m_focus;
|
||||
Doc* m_document;
|
||||
|
@ -728,7 +728,7 @@ void Editor::drawOneSpriteUnclippedRect(ui::Graphics* g, const gfx::Rect& sprite
|
||||
|
||||
// Draw the grid
|
||||
if (m_docPref.show.grid()) {
|
||||
gfx::Rect gridrc = m_docPref.grid.bounds();
|
||||
gfx::Rect gridrc = m_sprite->gridBounds();
|
||||
if (m_proj.applyX(gridrc.w) > 2 &&
|
||||
m_proj.applyY(gridrc.h) > 2) {
|
||||
int alpha = m_docPref.grid.opacity();
|
||||
@ -740,9 +740,10 @@ void Editor::drawOneSpriteUnclippedRect(ui::Graphics* g, const gfx::Rect& sprite
|
||||
alpha = MID(0, alpha, 255);
|
||||
}
|
||||
|
||||
if (alpha > 8)
|
||||
drawGrid(g, enclosingRect, m_docPref.grid.bounds(),
|
||||
if (alpha > 8) {
|
||||
drawGrid(g, enclosingRect, gridrc,
|
||||
m_docPref.grid.color(), alpha);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -343,8 +343,7 @@ void PixelsMovement::moveImage(const gfx::Point& pos, MoveModifier moveModifier)
|
||||
|
||||
if ((moveModifier & SnapToGridMovement) == SnapToGridMovement) {
|
||||
// Snap the x1,y1 point to the grid.
|
||||
gfx::Rect gridBounds = App::instance()
|
||||
->preferences().document(m_document).grid.bounds();
|
||||
gfx::Rect gridBounds = m_document->sprite()->gridBounds();
|
||||
gfx::PointF gridOffset(
|
||||
snap_to_grid(
|
||||
gridBounds,
|
||||
|
@ -596,7 +596,7 @@ bool StandbyState::onUpdateStatusBar(Editor* editor)
|
||||
}
|
||||
|
||||
if (editor->docPref().show.grid()) {
|
||||
auto gb = editor->docPref().grid.bounds();
|
||||
auto gb = sprite->gridBounds();
|
||||
if (!gb.isEmpty()) {
|
||||
int col = int((std::floor(spritePos.x) - (gb.x % gb.w)) / gb.w);
|
||||
int row = int((std::floor(spritePos.y) - (gb.y % gb.h)) / gb.h);
|
||||
|
@ -80,6 +80,7 @@ protected:
|
||||
int m_opacity;
|
||||
int m_tolerance;
|
||||
bool m_contiguous;
|
||||
gfx::Rect m_gridBounds;
|
||||
gfx::Point m_celOrigin;
|
||||
gfx::Point m_speed;
|
||||
tools::ToolLoop::Button m_button;
|
||||
@ -118,6 +119,7 @@ public:
|
||||
, m_opacity(m_toolPref.opacity())
|
||||
, m_tolerance(m_toolPref.tolerance())
|
||||
, m_contiguous(m_toolPref.contiguous())
|
||||
, m_gridBounds(site.gridBounds())
|
||||
, m_button(button)
|
||||
, m_ink(ink->clone())
|
||||
, m_controller(controller)
|
||||
@ -252,7 +254,7 @@ public:
|
||||
== app::gen::PixelConnectivity::EIGHT_CONNECTED);
|
||||
}
|
||||
|
||||
gfx::Rect getGridBounds() override { return m_docPref.grid.bounds(); }
|
||||
gfx::Rect getGridBounds() override { return m_gridBounds; }
|
||||
gfx::Point getCelOrigin() override { return m_celOrigin; }
|
||||
void setSpeed(const gfx::Point& speed) override { m_speed = speed; }
|
||||
gfx::Point getSpeed() override { return m_speed; }
|
||||
|
@ -72,6 +72,10 @@ struct AsepriteHeader {
|
||||
uint16_t ncolors;
|
||||
uint8_t pixel_width;
|
||||
uint8_t pixel_height;
|
||||
int16_t grid_x;
|
||||
int16_t grid_y;
|
||||
uint16_t grid_width;
|
||||
uint16_t grid_height;
|
||||
};
|
||||
|
||||
struct AsepriteFrameHeader {
|
||||
|
@ -58,6 +58,10 @@ bool AsepriteDecoder::decode()
|
||||
// Set pixel ratio
|
||||
sprite->setPixelRatio(doc::PixelRatio(header.pixel_width, header.pixel_height));
|
||||
|
||||
// Set grid bounds
|
||||
sprite->setGridBounds(gfx::Rect(header.grid_x, header.grid_y,
|
||||
header.grid_width, header.grid_height));
|
||||
|
||||
// Prepare variables for layer chunks
|
||||
doc::Layer* last_layer = sprite->root();
|
||||
doc::WithUserData* last_object_with_user_data = nullptr;
|
||||
@ -252,6 +256,10 @@ bool AsepriteDecoder::readHeader(AsepriteHeader* header)
|
||||
header->ncolors = read16();
|
||||
header->pixel_width = read8();
|
||||
header->pixel_height = read8();
|
||||
header->grid_x = (int16_t)read16();
|
||||
header->grid_y = (int16_t)read16();
|
||||
header->grid_width = read16();
|
||||
header->grid_height = read16();
|
||||
|
||||
if (header->ncolors == 0) // 0 means 256 (old .ase files)
|
||||
header->ncolors = 256;
|
||||
@ -588,8 +596,8 @@ doc::Cel* AsepriteDecoder::readCelChunk(doc::Sprite* sprite,
|
||||
{
|
||||
// Read chunk data
|
||||
doc::layer_t layer_index = read16();
|
||||
int x = ((short)read16());
|
||||
int y = ((short)read16());
|
||||
int x = ((int16_t)read16());
|
||||
int y = ((int16_t)read16());
|
||||
int opacity = read8();
|
||||
int cel_type = read16();
|
||||
readPadding(7);
|
||||
|
@ -34,6 +34,9 @@ namespace doc {
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Constructors/Destructor
|
||||
|
||||
// static
|
||||
gfx::Rect Sprite::DefaultGridBounds() { return gfx::Rect(0, 0, 16, 16); }
|
||||
|
||||
Sprite::Sprite(const ImageSpec& spec,
|
||||
int ncolors)
|
||||
: Object(ObjectType::Sprite)
|
||||
@ -43,6 +46,7 @@ Sprite::Sprite(const ImageSpec& spec,
|
||||
, m_frames(1)
|
||||
, m_frlens(1, 100) // First frame with 100 msecs of duration
|
||||
, m_root(new LayerGroup(this))
|
||||
, m_gridBounds(Sprite::DefaultGridBounds())
|
||||
, m_rgbMap(nullptr) // Initial RGB map
|
||||
, m_tags(this)
|
||||
, m_slices(this)
|
||||
|
@ -98,6 +98,10 @@ namespace doc {
|
||||
color_t transparentColor() const { return m_spec.maskColor(); }
|
||||
void setTransparentColor(color_t color);
|
||||
|
||||
static gfx::Rect DefaultGridBounds();
|
||||
const gfx::Rect& gridBounds() const { return m_gridBounds; }
|
||||
void setGridBounds(const gfx::Rect& rc) { m_gridBounds = rc; }
|
||||
|
||||
virtual int getMemSize() const override;
|
||||
|
||||
////////////////////////////////////////
|
||||
@ -188,6 +192,7 @@ namespace doc {
|
||||
std::vector<int> m_frlens; // duration per frame
|
||||
PalettesList m_palettes; // list of palettes
|
||||
LayerGroup* m_root; // main group of layers
|
||||
gfx::Rect m_gridBounds; // grid settings
|
||||
|
||||
// Current rgb map
|
||||
mutable RgbMap* m_rgbMap;
|
||||
|
Loading…
x
Reference in New Issue
Block a user