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