Sign in to follow this  
nycos62

SpriteSheet Grid Modifier

Recommended Posts

Hello folks,

 

wonderfull work !, already made 3 plugin for pixelart automations, I love codeLab

is there a way to change canvas Size by code with CodeLab ?, I didn't find informations about that on boltbait website

 

cheers !

 

 

Share this post


Link to post
Share on other sites

ok :)

thank you, anyway

 

I don't know if it could interest someone, but I made this :

image you have a spritesheet with Cells 32px by 32px with multiple layers ... ... and you want to draw a weapon but you didn't let enough room to draw it , so you must extend the cells size, it's a huge work to do with mouse/selection/displace things, but with this code it's really easy :

 

example:

spritesheet (canvas size 160*160, with 5*5 cells of 32*32 px)

you want now 40*40px

 

first you change canvas size as it cannot be done by code from 160*160 to 200*200 px (5 * 40 px )

so you set this (see picture attached)

 

 

source code : (quick and dirty but it's working... :) )

// Name: SpriteSheet Grid Modifier
// Submenu: PixelArt
// Author: Nycos62
// Title: SpriteSheet Grid Modifier
// Version: 0.1
// Desc: Modify Cell Grid Size in all layers
// Keywords:
// URL:
// Help:
#region UICode
IntSliderControl Amount1 = 0; // [0,100] X Cell number
IntSliderControl Amount2 = 0; // [0,100] Y Cell number
IntSliderControl Amount3 = 0; // [0,100] Original Cell width (X)
IntSliderControl Amount4 = 0; // [0,100] Original Cell height (Y)
IntSliderControl Amount5 = 0; // [0,100] Desired Cell width (New X)
IntSliderControl Amount6 = 0; // [0,100] Desired Cell height (New Y)
#endregion

void Render(Surface dst, Surface src, Rectangle rect)
{
    int XOffset = 0;
    int YOffset = 0;
    int XDiff = Amount5 - Amount3;
    int YDiff = Amount6 - Amount4;
    if (XDiff %2 == 0)
        XOffset = XDiff / 2;
    else
        XOffset = (int)(XDiff / 2);//odd even cell dimension TODO
    if (YDiff %2 == 0)
        YOffset = YDiff / 2;
    else
        YOffset = (int)(YDiff / 2);//odd even cell dimension TODO
    
    int XOffsetAfter = XDiff - XOffset;
    int YOffsetAfter = YDiff - YOffset;
    
    ColorBgra transparentPixel = new ColorBgra();
    transparentPixel.A = 0;
    transparentPixel.B = 0;
    transparentPixel.G = 0;
    transparentPixel.Bgra = 0;
        
    for (int y = rect.Top; y < rect.Bottom; y++)
    {
        for (int x = rect.Left; x < rect.Right; x++)
        {
            dst[x,y] = transparentPixel;
        }
    }
    
    for (int cx = 0; cx < Amount1; cx++)
    {
        int XDecay = Math.Max(cx,0) * XOffsetAfter;
        for (int cy = 0; cy < Amount2; cy++)
        {
            int YDecay = Math.Max(cy,0) * YOffsetAfter;
            
            if (IsCancelRequested) return;
            
            //Copy cell with Offset
            for (int cell_posX = 0; cell_posX < Amount3; cell_posX++)
            {
                
                for (int cell_posY = 0; cell_posY < Amount4; cell_posY++)
                {   
                    //TODO : ignore dst out of bound x,y
                    dst[cx * Amount3 + cell_posX + (cx+1) * XOffset + XDecay, cy * Amount4 + cell_posY + (cy+1) * YOffset + YDecay] = src[cx * Amount3 + cell_posX, cy * Amount4 + cell_posY];
                }
            }
        }
    }
}

I hope it could help someone one day , it was really a pain to do by mouse and selection before I discovered CodeLab

pluginExample.png

Edited by nycos62

Share this post


Link to post
Share on other sites
38 minutes ago, nycos62 said:

I don't know if it could interest someone, but I made this :

 

I don't work on spritesheets, but that seems like it would be very useful to some people.

 

Here are a few suggestions...

 

Change all the defaults from 0. That way, when someone first opens the effect they can see it's doing something; rather than just blanking the canvas.

 

 

Change this code:

ColorBgra transparentPixel = new ColorBgra();
transparentPixel.A = 0;
transparentPixel.B = 0;
transparentPixel.G = 0;
transparentPixel.Bgra = 0;
    
for (int y = rect.Top; y < rect.Bottom; y++)
{
    for (int x = rect.Left; x < rect.Right; x++)
    {
        dst[x,y] = transparentPixel;
    }
}

To this:

for (int y = rect.Top; y < rect.Bottom; y++)
{
    for (int x = rect.Left; x < rect.Right; x++)
    {
        dst[x,y] = ColorBgra.Transparent;
    }
}

Or, better yet, this one line:

dst.Clear(rect, ColorBgra.Transparent);

 

  • Like 1
  • Upvote 1

Share this post


Link to post
Share on other sites

After copying and pasting the original code into codelab I am able to preview the effect and see that a white layer would be rendered to square blocks.

Moving the sliders adjusts as expected but of course it doesn't render to canvas.

SpriteError.png.dbe43d869e9ce8e42724a7fd70018218.png

 

After I build and install the DLL, then restart Paint.Net, moving the fourth slider results in this crash report..

 

File: C:\Program Files\paint.net\Effects\SpriteSheetGridModifier.dll
      Name: SpriteSheetGridModifierEffect.SpriteSheetGridModifierEffectPlugin
      Version: 0.1.6963.23219
      Author: Copyright ©2019 by Nycos62
      Copyright: Modify Cell Grid Size in all layers
      Website: https://www.getpaint.net/redirect/plugins.html
      Full error message: PaintDotNet.WorkerThreadException: Worker thread threw an exception ---> System.ArgumentOutOfRangeException: Coordinates out of range, max={Width=799, Height=599}
Parameter name: (x,y)
Actual value was {X=-11,Y=0}.
   at PaintDotNet.ExceptionUtil.ThrowArgumentOutOfRangeException(String paramName, Object actualValue, String message) in D:\src\pdn\src\Base\ExceptionUtil.cs:line 88
   at PaintDotNet.Surface.GetSetItemThrow(Int32 x, Int32 y) in D:\src\pdn\src\Core\Surface.cs:line 813
   at SpriteSheetGridModifierEffect.SpriteSheetGridModifierEffectPlugin.Render(Surface dst, Surface src, Rectangle rect)
   at SpriteSheetGridModifierEffect.SpriteSheetGridModifierEffectPlugin.OnRender(Rectangle[] rois, Int32 startIndex, Int32 length)
   at PaintDotNet.Effects.Effect`1.Render(EffectConfigToken parameters, RenderArgs dstArgs, RenderArgs srcArgs, Rectangle[] rois, Int32 startIndex, Int32 length) in D:\src\pdn\src\Effects\Effect`1.cs:line 99
   at PaintDotNet.Effects.BackgroundEffectRenderer.RenderWithClipMask(Effect effect, EffectConfigToken token, RenderArgs dstArgs, RenderArgs srcArgs, RectInt32[] rois, IRenderer`1 clipMaskRenderer) in D:\src\pdn\src\PaintDotNet\Effects\BackgroundEffectRenderer.cs:line 196
   at PaintDotNet.Effects.BackgroundEffectRenderer.RendererContext.RenderTile(EffectConfigToken token, Int32 tileIndex) in D:\src\pdn\src\PaintDotNet\Effects\BackgroundEffectRenderer.cs:line 175
   at PaintDotNet.Effects.BackgroundEffectRenderer.RendererContext.RenderNextTile(EffectConfigToken token) in D:\src\pdn\src\PaintDotNet\Effects\BackgroundEffectRenderer.cs:line 167
   at PaintDotNet.Effects.BackgroundEffectRenderer.ThreadFunction() in D:\src\pdn\src\PaintDotNet\Effects\BackgroundEffectRenderer.cs:line 267
   --- End of inner exception stack trace ---
   at PaintDotNet.Effects.BackgroundEffectRenderer.DrainExceptions() in D:\src\pdn\src\PaintDotNet\Effects\BackgroundEffectRenderer.cs:line 443
   at PaintDotNet.Effects.BackgroundEffectRenderer.Abort() in D:\src\pdn\src\PaintDotNet\Effects\BackgroundEffectRenderer.cs:line 399
   at PaintDotNet.Effects.BackgroundEffectRenderer.Start() in D:\src\pdn\src\PaintDotNet\Effects\BackgroundEffectRenderer.cs:line 345
   at PaintDotNet.Menus.EffectMenuBase.<>c__DisplayClass41_4.<RunEffectImpl>b__4() in D:\src\pdn\src\PaintDotNet\Menus\EffectMenuBase.cs:line 926

Starting to think something might be wrong with my system :)

 

 

  • Like 1

Share this post


Link to post
Share on other sites
21 minutes ago, AndrewDavid said:

Starting to think something might be wrong with my system :)

 

Looks like this is the real issue:

Quote

Actual value was {X=-11,Y=0}.

A negative coordinate.  nycos62's math must be incorrect.

  • Like 1

Share this post


Link to post
Share on other sites

@toe_head2001

Thanks for the reply. Looks like it is very easy to go out of bounds. Adjusting the sliders in the proper order as not to go out of bounds is the answer. No safeguards to warn the user like I have seen in other plugins. Adjusting the sliders from the bottom seemed to work until I got to the top sliders and rendered another crash. Same issue with values set to negative numbers. Posted for @nycos62

  • Like 1

Share this post


Link to post
Share on other sites
1 hour ago, AndrewDavid said:

After I build and install the DLL, then restart Paint.Net, moving the fourth slider results in this crash report..

 

sorry, I posted a quick and dirty code as I was really excited with the discover of codeLab 15 minutes ago.

I rework the script tomorrow and post a bug free code 

  • Like 1

Share this post


Link to post
Share on other sites

Here it is :

// Name: SpriteSheet Grid Modifier
// Submenu: PixelArt
// Author: Nycos62
// Title: SpriteSheet Grid Modifier
// Version: 0.1
// Desc: Modify Cell Grid Size in all layers
// Keywords:
// URL:
// Help:
#region UICode
IntSliderControl Amount1 = 3; // [0,100] X Cell number
IntSliderControl Amount2 = 3; // [0,100] Y Cell number
IntSliderControl Amount3 = 10; // [0,100] Original Cell width (X)
IntSliderControl Amount4 = 10; // [0,100] Original Cell height (Y)
IntSliderControl Amount5 = 14; // [0,100] Desired Cell width (New X)
IntSliderControl Amount6 = 14; // [0,100] Desired Cell height (New Y)
#endregion

void Render(Surface dst, Surface src, Rectangle rect)
{
    //clear dest
    dst.Clear(rect, ColorBgra.Transparent);
    
    int XOffset = 0;
    int YOffset = 0;
    int XDiff = Amount5 - Amount3;
    int YDiff = Amount6 - Amount4;
    if (XDiff %2 == 0)
        XOffset = XDiff / 2;
    else
        XOffset = (int)(XDiff / 2); //TODO verify
    if (YDiff %2 == 0)
        YOffset = YDiff / 2;
    else
        YOffset = (int)(YDiff / 2); //TODO verify
    
    int XOffsetAfter = XDiff - XOffset;
    int YOffsetAfter = YDiff - YOffset;
    
    for (int cx = 0; cx < Amount1; cx++)
    {
        int XDecay = Math.Max(cx,0) * XOffsetAfter;
        for (int cy = 0; cy < Amount2; cy++)
        {
            int YDecay = Math.Max(cy,0) * YOffsetAfter;
            
            if (IsCancelRequested) return;
            
            //Copy cell with Offset
            for (int cell_posX = 0; cell_posX < Amount3; cell_posX++)
            {
                
                for (int cell_posY = 0; cell_posY < Amount4; cell_posY++)
                {   
                    int Xdest = cx * Amount3 + cell_posX + (cx+1) * XOffset + XDecay;
                    int Ydest = cy * Amount4 + cell_posY + (cy+1) * YOffset + YDecay;
                    int XSource = cx * Amount3 + cell_posX;
                    int YSource = cy * Amount4 + cell_posY;
                    //avoid drawing out of bounds dst/src [x,y]
                    if (Xdest < dst.Bounds.Width && Ydest < dst.Bounds.Height && 
                        XSource < dst.Bounds.Width && YSource < dst.Bounds.Height)
                        dst[Xdest, Ydest] = src[XSource, YSource];
                }
            }
        }
    }
}

 

  • Like 1

Share this post


Link to post
Share on other sites

DrawBackGroundGrid plugin to "draw a grid on the background spritesheet layer"

 

// Name: DrawGrid
// Submenu: PixelArt
// Author: Nycos62
// Title: DrawGrid
// Version: 0.1
// Desc: Draw a background spritesheet grid for a given width and height
// Keywords:
// URL:
// Help:
#region UICode
IntSliderControl Amount1 = 32; // [0,1000] Grid cell width (X)
IntSliderControl Amount2 = 32; // [0,1000] Grid cell height (Y)
#endregion

void Render(Surface dst, Surface src, Rectangle rect)
{
    ColorBgra GridOdd = ColorBgra.HotPink;
    ColorBgra GridEven = ColorBgra.Lime;
        
    for (int y = rect.Top; y < rect.Bottom; y++)
    {
        if (IsCancelRequested) return;
        for (int x = rect.Left; x < rect.Right; x++)
        {
            if (x/Amount1 %2 == 0)
                if (y/Amount2 %2 == 0)
                    dst[x,y] = GridOdd;
                else
                    dst[x,y] = GridEven;
            else
                if (y/Amount2 %2 == 0)
                    dst[x,y] = GridEven;
                else
                    dst[x,y] = GridOdd;
            
            
        }
    }
}

 

DrawGridPreview.png

Share this post


Link to post
Share on other sites

DrawCenterCell to draw a line on the center of the cell (line has 2 pixel width if cell dimension is even to see the real center of the cell)

 

// Name: DrawCenterCell
// Submenu: PixelArt
// Author: Nycos62
// Title: Draw Center Cell Indicator
// Version: 0.1
// Desc: Draw a line in center of cell for a given width and height
// Keywords:
// URL:
// Help:
#region UICode
IntSliderControl Amount1 = 32; // [0,1000] Grid cell width (X)
IntSliderControl Amount2 = 32; // [0,1000] Grid cell height (Y)
#endregion

void Render(Surface dst, Surface src, Rectangle rect)
{
	//clear dest
    dst.Clear(rect, ColorBgra.Transparent);
	
	
    ColorBgra LineColor = ColorBgra.White;
    int CellCenterX = Amount1 / 2;
    int CellCenterY = Amount2 / 2;
            
    for (int y = rect.Top; y < rect.Bottom; y++)
    {
        if (IsCancelRequested) return;
        for (int x = rect.Left; x < rect.Right; x++)
        {            
            if ((x + CellCenterX)%Amount1 == 0 && y%2 == 0)
                dst[x,y] = LineColor;
            if ((y + CellCenterY)%Amount2 == 0 && x%2 == 0)
                dst[x,y] = LineColor;
            if (Amount1 % 2 == 0)
                if ((x + CellCenterX - 1)%Amount1 == 0 && y%2 == 1)
                    dst[x,y] = LineColor;
            if (Amount2 % 2 == 0)
                if ((y + CellCenterY - 1)%Amount2 == 0 && x%2 == 1)
                    dst[x,y] = LineColor;
        }
    }
}

 

 

DrawCenterCellPreview.png

Edited by nycos62

Share this post


Link to post
Share on other sites
6 minutes ago, nycos62 said:

It could be great to add a OpenFileLocation Button after CodeLab generate a dll

 

CodeLab just puts the built zip files on the user's desktop.  They should be pretty easy to find by pressing and holding the windows key then pressing D.

Share this post


Link to post
Share on other sites

@nycos62

Thanks for the updated code. Works as expected now. I believe i can make use of it in something other than sprite sheets. The more code I gather, the more chance I have to learn.

Your other two may be a little redundant. We have a few grid makers already built, but the center line I believe is unique for centering on the sprite sheet squares. With over 1K plugins now, its difficult to find something new. :)

 

  • Like 1

Share this post


Link to post
Share on other sites

good news ! I could not find these plugins, searched about 1 hour, and found codeLab, cost less time to code than search 😃

 

Edited by nycos62

Share this post


Link to post
Share on other sites
On 1/26/2019 at 9:09 PM, AndrewDavid said:

We have a few grid makers already built

with this plugin you can guess the sprite dimensions when you start to work with pixel art materials found in google pictures, and you must know dimensions to import sprite sheets in game engine. For my personnal use I find them pretty effective. SpriteSheets are often packed, and in order to use AnimationHelper plugin from Pixelbyte Studio, you must center your sprite on tiles with same dimension

Edited by nycos62

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this