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  * Example:
34  * ---
35  * auto circle = new CircleShape();
36  * circle.radius = 150;
37  * circle.outlineColor = Color.Red;
38  * circle.outlineThickness = 5;
39  * circle.position = Vector2f(10, 20);
40  * ...
41  * window.draw(circle);
42  * ---
43  *
44  *$(PARA Since the graphics card can't draw perfect circles, we have to fake
45  * them with multiple triangles connected to each other. The "points count"
46  * property of $(U CircleShape) defines how many of these triangles to use, and
47  * therefore defines the quality of the circle.)
48  *
49  * See_Also:
50  * $(SHAPE_LINK), $(RECTANGLESHAPE_LINK), $(CONVEXSHAPE_LINK)
51  */
52 module dsfml.graphics.circleshape;
53 
54 import dsfml.graphics.shape;
55 
56 import dsfml.system.vector2;
57 
58 /**
59  * Specialized shape representing a circle.
60  */
61 class CircleShape : Shape
62 {
63     private
64     {
65         // Radius of the circle
66         float m_radius;
67         /// Number of points composing the circle
68         uint m_pointCount;
69     }
70 
71     /**
72      * Default constructor.
73      *
74      * Params:
75      * 		radius =		Radius of the circle
76      * 		pointCount =	Number of points composing the circle
77     */
78     this(float radius = 0, uint pointCount = 30)
79     {
80         m_radius = radius;
81         m_pointCount = pointCount;
82 
83         update();
84     }
85 
86     /// Destructor
87     ~this()
88     {
89         import dsfml.system.config;
90         mixin(destructorOutput);
91     }
92 
93     @property
94     {
95         /// The number of points of the circle.
96         uint pointCount(uint newPointCount)
97         {
98             m_pointCount = newPointCount;
99             return newPointCount;
100         }
101 
102         /// ditto
103         override uint pointCount() const
104         {
105             return m_pointCount;
106         }
107     }
108 
109     @property
110     {
111         /// The radius of the circle.
112         float radius(float newRadius)
113         {
114             m_radius = newRadius;
115             update();
116             return newRadius;
117         }
118 
119         /// ditto
120         float radius() const
121         {
122             return m_radius;
123         }
124     }
125 
126     /**
127      * Get a point of the shape.
128      *
129      * The result is undefined if index is out of the valid range.
130      *
131      * Params:
132      * 		index =	Index of the point to get, in range [0 .. pointCount - 1].
133      *
134      * Returns: Index-th point of the shape.
135      */
136     override Vector2f getPoint(uint index) const
137     {
138         import std.math;
139         static const(float) pi = 3.141592654f;
140 
141         float angle = index * 2 * pi / m_pointCount - pi / 2;
142 
143         float x = cos(angle) * m_radius;
144         float y = sin(angle) * m_radius;
145 
146         return Vector2f(m_radius + x, m_radius + y);
147     }
148 
149     /// Clones this CircleShape
150     @property
151     CircleShape dup() const
152     {
153         CircleShape temp = new CircleShape(m_radius, m_pointCount);
154 
155         temp.position = position;
156         temp.rotation = rotation;
157         temp.scale = scale;
158         temp.origin = origin;
159 
160         return temp;
161     }
162 }
163 
164 unittest
165 {
166     version(DSFML_Unittest_Graphics)
167     {
168         import std.stdio;
169         import dsfml.graphics;
170 
171         writeln("Unit test for CircleShape");
172         auto window = new RenderWindow(VideoMode(800,600), "CircleShape unittest");
173 
174         auto circleShape = new CircleShape(20);
175 
176         circleShape.fillColor = Color.Blue;
177 
178         circleShape.outlineColor = Color.Green;
179 
180         auto clock = new Clock();
181 
182 
183         while(window.isOpen())
184         {
185             Event event;
186 
187             while(window.pollEvent(event))
188             {
189                 //no events gonna do stuffs!
190             }
191 
192             //draws the shape for a while before closing the window
193             if(clock.getElapsedTime().asSeconds() > 1)
194             {
195                 window.close();
196             }
197 
198             window.clear();
199             window.draw(circleShape);
200             window.display();
201         }
202 
203         writeln();
204     }
205 }