Skip to content

Commit

Permalink
Merge pull request #2 from LeeWannacott/cut-sprite
Browse files Browse the repository at this point in the history
Spritesheet cutting into sprites
  • Loading branch information
kyle-wannacott authored Nov 1, 2024
2 parents f369494 + dcd50dc commit d63eecf
Show file tree
Hide file tree
Showing 2,358 changed files with 174 additions and 86 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module github.com/LeeWannacott/gontage

go 1.21
go 1.23

require github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // direct
Binary file added main
Binary file not shown.
39 changes: 28 additions & 11 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ func main() {
hframes := flag.Int("hf", 8, "Horizontal Frames: Amount of horizontal frames you want in your spritesheet: default 8.")
sprite_resize_px := flag.Int("sr", 0, "Sprite Resize: Resize each sprite to the pixel value provided.")
single_sprites := flag.Bool("ss", false, "Single Sprites: Output sprites rather than spritesheet use with -sr flag")
cpu_threads := flag.Int("t", 0, "CPU threads available (default max available)")
cut_spritesheet := flag.String("c", "", "Example: -c 128x128. Cut spritesheet into size individual sprites. ")
parent_folder_path := flag.String("mf", "", "Multiple Folders: path should be parent folder containing sub folders that contain folders with sprites/images in them. Refer to test_multi for example structure.")
useMontage := flag.Bool("montage", false, "Use montage with -mf instead of gontage (if installed)")
help := flag.Bool("h", false, "Display help")
Expand All @@ -54,9 +56,16 @@ func main() {
flag.PrintDefaults()
os.Exit(0)
}

gontage_args := gontage.GontageArgs{
Sprite_source_folder: filepath.Clean(*sprite_source_folder),
Hframes: *hframes,
Sprite_resize_px_resize: *sprite_resize_px,
Single_sprites: *single_sprites,
Cut_spritesheet: *cut_spritesheet,
Cpu_threads: *cpu_threads,
}
if *sprite_source_folder != "" {
gontage.Gontage(*sprite_source_folder, hframes, *sprite_resize_px, *single_sprites)
gontage.Gontage(gontage_args)
} else {
var wg sync.WaitGroup
if parent_folder_path != nil {
Expand All @@ -68,14 +77,16 @@ func main() {
if err != nil {
fmt.Println(err)
}
sub_folder_path_gontage := filepath.Join(*parent_folder_path, sub_folder.Name())
sub_folder_path_gontage :=
filepath.Join(*parent_folder_path, sub_folder.Name())
sub_folder_path := filepath.Join(pwd, *parent_folder_path, sub_folder.Name())
folder := folderInfo{
sub_folder_path: sub_folder_path,
sub_folder_path_gontage: sub_folder_path_gontage,
sprite_source_folder: *sprite_source_folder,
}
amount_of_sprites, folder_names, sprite_height, sprite_width := iterate_folder(sub_folder_path, i)
amount_of_sprites, folder_names, sprite_height, sprite_width :=
iterate_folder(sub_folder_path, i)
spritesheet := spritesheet{
sprite_height: sprite_height,
sprite_width: sprite_width,
Expand All @@ -93,7 +104,7 @@ func main() {
go func(i int, folder_name string) {
defer wg.Done()
folder.folder_name = folder_name
call_gontage_or_montage(i, spritesheet, folder, cli)
call_gontage_or_montage(i, spritesheet, folder, cli, gontage_args)
}(i, folder_name)
}
wg.Wait()
Expand All @@ -104,7 +115,7 @@ func main() {
}
}

func call_gontage_or_montage(i int, spritesheet spritesheet, folder folderInfo, cli cliOptions) {
func call_gontage_or_montage(i int, spritesheet spritesheet, folder folderInfo, cli cliOptions, gargs gontage.GontageArgs) {
spritesheet_width := spritesheet.hframes
spritesheet_height := math.Ceil(float64(spritesheet.amount_of_sprites[i]/spritesheet_width) + 1)
background_type := "transparent"
Expand All @@ -121,7 +132,15 @@ func call_gontage_or_montage(i int, spritesheet spritesheet, folder folderInfo,
}
fmt.Println(string(out), filepath.Join(folder.sub_folder_path_gontage, folder.folder_name)+"/*", sprite_name)
} else {
gontage.Gontage(filepath.Join(folder.sub_folder_path_gontage, folder.folder_name), &spritesheet.hframes, spritesheet.sprite_resize_px, false)
gontage_args := gontage.GontageArgs{
Sprite_source_folder: filepath.Join(folder.sub_folder_path_gontage, folder.folder_name),
Hframes: spritesheet.hframes,
Sprite_resize_px_resize: spritesheet.sprite_resize_px,
Single_sprites: false,
Cut_spritesheet: "",
Cpu_threads: gargs.Cpu_threads,
}
gontage.Gontage(gontage_args)
}
}

Expand Down Expand Up @@ -153,10 +172,8 @@ func iterate_folder(file_path_to_walk string, index int) ([]int, []string, int,
log.Fatal(err)
}
bounds := m.Bounds()
w := bounds.Dx()
h := bounds.Dy()
sprite_height = h
sprite_width = w
w, h := bounds.Dx(), bounds.Dy()
sprite_height, sprite_width = h, w
is_first_sprite_in_directory = false
reader.Close()
}
Expand Down
File renamed without changes
Binary file added sprite_cut/barrel_red_f18_v3/0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprite_cut/barrel_red_f18_v3/1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprite_cut/barrel_red_f18_v3/10.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprite_cut/barrel_red_f18_v3/11.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprite_cut/barrel_red_f18_v3/12.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprite_cut/barrel_red_f18_v3/13.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprite_cut/barrel_red_f18_v3/14.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprite_cut/barrel_red_f18_v3/15.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprite_cut/barrel_red_f18_v3/16.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprite_cut/barrel_red_f18_v3/17.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprite_cut/barrel_red_f18_v3/18.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprite_cut/barrel_red_f18_v3/19.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprite_cut/barrel_red_f18_v3/2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprite_cut/barrel_red_f18_v3/20.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprite_cut/barrel_red_f18_v3/21.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprite_cut/barrel_red_f18_v3/22.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprite_cut/barrel_red_f18_v3/23.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprite_cut/barrel_red_f18_v3/3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprite_cut/barrel_red_f18_v3/4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprite_cut/barrel_red_f18_v3/5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprite_cut/barrel_red_f18_v3/6.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprite_cut/barrel_red_f18_v3/7.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprite_cut/barrel_red_f18_v3/8.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprite_cut/barrel_red_f18_v3/9.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
219 changes: 145 additions & 74 deletions src/gontage.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import (
"os"
"path/filepath"
"runtime"
"strconv"
"strings"
"sync"
"time"

Expand All @@ -26,31 +28,45 @@ type drawingInfo struct {
spritesheet draw.Image
}

func Gontage(sprite_source_folder string, hframes *int, sprite_resize_px int, single_sprites bool) {
type GontageArgs struct {
Sprite_source_folder string
Hframes int
Sprite_resize_px_resize int
Single_sprites bool
Cut_spritesheet string
Cpu_threads int
}

func Gontage(gargs GontageArgs) {
// sprite_source_folder string, hframes *int, sprite_resize_px_resize int, single_sprites bool, cut_spritesheet bool
start := time.Now()
pwd, err := os.Getwd()
if err != nil {
fmt.Println(err)
os.Exit(1)
}

sprites_folder, err := os.ReadDir(filepath.Join(pwd, sprite_source_folder))
fmt.Println(filepath.Join(pwd, gargs.Sprite_source_folder))
sprites_folder, err := os.ReadDir(filepath.Join(pwd, gargs.Sprite_source_folder))
if err != nil {
log.Fatal(err)
} else if len(sprites_folder) == 0 {
fmt.Println("Looks like folder ", sprite_source_folder, "is empty...")
fmt.Println("Looks like folder ", gargs.Sprite_source_folder, "is empty...")
}

if len(sprites_folder) < *hframes {
*hframes = len(sprites_folder)
if len(sprites_folder) < gargs.Hframes {
gargs.Hframes = len(sprites_folder)
}

if len(sprites_folder) != 0 {
var chunkSize int
if runtime.NumCPU() > 12 && runtime.NumCPU()%4 == 0 {
if gargs.Cpu_threads > 0 {
chunkSize = gargs.Cpu_threads
runtime.GOMAXPROCS(gargs.Cpu_threads)
} else if runtime.NumCPU() > 12 && runtime.NumCPU()%4 == 0 {
chunkSize = runtime.NumCPU() / 4
} else {
chunkSize = 6
chunkSize = runtime.NumCPU()
}

var chunk_images_waitgroup sync.WaitGroup
Expand All @@ -66,7 +82,7 @@ func Gontage(sprite_source_folder string, hframes *int, sprite_resize_px int, si
chunk_images_waitgroup.Add(1)
go func(start int, end int) {
// Ideally decodeImages would write into all_decoded_images directly.
one_chunk_of_decoded_images, decoded_image_names := decodeImages(sprites_folder[start:end], sprite_source_folder, pwd, &chunk_images_waitgroup)
one_chunk_of_decoded_images, decoded_image_names := decodeImages(sprites_folder[start:end], gargs.Sprite_source_folder, pwd, &chunk_images_waitgroup)
for j, decoded_image := range one_chunk_of_decoded_images {
all_decoded_images[start+j] = decoded_image
all_decoded_images_names[start+j] = decoded_image_names[j]
Expand All @@ -75,66 +91,12 @@ func Gontage(sprite_source_folder string, hframes *int, sprite_resize_px int, si
}
chunk_images_waitgroup.Wait()

// TODO: refactor we use similiar code in other places as well...
if single_sprites && sprite_resize_px != 0 {
sprite_source_folder_resized_name := fmt.Sprintf("%v_resized_%vpx", sprite_source_folder, sprite_resize_px)
os.Mkdir(sprite_source_folder_resized_name, 0755)
encoder := png.Encoder{CompressionLevel: png.BestSpeed}
for i, decoded_image := range all_decoded_images {
resized_sprite_name := fmt.Sprintf("/%v", all_decoded_images_names[i])
f, err := os.Create(sprite_source_folder_resized_name + resized_sprite_name)
if err != nil {
panic(err)
}
resized_image := resize.Resize(uint(sprite_resize_px), uint(sprite_resize_px), decoded_image, resize.Lanczos3)
if err = encoder.Encode(f, resized_image); err != nil {
log.Printf("failed to encode: %v", err)
}
fmt.Println(sprite_source_folder_resized_name + resized_sprite_name)
f.Close()
}
fmt.Println(time.Since(start))
if gargs.Single_sprites && gargs.Sprite_resize_px_resize != 0 {
spritesToResizedSprites(gargs, all_decoded_images, all_decoded_images_names, start)
} else if gargs.Cut_spritesheet != "" {
cutSpritesheetIntoSprites(gargs, all_decoded_images, all_decoded_images_names, start)
} else {
spritesheet_width, spritesheet_height, vframes := calcSheetDimensions(*hframes, all_decoded_images)
spritesheet := image.NewNRGBA(image.Rect(0, 0, spritesheet_width, spritesheet_height))
draw.Draw(spritesheet, spritesheet.Bounds(), spritesheet, image.Point{}, draw.Src)
decoded_images_to_draw_chunked := sliceChunk(all_decoded_images, *hframes)
var make_spritesheet_wg sync.WaitGroup
for count_vertical_frames, sprite_chunk := range decoded_images_to_draw_chunked {
drawing := drawingInfo{
sprites: sprite_chunk,
hframes: *hframes,
vframes: int(vframes),
spritesheet: spritesheet,
}
make_spritesheet_wg.Add(1)
go func(vertical_frames_count int, sprite_chunk []image.Image) {
drawing.vertical_frames_count = vertical_frames_count
defer make_spritesheet_wg.Done()
drawSpritesheet(drawing)
}(count_vertical_frames, sprite_chunk)
}
make_spritesheet_wg.Wait()
spritesheet_name := fmt.Sprintf("%v_f%v_v%v.png", sprite_source_folder, len(all_decoded_images), vframes)
f, err := os.Create(spritesheet_name)
if err != nil {
panic(err)
}
encoder := png.Encoder{CompressionLevel: png.BestSpeed}
if sprite_resize_px != 0 {
resized_spritesheet := resize.Resize(uint(*hframes*sprite_resize_px), uint(int(vframes)*sprite_resize_px),
spritesheet, resize.Lanczos3)
if err = encoder.Encode(f, resized_spritesheet); err != nil {
log.Printf("failed to encode: %v", err)
}
} else {
if err = encoder.Encode(f, spritesheet); err != nil {
log.Printf("failed to encode: %v", err)
}
}

f.Close()
fmt.Println(spritesheet_name, ": ", time.Since(start))
spritesToSpritesheet(gargs, all_decoded_images, all_decoded_images_names, start)
}
}
}
Expand All @@ -144,14 +106,16 @@ func decodeImages(sprites_folder []fs.DirEntry, targetFolder string, pwd string,
var sprites_array []image.Image
var sprites_names []string
for _, sprite := range sprites_folder {
if reader, err := os.Open(filepath.Join(pwd, targetFolder, sprite.Name())); err == nil {
m, _, err := image.Decode(reader)
if err != nil {
log.Fatal(err)
if !sprite.IsDir() {
if reader, err := os.Open(filepath.Join(pwd, targetFolder, sprite.Name())); err == nil {
m, _, err := image.Decode(reader)
if err != nil {
log.Fatalln(err)
}
sprites_array = append(sprites_array, m)
sprites_names = append(sprites_names, sprite.Name())
reader.Close()
}
sprites_array = append(sprites_array, m)
sprites_names = append(sprites_names, sprite.Name())
reader.Close()
}
}
return sprites_array, sprites_names
Expand Down Expand Up @@ -192,3 +156,110 @@ func calcSheetDimensions(hframes int, all_decoded_images []image.Image) (int, in
}
return spritesheet_width, spritesheet_height, vframes
}

func spritesToResizedSprites(gargs GontageArgs, all_decoded_images []image.Image, all_decoded_images_names []string, start time.Time) {
sprite_source_folder_resized_name := fmt.Sprintf("%v_resized_%vpx", gargs.Sprite_source_folder, gargs.Sprite_resize_px_resize)
os.Mkdir(sprite_source_folder_resized_name, 0755)
encoder := png.Encoder{CompressionLevel: png.BestSpeed}
for i, decoded_image := range all_decoded_images {
resized_sprite_name := fmt.Sprintf("/%v", all_decoded_images_names[i])
f, err := os.Create(sprite_source_folder_resized_name + resized_sprite_name)
if err != nil {
panic(err)
}
resized_image := resize.Resize(uint(gargs.Sprite_resize_px_resize), uint(gargs.Sprite_resize_px_resize), decoded_image, resize.Lanczos3)
if err = encoder.Encode(f, resized_image); err != nil {
log.Printf("failed to encode: %v", err)
}
fmt.Println(sprite_source_folder_resized_name + resized_sprite_name)
f.Close()
}
fmt.Println(time.Since(start))
}

func cutSpritesheetIntoSprites(gargs GontageArgs, all_decoded_images []image.Image, all_decoded_images_names []string, start time.Time) {
image_size := strings.Split(gargs.Cut_spritesheet, "x")
image_size_x, err := strconv.Atoi(image_size[0])
image_size_y, err := strconv.Atoi(image_size[1])
if err != nil {
log.Fatalln(err)
}
var cut_spritesheet_wg sync.WaitGroup
for i, decoded_image := range all_decoded_images {
if decoded_image == nil {
continue
}
cut_spritesheet_wg.Add(1)
var hframes = decoded_image.Bounds().Dx() / image_size_x
var vframes = decoded_image.Bounds().Dy() / image_size_y
frame_count := 0
go func() {
defer cut_spritesheet_wg.Done()
for v := range vframes {
for h := range hframes {
cutted_image := image.NewNRGBA(image.Rect(h*image_size_x, v*image_size_y, (h*image_size_x)+image_size_x, (v*image_size_y)+image_size_y))
r := image.Rect(h*image_size_x, v*image_size_y, (h*image_size_x)+image_size_x, (v*image_size_y)+image_size_y)
draw.Draw(cutted_image, r, decoded_image, image.Point{h * image_size_x, v * image_size_y}, draw.Over)
folder_name := strings.Split(all_decoded_images_names[i], ".")
cut_sprite_name := filepath.Join(fmt.Sprintf("%v.png", frame_count))
os.Mkdir(filepath.Join(gargs.Sprite_source_folder, folder_name[0]), 0755)
sprite_output := filepath.Join(gargs.Sprite_source_folder, folder_name[0], cut_sprite_name)
f, err := os.Create(sprite_output)
if err != nil {
panic(err)
}
encoder := png.Encoder{CompressionLevel: png.BestSpeed}
if err = encoder.Encode(f, cutted_image); err != nil {
log.Printf("failed to encode: %v", err)
}
frame_count += 1
}
}
}()
}
cut_spritesheet_wg.Wait()
fmt.Println(all_decoded_images_names, ": \n total time: ", time.Since(start))
}

func spritesToSpritesheet(gargs GontageArgs, all_decoded_images []image.Image, all_decoded_images_names []string, start time.Time) {
spritesheet_width, spritesheet_height, vframes := calcSheetDimensions(gargs.Hframes, all_decoded_images)
spritesheet := image.NewNRGBA(image.Rect(0, 0, spritesheet_width, spritesheet_height))
draw.Draw(spritesheet, spritesheet.Bounds(), spritesheet, image.Point{}, draw.Src)
decoded_images_to_draw_chunked := sliceChunk(all_decoded_images, gargs.Hframes)
var make_spritesheet_wg sync.WaitGroup
for count_vertical_frames, sprite_chunk := range decoded_images_to_draw_chunked {
drawing := drawingInfo{
sprites: sprite_chunk,
hframes: gargs.Hframes,
vframes: int(vframes),
spritesheet: spritesheet,
}
make_spritesheet_wg.Add(1)
go func(vertical_frames_count int, sprite_chunk []image.Image) {
drawing.vertical_frames_count = vertical_frames_count
defer make_spritesheet_wg.Done()
drawSpritesheet(drawing)
}(count_vertical_frames, sprite_chunk)
}
make_spritesheet_wg.Wait()
spritesheet_name := fmt.Sprintf("%v_f%v_v%v.png", gargs.Sprite_source_folder, len(all_decoded_images), vframes)
f, err := os.Create(spritesheet_name)
if err != nil {
panic(err)
}
encoder := png.Encoder{CompressionLevel: png.BestSpeed}
if gargs.Sprite_resize_px_resize != 0 {
resized_spritesheet := resize.Resize(uint(gargs.Hframes*gargs.Sprite_resize_px_resize), uint(int(vframes)*gargs.Sprite_resize_px_resize),
spritesheet, resize.Lanczos3)
if err = encoder.Encode(f, resized_spritesheet); err != nil {
log.Printf("failed to encode: %v", err)
}
} else {
if err = encoder.Encode(f, spritesheet); err != nil {
log.Printf("failed to encode: %v", err)
}
}

f.Close()
fmt.Println(spritesheet_name, ": ", time.Since(start))
}
Binary file removed test/9_resized-0.png
Diff not rendered.
Binary file removed test/9_resized-1.png
Diff not rendered.
Binary file removed test/9_resized-10.png
Diff not rendered.
Binary file removed test/9_resized-11.png
Diff not rendered.
Binary file removed test/9_resized-12.png
Diff not rendered.
Binary file removed test/9_resized-2.png
Diff not rendered.
Binary file removed test/9_resized-3.png
Diff not rendered.
Binary file removed test/9_resized-4.png
Diff not rendered.
Binary file removed test/9_resized-5.png
Diff not rendered.
Binary file removed test/9_resized-6.png
Diff not rendered.
Binary file removed test/9_resized-7.png
Diff not rendered.
Binary file removed test/9_resized-8.png
Diff not rendered.
Binary file removed test/9_resized-9.png
Diff not rendered.
Binary file added test/sprite_cut/barrel_red_f18_v3.png
Binary file added test/sprite_cut/barrel_red_f18_v3/0.png
Binary file added test/sprite_cut/barrel_red_f18_v3/1.png
Binary file added test/sprite_cut/barrel_red_f18_v3/10.png
Binary file added test/sprite_cut/barrel_red_f18_v3/11.png
Binary file added test/sprite_cut/barrel_red_f18_v3/12.png
Binary file added test/sprite_cut/barrel_red_f18_v3/13.png
Binary file added test/sprite_cut/barrel_red_f18_v3/14.png
Binary file added test/sprite_cut/barrel_red_f18_v3/15.png
Binary file added test/sprite_cut/barrel_red_f18_v3/16.png
Binary file added test/sprite_cut/barrel_red_f18_v3/17.png
Binary file added test/sprite_cut/barrel_red_f18_v3/18.png
Binary file added test/sprite_cut/barrel_red_f18_v3/19.png
Binary file added test/sprite_cut/barrel_red_f18_v3/2.png
Binary file added test/sprite_cut/barrel_red_f18_v3/20.png
Binary file added test/sprite_cut/barrel_red_f18_v3/21.png
Binary file added test/sprite_cut/barrel_red_f18_v3/22.png
Binary file added test/sprite_cut/barrel_red_f18_v3/23.png
Binary file added test/sprite_cut/barrel_red_f18_v3/3.png
Binary file added test/sprite_cut/barrel_red_f18_v3/4.png
Binary file added test/sprite_cut/barrel_red_f18_v3/5.png
Binary file added test/sprite_cut/barrel_red_f18_v3/6.png
Binary file added test/sprite_cut/barrel_red_f18_v3/7.png
Binary file added test/sprite_cut/barrel_red_f18_v3/8.png
Binary file added test/sprite_cut/barrel_red_f18_v3/9.png
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
Binary file added test/test_multi/barrels/barrel_red_f18_v3.png
File renamed without changes
Binary file removed test_f13_v2.png
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Loading

0 comments on commit d63eecf

Please sign in to comment.