Skip to content

Chaining DeviceContext methods together

MWstudios edited this page Aug 26, 2021 · 4 revisions

How to do it

Aside from the extensions used for the new features, there are also extension methods that copy the already existing ones, with a small difference: They make the DeviceContext return itself, which means you can chain methods behind each other. As a result, all draw calls will no longer take an unnecassarily large amount of workspace. For example, this:

Global.Setups[0].DC.BeginDraw();
Global.Setups[0].DC.Clear(new RawColor4(1, 0, 0, 1));
Global.Setups[0].DC.FillRectangle(new RawRectangleF(0, 0, 100, 100), brush1);
Global.Setups[0].DC.DrawImage(shader1);
Global.Setups[0].DC.FillRectangle(new RawRectangleF(0, 100, 200, 400), brush2);
Global.Setups[0].DC.DrawImage(shader2, new RawVector2(100, 100));
Global.Setups[0].DC.DrawBitmap(someBitmap);
Global.Setups[0].DC.EndDraw();

can be shortened into this. Notice that the new() commands don't need to have a class name specified, which is a feature of .NET 5.

Global.Setups[0].DC.ChainBeginDraw()
	.ChainClear(new(1, 0, 0, 1))
	.ChainFillRectangle(new(0, 0, 100, 100), brush1)
	.ChainDrawImage(shader1)
	.ChainFillRectangle(new(0, 100, 200, 400), brush2)
	.ChainDrawImage(shader2, new(100, 100))
	.ChainDrawBitmap(someBitmap).EndDraw();

Same can be done when registering multiple effects at once:

Global.D2DFactory.RegisterEffect<Shader1>();
Global.D2DFactory.RegisterEffect<Shader2>();
Global.D2DFactory.RegisterEffect<Shader3>();
Global.D2DFactory.RegisterEffect<Shader4>();
Global.D2DFactory.RegisterEffect<Shader5>();
Global.D2DFactory.RegisterEffects<Shader1, Shader2, Shader3, Shader4, Shader5>();

How does it work?

Extension methods in C# are static methods in a static class that can "insert" themselves into another, non-static class and pretend they come from there. In Visual Studio they show up as an arrow next to a purple cube. See DCChaining.cs or Global.cs for all the extensions available. This is how an extension method looks like:

public static DeviceContext ChainBeginDraw(this DeviceContext d2dc)
{
	d2dc.BeginDraw(); return d2dc;
}

As you can see, the parameter has a this keyword in front of DeviceContext. On outside, the method will show up as DeviceContext.ChainBeginDraw(), but in reality, this method comes from a different class. The source class was simply replaced by the class of the first parameter.

In this wiki you can find out all the information on how to use the Ensoftener library. For more information on how to add Ensoftener to your project, see "Installing and running". The rest is dedicated to the library's features.

Notice: This wiki shows information for Ensoftener 5.0 and is currently outdated.

Clone this wiki locally