Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Allow MultiLineNode.Material setter to change in runtime
#1
Rainbow 
Hi

I have an scenario where I need to create many dimension lines that share same material that can react to my application settings, so I allocate much less resources by having single material for them all

However, I also need to Paint/Wash the lines when hovering or selecting them

Material property is init-only so I need a different material for each object to accomplish that

Could it be possible to make public setter to update material in runtime?
#2
FYI, I inherit my own class from MultiLineNode and added Wash and Paint methods that make the trick:

private readonly LineMaterial originalMaterial;
private static readonly PropertyInfo? MaterialProperty = typeof(LineBaseNode).GetProperty(nameof(DimensionLineMeshNode.Material), BindingFlags.Public | BindingFlags.Instance);

public void Paint(LineMaterial mat) => DimensionLineMeshNode.MaterialProperty?.SetValue(this, mat);
public void Wash() => DimensionLineMeshNode.MaterialProperty?.SetValue(this, this.originalMaterial);


public DimensionLineMeshNode(string name, Vector3[] positions, LineMaterial sharedMaterial)
    : base(name)
{
    this.originalMaterial = sharedMaterial;
    this.IsHitTestVisible = true;
    this.Material = sharedMaterial;
    this.Positions = positions;
}
#3
I see now that you solve that by using reflection.

But by deriving your own class from MultiLineNode (or any other class that is derived from LineBaseNode), you can change the protected material and lineBaseMaterial fields without using reflection.

For example, you can add the following code to a derived class to change the material:

Code:
        public void ChangeMaterial(Material? newMaterial)
        {
            if (ReferenceEquals(newMaterial, material))
                return;

            DisposeRenderingItems(); // dispose existing RenderingItems


            material = newMaterial;

            if (newMaterial != null)
            {
                CheckIfMaterialIsDisposed(newMaterial);

                if (Scene != null && !newMaterial.IsInitialized)
                    newMaterial.InitializeSceneResources(Scene);

                lastMaterialVersion = -1; // This will update the material in CollectRenderingItems
            }

            // we store material also as LineMaterial for improved performance in getters and setters
            lineBaseMaterial = newMaterial as LineMaterial;

            NotifyChange(SceneNodeDirtyFlags.MaterialChanged);
        }
Andrej Benedik
#4
Thanks Andrej
Your snippet is far better than mine

Great to have such a good customer support
  


Forum Jump:


Users browsing this thread:
1 Guest(s)