Path2D Studio Beta

Hi Developers!

We are excited to announce the Studio beta release of the new Path2D API and tooling to support this API, so you can create, edit, and visualize 2D splines. Path2D provides creators with a 2D spline instance, enabling them to create UI elements and effects like graph editors and UI animations.

image4

How to Enable and Use Path2D

To enable the beta feature:

  1. Launch Studio.
  2. Select File, Beta Features.
  3. Check the box next to “Path2D Beta” and click Save.
  4. When prompted, restart Studio.

To use Path2D:

  • Insert a Path2D instance (from the Explorer) in the UI hierarchy under any ScreenGUI, BillboardGUI and SurfaceGUI.
    • Path2D will also work as a child of any GuiObject but it won’t ignore folders like other UI elements.
  • After inserting a Path2D into the tree structure, select it in the Explorer to bring up the in-viewport tooling.
  • Path2D does not natively clip with other UI objects. However, you can use Path2D as a child of a Canvas Group to achieve clipping

Tooling

You can use the in-viewport tooling to create and modify Path2D instances. There are 3 tooling modes for editing the spline:

  1. Select Tool (Hot Key ‘s’)

image5

  1. Add Point (Hot Key ‘p’)

image4

  1. Add Tangent (Hot Key (‘t’)

image2

Tips

  • In Add Point mode, if there are already segments created, you will either need to click on the beginning or end control points and continue to add from there or you will be able to insert a control point anywhere along the Path2D.

image3

  • In Select Tool and Add Tangent modes, right clicking on control points or tangent handles will bring up a context menu with the following options:

    • Tangent handles, Delete tangent

    • Control Point, Break/Mirror tangents, Clear Tangents, Delete (control point)

    • Undo/Redo keys work as expected

image7

  • In the Path2D instance, you will be able to select a control point by inserting the correct index. It will then bring up info about the control point, the position and tangent values.

image1

API

Properties
  • Visible: bool

    • Determines if the spline should render or not. When visible == false, the spline is still queryable and updatable.
  • Thickness: Number

  • Color: Color3

  • GetPositionOnCurve(t: float) → UDim2

    • Queries the curve for the position at a given t
      • t == 0, beginning. t == 0.5 middle (parametric center), t == 1 end
  • GetPositionOnCurveArcLength(t: float) → UDim2

    • Queries the curve for the position at a given t
      • t == 0, beginning. t == 0.5 middle (geometric center), t == 1 end
    • The arc length makes sure that the distance between each point along the curve is consistent.
  • GetTangentOnCurve(t: float) → Vector2

    • Returns the tangent at a given t
    • t == 0, beginning. t == 0.5 middle (parametric center), t == 1 end
  • GetTangentOnCurveArcLength(t: float) → Vector2

    • Returns the tangent at a given t
    • t == 0, beginning. t == 0.5 middle (geometric center), t == 1 end
  • GetControlPoints() → List

  • SetControlPoints(List)

    • Sets all the control points for a given Path2D, replacing what was there.
    • Will fail if anything other than a Path2DControlPoint is passed in
    • Note: the resulting update is expensive so it is recommended that this only be used if all control points need to be changed
  • GetControlPoint(index: int) → Path2DControlPoint

    • Returns the control point at the requested index or nil in the Path2DControlPoint object
    • If the index is out of range, throws a warning.
  • UpdateControlPoint(index: int, Path2DControlPoint)

    • Updates the control point at the requested index. If the index does not exist, it will throw a warning
  • InsertControlPoint(index: int, Path2DControlPoint)

    • Creates a control point at the requested index. If the index is larger than the control point list size or less than 0 return an error.
    • This function will allow you to insert a control point at the beginning or end of the list of control points.
  • RemoveControlPoint(index: int)

    • Removes the control point at the requested index. If the index is out of range, throw a warning

New Luau Atomic Type: Path2DControlPoint

  • Path2DControlPoint.new()
  • Path2DControlPoint.new(position: UDim2)
  • Path2DControlPoint.new(position: UDim2, Left Tangent: UDim2, Right Tangent: UDim2)

See documentation for Path2D here.

Example Usage

The APIs GetPositionOnCurve, GetPositionOnCurveArcLength, GetTangentOnCurve, and GetTangentOnCurve are all used to sample the curve at a given t value. The t value must be between [0, 1]. Sampling at intervals between 0 and 1 can allow you to use the positions at any point along the curve. In this example, you can move a frame along a spline.

-- Make your Path2D using the in viewport tooling
-- Create a frame or some other object you'd like to move along the spline

local path = script.Parent.Path2D
local frame = script.Parent.Frame

local maxIter = 100

for counter = 0, maxIter do
	local t = counter / maxIter
	local position = path:GetPositionOnCurve(t)
	frame.Position = position
	wait()
end

Known Issues

  • Performance is still being improved.
  • Surface and billboard gui positions are not as expected
  • Path2D underneath a Canvas Group breaks in some cases, and we’re in the process of fixing this.
  • Team create has some issues with Path2D:
    • Editing Path2D won’t replicate to other users
    • Entering team test won’t show Path2D
    • The control points may get reset

We’d love to know your feedback and learn how you plan to use this API! If you run into any issues or have further questions, please let us know!

Special thanks to the team who worked on this feature: @PotionSeller33, @MetaVars, @wengawenga, @0xabcdef1234, @ProtoValence, @Slim_Fandango, @guacandtoast @TangyTrout and everyone else who helped contribute!

383 Likes

This topic was automatically opened after 10 minutes.

This is an awesome addition! Some notes:

  • It’d be nicer if we had this as a Luau data type rather than just an instance, so we can easily do Bezier curve computations in code when there’s no physical analogue showing on screen. As an instance, we have to deal with higher memory and engine interop overhead.
  • It’d be revolutionary if you could define closed paths with a fill colour. We’d have native polygon rendering!
  • Antialiasing pretty please :slight_smile:

This is fantastic news though and I love everything about what you’ve done with the editor. Keep up the banger updates!

140 Likes

Although I haven’t tried this yet, this looks like it’ll be game-changing when it comes to spline making.

Now I must ask, Path3D when? :thinking:

48 Likes

Closed paths with maybe even some primitive overlap computation would be amazing for this feature

14 Likes

The WIP while making the path looks straight up like we’re setting up a powerpoint :joy:
Took a peek on the documentation, pretty exciting that it has more control than TweenService (judging from the amount of methods applicable)

16 Likes

This is awesome that we can now create graph editors easily without hundreds of frames, however I can’t help but notice the lack of anti-aliasing.

I would love if anti-aliasing was added or at least a transparency property as its pretty unappealing to low resolution monitors currently

9 Likes

This is GREAT, I hope and wish that they add more GuiObjects like Sliders, Checkbox or Dropdowns, that would be SUPER GREAT, thank you very much Roblox for adding things like this

18 Likes

Another huge massive update, that will refine UI/UX possibilities. Thank you ROBLOX for making it simpler for us to animate UIs!

14 Likes
  1. you don’t see the curves and lines in-game (or you can toggle it on/off)
  2. anti-aliasing is really just the GIF compressing being badly rendered

if you’re not talking about image/frame outline using rotation properties in studio,
your concern about low-res is non-existent

6 Likes

This seems really cool.

Even if I may not use it frequently, I see it creating some opportunities for game ideas, which is always beneficial.

5 Likes

that’s great! but we need anti-aliasing pretty please :sob:
really essential for a clean UI

5 Likes

@Elttob

Thanks for the suggestions, we’ll consider these in the future!

You will be able to see Path2D in game but there is a Visible property you can use. But during the studio beta, Path2D will not work on any clients.

19 Likes

Adding on to this, if we get Path2D as a datatype, it would be cool to see a Path3D datatype for splines.

13 Likes

Thank you, i love you. Thank you, i love you. Thank you, i love you.

Side note: Can people give ideas for really cool things this can be used for. I would like to try to make them.

8 Likes

OH MY GOD??? ROBLOX. WHAT IS THIS NEW THING YOU JUST COOKED. As a Video Editor who understands the importance of visual, most games will need this in future brainstorms. I have not known the use case yet, but there’s definitely a lot for what this can be used for.

KEEP UP THE GOOD WORK GUYS

6 Likes

Really cool update! Right now the Path2D instances aren’t at all affected by any other UI instance sadly. Path2D Instance positioning seems to be really inconsistent too across SurfaceGui’s and ScreenGui’s, Example:
While inside a ScreenGui

and while inside a SurfaceGui

Would also be cool if we got some sort of Subdivision/Resolution property for the Path2D instances. I believe there could be plenty of use cases in which a lower resolution like for some sort of hard to see background detail or maybe even higher resolution for some rarer “high fidelity” cases.

10 Likes

I made this graph with Path2D.

I was just trying it out but it looks great and I’m impressed at how easy it is to make.

local function DrawGraphWithData(data: { number }, name: string?)
	local graph = path2D:Clone()
	graph.Parent = script.Parent
	graph.Color = BrickColor.random().Color
	
	local iterations = #data
	
	task.spawn(function()	-- dont mind this lol
		for i = 0, iterations do
			local alpha = i / iterations
			local number = data[i + 1]
			local udimPosition = UDim2.fromScale(alpha, number)
			
			graph:InsertControlPoint(i + 1, Path2DControlPoint.new(udimPosition))
		end
	end)
end
31 Likes

Looks really cool ngl! Cant wait to see what people will do once they get their hands on this

6 Likes

It’s not its own data type (it’s an instance), but we can create 3D splines using Vector3Curves, just thought you might like to know

6 Likes