godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.13k stars 78 forks source link

Add a Vector2/3 normalized direction export hint #397

Open Xrayez opened 4 years ago

Xrayez commented 4 years ago

Describe the project you are working on: Project-agnostic.

Describe the problem or limitation you are having in your project: The problem pertains to both project and editor needs. Oftentimes I need to export a property which takes a Vector2 to define a direction, to name a few:

  1. Specific floor directions used for physics parameters.
  2. Launching direction (for projectiles).
  3. Spawn directions (specifies a relative direction by which objects are spawned onto the level, which most of the time matches floor_direction).
  4. Defining custom gravity and external forces vectors (wind direction etc).

Ideally, a direction should be represented as a normalized vector as quite a bunch of vector math methods expect them to be normalized beforehand. Unfortunately, for any non-trivial direction (not orthogonal) it's quite difficult to set a normalized vector by hand.

Describe the feature / enhancement and how it helps to overcome the problem or limitation: I propose adding a new export hint to allow defining a direction represented via vectors. It means that:

  1. It's easy to determine the actual direction visually rather than digital representation of it.
  2. Doesn't need to be (re)-normalized via code to ensure no math errors occur.

Show a mock up screenshots/video or a flow diagram explaining how your proposal will work: Currently, when a Vector2 is exported, it looks something like this:

godot-vector2-hint

The visual representation would look like this:

godot-vector2-dir-hint

A specialized editor could also be used to set any type of vector, snapped to a grid:

godot-snapped-dir-editor

Dragging within the circle area is enough to change the Vector2 direction, and it would be automatically normalized for you (as an option). Snapping and precision could also be implemented to set orthogonal vectors more easily.

Describe implementation detail for your proposal (in code), if possible: It likely requires adding some new PROPERTY_HINT_DIRECTION or similar, and the respective UI editor of course.

If this enhancement will not be used often, can it be worked around with a few lines of script?: At least requires to write an editor inspector plugin, so no. It would be used quite often in my project, globally.

Is there a reason why this should be core and not an add-on in the asset library?: There are some areas in the project/editor settings which could benefit from this (not mentioning the existing ability to add custom settings to the list of existing ones per project):

godot-default-gravity-vector

I'm not sure if it's possible to provide a custom editor hint for the core basic type by writing an EditorInspectorPlugin alone which would be available globally throughout the project, and not restricted to specific object types.

The proposal can be seen as a specific use case which probably needs a more underlying engine support:

Allow to override and add custom property hints for core datatypes.

KoBeWi commented 4 years ago

Well, as a workaround you can export with a setter and then normalize the vector in the setter. I actually tried the same thing when implementing https://github.com/godotengine/godot/pull/26613, but ultimately decided that allowing non-normalized vector and then normalizing it in code allows for greater flexibility. You can e.g. easily set the direction to values like (2, 1) which are rather difficult to express normalized (possibly even with that funny widget).

Xrayez commented 4 years ago

Well, as a workaround you can export with a setter and then normalize the vector in the setter.

Yeah I think it's still necessary to do yet could save some stupid mistakes from happening during prototyping stages.

You can e.g. easily set the direction to values like (2, 1) which are rather difficult to express normalized (possibly even with that funny widget).

I'm not sure if I understand the benefit of having to set direction like that, do you say it would be easier to set certain angles by specifying ratios?

I admit the widget is overly simplified. Taking into consideration what you said, the editor could also represent any vector really, and be snapped to a grid:

godot-snapped-dir-editor

Also being able to configure max axis and step similar to Curve editor:

godot-curve-editor

I actually tried the same thing when implementing godotengine/godot#26613

Good to know direction is being used to set other stuff in core. 🙂

Xrayez commented 4 years ago

So I'm currently prototyping some editor for this. As noticed by @akien-mga in https://github.com/godotengine/godot/pull/26613#issuecomment-496486775, this must also handle 3D case. So I thought about it a little and we basically have these options:

  1. Make a single 3D editor with all those gizmos for both 2D and 3D.
  2. Make pseudo 3D via 2D.
  3. Make dedicated editors for both 2D and 3D.

As I'm not proficient in 3D, I've managed to come up with something like this to simulate 3D vector editing:

pseudo-3d-vector-editing

The depth is simulated by both arrow width and opacity. Of course that would be a visual representation for a Vector3 on a XY plane only which are color-coded by green and red lines respectively (blue for z). The user could then switch between the rest of the planes via editor buttons (XY, XZ, YZ) to edit depth more easily etc.

The editor could also handle any vector length, and have a checkbox to optionally normalize the vector while editing. I'm thinking this should work similar to ColorPicker popup.

vector-editor.zip

ghost commented 4 years ago

Interesting idea, I store directions too, my work around is use -180 to 180 hinted floats to use as angles and convert them to radians, then to vectors, which is a bit less efficient.

The 2D one would be nice, it would probably benefit from some togglable angle snapping. Maybe even an angle slider. That kind of circle would be a very fast and helpful visualization.

The 3D version would be challenging. For something analogous it would have to at least be a unit sphere with a mouse point projected onto the surface, and the normal starting from the center and ending on that mapped position.

The issues to overcome would be having some option to flip it's surface pointing towards and away the user, and the normalized vector is in the center pointing to that surface of this half sphere.

The second is that as the projection gets closer to the edges it becomes less precise and more difficult to select something on the edges of sphere. IE - A vector that would be V3(1.0, 0.0, 0.0).

Xrayez commented 4 years ago

So I'm having more fun with this, actually this time I created an editor (inspector) plugin and a resource to edit Vector2/3 which proves that it indeed can be done via script as I said before:

godot-vector-resource-editor

You can switch different orthogonal view projections of the vector, no 3D code... I could likely polish the code and make a plugin out of this first before this can be considered and adapted for core.

Xrayez commented 4 years ago

I've created a plugin as initial implementation for this feature. I thought it would be useful to at least provide some way to reuse existing plugin mechanism which can edit specific resources, so VectorResource was the most obvious choice for this (also submitted to AssetLib). 🙂

Waiting for more feedback regarding implementation/usability before we can consider adding something similar to core, else the plugin could mostly solve a lot of use cases already.

aaronfranke commented 4 years ago

If the vector is required to be normalized, why not expose an angle instead of a Vector2?

Xrayez commented 4 years ago

If the vector is required to be normalized, why not expose an angle instead of a Vector2?

@KoBeWi response:

You can e.g. easily set the direction to values like (2, 1) which are rather difficult to express normalized (possibly even with that funny widget).

To elaborate, it may be useful to set an angle which is not based on a number, but on a ratio.

But yeah, I've been thinking that the plugin would also benefit from being able to set an arbitrary angle from the inspector as well, but I haven't worked on this.

Note that this proposal can be seen as single use case as I've created it initially, but this evolved into a more general-purpose solution for vector editing now which is not restricted to normalized vector editing.

aaronfranke commented 4 years ago

If you want to be able to express values such as (2, 1) normalized, wouldn't you want to expose a regular Vector2 and then normalize the value when used, such that you can input any numbers in the inspector?

Xrayez commented 4 years ago

This is already the case if I understand you correctly. You can set a vector by typing numbers manually in the inspector and the view is updated accordingly. Here's an updated screenshot (notice Unit Value):

Annotation 2020-05-03 221146

But Unit Value is not meant to be edited via inspector though and is updated from Value, should be read-only! 😃

Notice that either Value or Unit Value is chosen when used via code with vector.xy, and depends on whether normalized property is on. I know it may sound a bit convoluted but I've stumbled upon "editing vs storing" issues when developing this (oftentimes I made silly mistakes by overwriting the regular vector with normalized value and vice versa).

Calinou commented 2 years ago

We discussed this proposal in a meeting. We found that this proposal as originally suggested lacks sufficient community support. On the other hand, we would welcome adding a "direction" property hint for angle properties where it makes sense (for 2D only). We are leaving this proposal open, but we are looking for ways to make the implementation smaller and more self-contained.

For example, a small directional arrow could be drawn next to the slider for those direction angle properties.

Some angle properties may not have a "logical" direction so to speak (such as rotation speeds), so the direction visual aid should remain optional on a per-property basis for angles.