User avatar
digimbyte
Topic Author
Posts: 47
Joined: 14 Nov 2017, 21:42

Trying to finding First Node from root

02 Jul 2019, 07:25

I've been looking at re-arranging my elements in Noesis, when any button is clicked, that root object needs to come forward.
I looked into getting the VisualTreeHelper.GetRoot from HitResult.VisualHit but I couldn't cast it as a UIElement
so I decided to try getting the Root from a list of HitTestResults
following https://docs.microsoft.com/en-us/dotnet ... arameters_ as a reference
private List<DependencyObject> hitResultsList = new List<DependencyObject>();
    private void Listen4ChildClick()
    {
        UnityEngine.Vector3 mousePos = Input.mousePosition;
        Point mousePoint = uiRoot.PointFromScreen(new Point(mousePos.x, Screen.height - mousePos.y));
        VisualTreeHelper.HitTest(uiRoot, null, new HitTestResultCallback(MyHitTestResult), new PointHitTestParameters(mousePoint));
        HitTestResult hit = VisualTreeHelper.HitTest(uiRoot, mousePoint); 
        if (hit.VisualHit != null)
        {
            UIElement Panel = VisualTreeHelper.GetRoot(hit.VisualHit) as UIElement;
            if (ActiveWindows.ContainsValue((UIElement)Panel))
            {
                uiRoot.Children.Remove(Panel);
                uiRoot.Children.Add(Panel);
            }
        }
    }
    private HitTestResultBehavior MyHitTestResult(HitTestResult result)
    {
        hitResultsList.Add(result.VisualHit);
        return HitTestResultBehavior.Continue;
    }
Currently, I have the following error with the newly implimented Hit Check
NullReferenceException: Object reference not set to an instance of an object
Noesis.VisualTreeHelper.OnHitTestFilter (System.Int32 callbacksId, System.IntPtr targetPtr) (at Assets/NoesisGUI/Plugins/API/Proxies/VisualTreeHelper.cs:57)
UnityEngine.Debug:LogException(Exception)
NoesisUnity:OnUnhandledException(Exception) (at Assets/NoesisGUI/Plugins/NoesisUnity.cs:142)
Noesis.Error:UnhandledException(Exception) (at Assets/NoesisGUI/Plugins/API/Core/NoesisError.cs:18)
Noesis.VisualTreeHelper:OnHitTestFilter(Int32, IntPtr) (at Assets/NoesisGUI/Plugins/API/Proxies/VisualTreeHelper.cs:61)
Noesis.VisualTreeHelper:VisualTreeHelper_HitTestCallback(HandleRef, Point&, Int32, Callback_HitTestFilter, Callback_HitTestResult)
Noesis.VisualTreeHelper:HitTestCallbackHelper(Visual, Point, Int32, Callback_HitTestFilter, Callback_HitTestResult) (at Assets/NoesisGUI/Plugins/API/Proxies/VisualTreeHelper.cs:83)
Noesis.VisualTreeHelper:HitTest(Visual, HitTestFilterCallback, HitTestResultCallback, HitTestParameters) (at Assets/NoesisGUI/Plugins/API/Proxies/VisualTreeHelper.cs:45)
 
User avatar
sfernandez
Site Admin
Posts: 1628
Joined: 22 Dec 2011, 19:20

Re: Trying to finding First Node from root

02 Jul 2019, 10:36

I guess you want to obtain View's content root, and that is exposed in NoesisView.Content property.

If you call VisualTreeHelper.GetRoot() it will give you the internal visual root node that manages also the popup layers, but I don't think you need that for object re-arrangement.

If you need to change Z-order of some elements you have 2 options:
  • Change the order how children are added to Panel.Children collection.
  • Set Panel.ZIndex property in children as required. You can do that manually by calling Panel.SetZIndex(child, order).
Does this help?
 
User avatar
digimbyte
Topic Author
Posts: 47
Joined: 14 Nov 2017, 21:42

Re: Trying to finding First Node from root

02 Jul 2019, 14:04

I already have a function to reorganise the children, the problem is finding the corresponding parent from child.
I dont think it would be efficient to attach an event listener to every UI element when I can have a single call that figures out the corresponding parant chain from the child.

I originally thought I could use get root but it seems its more for visual based instance and can't be converted to the logic tree.
so instead I have been looking at a combination of isMouseOver and Direct Mouse over but finding the correct panel is still proving to not be as simple as a reverse get children chain.
Currently, I am storing the active windows in a dictionary by a string ID, and i might have that as the windows Tag, and going from there.

alternativly would be to iterate over the entire logic tree but I dont think that would be ideal for something that should be as simple as a reorder
 
User avatar
sfernandez
Site Admin
Posts: 1628
Joined: 22 Dec 2011, 19:20

Re: Trying to finding First Node from root

02 Jul 2019, 20:41

As explained in Element Tree documentation, the UI is organized in 2 trees that coexist, the Logical Tree and the Visual Tree (that expands logical tree with the template visual trees).

If you want to get the logical parent of any element you have the child.Parent property.
If you want to access the visual parent of any element you can call VisualTreeHelper.GetParent(child).

Does this help with your problem?
 
User avatar
digimbyte
Topic Author
Posts: 47
Joined: 14 Nov 2017, 21:42

Re: Trying to finding First Node from root

03 Jul 2019, 15:33

I ended going with Zindex
changing the order of children ended breaking event handlers and capture Mouse was stuck perpetually on a single window index
possible bug?
Regardless, I implimented any window to have an OnLoaded event to make sure it had the latest Zindex and spent the last 6 hours figuring out a little gem
private void WindowClick()
    { 
        if (!uiRoot.IsMouseOver) return;
        int found = -1;
        Dictionary<int, int> order = new Dictionary<int, int>();
        // GET CURRENT STACKING ORDER
        for (int i = uiRoot.Children.Count - 1; i > -1; i--)
        {
            if (uiRoot.Children[i].IsMouseOver && Panel.GetZIndex(uiRoot.Children[i]) > found)
                found = i;
            order.Add(i, Panel.GetZIndex(uiRoot.Children[i]));
        }

        // SORT STACKING ORDER
        var list = order.ToList();
        list.Sort((item1, item2) => item1.Value.CompareTo(item2.Value));
        
        // SET NEW STACKING ORDER
        for (int i = uiRoot.Children.Count - 1; i > -1; i--)
        {
            Panel.SetZIndex(uiRoot.Children[list[i].Key], i);//uiRoot.Children[order[i]]
        }
        if (found != -1)
            Panel.SetZIndex(uiRoot.Children[found], uiRoot.Children.Count + 1);
    }
have that run in the update function and everything works as intended
 
User avatar
sfernandez
Site Admin
Posts: 1628
Joined: 22 Dec 2011, 19:20

Re: Trying to finding First Node from root

03 Jul 2019, 17:59

Capture Mouse was stuck perpetually on a single window index, possible bug?
Mouse capture does not depend on Panel Z-Index, what do you mean by stuck?
 
User avatar
digimbyte
Topic Author
Posts: 47
Joined: 14 Nov 2017, 21:42

Re: Trying to finding First Node from root

04 Jul 2019, 01:10

in my original script, pre-zdepth it wouldn't release the captureMouse when moving the panel index to the bottom of the children stack.
(particularly when instantiating new panels)
so the end result was the first panel had the captureMouse handler stuck on it but it wouldn't release it despite prompting it.

Who is online

Users browsing this forum: No registered users and 5 guests