Jump to content

How to make custom shapes for paint.net 4.0.6+


BoltBait

Recommended Posts

They are 2 different ways to create custom shapes:

The Easy Way - Shape Maker

The Hard Way - Explained below

Most of the shapes in my plugin pack were created the "hard way", that is coded by hand using the Kaxaml editor.

Before we begin, download and install Kaxaml: http://www.kaxaml.com/

There are 2 ways to hand code an XAML shape for paint.net:

  • Simple PathGeometry - House
  • GeometryGroup - Smart Phone / Cube

Both ways have their good points. However, you should know that there are things you can do in the GeometryGroup method that you can't do with the Simple PathGeometry. I'll explain both and you can choose which method to use.

 

 

Simple PathGeometry

Here is a template / example you can use right in Kaxaml:

<Page
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
	<Grid>  
		<Canvas>
			<Path Fill="#D2E9F6" Stroke="#5894C1" StrokeThickness="1"
				Data="F1 M 21,142 L 160,22 L 300,142 L 300,318 L 21,318 Z"
			/>
		</Canvas>
	</Grid>
</Page>

 

You just need to replace the data "F1 M 21,142 ... Z" etc. with the instructions to draw your own shape.

Here is the language reference: Language Reference for XAML Mini-Language

The string starts with either F0 (default if not specified) or F1 indicating fill mode 0 (even odd) or fill mode 1 (non-zero).

The M command moves to the specified point, the L command draws a line to the specified end point, and the Z command closes a shape by drawing a line back to the last M command.

Check the reference page for more commands, like curves, etc.

Once you are happy with the shape in Kaxaml, take the data string and drop it into the template for a paint.net shape:

<ps:SimpleGeometryShape xmlns="clr-namespace:PaintDotNet.UI.Media;assembly=PaintDotNet.Framework"
	xmlns:ps="clr-namespace:PaintDotNet.Shapes;assembly=PaintDotNet.Framework"
	DisplayName="House"
	Geometry="F1 M 21,142 L 160,22 L 300,142 L 300,318 L 21,318 Z" />

 

The "DisplayName" field is where you specify the shape name that will appear when you hover over the shape in the shape menu. The "Geometry" field is where you put your drawing instructions.

Once you've saved this file onto your Desktop, copy it to your shapes directory: C:\Program Files\paint.net\Shapes

Restart paint.net and check to see if it appears in the menu. If it doesn't appear, click the gear icon in the upper right corner of the paint.net screen and check in the plugin errors tab.

 

 

GeometryGroup

Here is a template / example you can use right in Kaxaml:

<Page
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
	<Grid>
		<Path Fill="#D2E9F6" Stroke="#5894C1" StrokeThickness="1">
			<Path.Data>
				<GeometryGroup>
					<RectangleGeometry Rect="10,10,184,307" RadiusX="10" RadiusY="10" />
					<RectangleGeometry Rect="15,40,174,227" RadiusX="10" RadiusY="10" />
					<RectangleGeometry Rect="74,21,60,7" RadiusX="10" RadiusY="10" />
					<EllipseGeometry Center="103,290" RadiusX="15" RadiusY="15" />
				</GeometryGroup>
			</Path.Data>
		</Path>
	</Grid>
</Page>

 

I chose to use basic shapes to create the cell phone because I needed to use rounded rectangles. These are easy here as you can specify RadiusX and RadiusY for rectangle corners... something you can't do using the mini-language.

And, here is how it would look as a paint.net shape:

<ps:SimpleGeometryShape xmlns="clr-namespace:PaintDotNet.UI.Media;assembly=PaintDotNet.Framework"
	xmlns:ps="clr-namespace:PaintDotNet.Shapes;assembly=PaintDotNet.Framework"
	DisplayName="Smart Phone">
		<GeometryGroup>
			<RectangleGeometry Rect="10,10,184,307" RadiusX="10" RadiusY="10" />
			<RectangleGeometry Rect="15,40,174,227" RadiusX="10" RadiusY="10" />
			<RectangleGeometry Rect="74,21,60,7" RadiusX="10" RadiusY="10" />
			<EllipseGeometry Center="103,290" RadiusX="15" RadiusY="15" />
		</GeometryGroup>
</ps:SimpleGeometryShape>

Notice the simple copy-and-paste needed. Then, don't forget to specify a Display Name.

Note: paint.net shapes are limited to one path data or one GeometryGroup.

 

 

Another Example

Here is an example of using a GeometryGroup that looks very similar to the Simple PathGeometry we learned first:

<Page
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
	<Grid>  
		<Path Fill="#D2E9F6" Stroke="#5894C1" StrokeThickness="1">
			<Path.Data>
				<PathGeometry FillRule="Nonzero">
					<PathFigure IsClosed="True" IsFilled="True" StartPoint="0,22">
						<LineSegment Point="58,0" IsSmoothJoin="True" />
						<LineSegment Point="116,22" IsSmoothJoin="True" />
						<LineSegment Point="116,93" IsSmoothJoin="True" />
						<LineSegment Point="58,116" IsSmoothJoin="True" />
						<LineSegment Point="0,93" IsSmoothJoin="True" />
						<LineSegment Point="0,22" IsSmoothJoin="True" />
					</PathFigure>
					<PathFigure IsClosed="False" IsFilled="False" StartPoint="58,46">
						<LineSegment Point="0,22" />
					</PathFigure>
					<PathFigure IsClosed="False" IsFilled="False" StartPoint="58,46">
						<LineSegment Point="58,116" />
					</PathFigure>
					<PathFigure IsClosed="False" IsFilled="False" StartPoint="58,46">
						<LineSegment Point="116,22" />
					</PathFigure>
				</PathGeometry>
			</Path.Data>
		</Path>
	</Grid>
</Page>

 

Here I chose to use the expanded syntax because I can control the shape of the line endings to make the drawing look better.

Here's how it looks as a paint.net shape:

<ps:SimpleGeometryShape xmlns="clr-namespace:PaintDotNet.UI.Media;assembly=PaintDotNet.Framework"
	xmlns:ps="clr-namespace:PaintDotNet.Shapes;assembly=PaintDotNet.Framework"
	DisplayName="Cube">
	<PathGeometry FillRule="Nonzero">
		<PathFigure IsClosed="True" IsFilled="True" StartPoint="0,22">
			<LineSegment Point="58,0" IsSmoothJoin="True" />
			<LineSegment Point="116,22" IsSmoothJoin="True" />
			<LineSegment Point="116,93" IsSmoothJoin="True" />
			<LineSegment Point="58,116" IsSmoothJoin="True" />
			<LineSegment Point="0,93" IsSmoothJoin="True" />
			<LineSegment Point="0,22" IsSmoothJoin="True" />
		</PathFigure>
		<PathFigure IsClosed="False" IsFilled="False" StartPoint="58,46">
			<LineSegment Point="0,22" />
		</PathFigure>
		<PathFigure IsClosed="False" IsFilled="False" StartPoint="58,46">
			<LineSegment Point="58,116" />
		</PathFigure>
		<PathFigure IsClosed="False" IsFilled="False" StartPoint="58,46">
			<LineSegment Point="116,22" />
		</PathFigure>
	</PathGeometry>
</ps:SimpleGeometryShape>

 

Just copy all of the PathGeometry tag into the paint.net template. Don't forget to specify a Display Name.

GeometryGroup and PathFigure are really the same method. You can combine them by putting a PathGeometry inside of a GeometryGroup at the same level as the RectangleGeometry or EllipseGeometry in the first example above.

____________________

Edited by toe_head2001
Fixed link to Kaxaml
  • Upvote 4
Link to comment
Share on other sites

The child element of SimpleGeometryShape can be any Geometry-derived class. You aren't restricted to PathGeometry or GroupGeometry.

 

For instance, you could have it be just an EllipseGeometry. Although at that point, just use the built-in ellipse/circle shape :)

  • Upvote 1

The Paint.NET Blog: https://blog.getpaint.net/

Donations are always appreciated! https://www.getpaint.net/donate.html

forumSig_bmwE60.jpg

Link to comment
Share on other sites

  • 8 months later...
  • 1 month later...

See - someone reads your tut @BoltBait. Took me a few tries - but by George I think I got it!

I plan to try using Kaxaml to draw my next shape.

And correct me if I'm wrong - you can't import the geo code into ShapeMaker. Figured that out all on my own but it did frustrate me for awhile.

 

Thanks for the tut and the examples. I enjoy learning new things. B)

 

 

  • Upvote 1

PaintNetSignature.png.6bca4e07f5d738b2436f83d0ce1b876f.png

Link to comment
Share on other sites

52 minutes ago, AndrewDavid said:

... you can't import the geo code into ShapeMaker.

 

ShapeMaker has a nice manual; let's see what it says about 'Paste Path Stream':

Paste Path is capable of interpreting StreamGeometry strings which are a lightweight version of
PathGeometry strings. Both can appear in XAML files - but only StreamGeometry can be parsed by
ShapeMaker. Users attempting to paste in PathGeometry strings will receive an error message even
though there is nothing 'wrong' with the string.

So, you can import StreamGeometry, but not PathGeometry.

 

BoltBait's example of StreamGeometry:

F1 M 21,142 L 160,22 L 300,142 L 300,318 L 21,318 Z

 

  • Upvote 1

(September 25th, 2023)  Sorry about any broken images in my posts. I am aware of the issue.

bp-sig.png
My Gallery  |  My Plugin Pack

Layman's Guide to CodeLab

Link to comment
Share on other sites

36 minutes ago, toe_head2001 said:

Paste Path Stream

That's for the advanced users.

 

Not there yet!

Thanks for the reference though.

Haven't played with that aspect yet @toe_head2001.

I'll get there.

PaintNetSignature.png.6bca4e07f5d738b2436f83d0ce1b876f.png

Link to comment
Share on other sites

  • 4 months later...

Thanks for the reply.

The .xaml file is somehow stored with an error and does not appear on paint.net. It is not recognized by the system. (Of course I'm using the correct folder, that's not the problem.)

 

When I try to retrieve with shapemaker the .xaml file (import PDN shape), only nonsensical streaks appear.

 

Maybe I'm doing something wrong while editing and then saving, even though I followed the instructions.

 

Is there any step that can be done wrong and generate files with error?
because that is not the only shape with which this happens to me.

 

I will continue to try, anyway, I would appreciate if you could upload the file shiny.xaml to the forum to be able to occupy it in the meantime.

GALT

Link to comment
Share on other sites

@Gustavo Lavanchy, I've sent you a private message regarding a localization bug. (which I think is your issue)

 

I meant to release a bugfix release of ShapeMaker a few weeks ago. I'll try to post it in the coming days.

(September 25th, 2023)  Sorry about any broken images in my posts. I am aware of the issue.

bp-sig.png
My Gallery  |  My Plugin Pack

Layman's Guide to CodeLab

Link to comment
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.

×
×
  • Create New...