void Slider::_notification(int p_what) { switch(p_what) { case NOTIFICATION_MOUSE_ENTER: { mouse_inside=true; update(); } break; case NOTIFICATION_MOUSE_EXIT: { mouse_inside=false; update(); } break; case NOTIFICATION_DRAW: { RID ci = get_canvas_item(); Size2i size = get_size(); Ref<StyleBox> style = get_stylebox("slider"); Ref<StyleBox> focus = get_stylebox("focus"); Ref<Texture> grabber = get_icon(mouse_inside||has_focus()?"grabber_hilite":"grabber"); Ref<Texture> tick = get_icon("tick"); if (orientation==VERTICAL) { style->draw(ci,Rect2i(Point2i(),Size2i(style->get_minimum_size().width+style->get_center_size().width,size.height))); //if (mouse_inside||has_focus()) // focus->draw(ci,Rect2i(Point2i(),Size2i(style->get_minimum_size().width+style->get_center_size().width,size.height))); float areasize = size.height - grabber->get_size().height; if (ticks>1) { int tickarea = size.height - tick->get_height(); for(int i=0;i<ticks;i++) { if( ! ticks_on_borders && (i == 0 || i + 1 == ticks) ) continue; int ofs = i*tickarea/(ticks-1); tick->draw(ci,Point2(0,ofs)); } } grabber->draw(ci,Point2i(size.width/2-grabber->get_size().width/2,size.height - get_unit_value()*areasize - grabber->get_size().height)); } else { style->draw(ci,Rect2i(Point2i(),Size2i(size.width,style->get_minimum_size().height+style->get_center_size().height))); //if (mouse_inside||has_focus()) // focus->draw(ci,Rect2i(Point2i(),Size2i(size.width,style->get_minimum_size().height+style->get_center_size().height))); float areasize = size.width - grabber->get_size().width; if (ticks>1) { int tickarea = size.width - tick->get_width(); for(int i=0;i<ticks;i++) { if( (! ticks_on_borders) && ( (i == 0) || ((i + 1) == ticks)) ) continue; int ofs = i*tickarea/(ticks-1); tick->draw(ci,Point2(ofs,0)); } } grabber->draw(ci,Point2i(get_unit_value()*areasize,size.height/2-grabber->get_size().height/2)); } } break; } }
void PngImageExt::FindNonOpaqueRect(Rect2i & rect) { rect = Rect2i(0, 0, GetWidth(), GetHeight()); for (uint32 y = 0; y < GetHeight(); ++y) if (IsHorzLineOpaque(y)) { rect.y++; rect.dy--; }else break; for (uint32 x = 0; x < GetWidth(); ++x) if (IsVertLineOpaque(x)) { rect.x++; rect.dx--; }else break; if ((rect.dx == 0) && (rect.dy == 0)) { rect.x = rect.y = 0; rect.dx = rect.dy = 1; return; } for (int32 y = GetHeight() - 1; y >= 0; --y) if (IsHorzLineOpaque(y))rect.dy--; else break; for (int32 x = GetWidth() - 1; x >= 0; --x) if (IsVertLineOpaque(x))rect.dx--; else break; }
Vector<Vector<Vector2> > BitMap::clip_opaque_to_polygons(const Rect2 &p_rect, float p_epsilon) const { Rect2i r = Rect2i(0, 0, width, height).clip(p_rect); print_verbose("BitMap: Rect: " + r); Point2i from; Ref<BitMap> fill; fill.instance(); fill->create(get_size()); Vector<Vector<Vector2> > polygons; for (int i = r.position.y; i < r.position.y + r.size.height; i++) { for (int j = r.position.x; j < r.position.x + r.size.width; j++) { if (!fill->get_bit(Point2(j, i)) && get_bit(Point2(j, i))) { Vector<Vector2> polygon = _march_square(r, Point2i(j, i)); print_verbose("BitMap: Pre reduce: " + itos(polygon.size())); polygon = reduce(polygon, r, p_epsilon); print_verbose("BitMap: Post reduce: " + itos(polygon.size())); polygons.push_back(polygon); fill_bits(this, fill, Point2i(j, i), r); } } } return polygons; }
void BitMap::set_bit_rect(const Rect2& p_rect,bool p_value) { Rect2i current = Rect2i(0,0,width,height).clip(p_rect); uint8_t *data = bitmask.ptr(); for(int i=current.pos.x;i<current.pos.x+current.size.x;i++) { for(int j=current.pos.y;j<current.pos.y+current.size.y;j++) { int ofs = width * j + i; int bbyte = ofs/8; int bbit = ofs % 8; uint8_t b = data[bbyte]; if (p_value) b|=(1<<bbit); else b&=!(1<<bbit); data[bbyte]=b; } } }
void PngImageExt::FindNonOpaqueRect(Rect2i & rect) { rect = Rect2i(0, 0, width, height); for (int y = 0; y < height; ++y) if (IsHorzLineOpaque(y)) { rect.y++; rect.dy--; }else break; for (int x = 0; x < width; ++x) if (IsVertLineOpaque(x)) { rect.x++; rect.dx--; }else break; if ((rect.dx == 0) && (rect.dy == 0)) { rect.x = rect.y = 0; rect.dx = rect.dy = 1; return; } for (int y = height - 1; y >= 0; --y) if (IsHorzLineOpaque(y))rect.dy--; else break; for (int x = width - 1; x >= 0; --x) if (IsVertLineOpaque(x))rect.dx--; else break; }
Rect2i Layout::getImageRect(std::size_t index) const { const std::pair<std::size_t, LineInfo> line = findLine(index); const int x = (index - line.first) % columns_ * cellStepX_; const int y = (index - line.first) / columns_ * cellStepY_ + line.second.cellTop; return Rect2i(x, y, x + imageWidth_, y + line.second.imageHeight); }
RectPacker::PackNode * RectPacker::PackNode::Insert(const Size2i & imageSize) { if (!isLeaf) { RectPacker::PackNode *newNode = child[0]->Insert(imageSize); if (newNode)return newNode; return child[1]->Insert(imageSize); } else { if (isImageSet)return 0; if ((imageSize.dx > rect.dx) || (imageSize.dy > rect.dy)) { return 0; } if ((imageSize.dx == rect.dx) && (imageSize.dy == rect.dy)) { isImageSet = true; return this; } isLeaf = false; child[0] = new RectPacker::PackNode; child[1] = new RectPacker::PackNode; int32 dw = rect.dx - imageSize.dx; int32 dh = rect.dy - imageSize.dy; if (dw > dh) { child[0]->rect = Rect2i( rect.x, rect.y, imageSize.dx, rect.dy); child[1]->rect = Rect2i( rect.x + imageSize.dx, rect.y, rect.dx - imageSize.dx, rect.dy); } else { child[0]->rect = Rect2i( rect.x, rect.y, rect.dx, imageSize.dy); child[1]->rect = Rect2i( rect.x, rect.y + imageSize.dy, rect.dx, rect.dy - imageSize.dy); } return child[0]->Insert(imageSize); } }
void ItemList::add_item(const String& p_item,const Ref<Texture>& p_texture,bool p_selectable) { Item item; item.icon=p_texture; item.icon_region=Rect2i(); item.text=p_item; item.selectable=p_selectable; item.selected=false; item.disabled=false; item.custom_bg=Color(0,0,0,0); items.push_back(item); update(); shape_changed=true; }
void BitMap::grow_mask(int p_pixels, const Rect2 &p_rect) { Rect2i r = Rect2i(0, 0, width, height).clip(p_rect); Ref<BitMap> copy; copy.instance(); copy->create(get_size()); copy->bitmask = bitmask; for (int i = r.position.y; i < r.position.y + r.size.height; i++) { for (int j = r.position.x; j < r.position.x + r.size.width; j++) { if (copy->get_bit(Point2(j, i))) continue; bool found = false; for (int y = i - p_pixels; y <= i + p_pixels; y++) { for (int x = j - p_pixels; x <= j + p_pixels; x++) { if (x < p_rect.position.x || x >= p_rect.position.x + p_rect.size.x) continue; if (y < p_rect.position.y || y >= p_rect.position.y + p_rect.size.y) continue; float d = Point2(j, i).distance_to(Point2(x, y)) - CMP_EPSILON; if (d > p_pixels) continue; if (copy->get_bit(Point2(x, y))) { found = true; break; } } if (found) break; } if (found) { set_bit(Point2(j, i), true); } } } }
void Slider::_notification(int p_what) { switch (p_what) { case NOTIFICATION_MOUSE_ENTER: { mouse_inside = true; update(); } break; case NOTIFICATION_MOUSE_EXIT: { mouse_inside = false; update(); } break; case NOTIFICATION_VISIBILITY_CHANGED: // fallthrough case NOTIFICATION_EXIT_TREE: { mouse_inside = false; grab.active = false; } break; case NOTIFICATION_DRAW: { RID ci = get_canvas_item(); Size2i size = get_size(); Ref<StyleBox> style = get_stylebox("slider"); Ref<StyleBox> focus = get_stylebox("focus"); Ref<StyleBox> grabber_area = get_stylebox("grabber_area"); Ref<Texture> grabber = get_icon(editable ? ((mouse_inside || has_focus()) ? "grabber_highlight" : "grabber") : "grabber_disabled"); Ref<Texture> tick = get_icon("tick"); if (orientation == VERTICAL) { int widget_width = style->get_minimum_size().width + style->get_center_size().width; float areasize = size.height - grabber->get_size().height; style->draw(ci, Rect2i(Point2i(size.width / 2 - widget_width / 2, 0), Size2i(widget_width, size.height))); grabber_area->draw(ci, Rect2i(Point2i((size.width - widget_width) / 2, size.height - areasize * get_as_ratio() - grabber->get_size().height / 2), Size2i(widget_width, areasize * get_as_ratio() + grabber->get_size().width / 2))); /* if (mouse_inside||has_focus()) focus->draw(ci,Rect2i(Point2i(),Size2i(style->get_minimum_size().width+style->get_center_size().width,size.height))); */ if (ticks > 1) { int tickarea = size.height - tick->get_height(); for (int i = 0; i < ticks; i++) { if (!ticks_on_borders && (i == 0 || i + 1 == ticks)) continue; int ofs = i * tickarea / (ticks - 1); tick->draw(ci, Point2i((size.width - widget_width) / 2, ofs)); } } grabber->draw(ci, Point2i(size.width / 2 - grabber->get_size().width / 2, size.height - get_as_ratio() * areasize - grabber->get_size().height)); } else { int widget_height = style->get_minimum_size().height + style->get_center_size().height; float areasize = size.width - grabber->get_size().width; style->draw(ci, Rect2i(Point2i(0, (size.height - widget_height) / 2), Size2i(size.width, widget_height))); grabber_area->draw(ci, Rect2i(Point2i(0, (size.height - widget_height) / 2), Size2i(areasize * get_as_ratio() + grabber->get_size().width / 2, widget_height))); /* if (mouse_inside||has_focus()) focus->draw(ci,Rect2i(Point2i(),Size2i(size.width,style->get_minimum_size().height+style->get_center_size().height))); */ if (ticks > 1) { int tickarea = size.width - tick->get_width(); for (int i = 0; i < ticks; i++) { if ((!ticks_on_borders) && ((i == 0) || ((i + 1) == ticks))) continue; int ofs = i * tickarea / (ticks - 1); tick->draw(ci, Point2i(ofs, (size.height - widget_height) / 2)); } } grabber->draw(ci, Point2i(get_as_ratio() * areasize, size.height / 2 - grabber->get_size().height / 2)); } } break; } }
Vector<Vector2> BitMap::_march_square(const Rect2i &rect, const Point2i &start) const { int stepx = 0; int stepy = 0; int prevx = 0; int prevy = 0; int startx = start.x; int starty = start.y; int curx = startx; int cury = starty; unsigned int count = 0; Set<Point2i> case9s; Set<Point2i> case6s; Vector<Vector2> _points; do { int sv = 0; { //square value /* checking the 2x2 pixel grid, assigning these values to each pixel, if not transparent +---+---+ | 1 | 2 | +---+---+ | 4 | 8 | <- current pixel (curx,cury) +---+---+ */ //NOTE: due to the way we pick points from texture, rect needs to be smaller, otherwise it goes outside 1 pixel Rect2i fixed_rect = Rect2i(rect.position, rect.size - Size2i(2, 2)); Point2i tl = Point2i(curx - 1, cury - 1); sv += (fixed_rect.has_point(tl) && get_bit(tl)) ? 1 : 0; Point2i tr = Point2i(curx, cury - 1); sv += (fixed_rect.has_point(tr) && get_bit(tr)) ? 2 : 0; Point2i bl = Point2i(curx - 1, cury); sv += (fixed_rect.has_point(bl) && get_bit(bl)) ? 4 : 0; Point2i br = Point2i(curx, cury); sv += (fixed_rect.has_point(br) && get_bit(br)) ? 8 : 0; ERR_FAIL_COND_V(sv == 0 || sv == 15, Vector<Vector2>()); } switch (sv) { case 1: case 5: case 13: /* going UP with these cases: 1 5 13 +---+---+ +---+---+ +---+---+ | 1 | | | 1 | | | 1 | | +---+---+ +---+---+ +---+---+ | | | | 4 | | | 4 | 8 | +---+---+ +---+---+ +---+---+ */ stepx = 0; stepy = -1; break; case 8: case 10: case 11: /* going DOWN with these cases: 8 10 11 +---+---+ +---+---+ +---+---+ | | | | | 2 | | 1 | 2 | +---+---+ +---+---+ +---+---+ | | 8 | | | 8 | | | 8 | +---+---+ +---+---+ +---+---+ */ stepx = 0; stepy = 1; break; case 4: case 12: case 14: /* going LEFT with these cases: 4 12 14 +---+---+ +---+---+ +---+---+ | | | | | | | | 2 | +---+---+ +---+---+ +---+---+ | 4 | | | 4 | 8 | | 4 | 8 | +---+---+ +---+---+ +---+---+ */ stepx = -1; stepy = 0; break; case 2: case 3: case 7: /* going RIGHT with these cases: 2 3 7 +---+---+ +---+---+ +---+---+ | | 2 | | 1 | 2 | | 1 | 2 | +---+---+ +---+---+ +---+---+ | | | | | | | 4 | | +---+---+ +---+---+ +---+---+ */ stepx = 1; stepy = 0; break; case 9: /* +---+---+ | 1 | | +---+---+ | | 8 | +---+---+ this should normally go UP, but if we already been here, we go down */ if (case9s.has(Point2i(curx, cury))) { //found, so we go down, and delete from case9s; stepx = 0; stepy = 1; case9s.erase(Point2i(curx, cury)); } else { //not found, we go up, and add to case9s; stepx = 0; stepy = -1; case9s.insert(Point2i(curx, cury)); } break; case 6: /* 6 +---+---+ | | 2 | +---+---+ | 4 | | +---+---+ this normally go RIGHT, but if its coming from UP, it should go LEFT */ if (case6s.has(Point2i(curx, cury))) { //found, so we go down, and delete from case6s; stepx = -1; stepy = 0; case6s.erase(Point2i(curx, cury)); } else { //not found, we go up, and add to case6s; stepx = 1; stepy = 0; case6s.insert(Point2i(curx, cury)); } break; default: ERR_PRINT("this shouldn't happen."); } //little optimization // if previous direction is same as current direction, // then we should modify the last vec to current curx += stepx; cury += stepy; if (stepx == prevx && stepy == prevy) { _points.write[_points.size() - 1].x = (float)(curx - rect.position.x); _points.write[_points.size() - 1].y = (float)(cury + rect.position.y); } else { _points.push_back(Vector2((float)(curx - rect.position.x), (float)(cury + rect.position.y))); } count++; prevx = stepx; prevy = stepy; ERR_FAIL_COND_V(count > width * height, _points); } while (curx != startx || cury != starty); return _points; }
void TexturePacker::PackToMultipleTextures(const char * excludeFolder, const char* outputPath, std::list<DefinitionFile*> & defList) { if (defList.size() != 1) if (CommandLineParser::Instance()->GetVerbose())printf("* ERROR: failed to pack to multiple textures\n"); for (int i = 0; i < (int)sortVector.size(); ++i) { DefinitionFile * defFile = sortVector[i].defFile; int frame = sortVector[i].frameIndex; if (CommandLineParser::Instance()->GetVerbose())printf("[MultiPack] prepack: %s frame: %d w:%d h:%d\n", defFile->filename.c_str(), frame, defFile->frameRects[frame].dx, defFile->frameRects[frame].dy); } std::vector<ImagePacker*> & packers = usedPackers; /* // OLD PACKING ALGORITHM ImagePacker * currentPacker = new ImagePacker(Rect2i::Make(0, 0, 1024, 1024)); packers.push_back(currentPacker); // Packing of sorted by size images for (int i = 0; i < sortVector.size(); ++i) { DefinitionFile * defFile = sortVector[i].defFile; int frame = sortVector[i].frameIndex; printf("[MultiPack] pack: %s frame: %d w:%d h:%d\n", defFile->filename.c_str(), frame, defFile->frameRects[frame].dx, defFile->frameRects[frame].dy); bool packed = false; for (int packerIndex = 0; packerIndex < packers.size(); ++packerIndex) { if (packers[packerIndex]->AddImage(Size2i::Make(defFile->frameRects[frame].dx, defFile->frameRects[frame].dy), &defFile->frameRects[frame])) { packed = true; printf("[MultiPack] added to packer: %d\n", packerIndex); break; } } if (!packed) { currentPacker = new ImagePacker(Rect2i::Make(0, 0, 1024, 1024)); packers.push_back(currentPacker); if (!currentPacker->AddImage(Size2i::Make(defFile->frameRects[frame].dx, defFile->frameRects[frame].dy), &defFile->frameRects[frame])) { printf("*** FATAL ERROR: image is too big: imageSize: %d, %d\n", defFile->frameRects[frame].dx, defFile->frameRects[frame].dy); return; }else { printf("[MultiPack] added to packer: %d\n", packers.size() - 1); } } } */ /* // ALGO #2 std::vector<SizeSortItem> sortVectorWork = sortVector; while(sortVectorWork.size() > 0) { // try to pack for each resolution int maxPackedObjects = 0; //int bestResolution = 1025 * 1025; printf("* Packing tries started: "); ImagePacker * bestPackerForThisStep = 0; std::vector<SizeSortItem> newWorkVector; for (int yResolution = 8; yResolution <= 1024; yResolution *= 2) for (int xResolution = 8; xResolution <= 1024; xResolution *= 2) { Rect2i textureRect = Rect2i::Make(0, 0, xResolution, yResolution); ImagePacker * packer = new ImagePacker(textureRect); std::vector<SizeSortItem> tempSortVector = sortVectorWork; int n = TryToPackFromSortVector(packer, tempSortVector); if (n > maxPackedObjects) { maxPackedObjects = n; SafeDelete(bestPackerForThisStep); bestPackerForThisStep = packer; newWorkVector = tempSortVector; } } sortVectorWork = newWorkVector; packers.push_back(bestPackerForThisStep); } */ std::vector<SizeSortItem> sortVectorWork = sortVector; while(sortVectorWork.size() > 0) { // try to pack for each resolution float maxValue = 0.0f; //int bestResolution = 1025 * 1025; if (CommandLineParser::Instance()->GetVerbose())printf("* Packing tries started: "); ImagePacker * bestPackerForThisStep = 0; std::vector<SizeSortItem> newWorkVector; for (int yResolution = 8; yResolution <= maxTextureSize; yResolution *= 2) for (int xResolution = 8; xResolution <= maxTextureSize; xResolution *= 2) { if (CommandLineParser::Instance()->IsFlagSet("--pvr") && (xResolution != yResolution))continue; if ((onlySquareTextures) && (xResolution != yResolution))continue; Rect2i textureRect = Rect2i(0, 0, xResolution, yResolution); ImagePacker * packer = new ImagePacker(textureRect); std::vector<SizeSortItem> tempSortVector = sortVectorWork; float n = TryToPackFromSortVectorWeight(packer, tempSortVector); if (n > maxValue) { maxValue = n; SafeDelete(bestPackerForThisStep); bestPackerForThisStep = packer; newWorkVector = tempSortVector; } } sortVectorWork = newWorkVector; packers.push_back(bestPackerForThisStep); } if (CommandLineParser::Instance()->GetVerbose())printf("* Writing %d final textures \n", (int)packers.size()); std::vector<PngImageExt*> finalImages; for (int imageIndex = 0; imageIndex < (int)packers.size(); ++imageIndex) { PngImageExt * image = new PngImageExt(); ImagePacker * packer = packers[imageIndex]; image->Create(packer->GetRect().dx, packer->GetRect().dy); finalImages.push_back(image); } for (std::list<DefinitionFile*>::iterator defi = defList.begin(); defi != defList.end(); ++defi) { DefinitionFile * defFile = *defi; for (int frame = 0; frame < defFile->frameCount; ++frame) { Rect2i * destRect; ImagePacker * foundPacker = 0; int packerIndex = 0; char name[256]; for (packerIndex = 0; packerIndex < (int)packers.size(); ++packerIndex) { destRect = packers[packerIndex]->SearchRectForPtr(&defFile->frameRects[frame]); if (destRect) { foundPacker = packers[packerIndex]; std::string withoutExt = defFile->filename.substr(0, defFile->filename.length() - 4); snprintf(name, 256, "%s%d.png", withoutExt.c_str(), frame); break; } } if (foundPacker) { if (CommandLineParser::Instance()->GetVerbose())printf("[MultiPack] pack to texture: %d\n", packerIndex); PngImageExt image; image.Read(name); finalImages[packerIndex]->DrawImage(destRect->x, destRect->y, &image); if (CommandLineParser::Instance()->IsFlagSet("--debug")) { finalImages[packerIndex]->DrawRect(*destRect, 0xFF0000FF); } } } } for (int image = 0; image < (int)packers.size(); ++image) { char temp[256]; sprintf(temp, "texture%d.png", image); std::string textureName = std::string(outputPath) + std::string(temp); finalImages[image]->Write(textureName.c_str()); } for (std::list<DefinitionFile*>::iterator defi = defList.begin(); defi != defList.end(); ++defi) { DefinitionFile * defFile = *defi; std::string textureName = std::string(outputPath) + std::string("texture"); if (!WriteMultipleDefinition(excludeFolder, outputPath, "texture", defFile)) { printf("* ERROR: failed to write definition\n"); } } }
void TexturePacker::PackToTextures(const char * excludeFolder, const char* outputPath, std::list<DefinitionFile*> & defsList) { lastPackedPacker = 0; for (std::list<DefinitionFile*>::iterator dfi = defsList.begin(); dfi != defsList.end(); ++dfi) { DefinitionFile * defFile = *dfi; for (int frame = 0; frame < defFile->frameCount; ++frame) { SizeSortItem sortItem; sortItem.imageSize = defFile->frameRects[frame].dx * defFile->frameRects[frame].dy; sortItem.defFile = defFile; sortItem.frameIndex = frame; sortVector.push_back(sortItem); } } // for (int i = 0; i < sortVector.size(); ++i) // { // DefinitionFile * defFile = sortVector[i].defFile; // int frame = sortVector[i].frameIndex; // printf("[SinglePack] before sort: %s frame: %d w:%d h:%d\n", defFile->filename.c_str(), frame, defFile->frameRects[frame].dx, defFile->frameRects[frame].dy); // } std::sort(sortVector.begin(), sortVector.end(), sortFn); // for (int i = 0; i < sortVector.size(); ++i) // { // DefinitionFile * defFile = sortVector[i].defFile; // int frame = sortVector[i].frameIndex; // printf("[SinglePack] after sort: %s frame: %d w:%d h:%d\n", defFile->filename.c_str(), frame, defFile->frameRects[frame].dx, defFile->frameRects[frame].dy); // } // try to pack for each resolution int bestResolution = (maxTextureSize + 1) * (maxTextureSize + 1); int bestXResolution, bestYResolution; if (CommandLineParser::Instance()->GetVerbose()) printf("* Packing tries started: "); bool isPvr = false; if (CommandLineParser::Instance()->IsFlagSet("--pvr")) isPvr = true; for (int yResolution = 8; yResolution <= maxTextureSize; yResolution *= 2) for (int xResolution = 8; xResolution <= maxTextureSize; xResolution *= 2) { if ((isPvr) && (xResolution != yResolution))continue; if ((onlySquareTextures) && (xResolution != yResolution))continue; Rect2i textureRect = Rect2i(0, 0, xResolution, yResolution); if (xResolution * yResolution < bestResolution) if (TryToPack(textureRect, defsList)) { bestResolution = xResolution * yResolution; bestXResolution = xResolution; bestYResolution = yResolution; } } if (CommandLineParser::Instance()->GetVerbose()) printf("\n"); if (bestResolution != (maxTextureSize + 1) * (maxTextureSize + 1)) { std::string textureName = std::string(outputPath) + std::string("texture"); if (CommandLineParser::Instance()->GetVerbose()) printf("* Writing final texture (%d x %d): %s\n", bestXResolution, bestYResolution , textureName.c_str()); PngImageExt finalImage; finalImage.Create(bestXResolution, bestYResolution); // Writing for (std::list<DefinitionFile*>::iterator dfi = defsList.begin(); dfi != defsList.end(); ++dfi) { DefinitionFile * defFile = *dfi; for (int frame = 0; frame < defFile->frameCount; ++frame) { Rect2i *destRect = lastPackedPacker->SearchRectForPtr(&defFile->frameRects[frame]); if (!destRect)printf("*** ERROR Can't find rect for frame\n"); char name[256]; std::string withoutExt = defFile->filename.substr(0, defFile->filename.length() - 4); snprintf(name, 256, "%s%d.png", withoutExt.c_str(), frame); PngImageExt image; image.Read(name); finalImage.DrawImage(destRect->x, destRect->y, &image); if (CommandLineParser::Instance()->IsFlagSet("--debug")) { finalImage.DrawRect(*destRect, 0xFF0000FF); } } if (!WriteDefinition(excludeFolder, outputPath, "texture", defFile)) { printf("* ERROR: failed to write definition\n"); } } char textureExtension[5] = "png"; if (CommandLineParser::Instance()->IsFlagSet("--pvr"))strcpy(textureExtension, "pvr"); textureName += std::string(".") + textureExtension; finalImage.Write(textureName.c_str()); } else { // PackToMultipleTextures(excludeFolder, outputPath, defsList); } }
void TexturePacker::PackToTexturesSeparate(const char * excludeFolder, const char* outputPath, std::list<DefinitionFile*> & defsList) { lastPackedPacker = 0; int textureIndex = 0; for (std::list<DefinitionFile*>::iterator dfi = defsList.begin(); dfi != defsList.end(); ++dfi) { sortVector.clear(); DefinitionFile * defFile = *dfi; for (int frame = 0; frame < defFile->frameCount; ++frame) { SizeSortItem sortItem; sortItem.imageSize = defFile->frameRects[frame].dx * defFile->frameRects[frame].dy; sortItem.defFile = defFile; sortItem.frameIndex = frame; sortVector.push_back(sortItem); } std::sort(sortVector.begin(), sortVector.end(), sortFn); // try to pack for each resolution int bestResolution = (maxTextureSize + 1) * (maxTextureSize + 1); int bestXResolution, bestYResolution; if (CommandLineParser::Instance()->GetVerbose()) printf("* Packing tries started: "); for (int yResolution = 8; yResolution <= maxTextureSize; yResolution *= 2) for (int xResolution = 8; xResolution <= maxTextureSize; xResolution *= 2) { Rect2i textureRect = Rect2i(0, 0, xResolution, yResolution); if (xResolution * yResolution < bestResolution) if (TryToPack(textureRect, defsList)) { bestResolution = xResolution * yResolution; bestXResolution = xResolution; bestYResolution = yResolution; } } if (CommandLineParser::Instance()->GetVerbose()) printf("\n"); if (bestResolution != (maxTextureSize + 1) * (maxTextureSize + 1)) { char textureNameWithIndex[50]; sprintf(textureNameWithIndex, "texture%d", textureIndex++); std::string textureName = std::string(outputPath) + std::string(textureNameWithIndex); if (CommandLineParser::Instance()->GetVerbose()) printf("* Writing final texture (%d x %d): %s\n", bestXResolution, bestYResolution , textureName.c_str()); PngImageExt finalImage; finalImage.Create(bestXResolution, bestYResolution); // Writing for (int frame = 0; frame < defFile->frameCount; ++frame) { Rect2i *destRect = lastPackedPacker->SearchRectForPtr(&defFile->frameRects[frame]); if (!destRect)printf("*** ERROR Can't find rect for frame\n"); char name[256]; std::string withoutExt = defFile->filename.substr(0, defFile->filename.length() - 4); snprintf(name, 256, "%s%d.png", withoutExt.c_str(), frame); PngImageExt image; image.Read(name); finalImage.DrawImage(destRect->x, destRect->y, &image); } if (!WriteDefinition(excludeFolder, outputPath, textureNameWithIndex, defFile)) { printf("* ERROR: failed to write definition\n"); } char textureExtension[5] = "png"; if (CommandLineParser::Instance()->IsFlagSet("--pvr"))strcpy(textureExtension, "pvr"); textureName += std::string(".") + textureExtension; finalImage.Write(textureName.c_str()); } } }
DefinitionFile * ResourcePackerScreen::ProcessPSD(const String & processDirectoryPath, const String & psdPathname, const String & psdName) { int32 maxTextureSize = 1024; if (CommandLineParser::Instance()->IsFlagSet("--tsize2048")) { maxTextureSize = 2048; } // TODO: Check CRC32 std::vector<Magick::Image> layers; String psdNameWithoutExtension = FileSystem::ReplaceExtension(psdName, ""); try { Magick::readImages(&layers, psdPathname); if (layers.size() == 0) { Logger::Error("Number of layers is too low: %s", psdPathname.c_str()); return 0; } if (layers.size() == 1) { layers.push_back(layers[0]); } //Logger::Debug("psd file: %s wext: %s", psdPathname.c_str(), psdNameWithoutExtension.c_str()); int width = (int)layers[0].columns(); int height = (int)layers[0].rows(); for(int k = 1; k < (int)layers.size(); ++k) { Magick::Image & currentLayer = layers[k]; /* MagickCore::ResetImagePropertyIterator(currentLayer.image()); const char * property = MagickCore::GetNextImageProperty(currentLayer.image()); if (property != (const char *) NULL) { printf(" Properties:\n"); while (property != (const char *) NULL) { printf(" %c",*property); if (strlen(property) > 1) printf("%s: ",property+1); if (strlen(property) > 80) printf("\n"); const char * value = MagickCore::GetImageProperty(currentLayer.image(), property); if (value != (const char *) NULL) printf("%s\n",value); property = MagickCore::GetNextImageProperty(currentLayer.image()); } } */ currentLayer.crop(Magick::Geometry(width,height, 0, 0)); currentLayer.magick("PNG"); String outputFile = processDirectoryPath + String("/") + psdNameWithoutExtension; outputFile += String(Format("%d.png", k - 1)); currentLayer.write(outputFile); } DefinitionFile * defFile = new DefinitionFile; defFile->filename = processDirectoryPath + String("/") + psdNameWithoutExtension + String(".txt"); // Logger::Debug("filename: %s", defFile->filename.c_str()); defFile->spriteWidth = width; defFile->spriteHeight = height; defFile->frameCount = (int)layers.size() -1; defFile->frameRects = new Rect2i[defFile->frameCount]; for(int k = 1; k < (int)layers.size(); ++k) { Magick::Image & currentLayer = layers[k]; Magick::Geometry bbox = currentLayer.page(); int xOff = (int)bbox.xOff(); if (bbox.xNegative()) xOff = -xOff; int yOff = (int)bbox.yOff(); if (bbox.yNegative()) yOff = -yOff; defFile->frameRects[k - 1] = Rect2i(xOff, yOff, (int32)bbox.width(), (int32)bbox.height()); //printf("Percent: %d Aspect: %d Greater: %d Less: %d\n", (int)bbox.percent(), (int)bbox.aspect(), (int)bbox.greater(), (int)bbox.less()); if ((defFile->frameRects[k - 1].dx >= maxTextureSize) || (defFile->frameRects[k - 1].dy >= maxTextureSize)) { printf("* WARNING * - frame of %s layer %d is bigger than maxTextureSize(%d) layer exportSize (%d x %d) FORCE REDUCE TO (%d x %d). Bewarned!!! Results not guaranteed!!!\n", psdName.c_str(), k - 1, maxTextureSize , defFile->frameRects[k - 1].dx, defFile->frameRects[k - 1].dy, width, height); defFile->frameRects[k - 1].dx = width; defFile->frameRects[k - 1].dy = height; } if (CommandLineParser::Instance()->IsFlagSet("--add0pixel")) { }else if (CommandLineParser::Instance()->IsFlagSet("--add1pixel")) { defFile->frameRects[k - 1].dx++; defFile->frameRects[k - 1].dy++; } else if (CommandLineParser::Instance()->IsFlagSet("--add2pixel")) { defFile->frameRects[k - 1].dx+=2; defFile->frameRects[k - 1].dy+=2; } else if (CommandLineParser::Instance()->IsFlagSet("--add4pixel")) { defFile->frameRects[k - 1].dx+=4; defFile->frameRects[k - 1].dy+=4; } else if(CommandLineParser::Instance()->IsFlagSet("--add2sidepixel")) { defFile->frameRects[k - 1].dx+=2; defFile->frameRects[k - 1].dy+=2; } else { defFile->frameRects[k - 1].dx++; defFile->frameRects[k - 1].dy++; } } return defFile; } catch( Magick::Exception &error_ ) { std::cout << "Caught exception: " << error_.what() << " file: "<< psdPathname << std::endl; return 0; } return 0; }
bool DefinitionFile::LoadPNGDef(const std::string & _filename, const std::string & pathToProcess) { if (CommandLineParser::Instance()->GetVerbose())printf("* Load PNG Definition: %s\n", _filename.c_str()); FILE * fp = fopen(_filename.c_str(), "rt"); fscanf(fp, "%d", &frameCount); String path; String name; CommandLineParser::SplitFilePath(_filename, path, name); String nameWithoutExt = name.substr(0, name.length() - 7); String corespondingPngImage = path + String("/") + nameWithoutExt + String(".png"); filename = pathToProcess + String("/") + nameWithoutExt + String(".txt"); PngImageExt image; image.Read(corespondingPngImage.c_str()); spriteWidth = image.GetWidth() / frameCount; spriteHeight = image.GetHeight(); // String dirWrite = path + String("/$process/"); // mkdir(dirWrite.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); if (CommandLineParser::Instance()->GetVerbose())printf("* frameCount: %d spriteWidth: %d spriteHeight: %d\n", frameCount, spriteWidth, spriteHeight); frameRects = new Rect2i[frameCount]; for (int k = 0; k < frameCount; ++k) { PngImageExt frameX; frameX.Create(spriteWidth, spriteHeight); frameX.DrawImage(0, 0, &image, Rect2i(k * spriteWidth, 0, spriteWidth, spriteHeight)); Rect2i reducedRect; frameX.FindNonOpaqueRect(reducedRect); if (CommandLineParser::Instance()->GetVerbose())printf("%s - reduced_rect(%d %d %d %d)\n", nameWithoutExt.c_str(), reducedRect.x, reducedRect.y, reducedRect.dx, reducedRect.dy); /*if (k == 1) { for (int y = 0; y < spriteWidth; ++y) { for (int x = 0; x < spriteWidth; ++x) { printf("%02x ", frameX.GetPixel(x, y)[3]); } printf("\n"); } }*/ PngImageExt frameX2; frameX2.Create(reducedRect.dx, reducedRect.dy); frameX2.DrawImage(0, 0, &frameX, reducedRect); char number[10]; sprintf(number, "%d", k); String fileWrite = pathToProcess + String("/") + nameWithoutExt + String(number) + String(".png"); frameX2.Write(fileWrite.c_str()); frameRects[k].x = reducedRect.x; frameRects[k].y = reducedRect.y; frameRects[k].dx = reducedRect.dx; frameRects[k].dy = reducedRect.dy; if (CommandLineParser::Instance()->IsFlagSet("--add0pixel")) { }else if (CommandLineParser::Instance()->IsFlagSet("--add1pixel")) { frameRects[k].dx++; frameRects[k].dy++; } else if (CommandLineParser::Instance()->IsFlagSet("--add2pixel")) { frameRects[k].dx+=2; frameRects[k].dy+=2; } else if (CommandLineParser::Instance()->IsFlagSet("--add4pixel")) { frameRects[k].dx+=4; frameRects[k].dy+=4; }else { frameRects[k].dx++; frameRects[k].dy++; } } fclose(fp); return true; }