Persistent undo menu#407
Conversation
…ditorVR into features/jono/undo-redo-flick
…se it's hard to keep it pressed in while flicking.
…nu to work together as expected.
There was a problem hiding this comment.
Overall nice work!
IMO there should be a visual means of denoting (perhaps with an arrow color and/or size change, etc) that there is an available undo or redo action that can be performed. I'm not really sure when I can or can't undo (mostly due to the broken undo/redo issue).
Aside from the PR comments, I ran into an issue that randomly showed itself when enabling and disabling the Radial menu. "Coroutine couldn't be started because the the game object 'UndoMenu(Clone)' is inactive!" Likely the undo menu needs to stopAllCoroutines on disable, or something along those lines.
In addition, on a few occassions, when quickly undoing and redoing on the left touch controller, I would get the Undo tooltip/feedback to lock, and not fade away, or stop displaying any longer. Though I couldn't find a reliable repro for that.
| @@ -1,5 +1,6 @@ | |||
| #if UNITY_EDITOR | |||
| using System; | |||
| using System.Collections; | |||
| { | ||
| m_MainMenuUI.targetFaceIndex += (int)Mathf.Sign(rotationInput); | ||
| this.Pulse(node, m_FaceRotationPulse); | ||
| if (rotationInput != 0f) |
There was a problem hiding this comment.
!Mathf.Approximately(rotationInput, 0f)
| this.Pulse(node, m_FaceRotationPulse); | ||
| if (rotationInput != 0f) | ||
| { | ||
| if (m_LastRotationInput == 0f) |
There was a problem hiding this comment.
Mathf.Approximately(m_LastRotationInput, 0f)
| var currentDuration = 0f; | ||
| while (transitionAmount < 1f) | ||
| { | ||
| m_UndoButtonMaterial.SetColor(k_MaterialColorProperty, Color.Lerp(undoStartingColor, targetColor, transitionAmount)); |
There was a problem hiding this comment.
Use SmoothInOutLerpFloat()
var smoothAmount = MathUtilsExt.SmoothInOutLerpFloat(transitionAmount);
m_UndoButtonMaterial.SetColor(k_MaterialColorProperty, Color.Lerp(undoStartingColor, targetColor, smoothAmount));
m_RedoButtonMaterial.SetColor(k_MaterialColorProperty, Color.Lerp(redoStartingColor, targetColor, smoothAmount));
There was a problem hiding this comment.
Orrrr maybe AnimateProperty, once that lands? I'm inclined to punt for that reason.
There was a problem hiding this comment.
I've switched to SmoothInOutLerp for now, but yep, that AnimateProperty sounds pretty good. Where's that branchwise?
There was a problem hiding this comment.
| targetColor.a = k_DisengagedAlpha; | ||
| while (transitionAmount < 1f) | ||
| { | ||
| var currentColor = Color.Lerp(startingColor, targetColor, transitionAmount); |
There was a problem hiding this comment.
Lerp using MathUtilsExt.SmoothInOutLerpFloat(transitionAmount), as mentioned above.
| ObjectUtils.Destroy(m_RedoButtonMaterial); | ||
| } | ||
|
|
||
| public void Setup() |
There was a problem hiding this comment.
Remove Setup function. Disable the UI gameObject in UndoMenu's Start() function.
| m_UndoMenuUI.alternateMenuOrigin = alternateMenuOrigin; | ||
| m_UndoMenuUI.actions = menuActions; | ||
| this.ConnectInterfaces(m_UndoMenuUI); // Connect interfaces before performing setup on the UI | ||
| m_UndoMenuUI.Setup(); |
There was a problem hiding this comment.
Remove setup method, just disable UI gameobject here.
There was a problem hiding this comment.
Yep! Though we use them in quite a few places, our goal is to avoid Setup methods where possible.
| void ShowFeedback() | ||
| { | ||
| List<VRInputDevice.VRControl> controls; | ||
| if (m_Controls.TryGetValue("Engage", out controls)) |
There was a problem hiding this comment.
Use singular class-level const string for "Engage"
| void ShowUndoPerformedFeedback(bool undo) | ||
| { | ||
| List<VRInputDevice.VRControl> controls; | ||
| if (m_Controls.TryGetValue("Engage", out controls)) |
There was a problem hiding this comment.
Use singular class-level const string for "Engage"
|
|
||
| if (undoRedoPerformed) | ||
| { | ||
| consumeControl(undoMenuInput.navigateX); |
There was a problem hiding this comment.
Should the AcceptInputAfterStickReleased coroutine be stopped here if currently running?
mtschoen-unity
left a comment
There was a problem hiding this comment.
Great work! Way to grok the coventions and common patterns right off the bat.
I was able to find an error after monkeying around for a bit (the student becomes the master!)
Coroutine couldn't be started because the the game object 'UndoMenu(Clone)' is inactive!
UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)
My guess is that it's from setting the gameobject to inactive in the visibility property without stopping all coroutines.
|
|
||
| public Node node { get; set; } | ||
|
|
||
| public event Action<Transform> itemWasSelected; |
There was a problem hiding this comment.
There's a warning about this being unused. Does UndoMenu need to be an IAlternateMenu? Could it just be an IMenu? I think we can still just attach it to the alternate menu origin but make it not actually be a IAlternateMenu. Same goes with IUsesRayOrigin (Included in IAlternateMenu). We don't seem to use/need it.
It looks like this will require a refactor of SpawnAlternateMenu, etc. but to look at it, all we do is check that it's the right interface, add a component, and connect interfaces. I think we could make it generic no problem.
|
|
||
| readonly BindingDictionary m_Controls = new BindingDictionary(); | ||
|
|
||
| public Transform rayOrigin { private get; set; } |
There was a problem hiding this comment.
Yep. We should kill it. See comment below.
| m_UndoMenuUI.alternateMenuOrigin = alternateMenuOrigin; | ||
| m_UndoMenuUI.actions = menuActions; | ||
| this.ConnectInterfaces(m_UndoMenuUI); // Connect interfaces before performing setup on the UI | ||
| m_UndoMenuUI.Setup(); |
There was a problem hiding this comment.
Yep! Though we use them in quite a few places, our goal is to avoid Setup methods where possible.
| var currentDuration = 0f; | ||
| while (transitionAmount < 1f) | ||
| { | ||
| m_UndoButtonMaterial.SetColor(k_MaterialColorProperty, Color.Lerp(undoStartingColor, targetColor, transitionAmount)); |
There was a problem hiding this comment.
Orrrr maybe AnimateProperty, once that lands? I'm inclined to punt for that reason.
| { | ||
| if (m_Engaged == value) | ||
| return; | ||
| m_Engaged = value; |
There was a problem hiding this comment.
Blank line after return;
| if (visible) | ||
| ShowFeedback(); | ||
| else | ||
| this.ClearFeedbackRequests(); |
There was a problem hiding this comment.
So... this doesn't allocate, but it does show up when I'm deep profiling (iterates over all feedback). I don't think it's a major worry but we should avoid spamming this method every frame. Feel free to punt until after this PR.
| } | ||
| } | ||
|
|
||
| List<ActionMenuData> m_Actions; |
There was a problem hiding this comment.
Do we do anything with actions? Is this just a vestige of RadialMenu? If so, should be removed as part of the not-alternate-menu refactor.
|
|
||
| m_Visible = value; | ||
|
|
||
| gameObject.SetActive(value); |
There was a problem hiding this comment.
Careful with this. We might want to kill coroutines before setting active to false.
AndrewTHEManeri
left a comment
There was a problem hiding this comment.
Nothing really to add except the note about using DateTime.
Looks solid, good work
| float m_LastRotationInput; | ||
| MenuHideFlags m_MenuHideFlags = MenuHideFlags.Hidden; | ||
| float m_RotationInputStartValue; | ||
| DateTime m_RotationInputStartTime; |
There was a problem hiding this comment.
Pretty unusual for us to use DateTime, normally we just use float since that is what Unity's Time class gives us
…into features/jono/undo-redo-flick # Conflicts: # Prefabs/UI/Tooltip.prefab
|
I did the IAlternateMenu refactor after merging with dev. Dev merge brought up a bug where a tooltip, if it is already visible, will not update its text if it changes and is shown again. Fixed that. |
…AssetGridItem, and Delete Action
…th CCU-wrapped call to that fix to fix "Driving RectTransform" undo issue
…ing on the thumb: Undo & AnnotationTool.
…ity-Technologies/EditorVR into features/jono/undo-redo-flick
…objects, not gameObject (EXR root).
…s from IAlternateMenu to IActionsMenu.
…e alternate menus can overlap the Tools Menu; Remove left/right to undo/redo in AnnotationTool; Consume stick press input in LocomotionTool while two-handed-scaling
…ditorVR into features/jono/undo-redo-flick # Conflicts: # Menus/MainMenu/MainMenu.cs # Menus/RadialMenu/RadialMenu.cs # Scripts/Core/EditorVR.Menus.cs # Scripts/Core/EditorVR.cs # Tools/AnnotationTool/AnnotationTool.cs # Tools/AnnotationTool/UserInterface/ColorPickerActivator.cs # Tools/CreatePrimitiveTool/CreatePrimitiveTool.cs # Tools/SelectionTool/SelectionTool.cs
…ding the radial menu
…-Technologies/EditorVR into features/jono/undo-redo-flick # Conflicts: # Scripts/Core/EditorVR.cs
…raw the next one; Remove undo/redo buttons from AnnotationUI
…ditorVR into features/jono/undo-redo-flick # Conflicts: # Menus/MainMenu/MainMenu.cs # Scripts/Core/EditorVR.cs
fcbba41 to
0d8c9f6
Compare
|
Conflicts resolved locally. Performing Github merge. |
Purpose of this PR
Implement a persistent undo/redo menu: any controller without a radial menu currently open can undo/redo. On Touch, click in the joystick and then flick left or right; on Vive, click in left/right on the touchpad.
This change necessitated changing the main menu behavior on Vive: it is now controlled by swiping the touchpad, rather than clicking in.
Testing status
Tested on Vive and Rift in various scenes. Some objects and operations take a long time to undo/redo, and undo/redo behavior can be inconsistent. This seems to be true across all undo/redo functionality in EVR, as I saw the same inconsistency & delay on some objects when also testing with the existing radial menu actions.
Technical risk
Medium: As this changes behavior in MainMenu, and also is a nearly-always-open menu consuming stick/pad input, the UX & interaction with other tools impact is non-trivial.
Comments to reviewers
-Note the inconsistent undo/redo behavior I described in testing status -- this is a big issue, out of the scope of this PR.
-I'm not fully satisfied with the MainMenu swipe behavior yet and intend to work that some more (and would love feedback about it) -- but wanted to get this in front of everyone asap.