Material instance is not reflected as a subclass of the reflected base material

I have no intention of creating a custom material class in code. That’s what the editor will reflect for me from the material assets.

If you wanted to collect multiple different material objects into an array for example and expect the exact same properties, the base material should be a supertype of a reflected material instance. That way you could iterate over them all simultaneously and update them as needed. Right now a material instance is being a subtype of material instead of its base material which I create an asset for.

MaterialsAsBase: []m_base = array {
  m_base {},
  mi_instance {}
}

for (Material: MaterialsAsBase) {
  set Material.Parameter = 1.0
}

Something like this is not possible as mi_instance does not share type relationship with m_base, but it should as mi_instance is actually m_base, but with potentially overridden parameters. Right now their common supertype will be only material, but it should be m_base.

Here’s an analogy in pure verse code.

m_pseudo_material_base := class {
  var SomeParameter: float = 0.0 
}

mi_pseudo_material:= class(m_pseudo_material_base) {
  var SomeParameter<override>: float = 1.0 
}

Right now here’s what the type relation is being reflected into:

What I personally expect it to be is this though:


Imagine this scenario. Many different meshes (mesh_components) use several different material instances which all originate from the same base material.

Right now you would need to cast each material slot to the concrete reflected material subtype in order to update a single parameter.

This should be much easier. All you have to do is to cast every material instance to the base material and update the parameter of interest on all different material instances.

The code right now:

# Reflected materials
m_my_material := class<final><public>(material):
  @editable
  var Saturation<public>: float = external {}

  @editable
  var Contrast<public>: float = external {}

mi_my_material_red := class<final><public>(material):
  @editable
  var Saturation<public>: float = external {}

  @editable
  var Contrast<public>: float = external {}

mi_my_material_green := class<final><public>(material):
  @editable
  var Saturation<public>: float = external {}

  @editable
  var Contrast<public>: float = external {}

mi_my_material_blue := class<final><public>(material):
  @editable
  var Saturation<public>: float = external {}

  @editable
  var Contrast<public>: float = external {}

# Reflected meshes
my_mesh_red := class<final><public>(mesh_component):
  @editable
  var MyMaterial<public>: material = external {} # uses `mi_my_material_red`

my_mesh_green := class<final><public>(mesh_component):
  @editable
  var MyMaterial<public>: material = external {} # uses `mi_my_material_green`

my_mesh_blue := class<final><public>(mesh_component):
  @editable
  var MyMaterial<public>: material = external {} # uses `mi_my_material_blue`
MyMeshRed := ...
MyMeshGreen := ...
MyMeshBlue := ...

# One need to update the materials individually and you have to know every concrete material type.
if (MaterialObject := mi_my_material_red[MyMeshRed.MyMaterial]) {
  set MaterialObject.Saturation = 0.0
}

if (MaterialObject := mi_my_material_green[MyMeshGreen.MyMaterial]) {
  set MaterialObject.Saturation = 0.0
}

if (MaterialObject := mi_my_material_blue[MyMeshBlue.MyMaterial]) {
  set MaterialObject.Saturation = 0.0
}

Versus the code how it should be:

# Reflected materials
m_my_material := class<public>(material):
  @editable
  var Saturation<public>: float = external {}

  @editable
  var Contrast<public>: float = external {}

mi_my_material_red := class<public>(m_my_material):

mi_my_material_green := class<public>(m_my_material):

mi_my_material_blue := class<public>(m_my_material):

# Reflected meshes
my_mesh_red := class<final><public>(mesh_component):
  @editable
  var MyMaterial<public>: material = external {} # uses `mi_my_material_red`

my_mesh_green := class<final><public>(mesh_component):
  @editable
  var MyMaterial<public>: material = external {} # uses `mi_my_material_green`

my_mesh_blue := class<final><public>(mesh_component):
  @editable
  var MyMaterial<public>: material = external {} # uses `mi_my_material_blue`
MyMeshRed := ...
MyMeshGreen := ...
MyMeshBlue := ...

# One need to update the materials individually and you have to know every concrete material type.
Materials: []material = array {
  MyMeshRed.MyMaterial,
  MyMeshGreen.MyMaterial,
  MyMeshBlue.MyMaterial
}

# Dynamically cast to `m_my_material` each material instance as in this example
# they correctly share `m_my_material` as its commons supertype.
if (Material: Materials, MaterialObject := m_my_material[Material]) {
  set MaterialObject.Saturation = 0.0
}

Since material instances can also have a parent material instance, this should also be reflected in verse as well.

The current reflection type relationship is not the same like the parent child relationship is of material and material instance assets is.