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  * There are four global states that can be applied to the drawn objects:
27  * $(UL
28  * $(LI the blend mode: how pixels of the object are blended with the
29  * background)
30  * $(LI the transform: how the object is positioned/rotated/scaled)
31  * $(LI the texture: what image is mapped to the object)
32  * $(LI the shader: what custom effect is applied to the object))
33  *
34  * High-level objects such as sprites or text force some of these states when
35  * they are drawn. For example, a sprite will set its own texture, so that you
36  * don't have to care about it when drawing the sprite.
37  *
38  * The transform is a special case: sprites, texts and shapes (and it's a good
39  * idea to do it with your own drawable classes too) combine their transform
40  * with the one that is passed in the RenderStates structure. So that you can
41  * use a "global" transform on top of each object's transform.
42  *
43  * Most objects, especially high-level drawables, can be drawn directly without
44  * defining render states explicitely – the default set of states is ok in most
45  * cases.
46  * ---
47  * RenderWindow window;
48  * Sprite sprite;
49  *
50  * ...
51  *
52  * window.draw(sprite);
53  * ---
54  *
55  * $(PARA If you want to use a single specific render state, for example a
56  * shader, you can construct a $(U RenderStates) object from it:)
57  * ---
58  * auto states = RenderStates(shader)
59  * window.draw(sprite, states);
60  *
61  * //or
62  * window.draw(sprite, RenderStates(shader));
63  * ---
64  *
65  * $(PARA When you're inside the `draw` function of a drawable object (inherited
66  * from $(DRAWABLE_LINK)), you can either pass the render states unmodified, or
67  * change some of them. For example, a transformable object will combine the
68  * current transform with its own transform. A sprite will set its texture.
69  * Etc.)
70  *
71  * See_Also:
72  * $(RENDERTARGET_LINK), $(DRAWABLE_LINK)
73  */
74 module dsfml.graphics.renderstates;
75 
76 import dsfml.graphics.blendmode;
77 import dsfml.graphics.transform;
78 import dsfml.graphics.texture;
79 import dsfml.graphics.shader;
80 import std.typecons:Rebindable;
81 
82 /**
83  * Define the states used for drawing to a RenderTarget.
84  */
85 struct RenderStates
86 {
87     /// The blending mode.
88     BlendMode blendMode;
89     /// The transform.
90     Transform transform;
91     private
92     {
93         Rebindable!(const(Texture)) m_texture;
94         Rebindable!(const(Shader)) m_shader;
95     }
96 
97     /**
98      * Construct a default set of render states with a custom blend mode.
99      *
100      * Params:
101      *	theBlendMode = Blend mode to use
102      */
103     this(BlendMode theBlendMode)
104     {
105         blendMode = theBlendMode;
106         transform = Transform();
107 
108         m_texture = null;
109         m_shader = null;
110 
111     }
112 
113     /**
114      * Construct a default set of render states with a custom transform.
115      *
116      * Params:
117      *	theTransform = Transform to use
118      */
119     this(Transform theTransform)
120     {
121         transform = theTransform;
122 
123         blendMode = BlendMode.Alpha;
124 
125         m_texture = null;
126         m_shader = null;
127     }
128 
129     /**
130      * Construct a default set of render states with a custom texture
131      *
132      * Params:
133      *	theTexture = Texture to use
134      */
135     this(const(Texture) theTexture)
136     {
137         m_texture = theTexture;
138 
139         blendMode = BlendMode.Alpha;
140 
141         transform = Transform();
142         m_shader = null;
143     }
144 
145     /**
146      * Construct a default set of render states with a custom shader
147      *
148      * Params:
149      * theShader = Shader to use
150      */
151     this(const(Shader) theShader)
152     {
153         m_shader = theShader;
154     }
155 
156     /**
157      * Construct a set of render states with all its attributes
158      *
159      * Params:
160      *	theBlendMode = Blend mode to use
161      *	theTransform = Transform to use
162      *	theTexture   = Texture to use
163      *	theShader    = Shader to use
164      */
165     this(BlendMode theBlendMode, Transform theTransform, const(Texture) theTexture, const(Shader) theShader)
166     {
167         blendMode = theBlendMode;
168         transform = theTransform;
169         m_texture = theTexture;
170         m_shader = theShader;
171     }
172 
173     @property
174     {
175         /// The shader to apply while rendering.
176         const(Shader) shader(const(Shader) theShader)
177         {
178             m_shader = theShader;
179             return theShader;
180         }
181         /// ditto
182         const(Shader) shader()
183         {
184             return m_shader;
185         }
186     }
187 
188     @property
189     {
190         /// The texture to apply while rendering.
191         const(Texture) texture(const(Texture) theTexture)
192         {
193             m_texture = theTexture;
194             return theTexture;
195         }
196         /// ditto
197         const(Texture) texture()
198         {
199             return m_texture;
200         }
201     }
202 }