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 import dutils.skeleton : Point;
24 /**Struct Color:  This data structure represents colors in the RGBA format.*/
25 public struct Color	{
26 	///Color.r is the 'R' value of the color.
27 	ubyte r = 0;
28 	///Color.g is the 'G' value of the color.
29 	ubyte g = 0;
30 	///Color.b is the 'B' value of the color.
31 	ubyte b = 0;
32 	//Color.a is the '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 /**Struct Sprite:  This data structure represents a sprite that would be painted over a face from dutils:skeleton*/
42 public struct Sprite	{
43 	///Sprite.colors is the array of colors that are used within the Sprite.
44 	Color[] colors;
45 	///Sprite.points is 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 */
70 public Sprite ReadSpriteFromFile(immutable(char)[] filename)	{ //Reads a sprite in my made up .spr format(trash, why does this even exist)
71 	ubyte[] ftext;
72 	Color[] colors;
73 	Point[][] points;
74 	import std.file;
75 	ftext = cast(ubyte[])read(filename);
76 	for(uint i = 0;i < ftext.length;i++)	{ //Parse the file...
77 		long main;
78 		short exp;
79 		uint x = 0;
80 		++colors.length;
81 		++points.length;
82 		colors[x].r = ftext[i]; //Set r color...
83 		++i;
84 		colors[x].g = ftext[i];
85 		++i;
86 		colors[x].b = ftext[i];
87 		++i;
88 		colors[x].a = ftext[i];
89 		++i;
90 		ubyte tempcolor = ftext[i];
91 		++i;
92 		long temp;
93 		for(ubyte j = 0;j < tempcolor; ++j)	{
94 			posfunc(ftext, main, exp, temp, i, j, points , x);
95 		}
96 	}
97 	return Sprite(colors, points);
98 }
99 	
100 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)	{
101 	++points[x].length;
102 	foreach(z;0 .. 3)	{
103 		short shift = 56;
104 		main = ftext[i];
105 		main <<= shift;
106 		++i;
107 		shift -= 8;
108 		while(shift >= 0)	{
109 			temp = ftext[i];
110 			main = (main <= (-0)) ? (main - temp) : (main + temp);
111 			++i;
112 			shift -= 8;
113 		}
114 		exp = ftext[i];
115 		exp <<= 8;	
116 		++i;
117 		exp += ftext[i];
118 		++i;
119 		switch(z)	{
120 			case 0:
121 				points[x][j].x = (main * 10^^exp);
122 				break;
123 			case 1:
124 				points[x][j].y = (main * 10^^exp);
125 				break;
126 			case 2:
127 				points[x][j].z = (main * 10^^exp);
128 				break;
129 			default:
130 				assert(false); //bruh...
131 		}		}
132 }