react-three-renderer icon indicating copy to clipboard operation
react-three-renderer copied to clipboard

What are the rules for <resources /> ?

Open AndrewRayCode opened this issue 9 years ago • 2 comments
trafficstars

Can you clarify what the rules for the <resources /> object is? I'm not sure when I can access a resources from a different part of my component tree, etc. Some specific questions are below.

  1. In individual component, can I reference a resourceId declared a parent component?
  2. Can I use a resource not defined in a parent component, but defined in a sibling component? As in, are resource names considered global to the render tree?
  3. Can I define multiple <resouce> tags in the same component?
  4. What happens if, in any place, I duplicate a resource / resourceId between components? Will the user of the resource look up the render tree until it finds one, or are they global and the "last" one wins?
  5. To what degree does render order matter for resources? If I referenceId a resource in a sibling component, the sibling might not have been created yet. Will this fail, or does it all get batched together at render time and sorted before render?
  6. What happens if I modify runtime properties of a resource at runtime? For example, I want to change the opacity of a material. Is this allowed / safe / efficient?

AndrewRayCode avatar Jan 24 '16 23:01 AndrewRayCode

  1. In individual component, can I reference a resourceId declared a parent component?
    • Yes
  2. Can I use a resource not defined in a parent component, but defined in a sibling component? As in, are resource names considered global to the render tree?
    • Not siblings, resources aren't global
  3. Can I define multiple tags in the same component?
    • <resource-like> (all within https://github.com/toxicFork/react-three-renderer/wiki/Resource-Types) tags can go only within <resources> in a component, and yes you can have multiple <resource-like> tags inside a <resources> tag. I have not tried multiple <resources> tag within a component.
  4. What happens if, in any place, I duplicate a resource / resourceId between components? Will the user of the resource look up the render tree until it finds one, or are they global and the "last" one wins?
    • This is a fun one. If a parent P has let's say resource for id 'foo', and a child C has resource for id 'foo', the references within the child C (and its children and grandchildren and so on) will use the inner foo. The parent's children (e.g. any siblings of child and these siblings' children) excluding this child C will use the outer one. So the 'nearest above' wins.

      <group> // group 1 start
        <resources>
          <meshBasicMaterial resourceId='foo' color={redColor}/>
        </resources>
        <mesh>
          <materialResource 
            resourceId='foo'
            // this will be red
          /> 
        </mesh>
        <group> // group 2 start
          <resources>
            <meshBasicMaterial resourceId='foo' color={greenColor}/>
          </resources>
          <mesh>
            <materialResource 
              resourceId='foo'
              // this will be green
            /> 
          </mesh>
          <group> // group 3 start 
            <resources>
              <meshBasicMaterial resourceId='foo' color={blueColor}/>
            </resources>
            <mesh>
              <materialResource 
                resourceId='foo'
                // this will be blue
              /> 
            </mesh>
            <group> // group 4 start
              <mesh>
                <materialResource 
                  resourceId='foo'
                  // this will be blue too
                /> 
              </mesh>
              <group> // group 5 start
                <mesh>
                  <materialResource 
                    resourceId='foo'
                    // this will be blue too
                  /> 
                </mesh>
              </group> // group 5 end
            </group> // group 4 end
            <mesh>
              <materialResource 
                resourceId='foo'
                // this will be blue
              /> 
            </mesh>
          </group> // group 3 end
          <mesh>
            <materialResource 
              resourceId='foo'
              // this will be green
            /> 
          </mesh>
        </group> // group 2 end
        <mesh>
          <materialResource 
            resourceId='foo'
            // this will be red
          /> 
        </mesh>
      </group> // group 1 end
      
      
  5. To what degree does render order matter for resources? If I referenceId a resource in a sibling component, the sibling might not have been created yet. Will this fail, or does it all get batched together at render time and sorted before render?
    • It is recommend to place <resources/> as the first element of any component because of multiple reasons:

      • It will be constructed before any other siblings, and anything within them will also be constructed first.

        e.g. render order

          <group> // 7
            <resources> // 3
              <a/> // 1
              <b/> // 2
            </resources>
            <mesh> // 4
            </mesh>
            <group> // 6
              <mesh/> // 5
            </group>
          </group>
        
        
        • This is not a huge issue, since after the resources are constructed the previous siblings references will be filled in, but it's not really nice as they may be re-rendered which can be expensive.
      • If any of the siblings BEFORE it get added or removed, then (because of how react renders) ALL of the resources within may get re-constructed which is super expensive and against all that is good in the world. This CAN be prevented if you place a key property on the resource, but that still means the objects before this may not be properly initialized.

    • Resources within a sibling cannot be referred to.

      <parent>
        <child-a>
          <resources>
          </resources>
        </child-a>
        <child-b>
          You cannot refer to anything in `<child a/>` here
        </child-b>
      </parent>
      
      
  6. What happens if I modify runtime properties of a resource at runtime? For example, I want to change the opacity of a material. Is this allowed / safe / efficient?
    • It's not only safe and efficient, it's even recommended! That's one of the main purposes for resources. You can use resources to change the color of a material for any number of meshes this way, e.g.

      <group>
        <resources>
          <meshBasicMaterial resourceId="mat1" color={>>change this<<}/>
          // ... geometry... resourceId="geom1"
        </resources>
        <Meshes/>
      </group>
      
      Meshes.prototype.render = () => {
        // all meshes refer to the same material and geometry instances
        return (<group>
          <mesh>
            <materialResource resourceId="mat1"/>
            <geometryResource resourceId="geom1"/>
          </mesh>
          <mesh>
            <materialResource resourceId="mat1"/>
            <geometryResource resourceId="geom1"/>
          </mesh>
          <mesh>
            <materialResource resourceId="mat1"/>
            <geometryResource resourceId="geom1"/>
          </mesh>
          // ... and so on
        </group>)
      }
      

I will add these in a FAQ :) It's a complex little beast!

toxicFork avatar Jan 26 '16 09:01 toxicFork

Updated comment above

toxicFork avatar Jan 26 '16 09:01 toxicFork