NaughtyAttributes icon indicating copy to clipboard operation
NaughtyAttributes copied to clipboard

[Request] Multiselect dropdown with different than enum types

Open Shelim opened this issue 6 years ago • 5 comments

This is effectively mixing [EnumFlags] with [Dropdown] like support.

Use case:

I need to create list of strings, where each string comes from a given (not known in compile time, but known in editor - so I cannot use enum) pool and each string can only appear once.

Example:

	[MultiDropdown("GetVectorValues")]
	public List<Vector3> AllowedDirections; // I can select more than one,
                                                // but each one at most once

	private DropdownList<Vector3> GetVectorValues()
	{
		return new DropdownList<Vector3>()
		{
			{ "Right",   Vector3.right },
			{ "Left",    Vector3.left },
			{ "Up",      Vector3.up },
			{ "Down",    Vector3.down },
			{ "Forward", Vector3.forward },
			{ "Back",    Vector3.back }
		};
	}

Shelim avatar Mar 06 '20 08:03 Shelim

This is cool, I will implement it. In the meantime, you can achieve it like this. I haven't tested this code, but it should work.

public List<Direction> AllowedDirections;

[Serializable]
public struct Direction
{
    [Dropdown("GetVectorValues")]
    public Vector3 Value;

    private DropdownList<Vector3> GetVectorValues()
    {
	return new DropdownList<Vector3>()
	{
		{ "Right",   Vector3.right },
		{ "Left",    Vector3.left },
		{ "Up",      Vector3.up },
		{ "Down",    Vector3.down },
		{ "Forward", Vector3.forward },
		{ "Back",    Vector3.back }
	};
    }
}

dbrizov avatar Mar 06 '20 09:03 dbrizov

Oh, so I believe I run into bug - the value is unselectable (keeps at default, no uncaught exception is thrown), unless I change

public struct Direction

to

public class Direction

-> Then it works reasonably for now, but it - obviously - allows duplicates... 😄 Thank you for considering this improvement!

Shelim avatar Mar 06 '20 10:03 Shelim

Sorry, I forgot that dropdowns don't work with structs. It's a known bug. I have it described in the documentation.

When nested inside a struct the value of the dropdown doesn’t update. This is because the value of the parent struct is updated via reflection. In order for the value to be updated the struct needs to be boxed and then unboxed. The struct is already passed as an object (boxed) to the dropdown drawer, but unfortunately, in order to unbox it I need to know the compile-time type of the struct, and I don’t. Nesting inside a class works as expected.

dbrizov avatar Mar 07 '20 06:03 dbrizov

+1 for MultiDropdown - "make Dropdown* support collection fields" feature. I'm using code from "In the meantime, you can achieve it like this", and added a CustomPropertyDrawer for that inner class to get rid of unnecessary Folding in the Editor, as it's basically one field class:

[CustomPropertyDrawer(typeof(Direction))]
public class DirectionDrawer : PropertyDrawer {
    private static string Property => nameof(Direction.value);

    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
        EditorGUI.PropertyField(position, property.FindPropertyRelative(Property));
    }
}

RunninglVlan avatar Jan 18 '21 15:01 RunninglVlan

+1 on this. Would be nice to either use collections or a named getter function that returns the updated values ^^ (as a List<T> maybe? :P )

+1 for MultiDropdown - "make Dropdown* support collection fields" feature.

NeatWolf avatar Jan 19 '21 16:01 NeatWolf