TL; DR: Как реализовать функциональность Unity «цвет с экрана», но с векторами?

Хорошо, так что название довольно упрощено для того, что я пытаюсь сделать:
Пользователь должен нажать кнопку, а затем щелкнуть позицию на экране, чтобы сохранить эту [мировую] позицию в качестве вектора. - В основном это работает, за исключением того, что он не обнаруживает левые щелчки за пределами инспектора.
Отключить щелчок левой кнопкой мыши для всего остального в редакторе единиц (поэтому, когда вы щелкаете позицию, она не меняет фокус на другой GameObject). - Это главная проблема.
Отслеживать мышь и определять мировую позицию было довольно просто, просто сохранять логическое значение, если мышь отслеживается, и SerializedProperty для сохранения того значения, в которое сохраняется позиция мыши.
Вот как выглядит мой атрибут:
public class VectorPickerAttribute : PropertyAttribute {
readonly bool relative;
/// <summary>
/// Works a lot like the color picker, except for vectors.
/// </summary>
/// <param name="relative">Make the final vector relative to the transform?</param>
public VectorPickerAttribute(bool relative = false) {
this.relative = relative;
}
}
Вот PropertyDrawer:
[CustomPropertyDrawer(typeof(VectorPickerAttribute))]
public class VectorPickerDrawer : PropertyDrawer {
bool trackMouse = false;
SerializedProperty v;
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
if(property.propertyType == SerializedPropertyType.Vector2) {
Rect button = new Rect(position);
button.x = position.width - 2;
button.width = position.height;
bool pressed = GUI.Button(button, "");
if(pressed) {
trackMouse = true;
v = property;
}
else if(Input.GetMouseButtonDown(0)) trackMouse = false;
bool tracking = trackMouse && v.propertyPath == property.propertyPath;
if(tracking) {
property.vector2Value =
Camera.main.ScreenToWorldPoint(
GUIUtility.GUIToScreenPoint(
Event.current.mousePosition
));
}
GUI.enabled = !tracking;
EditorGUI.Vector2Field(position, label.text, property.vector2Value);
GUI.enabled = true;
EditorUtility.SetDirty(property.serializedObject.targetObject);
}
}
}
И вот что он делает до сих пор:

Вы нажимаете кнопку справа, и он будет обновлять вектор до положения мыши, пока не обнаружит щелчок левой кнопкой мыши с помощью Input.GetMouseButtonDown(0)
.
Проблемы с этим:
Он будет обнаруживать щелчок только тогда, когда он фактически находится в окне инспектора.
Когда вы щелкаете за пределами окна инспектора, он либо ничего не изменит, либо выберет что-то другое, поэтому закроет инспектор (но, поскольку он сохраняет положение мыши каждые OnGUI()
, точка, в которой вы щелкнули, будет сохраняется в вектор, так что, я думаю, это работает ??).
Я пытался накрыть экран пустым окном, но мне не удалось заставить GUI.Window
или GUI.ModalWindow
что-либо сделать в PropertyDrawer. Я также пытался использовать GUI.UnfocusWindow()
, но либо он не работает в PropertyDrawer, либо он предназначен только для окон Unity или чего-то подобного.