This is how you can make Path2D visible and controllable in play mode (my bit of contribution)

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Suleymanov

I’ve been looking for a solution to make Path2D visible and controllable in game mode for ages. Even though I found a bit of info here and there, they were not complete and flawless. So I decided to make one for my game that actually works.

Godot community has always been extremely friendly and helpful to me to find solutions to various problems. Now is my turn to contribute back to community.

If you are looking for a way to make Path2D visible and controllable in play mode, here is the code to attach to the root node (replace the number of hyphens with the same number of tabs):

onready var path = get_node("Path2D")
var idx = 0
var c = Color.red

func _input(event):
-if event is InputEventScreenTouch:

#SELECT POINTS
for p in path.curve.get_point_count():
if path.curve.get_point_position(p).distance_to(event.position) < 40:
----idx = p
----update()

#SELECT HANDLES
var a = path.curve.get_point_position(p) - path.curve.get_point_out(p)
var b = path.curve.get_point_position(p) - path.curve.get_point_in(p)

if a.distance_to(event.position) < 40:
----idx = p

if b.distance_to(event.position) < 40:
----idx = p

-if event is InputEventScreenDrag:

#DRAG POINTS
for p in path.curve.get_point_count():
if path.curve.get_point_position(p).distance_to(event.position) < 40 :
----path.curve.set_point_position(idx, path.curve.get_point_position(idx) + event.relative)
----update()

#DRAG HANDLES
var a = path.curve.get_point_position(p) - path.curve.get_point_out(p)
var b = path.curve.get_point_position(p) - path.curve.get_point_in(p)
var d = path.curve.get_point_position(p) - event.position

if a.distance_to(event.position) < 40:
----path.curve.set_point_in(idx, -d + event.relative)
----path.curve.set_point_out(idx, d + event.relative)
----update()

if b.distance_to(event.position) < 40:
----path.curve.set_point_out(idx, -d + event.relative)
----path.curve.set_point_in(idx, d + event.relative)
----update()

#DRAW
func _draw():
-draw_polyline(path.curve.get_baked_points(), c, 1, true)
-for p in path.curve.get_point_count():
if p != 0 and p != path.curve.get_point_count() - 1:
draw_circle(path.curve.get_point_position(p), 8, c)
draw_circle(path.curve.get_point_position(p) - path.curve.get_point_in(p) * -1, 5, c)
draw_circle(path.curve.get_point_position(p) - path.curve.get_point_out(p) * -1, 5, c)
var a = path.curve.get_point_position(p) - path.curve.get_point_in(p) * -1
var b = path.curve.get_point_position(p) - path.curve.get_point_out(p) * -1
var cp = path.curve.get_point_position(p)
draw_polyline(PoolVector2Array([a, cp]), c, 1, true)
draw_polyline(PoolVector2Array([b, cp]), c, 1, true)
-update()

Or you can grab it from this GitHub link: Contribution to GODOT community. If you want to make Path2D visible and controllable in play/game mode, attach this script to the root node. Don't forget to check Emulate Touch From Mouse in Project settings / Pointing. · GitHub

Please fix the indentation :slight_smile:

clemens.tolboom | 2021-04-13 09:52

I’d love to, but I don’t know a better way to indent here except by multiple space keys which creates error in Godot. If there is a proper way, please let me know how, and I’ll update my post. Thank you!

Suleymanov | 2021-04-13 12:28

It is indeed annoying but I paste the code in VSCode/Atom/Notepad++ then regex search for newlines (\n) and replace by newline + 4 space (\n ) … I’ll have to test In shell whether sed s/\n/\n / or vi %s/\n/\n /g works too :slight_smile:

clemens.tolboom | 2021-04-13 12:37

I updated my post with hyphens to mimic tabs. One can with less effort replace them with the same number of tabs. If you find a way to further simplify the code, let’s do it :slight_smile:

Suleymanov | 2021-04-13 13:05

You know how to make the code clean so please do so so people can copy/paste it :-p

I can run your code but have trouble getting the first drawing … mouse has to come close to some point before even visible.

  • var idx is local to _input so no need for global scope

  • _draw() fails when not testing on if path == null: return

  • I had to if event is InputEventScreenTouch or event is InputEventMouseMotion: or check Emulate Touch From Mouse in Project settings.

  • dragging is triggered (breakpoint) but not working … not sure what I did wrong?

  • the drawing look great when functioning … Yeah :slight_smile:

clemens.tolboom | 2021-04-13 15:08

That’s interesting. I copy and paste this code on a new project and replace the hyphens with tabs and it works out of the box. I run it on Windows, Godot version 3.2.3.

var idx - yes, it can be down under input function. I’ll update that.

_draw() fails when not testing - that’s what I don’t experience here, can you elaborate on that?

Emulate Touch From Mouse - yes, that’s right. Initially made for screen touch devices.

Dragging is triggered but not working - What do we do differently to face different outcomes?

Do you run it on Windows or another system?

if path == null: return

I’ll add that even though it displays zero problem in my case.

Suleymanov | 2021-04-13 16:29

Thank you for the contribution. If you have an account on the Github, place it there (this can easily go in a gist).

Ertain | 2021-04-13 17:09

thank you! this is helpful

amadeus | 2021-08-05 03:57