+1 vote

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: https://gist.github.com/SamSuleymanov/27924888017b72c5ac82c2ac47e13bd1

Godot version 3.2.3
in Engine by (322 points)
edited by

Please fix the indentation :-)

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!

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 :-)

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 :)

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 :-)

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.

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

thank you! this is helpful

Please log in or register to answer this question.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.