1 /**
2 Copyright: Copyright (c) 2017-2018 Andrey Penechko.
3 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
4 Authors: Andrey Penechko.
5 */
6 module voxelman.graphics.sprite;
7 
8 import dlib.image.io.png;
9 import std.path : setExtension;
10 import std.stdio;
11 import std..string;
12 import std.range : zip;
13 import voxelman.math;
14 import voxelman.graphics;
15 import voxelman.graphics.image.crop;
16 
17 SpriteRef loadSprite(string filename, TextureAtlas texAtlas)
18 {
19 	string imageFilename = setExtension(filename, "png");
20 	auto image = new Bitmap(loadPNG(imageFilename));
21 	irect atlasRect = putSpriteIntoAtlas(image, irect(0,0,image.width, image.height), texAtlas);
22 	return new Sprite(atlasRect);
23 }
24 
25 SpriteRef[string] loadNamedSpriteSheet(string filename, TextureAtlas texAtlas, ivec2 spriteSize)
26 {
27 	string descriptionFilename = setExtension(filename, "txt");
28 	auto file = File(descriptionFilename);
29 
30 	SpriteRef[] spriteArray = loadIndexedSpriteSheet(filename, texAtlas, spriteSize);
31 	size_t spriteIndex;
32 
33 	SpriteRef[string] spriteMap;
34 	foreach(nameValue; zip(file.byLineCopy(), spriteArray))
35 	{
36 		spriteMap[strip(nameValue[0])] = nameValue[1];
37 	}
38 
39 	return spriteMap;
40 }
41 
42 SpriteRef[] loadIndexedSpriteSheet(string filename, TextureAtlas texAtlas, ivec2 spriteSize)
43 {
44 	string imageFilename = setExtension(filename, "png");
45 	auto image = new Bitmap(loadPNG(imageFilename));
46 
47 	SpriteRef[] sprites;
48 	size_t spriteIndex;
49 
50 	ivec2 imageSize = ivec2(image.width, image.height);
51 	ivec2 gridSize = imageSize / spriteSize;
52 	sprites.length = gridSize.x * gridSize.y;
53 
54 	foreach(j; 0..gridSize.y)
55 	foreach(i; 0..gridSize.x)
56 	{
57 		irect spriteSubRect = irect(ivec2(i,j) * spriteSize, spriteSize);
58 		cropImage(image, spriteSubRect.position, spriteSubRect.size);
59 
60 		irect atlasRect = putSpriteIntoAtlas(image, spriteSubRect, texAtlas);
61 		sprites[spriteIndex++] = new Sprite(atlasRect);
62 	}
63 
64 	return sprites;
65 }
66 
67 irect putSpriteIntoAtlas(Bitmap sourceBitmap, irect spriteRect, TextureAtlas texAtlas)
68 {
69 	ivec2 position = texAtlas.insert(sourceBitmap, spriteRect);
70 	return irect(position, spriteRect.size);
71 }
72 
73 struct Sprite
74 {
75 	irect atlasRect;
76 }
77 
78 alias SpriteRef = Sprite*;
79 
80 struct SpriteInstance
81 {
82 	SpriteRef sprite;
83 
84 	vec2 scale = vec2(1, 1);
85 	vec2 origin = vec2(0, 0);
86 }