HiddenMonk / Unity3DRuntimeTransformGizmo

A runtime transform gizmo similar to unitys editor so you can translate (move, rotate, scale) objects at runtime.
MIT License
707 stars 129 forks source link

Undo/Redo not work with UI button #30

Closed ilanb closed 4 years ago

ilanb commented 4 years ago

Hi, Tried to use undo/redo function with UGUI button but not work, the UndoRedoManager.Undo(); or Redo() not work. Tried to modify Updaate function too like `void Update() { HandleUndoRedo();

        if(!undo || !redo){

            SetSpaceAndType();

            if(redo)
            {
                UndoRedoManager.Redo();

            }

            if(undo)
            {
                UndoRedoManager.Undo();

            }

            if(manuallyHandleGizmo)
            {
                if(onCheckForSelectedAxis != null) onCheckForSelectedAxis();
            }else{
                SetNearAxis();
            }

            GetTarget();

            if(mainTargetRoot == null) return;

            TransformSelected();    
        }
    }`

Same object back to first pos and after impossible to select it... Please How can I use undo/redo with UI ?

Best,

HiddenMonk commented 4 years ago

You are trying to have it so a UI button can be used to undo or redo instead of using the hotkeys? I think you can just have the buttons onClick event call the UndoRedoManager.Undo(); or Redo. if that doesnt work and order is important (which it might be), then in the onclick event store in a bool that it was clicked and in the HandleUndoRedo method just check for that bool to decide if you should undo or redo.

ilanb commented 4 years ago

You are trying to have it so a UI button can be used to undo or redo instead of using the hotkeys? I think you can just have the buttons onClick event call the UndoRedoManager.Undo(); or Redo. if that doesnt work and order is important (which it might be), then in the onclick event store in a bool that it was clicked and in the HandleUndoRedo method just check for that bool to decide if you should undo or redo.

Thx HiddenMonk, already tested first idea, this not working, the update function cause problem , I need to test second proposal, can you provide simple function example ? Best,

ilanb commented 4 years ago

Ok for the second idea it's the same undo or redo not work, in my first post with update modification undo back to the first modification because I didn't make bool false after. If I set bool to false I can't select object after... Maybe you can share simple example working ? best

HiddenMonk commented 4 years ago

K try this, The Update method should be put back to what it originally was.

        void Update()
        {
            HandleUndoRedo();

            SetSpaceAndType();

            if(manuallyHandleGizmo)
            {
                if(onCheckForSelectedAxis != null) onCheckForSelectedAxis();
            }else{
                SetNearAxis();
            }

            GetTarget();

            if(mainTargetRoot == null) return;

            TransformSelected();
        }

Add this ontop

using UnityEngine.UI;
using UnityEngine.EventSystems;

then add the buttons

        public Button undoButton;
        public Button redoButton;

Then set them in Awake

        void Awake()
        {
            myCamera = GetComponent<Camera>();
            SetMaterial();

            if(undoButton != null) undoButton.onClick.AddListener(OnUndoButton);
            if(redoButton != null) redoButton.onClick.AddListener(OnRedoButton);
        }

Then unsubscribe them in Destroy

        void OnDestroy()
        {
            ClearAllHighlightedRenderers();

            if(undoButton != null) undoButton.onClick.RemoveListener(OnUndoButton);
            if(redoButton != null) redoButton.onClick.RemoveListener(OnRedoButton);
        }

Then add these methods

        bool shouldUndo, shouldRedo;
        void OnUndoButton()
        {
            shouldUndo = true;
        }
        void OnRedoButton()
        {
            shouldRedo = true;
        }

Make these changes to HandleUndoRedo

        void HandleUndoRedo()
        {
            if(maxUndoStored != UndoRedoManager.maxUndoStored) { UndoRedoManager.maxUndoStored = maxUndoStored; }

            if(shouldUndo)
            {
                UndoRedoManager.Undo();
            }
            else if(shouldRedo)
            {
                UndoRedoManager.Redo();
            }

            shouldUndo = false;
            shouldRedo = false;

            if(Input.GetKey(ActionKey))
            {
                if(Input.GetKeyDown(UndoAction))
                {
                    UndoRedoManager.Undo();
                }
                else if(Input.GetKeyDown(RedoAction))
                {
                    UndoRedoManager.Redo();
                }
            }
        }

Then add the !Eventsystem.current.IsPointerOverGameObject() check in the GetTarget method

        void GetTarget()
        {
            if(nearAxis == Axis.None && Input.GetMouseButtonDown(0))
            {
                bool isAdding = Input.GetKey(AddSelection);
                bool isRemoving = Input.GetKey(RemoveSelection);

                RaycastHit hitInfo; 
                if(Physics.Raycast(myCamera.ScreenPointToRay(Input.mousePosition), out hitInfo, Mathf.Infinity, selectionMask))
                {
                    Transform target = hitInfo.transform;

                    if(isAdding)
                    {
                        AddTarget(target);
                    }
                    else if(isRemoving)
                    {
                        RemoveTarget(target);
                    }
                    else if(!isAdding && !isRemoving)
                    {
                        ClearAndAddTarget(target);
                    }
                }else{
                    if(!isAdding && !isRemoving && !EventSystem.current.IsPointerOverGameObject())
                    {
                        ClearTargets();
                    }
                }
            }
        }

Seems to work for me.

ilanb commented 4 years ago

Thx HiddenMonk,

Undo/Redo work fine in your scene example :-).

But not in my AR scene :-( I use TransformGizmo in a AR app. I instanciate a cube with touch screen, I can rotate, move, scale, deselect or remove it with your TransformGizmo but when I click on undo/redo nothing happen, it's same setup like your example, just used ARfoundation and ARcore.

HiddenMonk commented 4 years ago

I dont know much about AR D=. I think the problem is the !EventSystem.current.IsPointerOverGameObject() check, I am assuming since AR doesnt have a mouse pointer, this method isnt working.

Try this. I removed the IsPointerOverGameObject check and put in if(EventSystem.current.currentSelectedGameObject != null && EventSystem.current.currentSelectedGameObject.GetComponent() != null) return;

        void GetTarget()
        {
            if(nearAxis == Axis.None && Input.GetMouseButtonDown(0))
            {
                if(EventSystem.current.currentSelectedGameObject != null && EventSystem.current.currentSelectedGameObject.GetComponent<UIBehaviour>() != null) return;

                bool isAdding = Input.GetKey(AddSelection);
                bool isRemoving = Input.GetKey(RemoveSelection);

                RaycastHit hitInfo; 
                if(Physics.Raycast(myCamera.ScreenPointToRay(Input.mousePosition), out hitInfo, Mathf.Infinity, selectionMask))
                {
                    Transform target = hitInfo.transform;

                    if(isAdding)
                    {
                        AddTarget(target);
                    }
                    else if(isRemoving)
                    {
                        RemoveTarget(target);
                    }
                    else if(!isAdding && !isRemoving)
                    {
                        ClearAndAddTarget(target);
                    }
                }else{
                    if(!isAdding && !isRemoving)
                    {
                        ClearTargets();
                    }
                }
            }
        }
ilanb commented 4 years ago

Ahhhh works like a charm HiddenMonk !! :-) The previous code worked only when I putting second finger on screen...

Many thanks for help HiddenMonk !

HiddenMonk commented 4 years ago

np =)