mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-01 01:13:40 +00:00
Move <cursors> to <parts> on theme.xml
For this the "pivot" property was added to doc::SliceKeys.
This commit is contained in:
parent
c08f7705f3
commit
f7cf65b245
@ -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
|
||||
|
@ -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" />
|
||||
|
@ -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" />
|
||||
|
@ -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
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user