godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.15k stars 97 forks source link

Add object snapping to the floor/vertices for the 3D editor viewport #755

Open Jummit opened 4 years ago

Jummit commented 4 years ago

Describe the project you are working on:

3D exploration game.

Describe the problem or limitation you are having in your project:

Placing objects in 3d is hard, because moving them is always aligned to the camera or to one of the axis.

Describe the feature / enhancement and how it helps to overcome the problem or limitation:

Snapping similar to Blender would make dragging-and-dropping objects into the scene much quicker. It would also make moving objects easier.

Describe how your proposal will work, with code, pseudocode, mockups, and/or diagrams:

2020-04-26-163227_2646x1024_scrot ezgif-4-6f95030788e2

More examples from #21006: Snap example

This is already implemented for when you drag a model into the scene, but just for a very short range: ezgif-4-887632b844d3

Seems like the distance is hardcoded to 10 here: https://github.com/godotengine/godot/blob/56437cddeb3b4ff362ff23db27e8eab84c820959/editor/plugins/spatial_editor_plugin.cpp#L3184-L3186

This should be used here if snapping is enabled.

If this enhancement will not be used often, can it be worked around with a few lines of script?:

You can use the "Snap to floor" option, but it is slower and not real time.

Is there a reason why this should be core and not an add-on in the asset library?:

It improves an existing feature and complements the core 3D editing experience well.

Bugsquad edit (keywords for easier searching): vertex

Calinou commented 4 years ago

Someone should check if the "Snap to Floor" functionality is fast enough to be used in real-time (or semi-realtime, e.g. every two frames).

Jummit commented 4 years ago

Someone should check if the "Snap to Floor" functionality is fast enough to be used in real-time (or semi-realtime, e.g. every two frames).

I think the already implemented method SpatialEditorViewport::_get_instance_position which is used when dropping objects into the scene should work.

Zireael07 commented 4 years ago

Related issue: https://github.com/godotengine/godot/issues/21006

GuyUnger commented 3 years ago

Unreal does this very well with "surface snapping". Also allowing the object to point up at the normal of the surface:

UnrealEditor_dXzy3JF0Oa

https://user-images.githubusercontent.com/7023847/129477343-bf97a36f-c2ba-4511-9749-b6074e5616eb.mp4

jordanlis commented 3 years ago

It would be usefull for 2D Too I think, given sometimes or some project does not use a tilemap editor.

YuriSizov commented 3 years ago

It would be usefull for 2D Too I think, given sometimes or some project does not use a tilemap editor.

Floor in 2D is a very arbitrary concept. You can always use grid snapping, even without tilemaps.

Calinou commented 3 years ago

Seems like the distance is hardcoded to 10 here:

For drag-and-drop, the issue is that we can't increase this distance too much. Otherwise, objects would appear far away when you drag and drop them without any collider behind.

We could have a way to dynamically adjust the drag-and-drop maximum distance while dragging (e.g. by using the mouse wheel). This is how 3D entity distance is set during dragging in Cube 2 editors, but this is difficult to discover for new users.

https://user-images.githubusercontent.com/180032/136942243-c6045a02-b293-4da1-b365-682655cbeab3.mp4

YuriSizov commented 3 years ago

For drag-and-drop, the issue is that we can't increase this distance too much. Otherwise, objects would appear far away when you drag and drop them without any collider behind.

Be that as it may, I personally have never found our current defaults usable. Objects just spawn in the face of the camera. Dropping to the scene dock is more useful than dropping to a scene directly.

Calinou commented 3 years ago

I guess we could increase this snapping distance to 20-30 units (and perhaps add an editor setting for it, or the aforementioned mouse wheel adjustment).

We can also increase the distance threshold for the Snap Object to Floor functionality while we're at it. I already did this a while ago, but it likely needs further adjustments to be more usable in large-scale scenes.

trommlbomml commented 2 years ago

I really can encourage this issue regarding vertex snapping: if I use assets which are blocks it is not easy at the moment to place them one to another. It is a very useful feature from unity I loved a lot and would improve a lot of prototyping and placement works.

As far as I understand this issue tackles vertex and surface snapping? Maybe it makes sense to have separate issues for each feature?

Calinou commented 2 years ago

I really can encourage this issue regarding vertex snapping: if I use assets which are blocks it is not easy at the moment to place them one to another. It is a very useful feature from unity I loved a lot and would improve a lot of prototyping and placement works.

As far as I understand this issue tackles vertex and surface snapping? Maybe it makes sense to have separate issues for each feature?

Vertex snapping doesn't need to rely on colliders being present, while surface snapping arguably requires collision meshes to be present for it to work reliably. Surface snapping based on colliders is already implemented in Godot, however:

Flavelius commented 2 years ago

I'm used to toggling to topdown perspective (y up) in ortho projection to place objects. In godot this just places the dragged objects ~100m above the ground for me, so i don't think increasing the distance by this little will be of any help. I also don't see the issue in increasing it; Have the default placement plane be at a low distance, but when intersecting a collider (at whatever distance) use the distance to that hitpoint. The only place where this might unrealistically fail is if the sky/far plane counted as collider.

jgillich commented 2 years ago

I wrote an addon for vertex snapping: https://github.com/jgillich/godot-snappy

The code is not ideal, but it could be used as a starting point for a in-engine implementation

sci-comp commented 2 years ago

I love all the ideas in here!

This makes me think of Octave 3D World Builder over in Unity. It's a very large package full of essential features for making 3D environments. It's not unique, there are other tools, like Prefab World Builder or Rider's new integration. Unity has a more bare-bones tool called ProBuilder as well.

jgillich's solution looks like a great addition to Godot to me,

Where would this snippet fit in Godot?

Calinou commented 2 years ago

Where would this snippet fit in Godot?

The core Godot editor is C++-only – it can't integrate add-ons written in GDScript. The add-on's code would have to be ported to C++ before it can be integrated in core Godot.

CardboardCarl commented 1 year ago

I wrote an addon for vertex snapping: https://github.com/jgillich/godot-snappy

The code is not ideal, but it could be used as a starting point for a in-engine implementation

I'll try to port this to C++ over the next week or two and get it working in the engine. Will update on progress!

Depending on how much time I have, I might also be able to make this work in 2D with Polygon2Ds, perhaps CollisionShape2Ds as well.

CardboardCarl commented 12 months ago

Finished up with a preliminary pass through the 3D editor class (i.e. adding button connections and an enabler variable). Almost finished translating jgillich's script, just trying to match up the GDScript functions with their internal counterparts.

Thinking of also changing the key action from press-and-hold to toggle, like the other snap functions. I'd like some input on that if possible.

I'm also trying to decide where to add in the functionality. Should I implement it as a new gizmo (seeing as the highlighted vertex will need to be drawn), or should I add it to the 3D editor class file with the other snap functions? @Calinou tagging because you would probably know better than me.

Calinou commented 12 months ago

I'm also trying to decide where to add in the functionality. Should I implement it as a new gizmo (seeing as the highlighted vertex will need to be drawn), or should I add it to the 3D editor class file with the other snap functions?

I'd put it in the 3D editor class, like the existing manipulation gizmo.

CardboardCarl commented 11 months ago

Giving an update: I had to shelve my work on this for a little while due to some unforseen circumstances with my schedule. Going to be starting back this week.

Ury18 commented 8 months ago

This is a must have feature. When using modular meshes to build, for example, scenarios It's almost impossible to make things fit together as desired. The only workaround is changing de Translate Snap value to make it lower so the grid snap is more precise but it's still far from ideal and even in some cases doesn't quite work.

CardboardCarl commented 8 months ago

Another update. A sad one, unfortunately. I accidentally force-pushed the main Godot branch and overwrote all of my changes, so I'm going to have to start from scratch... The good news is that I have a better grasp of the editor code now, so it shouldn't take very long to catch back up!

I think I made a mistake by skipping porting the Snappy module to GDNative and instead directly integrating a translation of it into the editor. It gave me no working base to reference and likely slowed my progress down to a halt. Going to learn from my mistakes and start by actually porting Snappy to GDNative first.

Calinou commented 8 months ago

Another update. A sad one, unfortunately. I accidentally force-pushed the main Godot branch and overwrote all of my changes, so I'm going to have to start from scratch... The good news is that I have a better grasp of the editor code now, so it shouldn't take very long to catch back up!

If you have a local copy of the repository before you've done the force push, you might be able to get the previous state of your code using git reflog and git checkout <reflog commit hash>. The reflog is essentially a local history that stores all commits for a certain duration even if they've been reset or force-pushed.

CardboardCarl commented 8 months ago

If you have a local copy of the repository before you've done the force push, you might be able to get the previous state of your code using git reflog and git checkout <reflog commit hash>. The reflog is essentially a local history that stores all commits for a certain duration even if they've been reset or force-pushed.

Unfortunately it looks like my reflog also got wiped... oh well. Probably better off starting from scratch anyways! :sweat_smile:

Reonu commented 8 months ago

This is absolutely a must have. I'm starting to learn godot and, as a somewhat experienced blender user, the absence of this feature is something I really notice

Calinou commented 8 months ago

@Reonu Please don't bump issues without contributing significant new information. Use the :+1: reaction button on the first post instead.

warent commented 5 months ago

Hey folks, FYI someone just created a plugin for this, and it works great: https://github.com/mharitsnf/ExtraSnaps Would be amazing to get this built-in natively!

ChildLearningClub commented 4 months ago

The Mirror's implementation of snapping seems to work well. Can their code be added back into the Godot Engine?

https://github.com/godotengine/godot/compare/master...the-mirror-gdp:godot:themirror

https://github.com/godotengine/godot-proposals/assets/25701774/f72e7925-49cf-47bf-91ee-8b0efe654ebf

Calinou commented 2 months ago

Note that it might be worth considering a floating pivot toggle as well to go with vertex snapping, as described in https://github.com/godotengine/godot-proposals/discussions/10359.

jgillich commented 1 week ago

PR looks fantastic, but unless I'm mistaken, it doesn't add vertex snapping. I think this needs to be reopened.

Repiteo commented 1 week ago

Oop, the issue auto-closed when merging, my b

Repiteo commented 1 week ago

REALLY wish there was a "partially closed" equivalent for issues, because that PR does handle floor-snapping