1 /*sprite.d by Ruby The Roobster*/
2 /*Version 1.0.0 Release*/
3 /*Last Update: 08/23/2021*/
4 /*Module for sprites in the D Programming Language 2.0*/
5 /*This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program.  If not, see <http://www.gnu.org/licenses/>.*/
17 
18 /** Copyright: 2021, Ruby The Roobster*/
19 /**Author: Ruby The Roobster, michaeleverestc79@gmail.com*/
20 /**Date: October 1, 2021*/
21 /** License:  GPL-3.0**/
22 module dutils.sprite;
23 public import dutils.skeleton : Point;
24 /**This data structure represents colors in the RGBA format.*/
25 public struct Color	{
26 	///'R' value of the color.
27 	ubyte r = 0;
28 	///'G' value of the color.
29 	ubyte g = 0;
30 	///'B' value of the color.
31 	ubyte b = 0;
32 	///'A' value of the color.
33 	ubyte a = 255;
34 	void opAssign(Color rhs)	{
35 		this.r = rhs.r;
36 		this.g = rhs.g;
37 		this.b = rhs.b;
38 		this.a = rhs.a;
39 	}
40 }
41 /**This data structure represents a sprite that would be painted over a face from dutils:skeleton*/
42 public struct Sprite	{
43 	///The array of colors that are used within the Sprite.
44 	Color[] colors;
45 	///A two-demensional array of the points corresponding to each color.
46 	Point[][] points;
47 	invariant()	{
48 		assert(colors.length == points.length, "Assertion failure: Sprite.colors.length and Sprite.points.length must always be equal...");
49 	}
50 	void opAssign(Sprite rhs)	{
51 		this.colors.length = rhs.colors.length;
52 		this.points.length = rhs.points.length;
53 		foreach(i;0 .. this.colors.length)	{
54 			this.colors[i] = rhs.colors[i];
55 		}
56 		foreach(i;0 .. this.points.length)	{
57 			this.points[i].length = rhs.points[i].length;
58 			foreach(j;0 .. this.points[i].length)	{
59 				this.points[i][j] = rhs.points[i][j];
60 			}
61 		}
62 	}
63 }
64 
65   /**ReadSpriteFromFile reads a file in .spr format and outputs a new 'Sprite" object from it.
66   Params:
67   filename =		The name of the file to read the sprite from.
68   Returns:  A new 'Sprite' object interpreted from the file.*/
69 public Sprite ReadSpriteFromFile(immutable(char)[] filename)	{ //Reads a sprite in my made up .spr format(trash, why does this even exist)
70 	ubyte[] ftext;
71 	Color[] colors;
72 	Point[][] points;
73 	import std.file;
74 	ftext = cast(ubyte[])read(filename);
75 	for(uint i = 0;i < ftext.length;i++)	{ //Parse the file...
76 		long main;
77 		short exp;
78 		uint x = 0;
79 		++colors.length;
80 		++points.length;
81 		colors[x].r = ftext[i]; //Set r color...
82 		++i;
83 		colors[x].g = ftext[i];
84 		++i;
85 		colors[x].b = ftext[i];
86 		++i;
87 		colors[x].a = ftext[i];
88 		++i;
89 		ubyte tempcolor = ftext[i];
90 		++i;
91 		long temp;
92 		for(ubyte j = 0;j < tempcolor; ++j)	{
93 			posfunc(ftext, main, exp, temp, i, j, points , x);
94 		}
95 	}
96 	return Sprite(colors, points);
97 }
98 	
99 package void posfunc(const ubyte[] ftext, ref long main, ref short exp, ref long temp, ref uint i, const ubyte j, ref Point[][] points, ref uint x)	{
100 	++points[x].length;
101 	foreach(z;0 .. 3)	{
102 		short shift = 56;
103 		main = ftext[i];
104 		main <<= shift;
105 		++i;
106 		shift -= 8;
107 		while(shift >= 0)	{
108 			temp = ftext[i];
109 			main = (main <= (-0)) ? (main - temp) : (main + temp);
110 			++i;
111 			shift -= 8;
112 		}
113 		exp = ftext[i];
114 		exp <<= 8;	
115 		++i;
116 		exp += ftext[i];
117 		++i;
118 		switch(z)	{
119 			case 0:
120 				points[x][j].x = (main * 10^^exp);
121 				break;
122 			case 1:
123 				points[x][j].y = (main * 10^^exp);
124 				break;
125 			case 2:
126 				points[x][j].z = (main * 10^^exp);
127 				break;
128 			default:
129 				assert(false); //bruh...
130 		}		}
131 }
132