mirror of
https://github.com/aseprite/aseprite.git
synced 2024-10-03 21:46:20 +00:00
Add subpixel bounds for reference layer cels
Now we can move a reference layer cel in a X,Y position with floating point coordinates (i.e. in a subpixel position).
This commit is contained in:
parent
4a7d601d5d
commit
080e7e3f68
@ -134,6 +134,7 @@ add_library(app-lib
|
||||
cmd/remove_palette.cpp
|
||||
cmd/replace_image.cpp
|
||||
cmd/reselect_mask.cpp
|
||||
cmd/set_cel_bounds.cpp
|
||||
cmd/set_cel_data.cpp
|
||||
cmd/set_cel_frame.cpp
|
||||
cmd/set_cel_opacity.cpp
|
||||
|
51
src/app/cmd/set_cel_bounds.cpp
Normal file
51
src/app/cmd/set_cel_bounds.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2016 David Capello
|
||||
//
|
||||
// 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_cel_bounds.h"
|
||||
|
||||
#include "app/document.h"
|
||||
#include "doc/cel.h"
|
||||
#include "doc/document_event.h"
|
||||
|
||||
namespace app {
|
||||
namespace cmd {
|
||||
|
||||
using namespace doc;
|
||||
|
||||
SetCelBoundsF::SetCelBoundsF(Cel* cel, const gfx::RectF& bounds)
|
||||
: WithCel(cel)
|
||||
, m_oldBounds(cel->boundsF())
|
||||
, m_newBounds(bounds)
|
||||
{
|
||||
}
|
||||
|
||||
void SetCelBoundsF::onExecute()
|
||||
{
|
||||
cel()->setBoundsF(m_newBounds);
|
||||
cel()->incrementVersion();
|
||||
}
|
||||
|
||||
void SetCelBoundsF::onUndo()
|
||||
{
|
||||
cel()->setBoundsF(m_oldBounds);
|
||||
cel()->incrementVersion();
|
||||
}
|
||||
|
||||
void SetCelBoundsF::onFireNotifications()
|
||||
{
|
||||
Cel* cel = this->cel();
|
||||
DocumentEvent ev(cel->document());
|
||||
ev.sprite(cel->sprite());
|
||||
ev.cel(cel);
|
||||
cel->document()->notify_observers<DocumentEvent&>(&DocumentObserver::onCelPositionChanged, ev);
|
||||
}
|
||||
|
||||
} // namespace cmd
|
||||
} // namespace app
|
40
src/app/cmd/set_cel_bounds.h
Normal file
40
src/app/cmd/set_cel_bounds.h
Normal file
@ -0,0 +1,40 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2016 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
|
||||
#ifndef APP_CMD_SET_CEL_BOUNDS_H_INCLUDED
|
||||
#define APP_CMD_SET_CEL_BOUNDS_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "app/cmd.h"
|
||||
#include "app/cmd/with_cel.h"
|
||||
#include "gfx/rect.h"
|
||||
|
||||
namespace app {
|
||||
namespace cmd {
|
||||
using namespace doc;
|
||||
|
||||
class SetCelBoundsF : public Cmd
|
||||
, public WithCel {
|
||||
public:
|
||||
SetCelBoundsF(Cel* cel, const gfx::RectF& bounds);
|
||||
|
||||
protected:
|
||||
void onExecute() override;
|
||||
void onUndo() override;
|
||||
void onFireNotifications() override;
|
||||
size_t onMemSize() const override {
|
||||
return sizeof(*this);
|
||||
}
|
||||
|
||||
private:
|
||||
gfx::RectF m_oldBounds;
|
||||
gfx::RectF m_newBounds;
|
||||
};
|
||||
|
||||
} // namespace cmd
|
||||
} // namespace app
|
||||
|
||||
#endif
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2015 David Capello
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -44,7 +44,7 @@ void ExtraCel::create(doc::Sprite* sprite,
|
||||
m_cel.reset(new doc::Cel(doc::frame_t(0), doc::ImageRef(nullptr)));
|
||||
}
|
||||
|
||||
m_cel->setPosition(bounds.origin());
|
||||
m_cel->setBounds(bounds);
|
||||
m_cel->setOpacity(opacity);
|
||||
m_cel->setFrame(frame);
|
||||
}
|
||||
|
@ -1028,6 +1028,17 @@ gfx::Point Editor::screenToEditor(const gfx::Point& pt)
|
||||
m_proj.removeY(pt.y - vp.y + scroll.y - m_padding.y));
|
||||
}
|
||||
|
||||
gfx::PointF Editor::screenToEditorF(const gfx::Point& pt)
|
||||
{
|
||||
View* view = View::getView(this);
|
||||
Rect vp = view->viewportBounds();
|
||||
Point scroll = view->viewScroll();
|
||||
|
||||
return gfx::PointF(
|
||||
m_proj.removeX<double>(pt.x - vp.x + scroll.x - m_padding.x),
|
||||
m_proj.removeY<double>(pt.y - vp.y + scroll.y - m_padding.y));
|
||||
}
|
||||
|
||||
Point Editor::editorToScreen(const gfx::Point& pt)
|
||||
{
|
||||
View* view = View::getView(this);
|
||||
|
@ -150,6 +150,7 @@ namespace app {
|
||||
void flashCurrentLayer();
|
||||
|
||||
gfx::Point screenToEditor(const gfx::Point& pt);
|
||||
gfx::PointF screenToEditorF(const gfx::Point& pt);
|
||||
gfx::Point editorToScreen(const gfx::Point& pt);
|
||||
gfx::Rect screenToEditor(const gfx::Rect& rc);
|
||||
gfx::Rect editorToScreen(const gfx::Rect& rc);
|
||||
|
@ -11,16 +11,17 @@
|
||||
#include "app/ui/editor/moving_cel_state.h"
|
||||
|
||||
#include "app/app.h"
|
||||
#include "app/cmd/set_cel_bounds.h"
|
||||
#include "app/context_access.h"
|
||||
#include "app/document_api.h"
|
||||
#include "app/document_range.h"
|
||||
#include "app/transaction.h"
|
||||
#include "app/ui/editor/editor.h"
|
||||
#include "app/ui/editor/editor_customization_delegate.h"
|
||||
#include "app/ui/main_window.h"
|
||||
#include "app/ui/status_bar.h"
|
||||
#include "app/ui/timeline.h"
|
||||
#include "app/ui_context.h"
|
||||
#include "app/transaction.h"
|
||||
#include "app/util/range_utils.h"
|
||||
#include "doc/cel.h"
|
||||
#include "doc/layer.h"
|
||||
@ -35,6 +36,7 @@ using namespace ui;
|
||||
MovingCelState::MovingCelState(Editor* editor, MouseMessage* msg)
|
||||
: m_reader(UIContext::instance(), 500)
|
||||
, m_canceled(false)
|
||||
, m_hasReference(false)
|
||||
{
|
||||
ContextWriter writer(m_reader);
|
||||
Document* document = editor->document();
|
||||
@ -55,12 +57,18 @@ MovingCelState::MovingCelState(Editor* editor, MouseMessage* msg)
|
||||
|
||||
if (layer && layer->isMovable() && !layer->isBackground()) {
|
||||
m_celList.push_back(cel);
|
||||
m_celStarts.push_back(cel->position());
|
||||
|
||||
if (cel->layer()->isReference()) {
|
||||
m_celStarts.push_back(cel->boundsF());
|
||||
m_hasReference = true;
|
||||
}
|
||||
else
|
||||
m_celStarts.push_back(cel->bounds());
|
||||
}
|
||||
}
|
||||
|
||||
m_cursorStart = editor->screenToEditor(msg->position());
|
||||
m_celOffset = gfx::Point(0, 0);
|
||||
m_cursorStart = editor->screenToEditorF(msg->position());
|
||||
m_celOffset = gfx::PointF(0, 0);
|
||||
editor->captureMouse();
|
||||
|
||||
// Hide the mask (temporarily, until mouse-up event)
|
||||
@ -71,23 +79,23 @@ MovingCelState::MovingCelState(Editor* editor, MouseMessage* msg)
|
||||
}
|
||||
}
|
||||
|
||||
MovingCelState::~MovingCelState()
|
||||
{
|
||||
}
|
||||
|
||||
bool MovingCelState::onMouseUp(Editor* editor, MouseMessage* msg)
|
||||
{
|
||||
Document* document = editor->document();
|
||||
|
||||
// Here we put back the cel into its original coordinate (so we can
|
||||
// add an undoer before).
|
||||
if (m_celOffset != gfx::Point(0, 0)) {
|
||||
if ((m_hasReference && m_celOffset != gfx::PointF(0, 0)) ||
|
||||
(!m_hasReference && gfx::Point(m_celOffset) != gfx::Point(0, 0))) {
|
||||
// Put the cels in the original position.
|
||||
for (size_t i=0; i<m_celList.size(); ++i) {
|
||||
Cel* cel = m_celList[i];
|
||||
const gfx::Point& celStart = m_celStarts[i];
|
||||
const gfx::RectF& celStart = m_celStarts[i];
|
||||
|
||||
cel->setPosition(celStart);
|
||||
if (cel->layer()->isReference())
|
||||
cel->setBoundsF(celStart);
|
||||
else
|
||||
cel->setBounds(gfx::Rect(celStart));
|
||||
}
|
||||
|
||||
// If the user didn't cancel the operation...
|
||||
@ -98,9 +106,18 @@ bool MovingCelState::onMouseUp(Editor* editor, MouseMessage* msg)
|
||||
|
||||
// And now we move the cel (or all selected range) to the new position.
|
||||
for (Cel* cel : m_celList) {
|
||||
api.setCelPosition(writer.sprite(), cel,
|
||||
cel->x() + m_celOffset.x,
|
||||
cel->y() + m_celOffset.y);
|
||||
// Change reference layer with subpixel precision
|
||||
if (cel->layer()->isReference()) {
|
||||
gfx::RectF celBounds = cel->boundsF();
|
||||
celBounds.x += m_celOffset.x;
|
||||
celBounds.y += m_celOffset.y;
|
||||
transaction.execute(new cmd::SetCelBoundsF(cel, celBounds));
|
||||
}
|
||||
else {
|
||||
api.setCelPosition(writer.sprite(), cel,
|
||||
cel->x() + m_celOffset.x,
|
||||
cel->y() + m_celOffset.y);
|
||||
}
|
||||
}
|
||||
|
||||
// Move selection if it was visible
|
||||
@ -131,7 +148,7 @@ bool MovingCelState::onMouseUp(Editor* editor, MouseMessage* msg)
|
||||
|
||||
bool MovingCelState::onMouseMove(Editor* editor, MouseMessage* msg)
|
||||
{
|
||||
gfx::Point newCursorPos = editor->screenToEditor(msg->position());
|
||||
gfx::PointF newCursorPos = editor->screenToEditorF(msg->position());
|
||||
|
||||
m_celOffset = newCursorPos - m_cursorStart;
|
||||
|
||||
@ -147,9 +164,14 @@ bool MovingCelState::onMouseMove(Editor* editor, MouseMessage* msg)
|
||||
|
||||
for (size_t i=0; i<m_celList.size(); ++i) {
|
||||
Cel* cel = m_celList[i];
|
||||
const gfx::Point& celStart = m_celStarts[i];
|
||||
gfx::RectF celBounds = m_celStarts[i];
|
||||
celBounds.x += m_celOffset.x;
|
||||
celBounds.y += m_celOffset.y;
|
||||
|
||||
cel->setPosition(celStart + m_celOffset);
|
||||
if (cel->layer()->isReference())
|
||||
cel->setBoundsF(celBounds);
|
||||
else
|
||||
cel->setBounds(gfx::Rect(celBounds));
|
||||
}
|
||||
|
||||
// Redraw the new cel position.
|
||||
@ -161,13 +183,24 @@ bool MovingCelState::onMouseMove(Editor* editor, MouseMessage* msg)
|
||||
|
||||
bool MovingCelState::onUpdateStatusBar(Editor* editor)
|
||||
{
|
||||
StatusBar::instance()->setStatusText
|
||||
(0,
|
||||
":pos: %3d %3d :offset: %3d %3d",
|
||||
(int)m_cursorStart.x,
|
||||
(int)m_cursorStart.y,
|
||||
(int)m_celOffset.x,
|
||||
(int)m_celOffset.y);
|
||||
if (m_hasReference) {
|
||||
StatusBar::instance()->setStatusText
|
||||
(0,
|
||||
":pos: %.2f %.2f :offset: %.2f %.2f",
|
||||
m_cursorStart.x,
|
||||
m_cursorStart.y,
|
||||
m_celOffset.x,
|
||||
m_celOffset.y);
|
||||
}
|
||||
else {
|
||||
StatusBar::instance()->setStatusText
|
||||
(0,
|
||||
":pos: %3d %3d :offset: %3d %3d",
|
||||
int(m_cursorStart.x),
|
||||
int(m_cursorStart.y),
|
||||
int(m_celOffset.x),
|
||||
int(m_celOffset.y));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2015 David Capello
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -25,7 +25,6 @@ namespace app {
|
||||
class MovingCelState : public StandbyState {
|
||||
public:
|
||||
MovingCelState(Editor* editor, ui::MouseMessage* msg);
|
||||
virtual ~MovingCelState();
|
||||
|
||||
virtual bool onMouseUp(Editor* editor, ui::MouseMessage* msg) override;
|
||||
virtual bool onMouseMove(Editor* editor, ui::MouseMessage* msg) override;
|
||||
@ -36,11 +35,12 @@ namespace app {
|
||||
private:
|
||||
ContextReader m_reader;
|
||||
CelList m_celList;
|
||||
std::vector<gfx::Point> m_celStarts;
|
||||
gfx::Point m_celOffset;
|
||||
gfx::Point m_cursorStart;
|
||||
std::vector<gfx::RectF> m_celStarts;
|
||||
gfx::PointF m_cursorStart;
|
||||
gfx::PointF m_celOffset;
|
||||
bool m_canceled;
|
||||
bool m_maskVisible;
|
||||
bool m_hasReference;
|
||||
};
|
||||
|
||||
} // namespace app
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite Document Library
|
||||
// Copyright (c) 2001-2015 David Capello
|
||||
// Copyright (c) 2001-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -77,6 +77,11 @@ void Cel::setBounds(const gfx::Rect& bounds)
|
||||
m_data->setBounds(bounds);
|
||||
}
|
||||
|
||||
void Cel::setBoundsF(const gfx::RectF& bounds)
|
||||
{
|
||||
m_data->setBoundsF(bounds);
|
||||
}
|
||||
|
||||
void Cel::setOpacity(int opacity)
|
||||
{
|
||||
m_data->setOpacity(opacity);
|
||||
|
@ -35,6 +35,7 @@ namespace doc {
|
||||
int y() const { return m_data->position().y; }
|
||||
gfx::Point position() const { return m_data->position(); }
|
||||
const gfx::Rect& bounds() const { return m_data->bounds(); }
|
||||
const gfx::RectF& boundsF() const { return m_data->boundsF(); }
|
||||
int opacity() const { return m_data->opacity(); }
|
||||
|
||||
LayerImage* layer() const { return m_layer; }
|
||||
@ -55,6 +56,7 @@ namespace doc {
|
||||
void setPosition(int x, int y);
|
||||
void setPosition(const gfx::Point& pos);
|
||||
void setBounds(const gfx::Rect& bounds);
|
||||
void setBoundsF(const gfx::RectF& bounds);
|
||||
void setOpacity(int opacity);
|
||||
|
||||
virtual int getMemSize() const override {
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite Document Library
|
||||
// Copyright (c) 2001-2015 David Capello
|
||||
// Copyright (c) 2001-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -20,21 +20,29 @@ namespace doc {
|
||||
CelData::CelData(const ImageRef& image)
|
||||
: WithUserData(ObjectType::CelData)
|
||||
, m_image(image)
|
||||
, m_opacity(255)
|
||||
, m_bounds(0, 0,
|
||||
image ? image->width(): 0,
|
||||
image ? image->height(): 0)
|
||||
, m_opacity(255)
|
||||
, m_boundsF(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
CelData::CelData(const CelData& celData)
|
||||
: WithUserData(ObjectType::CelData)
|
||||
, m_image(celData.m_image)
|
||||
, m_bounds(celData.m_bounds)
|
||||
, m_opacity(celData.m_opacity)
|
||||
, m_bounds(celData.m_bounds)
|
||||
, m_boundsF(celData.m_boundsF ? new gfx::RectF(*celData.m_boundsF):
|
||||
nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
CelData::~CelData()
|
||||
{
|
||||
delete m_boundsF;
|
||||
}
|
||||
|
||||
void CelData::setImage(const ImageRef& image)
|
||||
{
|
||||
ASSERT(image.get());
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite Document Library
|
||||
// Copyright (c) 2001-2015 David Capello
|
||||
// Copyright (c) 2001-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -20,6 +20,7 @@ namespace doc {
|
||||
public:
|
||||
CelData(const ImageRef& image);
|
||||
CelData(const CelData& celData);
|
||||
~CelData();
|
||||
|
||||
gfx::Point position() const { return m_bounds.origin(); }
|
||||
const gfx::Rect& bounds() const { return m_bounds; }
|
||||
@ -29,9 +30,29 @@ namespace doc {
|
||||
|
||||
void setImage(const ImageRef& image);
|
||||
void setPosition(const gfx::Point& pos) { m_bounds.setOrigin(pos); }
|
||||
void setBounds(const gfx::Rect& bounds) { m_bounds = bounds; }
|
||||
void setOpacity(int opacity) { m_opacity = opacity; }
|
||||
|
||||
void setBounds(const gfx::Rect& bounds) {
|
||||
m_bounds = bounds;
|
||||
if (m_boundsF)
|
||||
*m_boundsF = gfx::RectF(bounds);
|
||||
}
|
||||
|
||||
void setBoundsF(const gfx::RectF& boundsF) {
|
||||
if (m_boundsF)
|
||||
*m_boundsF = boundsF;
|
||||
else
|
||||
m_boundsF = new gfx::RectF(boundsF);
|
||||
|
||||
m_bounds = gfx::Rect(boundsF);
|
||||
}
|
||||
|
||||
const gfx::RectF& boundsF() const {
|
||||
if (!m_boundsF)
|
||||
m_boundsF = new gfx::RectF(m_bounds);
|
||||
return *m_boundsF;
|
||||
}
|
||||
|
||||
virtual int getMemSize() const override {
|
||||
ASSERT(m_image);
|
||||
return sizeof(CelData) + m_image->getMemSize();
|
||||
@ -39,8 +60,12 @@ namespace doc {
|
||||
|
||||
private:
|
||||
ImageRef m_image;
|
||||
gfx::Rect m_bounds;
|
||||
int m_opacity;
|
||||
gfx::Rect m_bounds;
|
||||
|
||||
// Special bounds for reference layers that can have subpixel
|
||||
// position.
|
||||
mutable gfx::RectF* m_boundsF;
|
||||
};
|
||||
|
||||
typedef base::SharedPtr<CelData> CelDataRef;
|
||||
|
@ -2,7 +2,6 @@
|
||||
# Copyright (C) 2001-2016 David Capello
|
||||
|
||||
add_library(gfx-lib
|
||||
clip.cpp
|
||||
hsv.cpp
|
||||
packing_rects.cpp
|
||||
region.cpp
|
||||
|
@ -1,64 +0,0 @@
|
||||
// Aseprite Gfx Library
|
||||
// Copyright (c) 2001-2014 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "gfx/clip.h"
|
||||
|
||||
namespace gfx {
|
||||
|
||||
bool Clip::clip(
|
||||
int avail_dst_w,
|
||||
int avail_dst_h,
|
||||
int avail_src_w,
|
||||
int avail_src_h)
|
||||
{
|
||||
// Clip srcBounds
|
||||
|
||||
if (src.x < 0) {
|
||||
size.w += src.x;
|
||||
dst.x -= src.x;
|
||||
src.x = 0;
|
||||
}
|
||||
|
||||
if (src.y < 0) {
|
||||
size.h += src.y;
|
||||
dst.y -= src.y;
|
||||
src.y = 0;
|
||||
}
|
||||
|
||||
if (src.x + size.w > avail_src_w)
|
||||
size.w -= src.x + size.w - avail_src_w;
|
||||
|
||||
if (src.y + size.h > avail_src_h)
|
||||
size.h -= src.y + size.h - avail_src_h;
|
||||
|
||||
// Clip dstBounds
|
||||
|
||||
if (dst.x < 0) {
|
||||
size.w += dst.x;
|
||||
src.x -= dst.x;
|
||||
dst.x = 0;
|
||||
}
|
||||
|
||||
if (dst.y < 0) {
|
||||
size.h += dst.y;
|
||||
src.y -= dst.y;
|
||||
dst.y = 0;
|
||||
}
|
||||
|
||||
if (dst.x + size.w > avail_dst_w)
|
||||
size.w -= dst.x + size.w - avail_dst_w;
|
||||
|
||||
if (dst.y + size.h > avail_dst_h)
|
||||
size.h -= dst.y + size.h - avail_dst_h;
|
||||
|
||||
return (size.w > 0 && size.h > 0);
|
||||
}
|
||||
|
||||
} // namespace gfx
|
@ -1,5 +1,5 @@
|
||||
// Aseprite Gfx Library
|
||||
// Copyright (c) 2001-2014 David Capello
|
||||
// Copyright (c) 2001-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -14,58 +14,59 @@
|
||||
|
||||
namespace gfx {
|
||||
|
||||
class Clip {
|
||||
template<typename T>
|
||||
class ClipT {
|
||||
public:
|
||||
Point dst;
|
||||
Point src;
|
||||
Size size;
|
||||
PointT<T> dst;
|
||||
PointT<T> src;
|
||||
SizeT<T> size;
|
||||
|
||||
Clip()
|
||||
ClipT()
|
||||
: dst(0, 0)
|
||||
, src(0, 0)
|
||||
, size(0, 0) {
|
||||
}
|
||||
|
||||
Clip(int w, int h)
|
||||
ClipT(T w, T h)
|
||||
: dst(0, 0)
|
||||
, src(0, 0)
|
||||
, size(w, h) {
|
||||
}
|
||||
|
||||
Clip(int dst_x, int dst_y, int src_x, int src_y, int w, int h)
|
||||
ClipT(T dst_x, T dst_y, T src_x, T src_y, T w, T h)
|
||||
: dst(dst_x, dst_y)
|
||||
, src(src_x, src_y)
|
||||
, size(w, h) {
|
||||
}
|
||||
|
||||
Clip(int dst_x, int dst_y, const Rect& srcBounds)
|
||||
ClipT(T dst_x, T dst_y, const RectT<T>& srcBounds)
|
||||
: dst(dst_x, dst_y)
|
||||
, src(srcBounds.x, srcBounds.y)
|
||||
, size(srcBounds.w, srcBounds.h) {
|
||||
}
|
||||
|
||||
Clip(const Point& dst, const Point& src, const Size& size)
|
||||
ClipT(const PointT<T>& dst, const PointT<T>& src, const SizeT<T>& size)
|
||||
: dst(dst)
|
||||
, src(src)
|
||||
, size(size) {
|
||||
}
|
||||
|
||||
Clip(const Point& dst, const Rect& srcBounds)
|
||||
ClipT(const PointT<T>& dst, const RectT<T>& srcBounds)
|
||||
: dst(dst)
|
||||
, src(srcBounds.x, srcBounds.y)
|
||||
, size(srcBounds.w, srcBounds.h) {
|
||||
}
|
||||
|
||||
Clip(const Rect& bounds)
|
||||
ClipT(const RectT<T>& bounds)
|
||||
: dst(bounds.x, bounds.y)
|
||||
, src(bounds.x, bounds.y)
|
||||
, size(bounds.w, bounds.h) {
|
||||
}
|
||||
|
||||
Rect dstBounds() const { return Rect(dst, size); }
|
||||
Rect srcBounds() const { return Rect(src, size); }
|
||||
RectT<T> dstBounds() const { return RectT<T>(dst, size); }
|
||||
RectT<T> srcBounds() const { return RectT<T>(src, size); }
|
||||
|
||||
bool operator==(const Clip& other) const {
|
||||
bool operator==(const ClipT<T>& other) const {
|
||||
return (dst == other.dst &&
|
||||
src == other.src &&
|
||||
size == other.size);
|
||||
@ -73,13 +74,58 @@ namespace gfx {
|
||||
|
||||
bool clip(
|
||||
// Available area
|
||||
int avail_dst_w,
|
||||
int avail_dst_h,
|
||||
int avail_src_w,
|
||||
int avail_src_h);
|
||||
T avail_dst_w,
|
||||
T avail_dst_h,
|
||||
T avail_src_w,
|
||||
T avail_src_h) {
|
||||
// Clip srcBounds
|
||||
|
||||
if (src.x < T(0)) {
|
||||
size.w += src.x;
|
||||
dst.x -= src.x;
|
||||
src.x = T(0);
|
||||
}
|
||||
|
||||
if (src.y < T(0)) {
|
||||
size.h += src.y;
|
||||
dst.y -= src.y;
|
||||
src.y = T(0);
|
||||
}
|
||||
|
||||
if (src.x + size.w > avail_src_w)
|
||||
size.w -= src.x + size.w - avail_src_w;
|
||||
|
||||
if (src.y + size.h > avail_src_h)
|
||||
size.h -= src.y + size.h - avail_src_h;
|
||||
|
||||
// Clip dstBounds
|
||||
|
||||
if (dst.x < T(0)) {
|
||||
size.w += dst.x;
|
||||
src.x -= dst.x;
|
||||
dst.x = T(0);
|
||||
}
|
||||
|
||||
if (dst.y < T(0)) {
|
||||
size.h += dst.y;
|
||||
src.y -= dst.y;
|
||||
dst.y = T(0);
|
||||
}
|
||||
|
||||
if (dst.x + size.w > avail_dst_w)
|
||||
size.w -= dst.x + size.w - avail_dst_w;
|
||||
|
||||
if (dst.y + size.h > avail_dst_h)
|
||||
size.h -= dst.y + size.h - avail_dst_h;
|
||||
|
||||
return (size.w > T(0) && size.h > T(0));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
typedef ClipT<int> Clip;
|
||||
typedef ClipT<double> ClipF;
|
||||
|
||||
} // namespace gfx
|
||||
|
||||
#endif
|
||||
|
@ -11,11 +11,13 @@
|
||||
namespace gfx {
|
||||
|
||||
template<typename T> class BorderT;
|
||||
template<typename T> class ClipT;
|
||||
template<typename T> class PointT;
|
||||
template<typename T> class RectT;
|
||||
template<typename T> class SizeT;
|
||||
|
||||
typedef BorderT<int> Border;
|
||||
typedef ClipT<int> Clip;
|
||||
typedef PointT<int> Point;
|
||||
typedef RectT<int> Rect;
|
||||
typedef SizeT<int> Size;
|
||||
|
@ -1,5 +1,5 @@
|
||||
# Aseprite Render Library
|
||||
# Copyright (C) 2001-2015 David Capello
|
||||
# Copyright (C) 2001-2016 David Capello
|
||||
|
||||
add_library(render-lib
|
||||
get_sprite_pixel.cpp
|
||||
|
@ -55,6 +55,14 @@ namespace render {
|
||||
applyY(r.y+r.h) - v);
|
||||
}
|
||||
|
||||
gfx::RectF apply(const gfx::RectF& r) const {
|
||||
double u = applyX(r.x);
|
||||
double v = applyY(r.y);
|
||||
return gfx::RectF(u, v,
|
||||
applyX(r.x+r.w) - u,
|
||||
applyY(r.y+r.h) - v);
|
||||
}
|
||||
|
||||
gfx::Rect remove(const gfx::Rect& r) const {
|
||||
int u = removeX(r.x);
|
||||
int v = removeY(r.y);
|
||||
@ -63,6 +71,14 @@ namespace render {
|
||||
removeY(r.y+r.h) - v);
|
||||
}
|
||||
|
||||
gfx::RectF remove(const gfx::RectF& r) const {
|
||||
double u = removeX(r.x);
|
||||
double v = removeY(r.y);
|
||||
return gfx::RectF(u, v,
|
||||
removeX(r.x+r.w) - u,
|
||||
removeY(r.y+r.h) - v);
|
||||
}
|
||||
|
||||
private:
|
||||
doc::PixelRatio m_pixelRatio;
|
||||
Zoom m_zoom;
|
||||
|
@ -446,33 +446,33 @@ void composite_image_scale_down_non_square_pixel_ratio(
|
||||
template<class DstTraits, class SrcTraits>
|
||||
void composite_image_general(
|
||||
Image* dst, const Image* src, const Palette* pal,
|
||||
const gfx::Clip& _area,
|
||||
const gfx::ClipF& _area,
|
||||
const int opacity,
|
||||
const BlendMode blendMode,
|
||||
const Projection& proj)
|
||||
const double sx,
|
||||
const double sy)
|
||||
{
|
||||
ASSERT(dst);
|
||||
ASSERT(src);
|
||||
ASSERT(DstTraits::pixel_format == dst->pixelFormat());
|
||||
ASSERT(SrcTraits::pixel_format == src->pixelFormat());
|
||||
|
||||
gfx::Clip area = _area;
|
||||
gfx::ClipF area = _area;
|
||||
if (!area.clip(dst->width(), dst->height(),
|
||||
proj.applyX(src->width()),
|
||||
proj.applyY(src->height())))
|
||||
sx*src->width(), sy*src->height()))
|
||||
return;
|
||||
|
||||
BlenderHelper<DstTraits, SrcTraits> blender(src, pal, blendMode);
|
||||
|
||||
gfx::Rect dstBounds = area.dstBounds();
|
||||
gfx::Rect srcBounds = area.srcBounds();
|
||||
gfx::RectF dstBounds = area.dstBounds();
|
||||
gfx::RectF srcBounds = area.srcBounds();
|
||||
|
||||
for (int y=0; y<dstBounds.h; ++y) {
|
||||
for (int x=0; x<dstBounds.w; ++x) {
|
||||
int dstX = dstBounds.x+x;
|
||||
int dstY = dstBounds.y+y;
|
||||
int srcX = proj.removeX(srcBounds.x+x);
|
||||
int srcY = proj.removeY(srcBounds.y+y);
|
||||
int dstY = dstBounds.y;
|
||||
for (int y=0; y<dstBounds.h; ++y, ++dstY) {
|
||||
int dstX = dstBounds.x;
|
||||
for (int x=0; x<dstBounds.w; ++x, ++dstX) {
|
||||
int srcX = (srcBounds.x+x)/sx;
|
||||
int srcY = (srcBounds.y+y)/sy;
|
||||
|
||||
if (srcX >= 0 && srcX < src->width() &&
|
||||
srcY >= 0 && srcY < src->height() &&
|
||||
@ -775,8 +775,9 @@ void Render::renderSprite(
|
||||
dstImage,
|
||||
m_previewImage,
|
||||
m_sprite->palette(frame),
|
||||
m_previewPos.x,
|
||||
m_previewPos.y,
|
||||
gfx::Rect(m_previewPos.x, m_previewPos.y,
|
||||
m_previewImage->width(),
|
||||
m_previewImage->height()),
|
||||
area,
|
||||
compositeImage,
|
||||
255,
|
||||
@ -899,19 +900,21 @@ void Render::renderImage(
|
||||
const int opacity,
|
||||
const BlendMode blendMode)
|
||||
{
|
||||
CompositeImageFunc compositeImage = get_image_composition(
|
||||
dst_image->pixelFormat(),
|
||||
src_image->pixelFormat(), m_proj);
|
||||
CompositeImageFunc compositeImage =
|
||||
get_image_composition(
|
||||
dst_image->pixelFormat(),
|
||||
src_image->pixelFormat(), m_proj);
|
||||
if (!compositeImage)
|
||||
return;
|
||||
|
||||
compositeImage(
|
||||
dst_image, src_image, pal,
|
||||
gfx::Clip(x, y, 0, 0,
|
||||
m_proj.applyX(src_image->width()),
|
||||
m_proj.applyY(src_image->height())),
|
||||
gfx::ClipF(x, y, 0, 0,
|
||||
m_proj.applyX(src_image->width()),
|
||||
m_proj.applyY(src_image->height())),
|
||||
opacity, blendMode,
|
||||
m_proj);
|
||||
m_proj.scaleX(),
|
||||
m_proj.scaleY());
|
||||
}
|
||||
|
||||
void Render::renderLayer(
|
||||
@ -960,21 +963,27 @@ void Render::renderLayer(
|
||||
if (cel) {
|
||||
Palette* pal = m_sprite->palette(frame);
|
||||
const Image* celImage;
|
||||
gfx::Point celPos;
|
||||
gfx::RectF celBounds;
|
||||
|
||||
// Is the 'm_previewImage' set to be used with this layer?
|
||||
if ((m_previewImage) &&
|
||||
(m_selectedLayer == layer) &&
|
||||
(m_selectedFrame == frame)) {
|
||||
celImage = m_previewImage;
|
||||
celPos = m_previewPos;
|
||||
celBounds = gfx::RectF(m_previewPos.x,
|
||||
m_previewPos.y,
|
||||
m_previewImage->width(),
|
||||
m_previewImage->height());
|
||||
|
||||
ASSERT(celImage->pixelFormat() == cel->image()->pixelFormat());
|
||||
}
|
||||
// If not, we use the original cel-image from the images' stock
|
||||
else {
|
||||
celImage = cel->image();
|
||||
celPos = cel->position();
|
||||
if (cel->layer()->isReference())
|
||||
celBounds = cel->boundsF();
|
||||
else
|
||||
celBounds = cel->bounds();
|
||||
}
|
||||
|
||||
if (celImage) {
|
||||
@ -1005,7 +1014,7 @@ void Render::renderLayer(
|
||||
|
||||
for (auto rc : originalAreas) {
|
||||
renderCel(
|
||||
image, celImage, pal, celPos,
|
||||
image, celImage, pal, celBounds,
|
||||
gfx::Clip(area.dst.x+rc.x-area.src.x,
|
||||
area.dst.y+rc.y-area.src.y, rc), compositeImage,
|
||||
opacity, layerBlendMode);
|
||||
@ -1015,7 +1024,7 @@ void Render::renderLayer(
|
||||
else {
|
||||
renderCel(
|
||||
image, celImage, pal,
|
||||
celPos, area, compositeImage,
|
||||
celBounds, area, compositeImage,
|
||||
opacity, layerBlendMode);
|
||||
}
|
||||
}
|
||||
@ -1044,7 +1053,7 @@ void Render::renderLayer(
|
||||
renderCel(
|
||||
image, m_extraImage,
|
||||
m_sprite->palette(frame),
|
||||
m_extraCel->position(),
|
||||
m_extraCel->bounds(),
|
||||
gfx::Clip(area.dst.x+extraArea.x-area.src.x,
|
||||
area.dst.y+extraArea.y-area.src.y,
|
||||
extraArea),
|
||||
@ -1059,7 +1068,7 @@ void Render::renderCel(
|
||||
Image* dst_image,
|
||||
const Image* cel_image,
|
||||
const Palette* pal,
|
||||
const gfx::Point& celPos,
|
||||
const gfx::RectF& celBounds,
|
||||
const gfx::Clip& area,
|
||||
const CompositeImageFunc compositeImage,
|
||||
const int opacity,
|
||||
@ -1068,8 +1077,7 @@ void Render::renderCel(
|
||||
renderImage(dst_image,
|
||||
cel_image,
|
||||
pal,
|
||||
celPos.x,
|
||||
celPos.y,
|
||||
celBounds,
|
||||
area,
|
||||
compositeImage,
|
||||
opacity,
|
||||
@ -1080,38 +1088,30 @@ void Render::renderImage(
|
||||
Image* dst_image,
|
||||
const Image* cel_image,
|
||||
const Palette* pal,
|
||||
const int x,
|
||||
const int y,
|
||||
const gfx::RectF& celBounds,
|
||||
const gfx::Clip& area,
|
||||
const CompositeImageFunc compositeImage,
|
||||
const int opacity,
|
||||
const BlendMode blendMode)
|
||||
{
|
||||
int cel_x = m_proj.applyX(x);
|
||||
int cel_y = m_proj.applyY(y);
|
||||
|
||||
gfx::Rect srcBounds =
|
||||
area.srcBounds().createIntersection(
|
||||
gfx::Rect(
|
||||
cel_x,
|
||||
cel_y,
|
||||
m_proj.applyX(cel_image->width()),
|
||||
m_proj.applyY(cel_image->height())));
|
||||
gfx::RectF scaledBounds = m_proj.apply(celBounds);
|
||||
gfx::RectF srcBounds = gfx::RectF(area.srcBounds()).createIntersection(scaledBounds);
|
||||
if (srcBounds.isEmpty())
|
||||
return;
|
||||
|
||||
compositeImage(
|
||||
dst_image, cel_image, pal,
|
||||
gfx::Clip(
|
||||
area.dst.x + srcBounds.x - area.src.x,
|
||||
area.dst.y + srcBounds.y - area.src.y,
|
||||
srcBounds.x - cel_x,
|
||||
srcBounds.y - cel_y,
|
||||
gfx::ClipF(
|
||||
double(area.dst.x) + srcBounds.x - double(area.src.x),
|
||||
double(area.dst.y) + srcBounds.y - double(area.src.y),
|
||||
srcBounds.x - scaledBounds.x,
|
||||
srcBounds.y - scaledBounds.y,
|
||||
srcBounds.w,
|
||||
srcBounds.h),
|
||||
opacity,
|
||||
blendMode,
|
||||
m_proj);
|
||||
m_proj.scaleX() * double(cel_image->width()) / celBounds.w,
|
||||
m_proj.scaleY() * double(cel_image->height()) / celBounds.h);
|
||||
}
|
||||
|
||||
void composite_image(Image* dst,
|
||||
|
@ -13,16 +13,13 @@
|
||||
#include "doc/color.h"
|
||||
#include "doc/frame.h"
|
||||
#include "doc/pixel_format.h"
|
||||
#include "gfx/clip.h"
|
||||
#include "gfx/point.h"
|
||||
#include "gfx/size.h"
|
||||
#include "render/extra_type.h"
|
||||
#include "render/onionskin_position.h"
|
||||
#include "render/projection.h"
|
||||
|
||||
namespace gfx {
|
||||
class Clip;
|
||||
}
|
||||
|
||||
namespace doc {
|
||||
class Cel;
|
||||
class FrameTag;
|
||||
@ -93,10 +90,11 @@ namespace render {
|
||||
Image* dst,
|
||||
const Image* src,
|
||||
const Palette* pal,
|
||||
const gfx::Clip& area,
|
||||
const gfx::ClipF& area,
|
||||
const int opacity,
|
||||
const BlendMode blendMode,
|
||||
const Projection& proj);
|
||||
const double sx,
|
||||
const double sy);
|
||||
|
||||
class Render {
|
||||
public:
|
||||
@ -194,7 +192,7 @@ namespace render {
|
||||
Image* dst_image,
|
||||
const Image* cel_image,
|
||||
const Palette* pal,
|
||||
const gfx::Point& celPos,
|
||||
const gfx::RectF& celBounds,
|
||||
const gfx::Clip& area,
|
||||
const CompositeImageFunc compositeImage,
|
||||
const int opacity,
|
||||
@ -204,8 +202,7 @@ namespace render {
|
||||
Image* dst_image,
|
||||
const Image* cel_image,
|
||||
const Palette* pal,
|
||||
const int x,
|
||||
const int y,
|
||||
const gfx::RectF& celBounds,
|
||||
const gfx::Clip& area,
|
||||
const CompositeImageFunc compositeImage,
|
||||
const int opacity,
|
||||
|
@ -14,10 +14,6 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace gfx {
|
||||
class Clip;
|
||||
}
|
||||
|
||||
namespace she {
|
||||
|
||||
class Font;
|
||||
|
Loading…
Reference in New Issue
Block a user