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