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  * This class inherits all the functions of $(TRANSFORMABLE_LINK) (position,
30  * rotation, scale, bounds, ...) as well as the functions of $(SHAPE_LINK)
31  * (outline, color, texture, ...).
32  *
33  * It is important to keep in mind that a convex shape must always be... convex,
34  * otherwise it may not be drawn correctly. Moreover, the points must be defined
35  * in order; using a random order would result in an incorrect shape.
36  *
37  * Example:
38  * ---
39  * auto polygon = new ConvexShape();
40  * polygon.pointCount = 3;
41  * polygon.setPoint(0, Vector2f(0, 0));
42  * polygon.setPoint(1, Vector2f(0, 10));
43  * polygon.setPoint(2, Vector2f(25, 5));
44  * polygon.outlineColor = Color.Red;
45  * polygon.outlineThickness = 5;
46  * polygon.position = Vector2f(10, 20);
47  * ...
48  * window.draw(polygon);
49  * ---
50  *
51  * See_Also:
52  * $(SHAPE_LINK), $(RECTANGLESHAPE_LINK), $(CIRCLESHAPE_LINK)
53  */
54 module dsfml.graphics.convexshape;
55 
56 import dsfml.system.vector2;
57 import dsfml.graphics.shape;
58 
59 /**
60  * Specialized shape representing a convex polygon.
61  */
62 class ConvexShape : Shape
63 {
64     private Vector2f[] m_points;
65 
66     /**
67      * Default constructor.
68      *
69      * Params:
70      * thePointCount = Number of points on the polygon
71      */
72     this(uint thePointCount = 0)
73     {
74         this.pointCount = thePointCount;
75         update();
76     }
77 
78     /// Destructor.
79     ~this()
80     {
81         import dsfml.system.config;
82         mixin(destructorOutput);
83     }
84 
85     @property
86     {
87         /// The number of points on the polygon
88         uint pointCount(uint newPointCount)
89         {
90             m_points.length = newPointCount;
91             update();
92             return newPointCount;
93         }
94 
95         /// ditto
96         override uint pointCount() const
97         {
98             import std.algorithm;
99             return cast(uint)min(m_points.length, uint.max);
100         }
101     }
102 
103     /**
104      * Get the position of a point.
105      *
106      * The result is undefined if index is out of the valid range.
107      *
108      * Params:
109      * 		index =	Index of the point to get, in range [0 .. `pointCount` - 1]
110      *
111      * Returns: Index-th point of the shape.
112      */
113     override Vector2f getPoint(uint index) const
114     {
115         return m_points[index];
116     }
117 
118     /**
119      * Set the position of a point.
120      *
121      * Don't forget that the polygon must remain convex, and the points need to
122      * stay ordered! `pointCount` must be changed first in order to set the total
123      * number of points. The result is undefined if index is out of the valid
124      *range.
125      *
126      * Params:
127      * 		index =	Index of the point to change, in range
128                     [0 .. `pointCount` - 1]
129      * 		point =	New position of the point
130      */
131     void setPoint(uint index, Vector2f point)
132     {
133         m_points[index] = point;
134     }
135 
136     /**
137      * Add a point to the polygon.
138      *
139      * Don't forget that the polygon must remain convex, and the points need to
140      * stay ordered!
141      *
142      * Params:
143      * 		point =	Position of the new point.
144      */
145     void addPoint(Vector2f point)
146     {
147         m_points ~=point;
148         update();
149     }
150 }
151 
152 unittest
153 {
154     version(DSFML_Unittest_Graphics)
155     {
156         import std.stdio;
157         import dsfml.graphics;
158 
159         writeln("Unit test for ConvexShape");
160         auto window = new RenderWindow(VideoMode(800,600), "ConvexShape unittest");
161 
162         auto convexShape = new ConvexShape();
163 
164         convexShape.addPoint(Vector2f(0,20));
165         convexShape.addPoint(Vector2f(10,10));
166         convexShape.addPoint(Vector2f(20,20));
167         convexShape.addPoint(Vector2f(20,30));
168         convexShape.addPoint(Vector2f(10,40));
169         convexShape.addPoint(Vector2f(0,30));
170 
171         convexShape.fillColor = Color.Blue;
172 
173         convexShape.outlineColor = Color.Green;
174 
175         auto clock = new Clock();
176 
177         while(window.isOpen())
178         {
179             Event event;
180 
181             while(window.pollEvent(event))
182             {
183                 //no events gonna do stuffs!
184             }
185 
186             //draws the shape for a while before closing the window
187             if(clock.getElapsedTime().asSeconds() > 1)
188             {
189                 window.close();
190             }
191 
192             window.clear();
193             window.draw(convexShape);
194             window.display();
195         }
196 
197         writeln();
198     }
199 }