Move <cursors> to <parts> on theme.xml

For this the "pivot" property was added to doc::SliceKeys.
This commit is contained in:
David Capello 2017-03-14 19:00:24 -03:00
parent c08f7705f3
commit f7cf65b245
16 changed files with 231 additions and 103 deletions

View File

@ -444,6 +444,7 @@ name = Slice Name:
user_data_tooltip = User Data
bounds = Bounds:
center = 9-Slices
pivot = Pivot
x = X
y = Y
width = Width

View File

@ -104,37 +104,34 @@
<color id="select_box_grid" value="#64c864" />
</colors>
<cursors>
<cursor id="normal" x="80" y="0" w="16" h="16" focusx="0" focusy="0" />
<cursor id="normal_add" x="80" y="16" w="16" h="16" focusx="0" focusy="0" />
<cursor id="crosshair" x="96" y="32" w="16" h="16" focusx="7" focusy="7" />
<cursor id="forbidden" x="80" y="32" w="16" h="16" focusx="0" focusy="0" />
<cursor id="hand" x="80" y="48" w="16" h="16" focusx="5" focusy="3" />
<cursor id="scroll" x="80" y="64" w="16" h="16" focusx="8" focusy="8" />
<cursor id="move" x="80" y="80" w="16" h="16" focusx="0" focusy="0" />
<cursor id="size_ns" x="80" y="112" w="16" h="16" focusx="8" focusy="8" />
<cursor id="size_we" x="80" y="144" w="16" h="16" focusx="8" focusy="8" />
<cursor id="size_n" x="80" y="112" w="16" h="16" focusx="8" focusy="8" />
<cursor id="size_ne" x="80" y="128" w="16" h="16" focusx="8" focusy="8" />
<cursor id="size_e" x="80" y="160" w="16" h="16" focusx="8" focusy="8" />
<cursor id="size_se" x="80" y="208" w="16" h="16" focusx="8" focusy="8" />
<cursor id="size_s" x="80" y="192" w="16" h="16" focusx="8" focusy="8" />
<cursor id="size_sw" x="80" y="176" w="16" h="16" focusx="8" focusy="8" />
<cursor id="size_w" x="80" y="144" w="16" h="16" focusx="8" focusy="8" />
<cursor id="size_nw" x="80" y="96" w="16" h="16" focusx="8" focusy="8" />
<cursor id="rotate_n" x="240" y="192" w="16" h="16" focusx="8" focusy="8" />
<cursor id="rotate_ne" x="256" y="160" w="16" h="16" focusx="8" focusy="8" />
<cursor id="rotate_e" x="256" y="176" w="16" h="16" focusx="8" focusy="8" />
<cursor id="rotate_se" x="256" y="208" w="16" h="16" focusx="8" focusy="8" />
<cursor id="rotate_s" x="256" y="192" w="16" h="16" focusx="8" focusy="8" />
<cursor id="rotate_sw" x="240" y="208" w="16" h="16" focusx="8" focusy="8" />
<cursor id="rotate_w" x="240" y="176" w="16" h="16" focusx="8" focusy="8" />
<cursor id="rotate_nw" x="240" y="160" w="16" h="16" focusx="8" focusy="8" />
<cursor id="eyedropper" x="80" y="224" w="16" h="16" focusx="0" focusy="15" />
<cursor id="magnifier" x="80" y="240" w="16" h="16" focusx="5" focusy="5" />
</cursors>
<parts>
<part id="cursor_normal" x="80" y="0" w="16" h="16" focusx="0" focusy="0" />
<part id="cursor_normal_add" x="80" y="16" w="16" h="16" focusx="0" focusy="0" />
<part id="cursor_crosshair" x="96" y="32" w="16" h="16" focusx="7" focusy="7" />
<part id="cursor_forbidden" x="80" y="32" w="16" h="16" focusx="0" focusy="0" />
<part id="cursor_hand" x="80" y="48" w="16" h="16" focusx="5" focusy="3" />
<part id="cursor_scroll" x="80" y="64" w="16" h="16" focusx="8" focusy="8" />
<part id="cursor_move" x="80" y="80" w="16" h="16" focusx="0" focusy="0" />
<part id="cursor_size_ns" x="80" y="112" w="16" h="16" focusx="8" focusy="8" />
<part id="cursor_size_we" x="80" y="144" w="16" h="16" focusx="8" focusy="8" />
<part id="cursor_size_n" x="80" y="112" w="16" h="16" focusx="8" focusy="8" />
<part id="cursor_size_ne" x="80" y="128" w="16" h="16" focusx="8" focusy="8" />
<part id="cursor_size_e" x="80" y="160" w="16" h="16" focusx="8" focusy="8" />
<part id="cursor_size_se" x="80" y="208" w="16" h="16" focusx="8" focusy="8" />
<part id="cursor_size_s" x="80" y="192" w="16" h="16" focusx="8" focusy="8" />
<part id="cursor_size_sw" x="80" y="176" w="16" h="16" focusx="8" focusy="8" />
<part id="cursor_size_w" x="80" y="144" w="16" h="16" focusx="8" focusy="8" />
<part id="cursor_size_nw" x="80" y="96" w="16" h="16" focusx="8" focusy="8" />
<part id="cursor_rotate_n" x="240" y="192" w="16" h="16" focusx="8" focusy="8" />
<part id="cursor_rotate_ne" x="256" y="160" w="16" h="16" focusx="8" focusy="8" />
<part id="cursor_rotate_e" x="256" y="176" w="16" h="16" focusx="8" focusy="8" />
<part id="cursor_rotate_se" x="256" y="208" w="16" h="16" focusx="8" focusy="8" />
<part id="cursor_rotate_s" x="256" y="192" w="16" h="16" focusx="8" focusy="8" />
<part id="cursor_rotate_sw" x="240" y="208" w="16" h="16" focusx="8" focusy="8" />
<part id="cursor_rotate_w" x="240" y="176" w="16" h="16" focusx="8" focusy="8" />
<part id="cursor_rotate_nw" x="240" y="160" w="16" h="16" focusx="8" focusy="8" />
<part id="cursor_eyedropper" x="80" y="224" w="16" h="16" focusx="0" focusy="15" />
<part id="cursor_magnifier" x="80" y="240" w="16" h="16" focusx="5" focusy="5" />
<part id="radio_normal" x="64" y="64" w="8" h="8" />
<part id="radio_selected" x="64" y="80" w="8" h="8" />
<part id="radio_disabled" x="64" y="64" w="8" h="8" />

View File

@ -30,10 +30,16 @@
<check text="@.center" id="center" />
<hbox homogeneous="true">
<entry maxsize="8" id="center_x" />
<entry maxsize="8" id="center_y" />
<entry maxsize="8" id="center_w" />
<entry maxsize="8" id="center_h" />
<entry maxsize="8" id="center_x" text="0" />
<entry maxsize="8" id="center_y" text="0" />
<entry maxsize="8" id="center_w" text="0" />
<entry maxsize="8" id="center_h" text="0" />
</hbox>
<check text="@.pivot" id="pivot" />
<hbox>
<entry maxsize="8" id="pivot_x" text="0" />
<entry maxsize="8" id="pivot_y" text="0" />
</hbox>
<separator horizontal="true" cell_hspan="2" />

View File

@ -310,21 +310,25 @@ For each slice... |
DWORD | Number of "slice keys"
DWORD | Flags
| 1 - It's a 9-patches slice
| 2 - Has pivot information
DWORD | Reserved
STRING | Name
For each slice key ... |
DWORD | Frame number (this slice is valid from
| this frame to the end of the animation)
SIGNED WORD | Slice X position
SIGNED WORD | Slice Y position
WORD | Slice Width (can be 0 if this slice hidden in the
SIGNED WORD | Slice X origin coordinate in the sprite
SIGNED WORD | Slice Y origin coordinate in the sprite
WORD | Slice width (can be 0 if this slice hidden in the
| animation from the given frame)
WORD | Slice Height
WORD | Slice height
If flags have bit 1 |
SIGNED WORD | Center X position (relative to slice bounds)
SIGNED WORD | Center Y position
WORD | Center Width
WORD | Center Height
WORD | Center width
WORD | Center height
If flags have bit 2 |
WORD | Pivot X position (relative to the slice origin)
WORD | Pivot Y position (relative to the slice origin)
### Notes

View File

@ -99,10 +99,12 @@ void SlicePropertiesCommand::onExecute(Context* context)
transaction.execute(new cmd::SetUserData(slice, window.userDataValue()));
if (key->bounds() != window.boundsValue() ||
key->center() != window.centerValue()) {
key->center() != window.centerValue() ||
key->pivot() != window.pivotValue()) {
SliceKey newKey = *key;
newKey.setBounds(window.boundsValue());
newKey.setCenter(window.centerValue());
newKey.setPivot(window.pivotValue());
transaction.execute(new cmd::SetSliceKey(slice, frame, newKey));
}

View File

@ -56,6 +56,7 @@
#define ASE_CEL_EXTRA_FLAG_PRECISE_BOUNDS 1
#define ASE_SLICE_FLAG_HAS_CENTER_BOUNDS 1
#define ASE_SLICE_FLAG_HAS_PIVOT_POINT 2
namespace app {
@ -1687,12 +1688,13 @@ static void ase_file_write_user_data_chunk(FILE* f, ASE_FrameHeader* frame_heade
static void ase_file_read_slices_chunk(FILE* f, Slices* slices)
{
TRACE("ase_file_read_slices_chunk\n");
size_t nslices = fgetl(f); // Number of slices
fgetl(f); // 8 bytes reserved
fgetl(f);
for (size_t i=0; i<nslices; ++i) {
size_t nkeys = fgetl(f); // Number of keys
size_t nkeys = fgetl(f); // Number of keys
int flags = fgetl(f); // Flags
fgetl(f); // 4 bytes reserved
std::string name = ase_file_read_string(f); // Name
@ -1702,8 +1704,9 @@ static void ase_file_read_slices_chunk(FILE* f, Slices* slices)
// For each key
for (size_t j=0; j<nkeys; ++j) {
frame_t frame = fgetl(f);
gfx::Rect bounds, center;
gfx::Point pivot = SliceKey::NoPivot;
frame_t frame = fgetl(f);
bounds.x = fgetl(f);
bounds.y = fgetl(f);
bounds.w = fgetl(f);
@ -1716,7 +1719,17 @@ static void ase_file_read_slices_chunk(FILE* f, Slices* slices)
center.h = fgetl(f);
}
slice->insert(frame, SliceKey(bounds, center));
if (flags & ASE_SLICE_FLAG_HAS_PIVOT_POINT) {
pivot.x = fgetl(f);
pivot.y = fgetl(f);
}
TRACE(" read key bounds=(%d %d %d %d) center=(%d %d %d %d) pivot=(%d %d)\n",
bounds.x, bounds.y, bounds.w, bounds.h,
center.x, center.y, center.w, center.h,
pivot.x, pivot.y);
slice->insert(frame, SliceKey(bounds, center, pivot));
}
slices->add(slice);
@ -1729,10 +1742,15 @@ static void ase_file_write_slices_chunk(FILE* f, ASE_FrameHeader* frame_header,
const frame_t fromFrame,
const frame_t toFrame)
{
TRACE("ase_file_write_slices_chunk\n");
ChunkWriter chunk(f, frame_header, ASE_FILE_CHUNK_SLICES);
size_t nslices = 0;
for (Slice* slice : *slices) {
TRACE(" fromFrame=%d toFrame=%d empty=%d\n",
fromFrame, toFrame,
slice->range(fromFrame, toFrame).empty());
// Skip slices that are outside of the given ROI
if (slice->range(fromFrame, toFrame).empty())
continue;
@ -1740,6 +1758,7 @@ static void ase_file_write_slices_chunk(FILE* f, ASE_FrameHeader* frame_header,
++nslices;
}
TRACE(" nslices=%d\n", nslices);
fputl(nslices, f);
fputl(0, f); // 8 reserved bytes
fputl(0, f);
@ -1750,11 +1769,17 @@ static void ase_file_write_slices_chunk(FILE* f, ASE_FrameHeader* frame_header,
if (range.empty())
continue;
TRACE(" range countKeys=%d\n", range.countKeys());
int flags = 0;
for (auto key : range) {
if (key && !key->center().isEmpty()) {
flags |= ASE_SLICE_FLAG_HAS_CENTER_BOUNDS;
break;
if (key) {
if (!key->center().isEmpty()) {
flags |= ASE_SLICE_FLAG_HAS_CENTER_BOUNDS;
}
if (key->hasPivot()) {
flags |= ASE_SLICE_FLAG_HAS_PIVOT_POINT;
}
}
}
@ -1788,6 +1813,22 @@ static void ase_file_write_slices_chunk(FILE* f, ASE_FrameHeader* frame_header,
}
}
if (flags & ASE_SLICE_FLAG_HAS_PIVOT_POINT) {
if (key && key->hasPivot()) {
fputl(key->pivot().x, f);
fputl(key->pivot().y, f);
}
else {
fputl(0, f);
fputl(0, f);
}
}
TRACE(" write key bounds=(%d %d %d %d) center=(%d %d %d %d) pivot=(%d %d)\n",
key->bounds().x, key->bounds().y, key->bounds().w, key->bounds().h,
key->center().x, key->center().y, key->center().w, key->center().h,
key->pivot().x, key->pivot().y);
oldKey = key;
}
++frame;

View File

@ -69,6 +69,15 @@ void updateXmlPartFromSliceKey(const SliceKey* key, TiXmlElement* xmlPart)
if (xmlPart->Attribute("w")) xmlPart->RemoveAttribute("w");
if (xmlPart->Attribute("h")) xmlPart->RemoveAttribute("h");
}
if (key->hasPivot()) {
xmlPart->SetAttribute("focusx", key->pivot().x);
xmlPart->SetAttribute("focusy", key->pivot().y);
}
else {
if (xmlPart->Attribute("focusx")) xmlPart->RemoveAttribute("focusx");
if (xmlPart->Attribute("focusy")) xmlPart->RemoveAttribute("focusy");
}
}
} // anonymous namespace
@ -1111,6 +1120,12 @@ void FileOp::loadData()
key.setBounds(gfx::Rect(x, y, w, h));
}
if (xmlPart->Attribute("focusx")) {
int x = xmlPart->Attribute("focusx") ? strtol(xmlPart->Attribute("focusx"), NULL, 10): 0;
int y = xmlPart->Attribute("focusy") ? strtol(xmlPart->Attribute("focusy"), NULL, 10): 0;
key.setPivot(gfx::Point(x, y));
}
slice->insert(0, key);
m_document->sprite()->slices().add(slice);
}

View File

@ -981,6 +981,7 @@ void Editor::drawSlices(ui::Graphics* g)
editorToScreen(key->bounds())
.offset(-bounds().origin());
// Center slices
if (!key->center().isEmpty()) {
gfx::Rect in =
editorToScreen(gfx::Rect(key->center()).offset(key->bounds().origin()))
@ -1000,6 +1001,19 @@ void Editor::drawSlices(ui::Graphics* g)
g->drawVLine(in_color, in.x2(), out.y, out.h);
}
// Pivot
if (key->hasPivot()) {
gfx::Rect in =
editorToScreen(gfx::Rect(key->pivot(), gfx::Size(1, 1)).offset(key->bounds().origin()))
.offset(-bounds().origin());
auto in_color = gfx::rgba(gfx::getr(color),
gfx::getg(color),
gfx::getb(color),
doc::rgba_geta(docColor)/4);
g->drawRect(in_color, in);
}
g->drawRect(color, out);
}
}

View File

@ -49,7 +49,7 @@ using namespace ui;
const char* SkinTheme::kThemesFolderName = "themes";
static const char* cursor_names[kCursorTypes] = {
static const char* g_cursor_names[kCursorTypes] = {
"null", // kNoCursor
"normal", // kArrowCursor
"normal_add", // kArrowPlusCursor
@ -58,10 +58,8 @@ static const char* cursor_names[kCursorTypes] = {
"hand", // kHandCursor
"scroll", // kScrollCursor
"move", // kMoveCursor
"size_ns", // kSizeNSCursor
"size_we", // kSizeWECursor
"size_n", // kSizeNCursor
"size_ne", // kSizeNECursor
"size_e", // kSizeECursor
@ -70,7 +68,6 @@ static const char* cursor_names[kCursorTypes] = {
"size_sw", // kSizeSWCursor
"size_w", // kSizeWCursor
"size_nw", // kSizeNWCursor
"rotate_n", // kRotateNCursor
"rotate_ne", // kRotateNECursor
"rotate_e", // kRotateECursor
@ -79,7 +76,6 @@ static const char* cursor_names[kCursorTypes] = {
"rotate_sw", // kRotateSWCursor
"rotate_w", // kRotateWCursor
"rotate_nw", // kRotateNWCursor
"eyedropper", // kEyedropperCursor
"magnifier" // kMagnifierCursor
};
@ -380,47 +376,6 @@ void SkinTheme::loadXml(const std::string& skinId)
}
}
// Load cursors
{
TiXmlElement* xmlCursor = handle
.FirstChild("theme")
.FirstChild("cursors")
.FirstChild("cursor").ToElement();
while (xmlCursor) {
std::string id = xmlCursor->Attribute("id");
int x = strtol(xmlCursor->Attribute("x"), NULL, 10);
int y = strtol(xmlCursor->Attribute("y"), NULL, 10);
int w = strtol(xmlCursor->Attribute("w"), NULL, 10);
int h = strtol(xmlCursor->Attribute("h"), NULL, 10);
int focusx = strtol(xmlCursor->Attribute("focusx"), NULL, 10);
int focusy = strtol(xmlCursor->Attribute("focusy"), NULL, 10);
int c;
LOG(VERBOSE) << "THEME: Loading cursor " << id << "\n";
for (c=0; c<kCursorTypes; ++c) {
if (id != cursor_names[c])
continue;
delete m_cursors[c];
m_cursors[c] = NULL;
she::Surface* slice = sliceSheet(NULL, gfx::Rect(x, y, w, h));
m_cursors[c] = new Cursor(slice,
gfx::Point(focusx*guiscale(), focusy*guiscale()));
break;
}
if (c == kCursorTypes) {
throw base::Exception("Unknown cursor specified in '%s':\n"
"<cursor id='%s' ... />\n", xml_filename.c_str(), id.c_str());
}
xmlCursor = xmlCursor->NextSiblingElement();
}
}
// Load parts
{
TiXmlElement* xmlPart = handle
@ -467,6 +422,30 @@ void SkinTheme::loadXml(const std::string& skinId)
part->setBitmap(7, sliceSheet(part->bitmap(7), gfx::Rect(x, y+h1, w1, h2))); // W
}
// Is it a mouse cursor?
if (std::strncmp(part_id, "cursor_", 7) == 0) {
std::string cursorName = std::string(part_id).substr(7);
int focusx = std::strtol(xmlPart->Attribute("focusx"), NULL, 10);
int focusy = std::strtol(xmlPart->Attribute("focusy"), NULL, 10);
for (int c=0; c<kCursorTypes; ++c) {
if (cursorName != g_cursor_names[c])
continue;
LOG(VERBOSE) << "THEME: Loading cursor '" << cursorName << "'\n";
delete m_cursors[c];
m_cursors[c] = nullptr;
// TODO share the Surface with the SkinPart
she::Surface* slice = sliceSheet(nullptr, gfx::Rect(x, y, w, h));
m_cursors[c] = new Cursor(slice,
gfx::Point(focusx*guiscale(),
focusy*guiscale()));
break;
}
}
xmlPart = xmlPart->NextSiblingElement();
}
}

View File

@ -40,6 +40,7 @@ SliceWindow::SliceWindow(const doc::Sprite* sprite,
boundsH()->setTextf("%d", key->bounds().h);
center()->Click.connect(base::Bind<void>(&SliceWindow::onCenterChange, this));
pivot()->Click.connect(base::Bind<void>(&SliceWindow::onPivotChange, this));
if (!key->center().isEmpty()) {
center()->setSelected(true);
@ -48,8 +49,18 @@ SliceWindow::SliceWindow(const doc::Sprite* sprite,
centerW()->setTextf("%d", key->center().w);
centerH()->setTextf("%d", key->center().h);
}
else
else {
onCenterChange();
}
if (key->hasPivot()) {
pivot()->setSelected(true);
pivotX()->setTextf("%d", key->pivot().x);
pivotY()->setTextf("%d", key->pivot().y);
}
else {
onPivotChange();
}
}
bool SliceWindow::show()
@ -88,6 +99,15 @@ gfx::Rect SliceWindow::centerValue() const
return rc;
}
gfx::Point SliceWindow::pivotValue() const
{
if (!pivot()->isSelected())
return doc::SliceKey::NoPivot;
return gfx::Point(pivotX()->textInt(),
pivotY()->textInt());
}
void SliceWindow::onCenterChange()
{
bool state = center()->isSelected();
@ -105,6 +125,19 @@ void SliceWindow::onCenterChange()
}
}
void SliceWindow::onPivotChange()
{
bool state = pivot()->isSelected();
pivotX()->setEnabled(state);
pivotY()->setEnabled(state);
if (state) {
pivotX()->setText("0");
pivotY()->setText("0");
}
}
void SliceWindow::onPopupUserData()
{
show_user_data_popup(userData()->bounds(), m_userData);

View File

@ -32,10 +32,12 @@ namespace app {
std::string nameValue() const;
gfx::Rect boundsValue() const;
gfx::Rect centerValue() const;
gfx::Point pivotValue() const;
const doc::UserData& userDataValue() { return m_userData; }
private:
void onCenterChange();
void onPivotChange();
void onPopupUserData();
doc::UserData m_userData;

View File

@ -85,7 +85,8 @@ namespace doc {
return RangeIterator(m_fromIt, m_endIt, m_to);
}
bool empty() const {
return (m_fromIt == m_endIt);
return (m_fromIt == m_endIt ||
m_to < m_fromIt->frame());
}
size_t countKeys() const {
size_t count = 0;
@ -129,7 +130,9 @@ namespace doc {
T* operator[](const frame_t frame) {
auto it = getIterator(frame);
if (it != end() && it->value())
if (it != end() &&
it->value() &&
frame >= it->frame())
return it->value();
else
return nullptr;
@ -150,8 +153,9 @@ namespace doc {
auto next = it;
for (; it != end; it=next) {
++next;
if ((frame >= it->frame()) &&
(next == end || frame < next->frame())) {
if (((frame >= it->frame()) &&
(next == end || frame < next->frame())) ||
(frame < it->frame())) {
return it;
}
}

View File

@ -123,9 +123,21 @@ TEST(Keyframes, Range)
EXPECT_EQ(1, k.range(2, 3).countKeys());
EXPECT_EQ(2, k.range(2, 4).countKeys());
EXPECT_EQ(3, k.range(3, 7).countKeys());
EXPECT_EQ(2, k.range(5, 6).countKeys());
EXPECT_EQ(1, k.range(6, 6).countKeys());
EXPECT_EQ(1, k.range(7, 7).countKeys());
}
TEST(Keyframes, BugEmptyCount)
{
Keyframes<int> k;
k.insert(7, new int(5));
EXPECT_EQ(0, k.range(-1, 6).countKeys());
EXPECT_EQ(1, k.range(0, 7).countKeys());
EXPECT_EQ(1, k.range(8, 9).countKeys());
EXPECT_EQ(5, **k.range(8, 9).begin());
}
int main(int argc, char** argv)
{
::testing::InitGoogleTest(&argc, argv);

View File

@ -15,15 +15,20 @@
namespace doc {
const gfx::Point SliceKey::NoPivot(std::numeric_limits<int32_t>::min(),
std::numeric_limits<int32_t>::min());
SliceKey::SliceKey()
: m_pivot(NoPivot)
{
}
SliceKey::SliceKey(// const frame_t frame,
const gfx::Rect& bounds,
const gfx::Rect& center)
SliceKey::SliceKey(const gfx::Rect& bounds,
const gfx::Rect& center,
const gfx::Point& pivot)
: m_bounds(bounds)
, m_center(center)
, m_pivot(pivot)
{
}

View File

@ -11,6 +11,7 @@
#include "doc/frame.h"
#include "doc/keyframes.h"
#include "doc/with_user_data.h"
#include "gfx/point.h"
#include "gfx/rect.h"
#include <string>
@ -20,21 +21,28 @@ namespace doc {
class SliceKey {
public:
static const gfx::Point NoPivot;
SliceKey();
SliceKey(const gfx::Rect& bounds,
const gfx::Rect& center = gfx::Rect());
const gfx::Rect& center = gfx::Rect(),
const gfx::Point& pivot = SliceKey::NoPivot);
bool isEmpty() const { return m_bounds.isEmpty(); }
bool hasPivot() const { return m_pivot != NoPivot; }
const gfx::Rect& bounds() const { return m_bounds; }
const gfx::Rect& center() const { return m_center; }
const gfx::Point& pivot() const { return m_pivot; }
void setBounds(const gfx::Rect& bounds) { m_bounds = bounds; }
void setCenter(const gfx::Rect& center) { m_center = center; }
void setPivot(const gfx::Point& pivot) { m_pivot = pivot; }
private:
gfx::Rect m_bounds;
gfx::Rect m_center;
gfx::Point m_pivot;
};
class Slice : public WithUserData {

View File

@ -65,11 +65,14 @@ void write_slicekey(std::ostream& os, const SliceKey& sliceKey)
write32(os, sliceKey.center().y);
write32(os, sliceKey.center().w);
write32(os, sliceKey.center().h);
write32(os, sliceKey.pivot().x);
write32(os, sliceKey.pivot().y);
}
SliceKey read_slicekey(std::istream& is)
{
gfx::Rect bounds, center;
gfx::Point pivot;
bounds.x = read32(is);
bounds.y = read32(is);
bounds.w = read32(is);
@ -78,7 +81,9 @@ SliceKey read_slicekey(std::istream& is)
center.y = read32(is);
center.w = read32(is);
center.h = read32(is);
return SliceKey(bounds, center);
pivot.x = read32(is);
pivot.y = read32(is);
return SliceKey(bounds, center, pivot);
}
}