BoltBait.com

Adding a User Interfact to Your GPU Drawing Plugin

Let's add a UI to the Red X plugin


Imagine that we want to improve our "Red X" plugin by adding a integer slider to it so that you can control the size of the lines drawn.

Open Paint.NET, make a selection, and run Effects > Advanced > CodeLab. Open the RedX.cs file we saved at the end of the previous lesson.


Red X

Here is our "Red X" plugin code that we ended the last lesson with:

protected override unsafe void OnDraw(IDeviceContext deviceContext)
{
    deviceContext.DrawImage(Environment.SourceImage);  // preserve background

    // find out where our selection is located
    RectInt32 selection = Environment.Selection.RenderBounds;

    // define your brush and stroke style
    ISolidColorBrush redBrush = deviceContext.CreateSolidColorBrush(LinearColors.Red);
    IStrokeStyle redStrokeStyle = deviceContext.Factory.CreateStrokeStyle(StrokeStyleProperties.Default);

    // setup drawing mode
    deviceContext.AntialiasMode = AntialiasMode.PerPrimitive;  // or .Aliased

    // draw your lines and shapes
    deviceContext.DrawLine(
        selection.Left, selection.Top,
        selection.Right, selection.Bottom,
        redBrush, 5, redStrokeStyle);
    deviceContext.DrawLine(
        selection.Right, selection.Top, 
        selection.Left, selection.Bottom, 
        redBrush, 5, redStrokeStyle);
    deviceContext.DrawRectangle(
        selection.Left,selection.Top,
        selection.Width,selection.Height,
        redBrush, 5*2, redStrokeStyle);
}

The first thing you need to do is press Ctrl+I to open the UI Designer and add a slider. Follow the instructions on the UI Designer page to add an integer slider with the name "Line thickness", a variable name of "Amount1", a minimum of 1, a maximum of 25 and a default of 5.

Once you're done with the designer and have clicked OK to update your script, you should see the following lines at the top of your script:

#region UICode
IntSliderControl Amount1 = 5; // [1,25] Line thickness
#endregion

If your code doesn't look exactly like that, just copy and paste it from here.

Now that we have a slider on the screen, we need to update the code in our script to use it. It's not too hard.

Go look at the drawing section. You'll see this code:

deviceContext.DrawLine(
    selection.Left, selection.Top,
    selection.Right, selection.Bottom,
    redBrush, 5, redStrokeStyle);
deviceContext.DrawLine(
    selection.Right, selection.Top, 
    selection.Left, selection.Bottom, 
    redBrush, 5, redStrokeStyle);
deviceContext.DrawRectangle(
    selection.Left,selection.Top,
    selection.Width,selection.Height,
    redBrush, 5*2, redStrokeStyle);

As you can see, this is hard coded to always use a line thickness of 5. In order to make that settable, we just need to use the "Amount1" variable that is tied to our new slider. In your script, replace "5" with "Amount1", like this:

deviceContext.DrawLine(
    selection.Left, selection.Top,
    selection.Right, selection.Bottom,
    redBrush, Amount1, redStrokeStyle);
deviceContext.DrawLine(
    selection.Right, selection.Top, 
    selection.Left, selection.Bottom, 
    redBrush, Amount1, redStrokeStyle);
deviceContext.DrawRectangle(
    selection.Left,selection.Top,
    selection.Width,selection.Height,
    redBrush, Amount1*2, redStrokeStyle);

Be sure to change it in all three places.

You can press Ctrl+P to preview the effect and play with the slider to see how it works.

Your full script should look like this now:

#region UICode
IntSliderControl Amount1 = 5; // [1,25] Line thickness
#endregion
protected override unsafe void OnDraw(IDeviceContext deviceContext)
{
    deviceContext.DrawImage(Environment.SourceImage);  // preserve background

    // find out where our selection is located
    RectInt32 selection = Environment.Selection.RenderBounds;

    // define your brush and stroke style
    ISolidColorBrush redBrush = deviceContext.CreateSolidColorBrush(LinearColors.Red);
    IStrokeStyle redStrokeStyle = deviceContext.Factory.CreateStrokeStyle(StrokeStyleProperties.Default);

    // setup drawing mode
    deviceContext.AntialiasMode = AntialiasMode.PerPrimitive;  // or .Aliased

    // draw your lines and shapes
    deviceContext.DrawLine(
        selection.Left, selection.Top,
        selection.Right, selection.Bottom,
        redBrush, Amount1, redStrokeStyle);
    deviceContext.DrawLine(
        selection.Right, selection.Top, 
        selection.Left, selection.Bottom, 
        redBrush, Amount1, redStrokeStyle);
    deviceContext.DrawRectangle(
        selection.Left,selection.Top,
        selection.Width,selection.Height,
        redBrush, Amount1*2, redStrokeStyle);
}

Let's add a check box to our plugin to make the antialiasing optional.

Since you already have your script open, the first thing you need to do is press Ctrl+I to open the UI Designer and add a check box. Follow the instructions on the UI Designer page to add a check box with the name "Antialias lines", a variable name of "Amount2", with a default of 1.

Once you're done with the designer and have clicked OK to update your script, you should see the following lines at the top of your script:

#region UICode
IntSliderControl Amount1 = 5; // [1,25] Line thickness
CheckboxControl Amount2 = true; // Antialias lines
#endregion

If your code doesn't look exactly like that, just copy and paste it from here.

Now that we have a check box on the screen, we need to update the code in our script to use it. It's not too hard.

Go look at the antialias section. You'll see this code:

// setup drawing mode
deviceContext.AntialiasMode = AntialiasMode.PerPrimitive;  // or .Aliased

All we need to do is add an "if" statement around both options. We can implement it like this:

// setup drawing mode
if (Amount2)
{
	deviceContext.AntialiasMode = AntialiasMode.PerPrimitive;
}
else
{
	deviceContext.AntialiasMode = AntialiasMode.Aliased;
}

If you've been following along, your final script should look like this:

#region UICode
IntSliderControl Amount1 = 5; // [1,25] Line thickness
CheckboxControl Amount2 = true; // Antialias lines
#endregion
protected override unsafe void OnDraw(IDeviceContext deviceContext)
{
    deviceContext.DrawImage(Environment.SourceImage);  // preserve background

    // find out where our selection is located
    RectInt32 selection = Environment.Selection.RenderBounds;

    // define your brush and stroke style
    ISolidColorBrush redBrush = deviceContext.CreateSolidColorBrush(LinearColors.Red);
    IStrokeStyle redStrokeStyle = deviceContext.Factory.CreateStrokeStyle(StrokeStyleProperties.Default);

    // setup drawing mode
    if (Amount2)
    {
        deviceContext.AntialiasMode = AntialiasMode.PerPrimitive;
    }
    else
    {
        deviceContext.AntialiasMode = AntialiasMode.Aliased;
    }

    // draw your lines and shapes
    deviceContext.DrawLine(
        selection.Left, selection.Top,
        selection.Right, selection.Bottom,
        redBrush, Amount1, redStrokeStyle);
    deviceContext.DrawLine(
        selection.Right, selection.Top, 
        selection.Left, selection.Bottom, 
        redBrush, Amount1, redStrokeStyle);
    deviceContext.DrawRectangle(
        selection.Left,selection.Top,
        selection.Width,selection.Height,
        redBrush, Amount1*2, redStrokeStyle);
}

Now, let's add a color wheel control to control the color of the lines drawn.

Since you already have your script open, the first thing you need to do is press Ctrl+I to open the UI Designer and add a colorwheel control. Follow the instructions on the UI Designer page to add a colorwheel with the name "Select a color", a variable name of "Amount3", with a default of Red.

Once you're done with the designer and have clicked OK to update your script, you should see the following lines at the top of your script:

#region UICode
IntSliderControl Amount1 = 5; // [1,25] Line thickness
CheckboxControl Amount2 = true; // Antialias lines
ColorWheelControl Amount3 = ColorBgra.FromBgr(0, 0, 255); // [Red] Select a color
#endregion

Now, in your script where you're specifying "LinearColors.Red", simply replace that with "Amount3".

Also, since your brush may not be red, change the "redBrush" variable to "myBrush" and change "redStrokeStyle" to "myStrokeStyle". (Be sure to change them in all lines.)

If you've been following along, your final script should look like this:

#region UICode
IntSliderControl Amount1 = 5; // [1,25] Line thickness
CheckboxControl Amount2 = true; // Antialias lines
ColorWheelControl Amount3 = ColorBgra.FromBgr(0, 0, 255); // [Red] Select a color
#endregion
protected override unsafe void OnDraw(IDeviceContext deviceContext)
{
    deviceContext.DrawImage(Environment.SourceImage);  // preserve background

    // find out where our selection is located
    RectInt32 selection = Environment.Selection.RenderBounds;

    // define your brush and stroke style
    ISolidColorBrush myBrush = deviceContext.CreateSolidColorBrush(Amount3);
    IStrokeStyle myStrokeStyle = deviceContext.Factory.CreateStrokeStyle(StrokeStyleProperties.Default);

    // setup drawing mode
    if (Amount2)
    {
        deviceContext.AntialiasMode = AntialiasMode.PerPrimitive;
    }
    else
    {
        deviceContext.AntialiasMode = AntialiasMode.Aliased;
    }

    // draw your lines and shapes
    deviceContext.DrawLine(
        selection.Left, selection.Top,
        selection.Right, selection.Bottom,
        myBrush, Amount1, myStrokeStyle);
    deviceContext.DrawLine(
        selection.Right, selection.Top, 
        selection.Left, selection.Bottom, 
        myBrush, Amount1, myStrokeStyle);
    deviceContext.DrawRectangle(
        selection.Left,selection.Top,
        selection.Width,selection.Height,
        myBrush, Amount1*2, myStrokeStyle);
}

Go ahead and press Ctrl+P to preview your effect. Play with the slider and check box.


Finishing Up

Once you've got that working, remember to save your script! I wouldn't want you to lose any of your hard work.

"File > Save" your RedX.cs file.

If you'd like to make that plugin a permanent part of your Paint.NET installation, read:

How to Build a DLL from a CodeLab script
How to install a DLL into Paint.NET


What's Next?

Now that you know a bit about the UI design, let's dig a little deeper and design and implement a more complicated effect that draws text on the screen!

Rendering Text

Or, you can...

Head back to the Tutorial Index to learn something else



Donate

The best way to say "Thanks" for teaching you something here, is to fill out this form. It uses PayPal to process your donation. You don't need a PayPal account, just a credit/debit card will do. If PayPal doesn't work for you, no need to worry--just enjoy the tutorials for free!

$
Thank you for your donation. I don't get many, so you can be sure I really appreciate yours!



 

 
 

News



CodeLab 6.12 Released
(February 11, 2024)
This latest release of CodeLab for Paint.NET includes the ability to write GPU accelerated plugins.
More...

Double-Six Dominoes 3.1
(May 10, 2021)
This long-awaited refresh of the most popular dominoes game on Download.com is now available!
More...

HTML Editor 1.5 Released
(March 31, 2016)
This latest release is a complete rewrite adding a wysiwyg editor mode and a much improved UI.
More...