mirror of https://github.com/mosra/magnum.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
66 lines
2.9 KiB
66 lines
2.9 KiB
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 |
|
*/ |
|
}
|
|
|