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 ///NOTICE:  THIS CODE OBVIOUSLY SUCKS.  IT WILL BE OUTRIGHT DELETED.
19 
20 
21 /** Copyright: 2021, Ruby The Roobster*/
22 /**Author: Ruby The Roobster, rubytheroobster@yandex.com*/
23 /**Date: October 1, 2021*/
24 /** License:  GPL-3.0**/
25 module dutils.sprite;
26 public import dutils.skeleton : Point;
27 /**This data structure represents colors in the RGBA format.*/
28 public struct Color	{
29 	///'R' value of the color.
30 	ubyte r = 0;
31 	///'G' value of the color.
32 	ubyte g = 0;
33 	///'B' value of the color.
34 	ubyte b = 0;
35 	///'A' value of the color.
36 	ubyte a = 255;
37 	void opAssign(Color rhs)	{
38 		this.r = rhs.r;
39 		this.g = rhs.g;
40 		this.b = rhs.b;
41 		this.a = rhs.a;
42 	}
43 }
44 /**This data structure represents a sprite that would be painted over a face from dutils:skeleton*/
45 public struct Sprite	{
46 	///The array of colors that are used within the Sprite.
47 	Color[] colors;
48 	///A two-demensional array of the points corresponding to each color.
49 	Point[][] points;
50 	invariant()	{
51 		assert(colors.length == points.length, "Assertion failure: Sprite.colors.length and Sprite.points.length must always be equal...");
52 	}
53 	void opAssign(Sprite rhs)	{
54 		this.colors.length = rhs.colors.length;
55 		this.points.length = rhs.points.length;
56 		foreach(i;0 .. this.colors.length)	{
57 			this.colors[i] = rhs.colors[i];
58 		}
59 		foreach(i;0 .. this.points.length)	{
60 			this.points[i].length = rhs.points[i].length;
61 			foreach(j;0 .. this.points[i].length)	{
62 				this.points[i][j] = rhs.points[i][j];
63 			}
64 		}
65 	}
66 }
67 
68   /**ReadSpriteFromFile reads a file in .spr format and outputs a new 'Sprite" object from it.
69   Params:
70   filename =		The name of the file to read the sprite from.
71   Returns:  A new 'Sprite' object interpreted from the file.*/
72 public Sprite ReadSpriteFromFile(immutable(char)[] filename)	{ //Reads a sprite in my made up .spr format(trash, why does this even exist)
73 	ubyte[] ftext;
74 	Color[] colors;
75 	Point[][] points;
76 	import std.file;
77 	ftext = cast(ubyte[])read(filename);
78 	for(uint i = 0;i < ftext.length;i++)	{ //Parse the file...
79 		long main;
80 		short exp;
81 		uint x = 0;
82 		++colors.length;
83 		++points.length;
84 		colors[x].r = ftext[i]; //Set r color...
85 		++i;
86 		colors[x].g = ftext[i];
87 		++i;
88 		colors[x].b = ftext[i];
89 		++i;
90 		colors[x].a = ftext[i];
91 		++i;
92 		ubyte tempcolor = ftext[i];
93 		++i;
94 		long temp;
95 		for(ubyte j = 0;j < tempcolor; ++j)	{
96 			posfunc(ftext, main, exp, temp, i, j, points , x);
97 		}
98 	}
99 	return Sprite(colors, points);
100 }
101 	
102 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)	{
103 	++points[x].length;
104 	foreach(z;0 .. 3)	{
105 		short shift = 56;
106 		main = ftext[i];
107 		main <<= shift;
108 		++i;
109 		shift -= 8;
110 		while(shift >= 0)	{
111 			temp = ftext[i];
112 			main = (main <= (-0)) ? (main - temp) : (main + temp);
113 			++i;
114 			shift -= 8;
115 		}
116 		exp = ftext[i];
117 		exp <<= 8;	
118 		++i;
119 		exp += ftext[i];
120 		++i;
121 		switch(z)	{
122 			case 0:
123 				points[x][j].x = (main * 10^^exp);
124 				break;
125 			case 1:
126 				points[x][j].y = (main * 10^^exp);
127 				break;
128 			case 2:
129 				points[x][j].z = (main * 10^^exp);
130 				break;
131 			default:
132 				assert(false); //bruh...
133 		}		}
134 }
135