Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify the <lume-mesh> type system by using child elements instead of behaviors for geometries and materials. #270

Open
trusktr opened this issue Jul 26, 2023 · 0 comments

Comments

@trusktr
Copy link
Member

trusktr commented Jul 26, 2023

I'd like to simplify the classes a bit to make it easier to keep the element types updated. Right now at the bottom of an element class, f.e. in Mesh.ts we do this dance of combining the behavior types so that the Mesh class will have all possible types of properties from all of the behaviors it can have, and they are all marked as optional.

If the classes can have types that come from their class only, it will be easier to compile with ByteScript sooner (maybe we'll never be able to otherwise, as we may never support such dynamic types).

Plus it isn't scalable: for example, if a 3rd party defines a new geometry or material, then they have to painstakingly augment the Mesh type to have new possible properties (I haven't tried it).

So instead of behaviors via attributes, I think that we can switch to this format, so that types align 1-to-1 with element classes, and instead of having a mashup of unknown properties added to host elements by behaviors, all properties are known up front on their elements:

<lume-mesh rotation="1 2 3">
  <lume-physical-material color="skyblue">
  </lume-physical-material>

  <lume-box-geometry centered>
  </lume-box-geometry>

  ...other child nodes as usual...
</lume-mesh>

Instead of Mesh having the mashup of properties/attributes, the new material and geometry elements will have specific properties clearly known up front like color and centered, etc.

Anyone can easily make a geometry or material element with its own types from its own class definition, without having to patch mesh types. So now, properties are set only on these new elements.

It is possible that we could enforce this sort of type separation for behaviors, but the downside is it won't be exposed via markup, and would require JavaScript to set color or centered. F.e. we would remove the current type/properties mashup from Mesh, and would have to do this:

<lume-mesh id="mesh" has="physical-material box-geometry" rotation="1 2 3"></lume-mesh>

<script>
  const mesh = document.getElementById('mesh')

  const geometry = mesh.behaviors.get('box-geometry')
  geometry.centered = true

  const material = mesh.behaviors.get('physical-material')
  material.color = 'skyblue'
</script>

The types can be directly on the behaviors only, but we have to break out if HTML to have proper types without using attributes on the host element.

Plus behaviors in that form (without the properties added to host elements) are not compatible with any DOM frameworks like React/Vue/Angular/Solid/Svelte/etc, their markup languages don't have a way to set behavior properties directly, only element properties.

Switching to child elements for this purpose will have clean types, and still be compatible with all the template systems of those frameworks because they are all designed to manipulate elements. Plus all the element classes will be easy to compile with ByteScript. It will be a win-win-win.

The only problem with the new approach is that mashed up attributes are actually more aligned with how CSS for SVG works. With SVG, you can use a mashup of style attributes on SVG elements, it apply the same CSS properties instead. This translates to the following concept. Currently we write the above mesh example like so:

<lume-mesh id="mesh" has="physical-material box-geometry" rotation="1 2 3" color="skyblue" centered></lume-mesh>

With the current CSS idea, we'd add CSS support and write something like the following instead:

<lume-mesh id="mesh" has="physical-material box-geometry"></lume-mesh>

<style>
  lume-mesh {
    --material: physical;
    --geometry: box;
    --rotation: 1 2 3;
    --color: skyblue;
    --centered: true;
  }
</style>

But maybe, regardless of the syntax, we'll be ok. Perhaps we just make a rule that the properties in CSS override the precedence of the child geometry and material elements, or the other way around.

Also the CSS syntax/format is totally up for debate. Maybe now that we have CSS Nesting, it makes sense to align with element geometries and materials. F.e. maybe it could be like this:

<lume-mesh id="mesh" has="physical-material box-geometry"></lume-mesh>

<style>
  lume-mesh {
    --rotation: 1 2 3;

    & > lume-box-geometry {
      --centered: true;
    }

    & > lume-physical-material {
      --color: skyblue;
    }
  }
</style>

This has pros and cons, but we can get into that in a separate CSS thread.

For now, I think that having the better types in the elements is going to be great no matter the implications for upcoming CSS support.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant