1 /* 2 * DSFML - The Simple and Fast Multimedia Library for D 3 * 4 * Copyright (c) 2013 - 2017 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 8 * use of this software. 9 * 10 * Permission is granted to anyone to use this software for any purpose, 11 * including commercial applications, and to alter it and redistribute it 12 * freely, subject to the following restrictions: 13 * 14 * 1. The origin of this software must not be misrepresented; you must not claim 15 * that you wrote the original software. If you use this software in a product, 16 * an acknowledgment in the product documentation would be appreciated but is 17 * not required. 18 * 19 * 2. Altered source versions must be plainly marked as such, and must not be 20 * misrepresented as being the original software. 21 * 22 * 3. This notice may not be removed or altered from any source distribution 23 */ 24 25 /** 26 * $(U VertexArray) is a very simple wrapper around a dynamic array of vertices 27 *and a primitives type. 28 * 29 * It inherits $(DRAWABLE_LINK), but unlike other drawables it is not 30 * transformable. 31 * 32 * Example: 33 * --- 34 * VertexArray lines(PrimitiveType.LineStrip, 4); 35 * lines[0].position = Vector2f(10, 0); 36 * lines[1].position = Vector2f(20, 0); 37 * lines[2].position = Vector2f(30, 5); 38 * lines[3].position = Vector2f(40, 2); 39 * 40 * window.draw(lines); 41 * --- 42 * 43 * See_Also: 44 * $(VERTEX_LINK) 45 */ 46 module dsfml.graphics.vertexarray; 47 48 import dsfml.graphics.vertex; 49 import dsfml.graphics.primitivetype; 50 import dsfml.graphics.rect; 51 import dsfml.graphics.drawable; 52 import dsfml.graphics.rendertarget; 53 import dsfml.graphics.renderstates; 54 55 import dsfml.system.vector2; 56 57 /** 58 * Define a set of one or more 2D primitives. 59 */ 60 class VertexArray : Drawable 61 { 62 /** 63 * The type of primitive to draw. 64 * 65 * Can be any of the following: 66 * - Points 67 * - Lines 68 * - Triangles 69 * - Quads 70 * 71 * The default primitive type is Points. 72 */ 73 PrimitiveType primitiveType; 74 private Vertex[] Vertices; 75 76 /** 77 * Default constructor 78 * 79 * Creates an empty vertex array. 80 */ 81 this() 82 { 83 } 84 85 /** 86 * Construct the vertex array with a type and an initial number of vertices 87 * 88 * Params: 89 * type = Type of primitives 90 * vertexCount = Initial number of vertices in the array 91 */ 92 this(PrimitiveType type, uint vertexCount) 93 { 94 primitiveType = type; 95 Vertices = new Vertex[vertexCount]; 96 } 97 98 private this(PrimitiveType type, Vertex[] vertices) 99 { 100 primitiveType = type; 101 Vertices = vertices; 102 } 103 104 /// Destructor. 105 ~this() 106 { 107 import dsfml.system.config; 108 mixin(destructorOutput); 109 } 110 111 /** 112 * Compute the bounding rectangle of the vertex array. 113 * 114 * This function returns the axis-aligned rectangle that contains all the 115 * vertices of the array. 116 * 117 * Returns: Bounding rectangle of the vertex array. 118 */ 119 FloatRect getBounds() 120 { 121 if (Vertices.length>0) 122 { 123 float left = Vertices[0].position.x; 124 float top = Vertices[0].position.y; 125 float right = Vertices[0].position.x; 126 float bottom = Vertices[0].position.y; 127 128 for (size_t i = 1; i < Vertices.length; ++i) 129 { 130 Vector2f position = Vertices[i].position; 131 132 // Update left and right 133 if (position.x < left) 134 left = position.x; 135 else if (position.x > right) 136 right = position.x; 137 138 // Update top and bottom 139 if (position.y < top) 140 top = position.y; 141 else if (position.y > bottom) 142 bottom = position.y; 143 } 144 145 return FloatRect(left, top, right - left, bottom - top); 146 } 147 else 148 { 149 return FloatRect(0,0,0,0); 150 } 151 } 152 153 /** 154 * Return the vertex count. 155 * 156 * Returns: Number of vertices in the array 157 */ 158 uint getVertexCount() 159 { 160 import std.algorithm; 161 return cast(uint)min(uint.max, Vertices.length); 162 } 163 164 /** 165 * Add a vertex to the array. 166 * 167 * Params: 168 * vertex = Vertex to add. 169 */ 170 void append(Vertex newVertex) 171 { 172 Vertices ~= newVertex; 173 } 174 175 /** 176 * Clear the vertex array. 177 * 178 * This function removes all the vertices from the array. It doesn't 179 * deallocate the corresponding memory, so that adding new vertices after 180 * clearing doesn't involve reallocating all the memory. 181 */ 182 void clear() 183 { 184 Vertices.length = 0; 185 } 186 187 /** 188 * Draw the object to a render target. 189 * 190 * Params: 191 * renderTarget = Render target to draw to 192 * renderStates = Current render states 193 */ 194 override void draw(RenderTarget renderTarget, RenderStates renderStates) 195 { 196 if(Vertices.length != 0) 197 { 198 renderTarget.draw(Vertices, primitiveType,renderStates); 199 } 200 } 201 202 /** 203 * Resize the vertex array. 204 * 205 * If vertexCount is greater than the current size, the previous vertices 206 * are kept and new (default-constructed) vertices are added. If vertexCount 207 * is less than the current size, existing vertices are removed from the 208 * array. 209 * 210 * Params: 211 * vertexCount = New size of the array (number of vertices). 212 */ 213 void resize(uint length) 214 { 215 Vertices.length = length; 216 } 217 218 /** 219 * Get a read-write access to a vertex by its index 220 * 221 * This function doesn't check index, it must be in range 222 * [0, getVertexCount() - 1]. The behavior is undefined otherwise. 223 * 224 * Params: 225 * index = Index of the vertex to get 226 * 227 * Returns: Reference to the index-th vertex. 228 */ 229 ref Vertex opIndex(size_t index) 230 { 231 return Vertices[index]; 232 } 233 } 234 235 unittest 236 { 237 version(DSFML_Unittest_Graphics) 238 { 239 import std.stdio; 240 import dsfml.graphics.texture; 241 import dsfml.graphics.rendertexture; 242 import dsfml.graphics.color; 243 244 writeln("Unit test for VertexArray"); 245 246 auto texture = new Texture(); 247 248 assert(texture.loadFromFile("res/TestImage.png")); 249 250 251 252 auto dimensions = FloatRect(0,0,texture.getSize().x,texture.getSize().y); 253 254 auto vertexArray = new VertexArray(PrimitiveType.Quads, 0); 255 256 //Creates a vertex array at position (0,0) the width and height of the loaded texture 257 vertexArray.append(Vertex(Vector2f(dimensions.left,dimensions.top), Color.Blue, Vector2f(dimensions.left,dimensions.top))); 258 vertexArray.append(Vertex(Vector2f(dimensions.left,dimensions.height), Color.Blue, Vector2f(dimensions.left,dimensions.height))); 259 vertexArray.append(Vertex(Vector2f(dimensions.width,dimensions.height), Color.Blue, Vector2f(dimensions.width,dimensions.height))); 260 vertexArray.append(Vertex(Vector2f(dimensions.width,dimensions.top), Color.Blue, Vector2f(dimensions.width,dimensions.top))); 261 262 263 auto renderStates = RenderStates(texture); 264 265 266 auto renderTexture = new RenderTexture(); 267 268 renderTexture.create(100,100); 269 270 renderTexture.clear(); 271 272 //draw the VertexArray with the texture we loaded 273 renderTexture.draw(vertexArray, renderStates); 274 275 renderTexture.display(); 276 277 writeln(); 278 } 279 }