View Issue Details

IDProjectCategoryView StatusLast Update
0002935NoesisGUIUnitypublic2024-01-24 21:33
Reporterstonstad Assigned Tojsantos  
PrioritynormalSeverityblock 
Status resolvedResolutionfixed 
Product Version3.2.2 
Target Version3.2.3Fixed in Version3.2.3 
Summary0002935: NoesisWorldUI should not recreate or evict state on GameObject.Enable/Disable
Description

This isn't the correct behavior for Unity. In Unity, disabling a game object within the hierarchy should not mutate state -- or in this case, cause state to be evicted or reloaded. What would be more appropriate here is to just disable the renderer. I think what the developer is looking for is OnDestroy.

PlatformAny

Activities

stonstad

stonstad

2023-12-11 22:14

reporter   ~0009007

https://www.noesisengine.com/forums/viewtopic.php?p=16401#p16401

stonstad

stonstad

2023-12-11 22:38

reporter   ~0009008

I am loading state in Awake(), and this is working well for me.

sfernandez

sfernandez

2023-12-12 13:05

manager   ~0009014

Yes, it makes sense. We will study moving the loading/destruction to the Awake/OnDestroy methods, and leave Enable/Disable to just add/remove the loaded xaml to the View.

sfernandez

sfernandez

2023-12-12 14:03

manager   ~0009017

I implemented it as mentioned above, could you try the attached script?

sfernandez

sfernandez

2023-12-12 14:03

manager   ~0009018

NoesisWorldUI.cs (4,426 bytes)   
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using UnityEngine;
using Noesis;

public class NoesisWorldUI : MonoBehaviour
{
    [SerializeField]
    private NoesisView _view;
    public NoesisView View
    {
        get => _view;
        set
        {
            if (_view != value)
            {
                _view = value;
                RemoveContent();
                FindContainer();
                AddContent();
            }
        }
    }

    [SerializeField]
    private string _container = "Root";
    public string Container
    {
        get => _container;
        set
        {
            if (_container != value)
            {
                _container = value;
                RemoveContent();
                FindContainer();
                AddContent();
            }
        }
    }

    [SerializeField]
    private NoesisXaml _xaml;
    public NoesisXaml Xaml
    {
        get => _xaml;
        set
        {
            if (_xaml != value)
            {
                _xaml = value;
                RemoveContent();
                LoadContent();
                AddContent();
            }
        }
    }

    [SerializeField]
    private float _scale = 0.005f;
    public float Scale { get => _scale; set { _scale = value; } }

    [SerializeField]
    private Vector3 _offset = new Vector3();
    public Vector3 Offset { get => _offset; set { _offset = value; } }

    [SerializeField]
    private bool _center = true;
    public bool Center { get => _center; set { _center = value; } }

    public FrameworkElement Content => _content;

    private void Awake()
    {
        FindContainer();
        LoadContent();
    }

    void OnEnable()
    {
        AddContent();
    }

    void OnDisable()
    {
        RemoveContent();
    }

    private void OnDestroy()
    {
        _content = null;
        _transform = null;
        _containerPanel = null;
        _camera = null;
        _view = null;
        _xaml = null;
    }

    void Update()
    {
        if (_content != null && _camera != null)
        {
            float width = 0.0f;
            float height = 0.0f;

            if (Center)
            {
                _content.Measure(new Size(float.PositiveInfinity, float.PositiveInfinity));
                width = _content.DesiredSize.Width;
                height = _content.DesiredSize.Height;
            }

            Matrix4x4 mtx = transform.localToWorldMatrix * Matrix4x4.Translate(Offset) *
                Matrix4x4.Scale(new Vector3(Scale, -Scale, Scale)) *
                Matrix4x4.Translate(new Vector3(-0.5f * width, -0.5f * height, 0.00f));

            _transform.Matrix = new Matrix3D
            (
                mtx[0, 0], mtx[1, 0], mtx[2, 0],
                mtx[0, 1], mtx[1, 1], mtx[2, 1],
                mtx[0, 2], mtx[1, 2], mtx[2, 2],
                mtx[0, 3], mtx[1, 3], mtx[2, 3]
            );

            float z = (_camera.worldToCameraMatrix * transform.localToWorldMatrix).m23;
            Panel.SetZIndex(_content, (int)(z * 100.0f));
        }
    }

    void FindContainer()
    {
        _containerPanel = null;
        _camera = null;

        if (View != null && !string.IsNullOrEmpty(Container))
        {
            _containerPanel = View.Content?.FindName(Container) as Panel;
            _camera = View.GetComponent<Camera>();
        }
    }

    void LoadContent()
    {
        _content = null;
        _transform = null;

        if (Xaml != null)
        {
            _content = Xaml.Load() as FrameworkElement;
            if (_content != null)
            {
                _transform = new MatrixTransform3D();
                _content.Transform3D = _transform;
            }
        }
    }

    void AddContent()
    {
        if (enabled && _containerPanel != null && _content != null)
        {
            _containerPanel.Children.Add(_content);
        }
    }

    void RemoveContent()
    {
        if (_containerPanel != null && _content != null)
        {
            _containerPanel.Children.Remove(_content);
        }
    }

    private Panel _containerPanel;
    private Camera _camera;
    private FrameworkElement _content;
    private MatrixTransform3D _transform;
}
NoesisWorldUI.cs (4,426 bytes)   
stonstad

stonstad

2023-12-12 15:58

reporter   ~0009019

Thank you Sergio. Very cool stuff. OK, I tried it out and it looks like View.Content? is null when FindContainer is called in Awake()

I believe the cause is that this particular game object is not active in the hierarchy when WorldSpaceUI.Awake() is initially called.

image.png (69,284 bytes)   
image.png (69,284 bytes)   
sfernandez

sfernandez

2023-12-12 20:33

manager   ~0009021

This might be related to 0002586.
Could you try to add the following attribute to the NoesisWorldUI component to make sure it is executed after NoesisView loads its xaml:

[DefaultExecutionOrder(100)]
public class NoesisWorldUI : MonoBehaviour
{
...
}

jsantos

jsantos

2024-01-24 21:33

manager   ~0009116

Attaching latest version that is coming with 3.2.3

NoesisWorldUI-2.cs (4,722 bytes)   
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using UnityEngine;
using Noesis;

[DefaultExecutionOrder(100)]
public class NoesisWorldUI : MonoBehaviour
{
    [SerializeField]
    private NoesisView _view;
    public NoesisView View
    {
        get => _view;
        set
        {
            if (_view != value)
            {
                _view = value;

                RemoveContent();
                FindContainer();
                AddContent();
            }
        }
    }

    [SerializeField]
    private string _container = "Root";
    public string Container
    {
        get => _container;
        set
        {
            if (_container != value)
            {
                _container = value;

                RemoveContent();
                FindContainer();
                AddContent();
            }
        }
    }

    [SerializeField]
    private NoesisXaml _xaml;
    public NoesisXaml Xaml
    {
        get => _xaml;
        set
        {
            if (_xaml != value)
            {
                _xaml = value;

                RemoveContent();
                LoadContent();
                AddContent();
            }
        }
    }

    [SerializeField]
    private float _scale = 0.005f;
    public float Scale { get => _scale; set { _scale = value; } }

    [SerializeField]
    private Vector3 _offset = new Vector3();
    public Vector3 Offset { get => _offset; set { _offset = value; } }

    [SerializeField]
    private bool _center = true;
    public bool Center { get => _center; set { _center = value; } }

    public FrameworkElement Content => _content;

    void OnEnable()
    {
        EnsureContainer();
        EnsureContent();
        AddContent();
    }

    void OnDisable()
    {
        RemoveContent();
    }

    void OnDestroy()
    {
        _content = null;
        _transform = null;
        _containerPanel = null;
        _camera = null;
        _view = null;
        _xaml = null;
    }

    void Update()
    {
        if (_content != null && _camera != null)
        {
            float width = 0.0f;
            float height = 0.0f;

            if (Center)
            {
                _content.Measure(new Size(float.PositiveInfinity, float.PositiveInfinity));
                width = _content.DesiredSize.Width;
                height = _content.DesiredSize.Height;
            }

            Matrix4x4 mtx = transform.localToWorldMatrix * Matrix4x4.Translate(Offset) *
                Matrix4x4.Scale(new Vector3(Scale, -Scale, Scale)) *
                Matrix4x4.Translate(new Vector3(-0.5f * width, -0.5f * height, 0.00f));

            _transform.Matrix = new Matrix3D
            (
                mtx[0, 0], mtx[1, 0], mtx[2, 0],
                mtx[0, 1], mtx[1, 1], mtx[2, 1],
                mtx[0, 2], mtx[1, 2], mtx[2, 2],
                mtx[0, 3], mtx[1, 3], mtx[2, 3]
            );

            float z = (_camera.worldToCameraMatrix * transform.localToWorldMatrix).m23;
            Panel.SetZIndex(_content, (int)(z * 100.0f));
        }
    }

    void EnsureContainer()
    {
        if (_containerPanel == null)
        {
            FindContainer();
        }
    }

    void FindContainer()
    {
        _containerPanel = null;
        _camera = null;

        if (View != null && !string.IsNullOrEmpty(Container))
        {
            _containerPanel = View.Content?.FindName(Container) as Panel;
            _camera = View.GetComponent<Camera>();
        }
    }

    void EnsureContent()
    {
        if (_content == null)
        {
            LoadContent();
        }
    }

    void LoadContent()
    {
        _content = null;
        _transform = null;

        if (Xaml != null)
        {
            _content = Xaml.Load() as FrameworkElement;
            if (_content != null)
            {
                _transform = new MatrixTransform3D();
                _content.Transform3D = _transform;
            }
        }
    }

    void AddContent()
    {
        if (enabled)
        {
            if (_containerPanel != null && _content != null)
            {
                _containerPanel.Children.Add(_content);
            }
        }
    }

    void RemoveContent()
    {
        if (_containerPanel != null && _content != null)
        {
            _containerPanel.Children.Remove(_content);
        }
    }

    private Panel _containerPanel;
    private Camera _camera;
    private FrameworkElement _content;
    private MatrixTransform3D _transform;
}
NoesisWorldUI-2.cs (4,722 bytes)   

Issue History

Date Modified Username Field Change
2023-12-11 22:13 stonstad New Issue
2023-12-11 22:14 stonstad Note Added: 0009007
2023-12-11 22:38 stonstad Note Added: 0009008
2023-12-12 12:50 jsantos Assigned To => sfernandez
2023-12-12 12:50 jsantos Status new => assigned
2023-12-12 12:50 jsantos Target Version => 3.2.3
2023-12-12 13:05 sfernandez Note Added: 0009014
2023-12-12 14:03 sfernandez Status assigned => feedback
2023-12-12 14:03 sfernandez Note Added: 0009017
2023-12-12 14:03 sfernandez Note Added: 0009018
2023-12-12 14:03 sfernandez File Added: NoesisWorldUI.cs
2023-12-12 15:58 stonstad Note Added: 0009019
2023-12-12 15:58 stonstad File Added: image.png
2023-12-12 15:58 stonstad Status feedback => assigned
2023-12-12 20:33 sfernandez Status assigned => feedback
2023-12-12 20:33 sfernandez Note Added: 0009021
2024-01-22 11:47 sfernandez Target Version 3.2.3 => 3.2.4
2024-01-22 11:48 sfernandez Target Version 3.2.4 => 3.2.3
2024-01-23 18:59 sfernandez Assigned To sfernandez =>
2024-01-23 18:59 sfernandez Assigned To => jsantos
2024-01-23 18:59 sfernandez Status feedback => assigned
2024-01-24 21:33 jsantos Note Added: 0009116
2024-01-24 21:33 jsantos File Added: NoesisWorldUI-2.cs
2024-01-24 21:33 jsantos Status assigned => resolved
2024-01-24 21:33 jsantos Resolution open => fixed
2024-01-24 21:33 jsantos Fixed in Version => 3.2.3
2025-10-10 13:29 jsantos Category Unity3D => Unity