Прежде всего, начинать следует с изучения CodeLab Help от BoltBait'а.
Если вы изучили CodeLab Help и у вас пока нет никаких идей по созданию эффектов, начните с обновления старых плагинов, разработанных другими авторами.
Просматривая getpaint.net форум Plugins - Publishing ONLY!, я нашел неплохой пример для небольшого учебного пособия в разделе Simple Lines Plugin.
На рисунке представлен интерфейс эффекта Lines, автором которого является spongey437.
Он рисует линии шириной в 1 пиксель и имеет два элемента управления: Width - интервал между линиями и X - Y - направление линий (по горизонтали и вертикали соответственно).
Итак, начнем.
Откройте раздел Simple Lines Plugin, выделите и скопируйте (Ctl+C) текст сценария.
Откройте CodeLab: Эффекты -> Advanced -> CodeLab.
Выделите в CodeLab текст сценария (Ctl+A) и вставьте скопированный сценарий (Ctl+V).
Сохраните сценарий с именем Lines для последующей работы с ним: Файл -> Сохранить
Прежде всего, откройте Конструктор интерфейса (Файл -> Конструктор интерфейса). Выделите в нем строку Width (1..10..100), в поле Имя элемента замените Width на Ширина и нажмите OK. Ваш новый сценарий приобретет следующий вид:
Код: Выделить всё
#region UICode
int Amount1 = 10; // [1,100] Ширина
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;
}
}
}
}
Код: Выделить всё
// int Amount1=10; //[1,100]Width
// int Amount2=2; //[1,2]X - Y
Следующие строки (кроме ColorBgra PrimaryColor) нам также не понадобятся:
Код: Выделить всё
// 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;
Код: Выделить всё
ColorBgra PrimaryColor = (ColorBgra)EnvironmentParameters.PrimaryColor;
Если вы внимательно изучили CodeLab Help, то вы, вероятно, заметили что в вашем новом сценарии нет необходимости разделять CurrentPixel на составляющие части (R, G, B и A). Поэтому следующие строки
Код: Выделить всё
CurrentPixel.R = (byte)PrimaryColor.R;
CurrentPixel.G = (byte)PrimaryColor.G;
CurrentPixel.B = (byte)PrimaryColor.B;
CurrentPixel.A = (byte)PrimaryColor.A;
Код: Выделить всё
CurrentPixel = PrimaryColor;
Код: Выделить всё
if ((x % Amount1 == 0) || (y % Amount1 == 0))
Код: Выделить всё
if(Amount2 == 3)
{
if ((x % Amount1 == 0) || (y % Amount1 == 0))
{
// Access RGBA values this way, for example:
CurrentPixel = PrimaryColor;
}
}
В поле Максимум установите значение в 3, а в поле Имя элемента впишите X -Y - Сетка. Нажмите кнопку Обновить, затем Ok. Ваш сценарий будет выглядеть вот так:
Код: Выделить всё
#region UICode
int Amount1 = 10; // [1,100] Ширина
int Amount2 = 2; // [1,3] X - Y - Сетка
#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;
}
}
}
}
Закройте CodeLab и Paint.NET. Запустите на рабочем столе файл Install_Lines_Grid, который поместит файл Lines_Grid.dll в папку Эффекты (или перетащите файл Lines_Grid.dll в папку Эффекты).
Запустите Paint.NET и вы увидите свой эффект в меню Эффекты, запустите его и проверьте как он работает. Вероятно, вас не очень устраивает переключать вид линий при помощи слайдера. Возможно, вы также заметили, что работает эффект несколько замедленно. Тогда приступим к следующему шагу обновления.
Запустите CodeLab и откройте ваш сценарий Lines_Grid. Прежде всего удалите следующие строки:
Код: Выделить всё
{
if (selectionRegion.IsVisible(x, y))
Строка
Код: Выделить всё
PdnRegion selectionRegion = EnvironmentParameters.GetSelection(src.Bounds);
Откройте Конструктор интерфейса и выделите в нем строку X - Y - Сетка (1..2..3). В выпадающем спискеТип элемента выберите Radio Button List. В поле Имя элемента впишите Вид, а в поле Параметры впишите виды линий, разделив их символом вертикальной черты(|): Вертикальные линии|Горизонтальные линии|Сетка. Нажмите кнопку Обновить и затем Ok. Теперь ваш сценарий выглядит так:
Код: Выделить всё
#region UICode
int Amount1 = 10; // [1,100] Ширина
byte Amount2 = 0; // [1] Вид|Вертикальные линии|Горизонтальные линии|Сетка
#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;
}
}
}
Код: Выделить всё
byte Amount2 = 0; // [1] Вид|Вертикальные линии|Горизонтальные линии|Сетка
С точки зрения программирования наш код не очень корректен, поэтому, заглянув в CodeLab UI Elements, заменим строки
Код: Выделить всё
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;
}
}
Код: Выделить всё
switch(Amount2)
{
case 0: // вертикальные линии
if (x % Amount1 == 0) {CurrentPixel = PrimaryColor;}
break;
case 1: // горизонтальные линии
if (y % Amount1 == 0) {CurrentPixel = PrimaryColor;}
break;
case 2: // сетка
if ((x % Amount1 == 0) || (y % Amount1 == 0)) {CurrentPixel = PrimaryColor;}
break;
}
Код: Выделить всё
#region UICode
int Amount1 = 10; // [1,100] Ширина
byte Amount2 = 0; // [1] Вид|Вертикальные линии|Горизонтальные линии|Сетка
#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;
}
}
}
Цвет линий нашего эффекта зависит от Основного цвета, выбранного в окне Палитра. Если вы захотите нарисовать линии или сетку другим цветом, вам придется предварительно установить этот цвет в окне Палитра, а затем запустить ваш эффект. А можно ли выбирать цвет линий непосредственно в эффекте, не обращаясь к окну Палитра? Конечно, можно. Для этого продолжим обновлять наш эффект.
Откройте в CodeLab ваш сценарий Lines_Grid_1. Откройте Конструктор интерфейса и в выпадающем списке Тип элемента выберите элемент управления Color Wheel. В поле Имя элемента впишите Цвет, нажмите кнопку Добавить и переместите этот элемент управления при помощи кнопки вверх на одну позицию. Нажмите кнопку Ok.
Блок кода интерфейса UI выглядит теперь так:
Код: Выделить всё
#region UICode
int Amount1 = 10; // [1,100] Ширина
ColorBgra Amount2 = ColorBgra.FromBgr(0,0,0); // Цвет
byte Amount3 = 0; // [1] Вид|Вертикальные линии|Горизонтальные линии|Сетка
#endregion
Теперь у вас есть возможность выбирать цвет непосредственно в интерфейсе эффекта и мы не зависим от Основного цвета в окне Палитра! Это значит что CurrentPixel = PrimaryColor; мы можем заменить на CurrentPixel = Amount2; и удалить строку ColorBgra PrimaryColor = (ColorBgra)EnvironmentParameters.PrimaryColor;.
Сохраните ваш сценарий с именем Lines_Grid_2 и создайте DLL с тем же именем. Проверьте ваш эффект в работе. Возможно, теперь вы захотите изменить ширину линий и интервал между ними. Тогда продолжим.
Откройте в CodeLab ваш сценарий Lines_Grid_2. Откройте Конструктор интерфейса, выделите строку Ширина (1..10..100), переименуйте ее в Ширина линии и нажмите кнопку Обновить. Затем в выпадающем списке Тип элемента выберите элемент управления Integer Slider, назовите его Ширина интервала. В поле Минимум впишите значение 1, в поле По умолчанию - 10. Нажмите кнопку Добавить и переместите строку при помощи кнопки на одну позицию вверх. Нажмите кнопку Ok.
Теперь блок кода интерфейса UI будет выглядеть так:
Код: Выделить всё
#region UICode
int Amount1 = 10; // [1,100] Ширина линии
ColorBgra Amount2 = ColorBgra.FromBgr(0,0,0); // Цвет
int Amount3 = 10; // [1,100] Ширина интервала
byte Amount4 = 0; // [1] Вид|Вертикальные линии|Горизонтальные линии|Сетка
#endregion
Теперь введем переменную Lines как сумму Amount1 и Amount3, расположив ее перед строкой ColorBgra CurrentPixel;
Код: Выделить всё
int Lines = Amount1 + Amount3;
Код: Выделить всё
if (x % Amount1 == 0)
if (y % Amount1 == 0)
Код: Выделить всё
if (x % Lines < Amount1)
if (y % Lines < Amount1)
Код: Выделить всё
#region UICode
int Amount1 = 10; // [1,100] Ширина линии
ColorBgra Amount2 = ColorBgra.FromBgr(0,0,0); // Цвет
int Amount3 = 10; // [1,100] Ширина интервала
byte Amount4 = 0; // [1] Вид|Вертикальные линии|Горизонтальные линии|Сетка
#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(Amount5)
{
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;
}
}
}
Вернемся к нашему последнему сценарию. A что если мы добавим еще один элемент управления.
Откройте Конструктор интерфейса и в поле выпадающего списка Тип элемента выберите элемент управления Check Box. В поле Имя элемента впишите Инвертировать, в поле По умолчанию установите 0 и нажмите кнопку Добавить. Нажмите кнопку Ok.
Теперь блок кода интерфейса выглядит так:
Код: Выделить всё
#region UICode
int Amount1 = 10; // [1,100] Ширина линии
ColorBgra Amount2 = ColorBgra.FromBgr(0,0,0); // Цвет
int Amount3 = 10; // [1,100] Ширина интервала
byte Amount4 = 0; // [1] Вид|Вертикальные линии|Горизонтальные линии|Сетка
bool Amount5 = false; // [0,1] Инвертировать
#endregion
Окончательно наш код выглядит так:
Код: Выделить всё
#region UICode
int Amount1 = 10; // [1,100] Ширина линии
ColorBgra Amount2 = ColorBgra.FromBgr(0,0,0); // Цвет
int Amount3 = 10; // [1,100] Ширина интервала
byte Amount4 = 0; // [1] Вид|Вертикальные линии|Горизонтальные линии|Сетка
bool Amount5 = false; // [0,1] Инвертировать
#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
if ((x % Lines < Amount1) || (y % Lines < Amount1)) {CurrentPixel = Amount2;}
break;
}
}
else
{
switch(Amount4)
{
case 0: // Vertical Lines
if (x % Lines + 1 > Amount1) {CurrentPixel = Amount2;}
break;
case 1: // Horizontal Lines
if (y % Lines + 1 > Amount1) {CurrentPixel = Amount2;}
break;
case 2: // Grid
if ((x % Lines + 1 > Amount1) && (y % Lines + 1 > Amount1)) {CurrentPixel = Amount2;}
break;
}
}
dst[x,y] = CurrentPixel;
}
}
}
На этом можно было бы закончить, но... Давайте обратимся к Using CodeLab to Build a DLL BoltBait'а. В секции Default мы найдем некоторую полезную информацию и оформим аналогичную для нашего сценария:
// Submenu: Render - поместим наш эффект в подменю Узоры меню Эффекты (кстати, для CodeLab Render и Узоры - записи равнозначные)
// Name: Линии/Сетка - название эффекта в меню
// Title: Линии/Сетка - заголовок интерфейса UI эффекта
// Author: ReMake - имя автора эффекта
// Desc: Рисование прямых линий или сетки - описание эффекта
// Keywords: paint.net|эффект|рисование|линии|сетка - ключевые слова, по которым ваш эффект может быть найден в интернете
// URL: http://www.getpaint.net/redirect/plugins.html - ваш адрес в сети (или на форуме)
Вставим эту информацию над блоком кода интерфейса UI:
Код: Выделить всё
// Submenu: Render
// Name: Линии/Сетка
// Title: Линии/Сетка
// Author: ReMake
// Desc: Рисование прямых линий или сетки
// Keywords: paint.net|эффект|рисование|линии|сетка
// URL: http://www.getpaint.net/redirect/plugins.html
#region UICode
int Amount1 = 10; // [1,100] Ширина линии
ColorBgra Amount2 = ColorBgra.FromBgr(0,0,0); // Цвет
int Amount3 = 10; // [1,100] Ширина интервала
byte Amount4 = 0; // [1] Вид|Вертикальные линии|Горизонтальные линии|Сетка
bool Amount5 = false; // [0,1] Инвертировать
#endregion
И последнее, осталось оформить значок для интерфейса нашего эффекта в виде файла PNG размером 16 на 16 пикселей. С помощью нашего эффекта я создал вот такой значок:
Теперь давайте сохраним наш эффект как DLL файл: Файл -> Сохранить как DLL... В представленном вам диалоге есть почти вся информация. Щелкните по ссылке Выбор значка и выберите ваш значок. Нажмите кнопку Создать - ваш новый эффект готов!
Сравните интерфейс вашего эффекта с рисунком, приведенным выше.
С точки зрения программирования наш код, может быть, не очень элегантен, но это всего лишь учебное руководство. Я также не ставил перед собой цель объяснить алгоритм работы сценария - разобраться в этом задача пользователя.
Примеры работы эффекта смотрите в теме Линии/Сетка.
Надеюсь первый шаг в CodeLab оказался не очень сложным.