1 /*
2 DSFML - The Simple and Fast Multimedia Library for D
3 
4 Copyright (c) 2013 - 2015 Jeremy DeHaan (dehaan.jeremiah@gmail.com)
5 
6 This software is provided 'as-is', without any express or implied warranty.
7 In no event will the authors be held liable for any damages arising from the use of this software.
8 
9 Permission is granted to anyone to use this software for any purpose, including commercial applications,
10 and to alter it and redistribute it freely, subject to the following restrictions:
11 
12 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software.
13 If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
14 
15 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
16 
17 3. This notice may not be removed or altered from any source distribution
18 */
19 
20 module dsfml.graphics.vertexarray;
21 
22 import dsfml.graphics.vertex;
23 import dsfml.graphics.primitivetype;
24 import dsfml.graphics.rect;
25 import dsfml.graphics.drawable;
26 import dsfml.graphics.rendertarget;
27 import dsfml.graphics.renderstates;
28 
29 import dsfml.system.vector2;
30 
31 /++
32  + Define a set of one or more 2D primitives.
33  + 
34  + VertexArray is a very simple wrapper around a dynamic array of vertices and a primitives type.
35  + 
36  + It inherits Drawable, but unlike other drawables it is not transformable.
37  + 
38  + Authors: Laurent Gomila, Jeremy DeHaan
39  + See_Also: http://www.sfml-dev.org/documentation/2.0/classsf_1_1VertexArray.php#details
40  +/
41 class VertexArray : Drawable
42 {
43 	/**
44 	 * The type of primitive to draw.
45 	 * 
46 	 * Can be any of the following:
47 	 * - Points
48 	 * - Lines
49 	 * - Triangles
50 	 * - Quads
51 	 * 
52 	 * The default primitive type is Points.
53 	 */
54 	PrimitiveType primitiveType;
55 	private Vertex[] Vertices;
56 
57 	this(PrimitiveType type, uint vertexCount)
58 	{
59 		primitiveType = type;
60 		Vertices = new Vertex[vertexCount];
61 	}
62 	
63 	private this(PrimitiveType type, Vertex[] vertices)
64 	{
65 		primitiveType = type;
66 		Vertices = vertices;
67 	}
68 	
69 	~this()
70 	{
71 		import dsfml.system.config;
72 		mixin(destructorOutput);
73 	}
74 
75 	/**
76 	 * Compute the bounding rectangle of the vertex array.
77 	 * 
78 	 * This function returns the axis-aligned rectangle that contains all the vertices of the array.
79 	 * 
80 	 * Returns: Bounding rectangle of the vertex array.
81 	 */
82 	FloatRect getBounds()
83 	{
84 		if (Vertices.length>0)
85 		{
86 			float left = Vertices[0].position.x;
87 			float top = Vertices[0].position.y;
88 			float right = Vertices[0].position.x;
89 			float bottom = Vertices[0].position.y;
90 			
91 			for (size_t i = 1; i < Vertices.length; ++i)
92 			{
93 				Vector2f position = Vertices[i].position;
94 				
95 				// Update left and right
96 				if (position.x < left)
97 					left = position.x;
98 				else if (position.x > right)
99 					right = position.x;
100 				
101 				// Update top and bottom
102 				if (position.y < top)
103 					top = position.y;
104 				else if (position.y > bottom)
105 					bottom = position.y;
106 			}
107 			
108 			return FloatRect(left, top, right - left, bottom - top);
109 		}
110 		else
111 		{
112 			return FloatRect(0,0,0,0);
113 		}
114 	}
115 
116 	/**
117 	 * Return the vertex count.
118 	 * 
119 	 * Returns: Number of vertices in the array
120 	 */
121 	uint getVertexCount()
122 	{
123 		import std.algorithm;
124 		return cast(uint)min(uint.max, Vertices.length);
125 	}
126 
127 	/**
128 	 * Add a vertex to the array.
129 	 * 
130 	 * Params:
131 	 * 		vertex	= Vertex to add.
132 	 */
133 	void append(Vertex newVertex)
134 	{
135 		Vertices ~= newVertex;
136 	}
137 
138 	/**
139 	 * Clear the vertex array.
140 	 * 
141 	 * This function removes all the vertices from the array. It doesn't deallocate the corresponding memory, so that adding new vertices after clearing doesn't involve reallocating all the memory.
142 	 */
143 	void clear()
144 	{
145 		Vertices.length = 0;
146 	}
147 
148 	/**
149 	 * Draw the object to a render target.
150 	 * 
151 	 * Params:
152 	 *  		renderTarget =	Render target to draw to
153 	 *  		renderStates =	Current render states
154 	 */
155 	override void draw(RenderTarget renderTarget, RenderStates renderStates)
156 	{
157 		if(Vertices.length != 0)
158 		{
159 			renderTarget.draw(Vertices, primitiveType,renderStates);
160 		}
161 	}
162 
163 	/**
164 	 * Resize the vertex array.
165 	 * 
166 	 * If vertexCount is greater than the current size, the previous vertices are kept and new (default-constructed) vertices are added. If vertexCount is less than the current size, existing vertices are removed from the array.
167 	 * 
168 	 * Params:
169 	 * 		vertexCount	= New size of the array (number of vertices).
170 	 */
171 	void resize(uint length)
172 	{
173 		Vertices.length = length;
174 	}
175 
176 	ref Vertex opIndex(size_t index)
177 	{
178 		return Vertices[index];
179 	}
180 }
181 
182 unittest
183 {
184 	version(DSFML_Unittest_Graphics)
185 	{
186 		import std.stdio;
187 		import dsfml.graphics.texture;
188 		import dsfml.graphics.rendertexture;
189 		import dsfml.graphics.color;
190 
191 		writeln("Unit test for VertexArray");
192 
193 		auto texture = new Texture();
194 
195 		assert(texture.loadFromFile("res/TestImage.png"));
196 
197 
198 
199 		auto dimensions = FloatRect(0,0,texture.getSize().x,texture.getSize().y);
200 
201 		auto vertexArray = new VertexArray(PrimitiveType.Quads, 0);
202 
203 		//Creates a vertex array at position (0,0) the width and height of the loaded texture
204 		vertexArray.append(Vertex(Vector2f(dimensions.left,dimensions.top), Color.Blue, Vector2f(dimensions.left,dimensions.top)));
205 		vertexArray.append(Vertex(Vector2f(dimensions.left,dimensions.height), Color.Blue, Vector2f(dimensions.left,dimensions.height)));
206 		vertexArray.append(Vertex(Vector2f(dimensions.width,dimensions.height), Color.Blue, Vector2f(dimensions.width,dimensions.height)));
207 		vertexArray.append(Vertex(Vector2f(dimensions.width,dimensions.top), Color.Blue, Vector2f(dimensions.width,dimensions.top)));
208 
209 
210 		auto renderStates = RenderStates(texture);
211 
212 
213 		auto renderTexture = new RenderTexture();
214 		
215 		renderTexture.create(100,100);
216 
217 		renderTexture.clear();
218 
219 		//draw the VertexArray with the texture we loaded
220 		renderTexture.draw(vertexArray, renderStates);
221 
222 		renderTexture.display();
223 
224 		writeln();
225 	}
226 }