ReMake Posted March 11, 2015 Share Posted March 11, 2015 (edited) Each user who starts mastering CodeLab, asks a question - where to begin? First of all, it's necessary to begin with studying the CodeLab Help by BoltBait. If you have studied CodeLab Help and you have no ideas for creating effects, begin with updating of the old plugins developed by other authors. Looking through the forum Plugins - Publishing ONLY!, I found a topic Simple Lines Plugin. This is a good example for a small tutorial. The picture shows the user interface of the Lines effect by spongey437. This effect draws a line width of 1 pixel and has two controls: Width - an interval between lines and X - Y - the direction of lines (horizontal and vertical respectively). So, let's get started. Open the Simple Lines Plugin topic, select and copy (Ctl+C) the text of the script. Open CodeLab: Effects -> Advanced -> CodeLab. Select the CodeLab script text (Ctrl+A) and paste the previously copied script (Ctl+V). Save the script with the Lines name for further working with it: File -> Save... First of all, open the designer interface (File -> User Interface Designer) and just click OK. Your new script will look like this: #region UICode int Amount1 = 10; // [1,100] Width int Amount2 = 2; // [1,2] X - Y #endregion // int Amount1=10; //[1,100]Width // int Amount2=2; //[1,2]X - Y void Render(Surface dst, Surface src, Rectangle rect) { PdnRegion selectionRegion = EnvironmentParameters.GetSelection(src.Bounds); // Delete any of these lines you don't need Rectangle selection = this.EnvironmentParameters.GetSelection(src.Bounds).GetBoundsInt(); long CenterX = (long)(((selection.Right - selection.Left) / 2)+selection.Left); long CenterY = (long)(((selection.Bottom - selection.Top) / 2)+selection.Top); ColorBgra PrimaryColor = (ColorBgra)EnvironmentParameters.PrimaryColor; ColorBgra SecondaryColor = (ColorBgra)EnvironmentParameters.SecondaryColor; int BrushWidth = (int)EnvironmentParameters.BrushWidth; ColorBgra CurrentPixel; for(int y = rect.Top; y < rect.Bottom; y++) { for (int x = rect.Left; x < rect.Right; x++) { if (selectionRegion.IsVisible(x, y)) { CurrentPixel = src[x,y]; // TODO: Add pixel processing code here if(Amount2 == 1) { if (x % Amount1 == 0) { // Access RGBA values this way, for example: CurrentPixel.R = (byte)PrimaryColor.R; CurrentPixel.G = (byte)PrimaryColor.G; CurrentPixel.B = (byte)PrimaryColor.B; CurrentPixel.A = (byte)PrimaryColor.A; } } if(Amount2 == 2) { if (y % Amount1 == 0) { // Access RGBA values this way, for example: CurrentPixel.R = (byte)PrimaryColor.R; CurrentPixel.G = (byte)PrimaryColor.G; CurrentPixel.B = (byte)PrimaryColor.B; CurrentPixel.A = (byte)PrimaryColor.A; } } dst[x,y] = CurrentPixel; } } } } Delete this two commented lines: // int Amount1=10; //[1,100]Width // int Amount2=2; //[1,2]X - Y they aren't necessary any more. The next lines (except ColorBgra PrimaryColor) will also not be necessary for us: // Delete any of these lines you don't need Rectangle selection = this.EnvironmentParameters.GetSelection(src.Bounds).GetBoundsInt(); long CenterX = (long)(((selection.Right - selection.Left) / 2)+selection.Left); long CenterY = (long)(((selection.Bottom - selection.Top) / 2)+selection.Top); ColorBgra SecondaryColor = (ColorBgra)EnvironmentParameters.SecondaryColor; int BrushWidth = (int)EnvironmentParameters.BrushWidth; so remove them, leaving a string ColorBgra PrimaryColor = (ColorBgra)EnvironmentParameters.PrimaryColor; and again save your script with the name Lines_1. If you have carefully studied CodeLab Help, you probably noticed that in your new script there is no need to divide CurrentPixel into components (R, G, B and A). Therefore, the following lines CurrentPixel.R = (byte)PrimaryColor.R; CurrentPixel.G = (byte)PrimaryColor.G; CurrentPixel.B = (byte)PrimaryColor.B; CurrentPixel.A = (byte)PrimaryColor.A; replace with CurrentPixel = PrimaryColor; If this effect draws a horizontal or vertical line separately, can it draw both lines at the same time? Yes, it can. To do this, you must perform the condition: if ((x % Amount1 == 0) || (y % Amount1 == 0)) Add before dst[x,y] = CurrentPixel; the following lines: if(Amount2 == 3) { if ((x % Amount1 == 0) || (y % Amount1 == 0)) { // Access RGBA values this way, for example: CurrentPixel = PrimaryColor; } } Now open the User Interface Designer and select the line X-Y (1..2..2). In the Maximum box set the value to 3 and in the Control name box type X - Y - Grid. Click Update button, then click Ok. Your script will look like this: #region UICode int Amount1 = 10; // [1,100] Width int Amount2 = 2; // [1,3] X - Y - Grid #endregion void Render(Surface dst, Surface src, Rectangle rect) { PdnRegion selectionRegion = EnvironmentParameters.GetSelection(src.Bounds); ColorBgra PrimaryColor = (ColorBgra)EnvironmentParameters.PrimaryColor; ColorBgra CurrentPixel; for(int y = rect.Top; y < rect.Bottom; y++) { for (int x = rect.Left; x < rect.Right; x++) { if (selectionRegion.IsVisible(x, y)) { CurrentPixel = src[x,y]; // TODO: Add pixel processing code here if(Amount2 == 1) { if (x % Amount1 == 0) { // Access RGBA values this way, for example: CurrentPixel = PrimaryColor; } } if(Amount2 == 2) { if (y % Amount1 == 0) { // Access RGBA values this way, for example: CurrentPixel = PrimaryColor; } } if(Amount2 == 3) { if ((x % Amount1 == 0) || (y % Amount1 == 0)) { // Access RGBA values this way, for example: CurrentPixel = PrimaryColor; } } dst[x,y] = CurrentPixel; } } } } Save your script with Lines_Grid name now. Open File -> Save as DLL... and save your first update of the effect. Close CodeLab and Paint.NET. Run the Install_Lines_Grid file on your desktop, which will place the Lines_Grid.dll file into the Effects folder (or drag the Lines_Grid.dll file to the Effects folder manually). Start Paint.NET and you'll see your effect in the Effects menu, run it and check how it works. Probably, you don't want to switch a view of lines using the slider. You may have also noticed that the effect works is somewhat slow. Then let's go to the next step of the update. Start CodeLab and open your Lines_Grid script. First of all delete the following line: { if (selectionRegion.IsVisible(x, y)) and one of the closing braces ( } ) at the bottom of the script. This line PdnRegion selectionRegion = EnvironmentParameters.GetSelection(src.Bounds); now we will not need and delete it too. Open the User Interface Designer and select the line X-Y - Grid (1..2..3). In a drop-down list select the Radio Button List control. Enter View in the Control name box, and in the Parameters box enter the kinds of lines, separated by the pipe symbol (|): Vertical Lines|Horizontal Lines|Grid. Click Update button, and then click Ok. Now your script looks like this: #region UICode int Amount1 = 10; // [1,100] Width byte Amount2 = 0; // [1] View|Vertical Lines|Horizontal Lines|Grid #endregion void Render(Surface dst, Surface src, Rectangle rect) { ColorBgra PrimaryColor = (ColorBgra)EnvironmentParameters.PrimaryColor; ColorBgra CurrentPixel; for(int y = rect.Top; y < rect.Bottom; y++) { for (int x = rect.Left; x < rect.Right; x++) { CurrentPixel = src[x,y]; // TODO: Add pixel processing code here if(Amount2 == 0) { if (x % Amount1 == 0) { // Access RGBA values this way, for example: CurrentPixel = PrimaryColor; } } if(Amount2 == 1) { if (y % Amount1 == 0) { // Access RGBA values this way, for example: CurrentPixel = PrimaryColor; } } if(Amount2 == 2) { if ((x % Amount1 == 0) || (y % Amount1 == 0)) { // Access RGBA values this way, for example: CurrentPixel = PrimaryColor; } } dst[x,y] = CurrentPixel; } } } Pay attention for the line byte Amount2 = 0; // [1] View|Vertical Lines|Horizontal Lines|Grid Here, the initial value of Amount2 is 0, which corresponds to the Vertical Lines. Replace in this line 0 to 1 and you get a Horizontal lines. Under the terms of programming our code is not very correct, so looking into CodeLab UI Elements, replace the lines if(Amount2 == 0) { if (x % Amount1 == 0) { // Access RGBA values this way, for example: CurrentPixel = PrimaryColor; } } if(Amount2 == 1) { if (y % Amount1 == 0) { // Access RGBA values this way, for example: CurrentPixel = PrimaryColor; } } if(Amount2 == 2) { if ((x % Amount1 == 0) || (y % Amount1 == 0)) { // Access RGBA values this way, for example: CurrentPixel = PrimaryColor; } } with next lines switch(Amount2) { case 0: // Vertical Lines if (x % Amount1 == 0) {CurrentPixel = PrimaryColor;} break; case 1: // Horizontal Lines if (y % Amount1 == 0) {CurrentPixel = PrimaryColor;} break; case 2: // Horizontal Lines if ((x % Amount1 == 0) || (y % Amount1 == 0)) {CurrentPixel = PrimaryColor;} break; } Now our script would look like this: #region UICode int Amount1 = 10; // [1,100] Width byte Amount2 = 0; // [1] View|Vertical Lines|Horizontal Lines|Grid #endregion void Render(Surface dst, Surface src, Rectangle rect) { ColorBgra PrimaryColor = (ColorBgra)EnvironmentParameters.PrimaryColor; ColorBgra CurrentPixel; for(int y = rect.Top; y < rect.Bottom; y++) { for (int x = rect.Left; x < rect.Right; x++) { CurrentPixel = src[x,y]; // TODO: Add pixel processing code here switch(Amount2) { case 0: // Vertical Lines if (x % Amount1 == 0) {CurrentPixel = PrimaryColor;} break; case 1: // Horizontal Lines if (y % Amount1 == 0) {CurrentPixel = PrimaryColor;} break; case 2: // Grid if ((x % Amount1 == 0) || (y % Amount1 == 0)) {CurrentPixel = PrimaryColor;} break; } dst[x,y] = CurrentPixel; } } } Save your script with Lines_Grid_1 name and create a DLL with the same name. Check how works your effect. Lines color of our effect depends of the Primary Color, which was selected in the Colors window. If you want to draw a line or grid in other color, you will need to pre-set the color in the Colors window, and then run your effect. Is it possible to choose the color of the lines from effect directly, without addressing to the Colors window? Of course, it's possible. To do this, we will continue to update our effect. Open with CodeLab your Lines_Grid_1 script. Open the User Interface Designer and in the drop-down list select the Color Wheel control. Write the Color in the Control name box, click the Add button and move up the control to one position with button . Click Ok. Now the code block of user interface (UI) will look like this: #region UICode int Amount1 = 10; // [1,100] Width ColorBgra Amount2 = ColorBgra.FromBgr(0,0,0); // Color byte Amount3 = 0; // [1] View|Vertical Lines|Horizontal Lines|Grid #endregion Note: View control is named now Amount3, therefore replace Amount2 to Amount3 in the line switch. Now you have a possibility to select color immediately in the interface of effect and we don't depend on Primary color in the Colors window! It means that CurrentPixel = PrimaryColor; we can replace to CurrentPixel = Amount2; and we can delete the ColorBgra PrimaryColor = (ColorBgra)EnvironmentParameters.PrimaryColor; line. Save your script with Lines_Grid_2 name and create a DLL with the same name. Check how works your effect. Probably, now you want to change width of lines and an interval between the lines. Let us continue. Open with CodeLab your Lines_Grid_2 script. Open the User Interface Designer, select the Width (1..10..100) line, rename it to Line Width and click the Update button. Then from the drop-down list select the Integer Slider control and name it Interval Width. Write 1 in the Minimum box, in the Default box write 10. Click the Add button and move up the control to one position with button . Click Ok. Now the code block of user interface (UI) will look like this: #region UICode int Amount1 = 10; // [1,100] Line Width ColorBgra Amount2 = ColorBgra.FromBgr(0,0,0); // Color int Amount3 = 10; // [1,100] Interval Width byte Amount4 = 0; // [1] View|Vertical Lines|Horizontal Lines|Grid #endregion View control is named now Amount4, therefore replace Amount3 to Amount4 in the line switch. Now we enter variable Lines as a sum of Amount1 and Amount2 and place it before ColorBgra CurrentPixel; line int Lines = Amount1 + Amount3; and change the conditions if (x % Amount1 == 0) if (y % Amount1 == 0) to if (x % Lines < Amount1) if (y % Lines < Amount1) Our script has now the following view: #region UICode int Amount1 = 10; // [1,100] Line Width ColorBgra Amount2 = ColorBgra.FromBgr(0,0,0); // Color int Amount3 = 10; // [1,100] Interval Width byte Amount4 = 0; // [1] View|Vertical Lines|Horizontal Lines|Grid #endregion void Render(Surface dst, Surface src, Rectangle rect) { int Lines = Amount1 + Amount3; ColorBgra CurrentPixel; for(int y = rect.Top; y < rect.Bottom; y++) { for (int x = rect.Left; x < rect.Right; x++) { CurrentPixel = src[x,y]; // TODO: Add pixel processing code here switch(Amount4) { case 0: // Vertical Lines if (x % Lines < Amount1) {CurrentPixel = Amount2;} break; case 1: // Horizontal Lines if (y % Lines < Amount1) {CurrentPixel = Amount2;} break; case 2: // Grid if ((x % Lines < Amount1) || (y % Lines < Amount1)) {CurrentPixel = Amount2;} break; } dst[x,y] = CurrentPixel; } } } Let's return to our last script. What if we add one more control item. Open the User Interface Designer and in the drop-down list select the Check Box control. Write the Inverse in the Control name box, write 0 in the Default box and click the Add button. Click Ok. Now the code block of user interface (UI) looks like this: #region UICode int Amount1 = 1; // [1,100] Line Width ColorBgra Amount2 = ColorBgra.FromBgr(0,0,0); // Color int Amount3 = 10; // [1,100] Interval Width byte Amount4 = 0; // [1] View|Vertical Lines|Horizontal Lines|Grid bool Amount5 = false; // [0,1] Inverse #endregion Let's set conditions for a checkbox. If the checkbox is unchecked, lines color accepts the color value, selected from a Color control. If the checkbox is checked, intervals color accepts the color value, selected from a Color control. Final our code looks like this: #region UICode int Amount1 = 1; // [1,100] Line Width ColorBgra Amount2 = ColorBgra.FromBgr(0,0,0); // Color int Amount3 = 10; // [1,100] Interval Width byte Amount4 = 0; // [1] View|Vertical Lines|Horizontal Lines|Grid bool Amount5 = false; // [0,1] Inverse #endregion void Render(Surface dst, Surface src, Rectangle rect) { int Lines = Amount1 + Amount3; ColorBgra CurrentPixel; for (int y = rect.Top; y < rect.Bottom; y++) { for (int x = rect.Left; x < rect.Right; x++) { CurrentPixel = src[x,y]; // TODO: Add pixel processing code here if(!Amount5) { switch (Amount4) { case 0: // Vertical Lines if (x % Lines < Amount1) {CurrentPixel = Amount2;} break; case 1: // Horizontal Lines if (y % Lines < Amount1) {CurrentPixel = Amount2;} break; case 2: // Grid from lines if ((x % Lines < Amount1) || (y % Lines < Amount1)) {CurrentPixel = Amount2;} break; } } else { switch(Amount4) { case 0: // Vertical Intervals if (x % Lines + 1 > Amount1) {CurrentPixel = Amount2;} break; case 1: // Horizontal Intervals if (y % Lines + 1 > Amount1) {CurrentPixel = Amount2;} break; case 2: // Grid from intervals if ((x % Lines + 1 > Amount1) && (y % Lines + 1 > Amount1)) {CurrentPixel = Amount2;} break; } } dst[x,y] = CurrentPixel; } } } Save your script with name Lines_Grid_4 and create DLL with the same name. Here would be possible to finish, but... Let's address to BoltBait's Using CodeLab to Build a DLL. We can find some usefull information in the Default section and we can create similar for our script:// Submenu: Render - let's place our effect under a Render submenu of the Effects menu// Name: Lines/Grid - name of effect in the menu (or submenu)// Title: Lines/Grid - a title of the effect's interface// Author: ReMake - name of the effect's author// Desc: Drawing of direct lines or a grid - the effect description// Keywords: effect|drawing|lines|grid - a keywords from which your effect can be found in the Internet// URL: http://www.getpaint.net/redirect/plugins.html - your address in a network (or in the forum) Let's place this information before the code block of the interface: // Submenu: Render // Name: Lines/Grid // Title: Lines/Grid // Author: ReMake // Desc: Drawing of direct lines or a grid // Keywords: effect|lines|grid // URL: http://www.getpaint.net/redirect/plugins.html #region UICode int Amount1 = 1; // [1,100] Line Width ColorBgra Amount2 = ColorBgra.FromBgr(0,0,0); // Color int Amount3 = 10; // [1,100] Interval Width byte Amount4 = 0; // [1] View|Vertical Lines|Horizontal Lines|Grid bool Amount5 = false; // [0,1] Inverse #endregion Save this script with the name LinesGrid. And last, it is necessary to create an icon for the interface of our effect from the PNG file, which have the size of 16x16 pixels. By means of our effect I have created such icon: Now let's save our effect as a DLL file: File-> Save as DLL... Almost all information is in the dialog box, which presented to you. Click the Select icon link and select the icon. Click the Build button - your new effect is ready! Compare the interface of your effect with a picture shown above. Our code, from the point of view of programming, maybe is not so elegant, but it only the tutorial. I also did not put the aim to explain algorithm of operation of this script - to understand it the task of the user. I hope the first step in CodeLab was not so difficult. Results of this effect works you can see in a Lines/Grid effect topic. Thanks BoltBait for his CodeLab and CodeLab Help. Thanks HELEN - my first reader - for her assessment of 'my' English. Вариант этой темы на русском языке смотрите здесь. Edited July 26, 2018 by toe_head2001 Formatting 5 Quote Link to comment Share on other sites More sharing options...
Ego Eram Reputo Posted March 11, 2015 Share Posted March 11, 2015 Excellent tutorial. How about showing how the effect affects the canvas (i.e. what it renders)? Can I also suggest a PDF version be made available? Quote ebook: Mastering Paint.NET | resources: Plugin Index | Stereogram Tut | proud supporter of Codelab plugins: EER's Plugin Pack | Planetoid | StickMan | WhichSymbol+ | Dr Scott's Markup Renderer | CSV Filetype | dwarf horde plugins: Plugin Browser | ShapeMaker Link to comment Share on other sites More sharing options...
ReMake Posted March 11, 2015 Author Share Posted March 11, 2015 Excellent tutorial. How about showing how the effect affects the canvas (i.e. what it renders)? I will try to attach pictures tomorrow. I barely coped with formatting codes (or helped someone from admins or moderators). Can I also suggest a PDF version be made available? I will try to do it with your help. Quote Link to comment Share on other sites More sharing options...
Red ochre Posted March 12, 2015 Share Posted March 12, 2015 Well done Remake! - 'your' English is very good, infinitely better than my Belarusian! - probably better than 'my' English too. Quote Red ochre Plugin pack.............. Diabolical Drawings ................Real Paintings Link to comment Share on other sites More sharing options...
ReMake Posted March 12, 2015 Author Share Posted March 12, 2015 Well done Remake! - 'your' English is very good, infinitely better than my Belarusian! - probably better than 'my' English too. Nobody knows English better than an Englishman. Thank You Red ochre. I am very pleased to hear Your estimation. Quote Link to comment Share on other sites More sharing options...
Pixey Posted March 12, 2015 Share Posted March 12, 2015 This is very interesting stuff @ReMake, thank you . I will study it at leasure and hope to understand at least some of it! This subject has always intrigued, as well as mystified me. P.S. My father spoke Russian (he was actually Polish) but, alas, the only words I remember learning from him were На здоровье & dziękuję. Quote How I made Jennifer & Halle in Paint.net My Gallery | My Deviant Art "Rescuing one animal may not change the world, but for that animal their world is changed forever!" anon. Link to comment Share on other sites More sharing options...
ReMake Posted March 12, 2015 Author Share Posted March 12, 2015 This is very interesting stuff @ReMake, thank you . I will study it at leasure and hope to understand at least some of it! This subject has always intrigued, as well as mystified me. P.S. My father spoke Russian (he was actually Polish) but, alas, the only words I remember learning from him were На здоровье & dziękuję. Dziękuję bardzo, as would said Your father. I speak Polish, some a little. Thank You Pixey for your assessment. Quote Link to comment Share on other sites More sharing options...
HELEN Posted March 12, 2015 Share Posted March 12, 2015 See? Very understandable. You did a nice job. @Red: You speak a different language? I speak Russian. Quote Don't spit into the well, you might drink from it later. -----Yiddish ProverbGlossy Galaxy Ball---How to Make FoliageMy Gallery PDN Fans--My DA Link to comment Share on other sites More sharing options...
ReMake Posted March 12, 2015 Author Share Posted March 12, 2015 (edited) See? Very understandable. You did a nice job. Thank You HELEN. You brought me confidence when You have read my 'opus'. I have updated the first post of this topic, because was detected error in the final program code and the result of the effect's work with checked Inverse control was not that was expected. The effect works correctly now. Edited March 12, 2015 by ReMake Quote Link to comment Share on other sites More sharing options...
Red ochre Posted March 12, 2015 Share Posted March 12, 2015 infinitely better than my Belarusian! @Red: You speak a different language? Infinitely better meaning I do not speak any other languages, sadly, apart from jibberish sometimes . I greatly respect those who speak many - including C#! Sorry for going off topic Remake. 1 Quote Red ochre Plugin pack.............. Diabolical Drawings ................Real Paintings Link to comment Share on other sites More sharing options...
ReMake Posted March 14, 2015 Author Share Posted March 14, 2015 (edited) I renamed this topic because I have decided to continue the theme 'Codelab - First Steps'. Edited March 14, 2015 by ReMake Quote Link to comment Share on other sites More sharing options...
toe_head2001 Posted March 14, 2015 Share Posted March 14, 2015 For the benefit of absolute beginners (people that haven't worked with paint.net resources or C#), perhaps it would be a good idea to identify which parts of the code are specific to paint.net and which are generic C#. Visual Studio (and Mono Develop) do a good job of telling you what comes from where, but people using CodeLab don't get that. From my own experience, I would say I was somewhat lost in some places until I switch to Visual Studio... but maybe that's just me. Quote My Gallery | My Plugin Pack Layman's Guide to CodeLab Link to comment Share on other sites More sharing options...
ReMake Posted March 14, 2015 Author Share Posted March 14, 2015 For the benefit of absolute beginners (people that haven't worked with paint.net resources or C#), perhaps it would be a good idea to identify which parts of the code are specific to paint.net and which are generic C#. ... Each user who starts mastering CodeLab, asks a question - where to begin? First of all, it's necessary to begin with studying the CodeLab Help by BoltBait. "First, you must learn C# at least to a basic level. Now, if you have expirience with C, C++, or even Pascal, you'll probably do fine. If not, you must first learn C#" - said BoltBait in his CodeLab Tutorial Part 1 - Simple. For absolute newbies will be difficult to understand of all without basic knowledge of C#. Before proceeding to VS, maybe they should experiment in CodeLab, even on the examples of other authors. Quote Link to comment Share on other sites More sharing options...
toe_head2001 Posted March 14, 2015 Share Posted March 14, 2015 Fair enough... I guess I took the unconventional route of learning both at the same time. 1 Quote My Gallery | My Plugin Pack Layman's Guide to CodeLab Link to comment Share on other sites More sharing options...
ReMake Posted March 14, 2015 Author Share Posted March 14, 2015 On 3/15/2015 at 12:35 AM, toe_head2001 said: Fair enough... I guess I took the unconventional route of learning both at the same time. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.