mirror of https://github.com/mosra/magnum.git
2 changed files with 70 additions and 3 deletions
@ -0,0 +1,66 @@ |
|||||||
|
namespace Magnum { |
||||||
|
/** @page method-chaining Method chaining |
||||||
|
|
||||||
|
@brief Little feature helping to reduce typing and encourage best practices. |
||||||
|
|
||||||
|
Method chaining ([Wikipedia](http://en.wikipedia.org/wiki/Method_chaining)) is a |
||||||
|
feature which allows you to chain method calls one after another without |
||||||
|
repeatedly specifying variable the method is called on. Its primary goal is to |
||||||
|
reduce unnecessary repeated names, improving code readability. |
||||||
|
|
||||||
|
%Magnum uses this feature for configuring OpenGL objects (such as various mesh |
||||||
|
and framebuffer options, shader uniforms etc.). Because OpenGL was designed with |
||||||
|
"bind-to-modify" approach, most configuration calls need to bind the object |
||||||
|
first and only after that change the parameters (unless @extension{EXT,direct_state_access} |
||||||
|
extension is available to avoid this). To reduce unneeded bind calls, %Magnum |
||||||
|
binds the object only if it is not already bound somewhere. Method chaining |
||||||
|
encourages you to configure whole object in one run, effectively reducing the |
||||||
|
number of needed bindings. Consider the following example: |
||||||
|
@code |
||||||
|
Texture2D *carDiffuseTexture, *carSpecularTexture, *carBumpTexture; |
||||||
|
|
||||||
|
carDiffuseTexture->setStorage(5, Texture2D::InternalFormat::SRGB8); |
||||||
|
carSpecularTexture->setStorage(3, Texture2D::InternalFormat::R8); |
||||||
|
carBumpTexture->setStorage(5, Texture2D::InternalFormat::RGB8); |
||||||
|
carDiffuseTexture->setSubImage(0, {}, diffuse); |
||||||
|
carSpecularTexture->setSubImage(0, {}, specular; |
||||||
|
carBumpTexture->setSubImage(0, {}, bump); |
||||||
|
carDiffuseTexture->generateMipmap(); |
||||||
|
carSpecularTexture->generateMipmap(); |
||||||
|
carBumpTexture->generateMipmap(); |
||||||
|
@endcode |
||||||
|
|
||||||
|
This code is written that similar configuration steps are grouped together, |
||||||
|
which might be good when somebody needs to change something for all three |
||||||
|
textures at once, but on the other hand the code is cluttered with repeated |
||||||
|
names and after each configuration step the texture must be rebound to another. |
||||||
|
With method chaining used the code looks much lighter and each object is |
||||||
|
configured in one run, reducing count of bind calls from 9 to 3. |
||||||
|
@code |
||||||
|
carDiffuseTexture->setStorage(5, Texture2D::InternalFormat::SRGB8) |
||||||
|
->setSubImage(0, {}, diffuse) |
||||||
|
->generateMipmap(); |
||||||
|
carSpecularTexture->setStorage(3, Texture2D::InternalFormat::R8) |
||||||
|
->setSubImage(0, {}, diffuse) |
||||||
|
->generateMipmap(); |
||||||
|
carBumpTexture->setStorage(5, Texture2D::InternalFormat::RGB8) |
||||||
|
->setSubImage(0, {}, bump) |
||||||
|
->generateMipmap(); |
||||||
|
@endcode |
||||||
|
|
||||||
|
Method chaining is not used on non-configuring functions, such as Framebuffer::clear() |
||||||
|
or Mesh::draw(), as these won't be commonly used in conjunction with other |
||||||
|
functions anyway. |
||||||
|
|
||||||
|
Method chaining is also used in SceneGraph and other libraries and in some cases |
||||||
|
it allows you to just "configure and forget" without even saving the created |
||||||
|
object to some variable, for example when adding static object to an scene: |
||||||
|
@code |
||||||
|
Scene3D scene; |
||||||
|
|
||||||
|
(new MyObject(&scene)) |
||||||
|
->rotateX(90.0_degf) |
||||||
|
->translate({-1.5f, 0.5f, 7.0f}); |
||||||
|
@endcode |
||||||
|
*/ |
||||||
|
} |
||||||
Loading…
Reference in new issue