UNPKG

@playcanvas/react

Version:

A React renderer for PlayCanvas – build interactive 3D applications using React's declarative paradigm.

54 lines 2.3 kB
import { useLayoutEffect, useMemo } from 'react'; import { StandardMaterial } from 'playcanvas'; import { useApp } from './use-app'; import { getColorPropertyNames, useColors } from '../utils/color'; import { validateAndSanitizeProps, createComponentDefinition } from '../utils/validation'; /** * This hook is used to create a material instance and update its properties when the props change. * @param {Materialrops} props - The props to pass to the material. * @returns {StandardMaterial} material - The material instance. * @see https://api.playcanvas.com/engine/classes/StandardMaterial.html * * @example * const material = useMaterial({ * diffuse: 'red', * opacity: 0.5, * }); * * // use the material * <Render type="box" material={material} /> */ export const useMaterial = (props) => { const app = useApp(); const safeProps = validateAndSanitizeProps(props, componentDefinition); // Get color props with proper type checking const colorProps = useColors(props, colors); const propsWithColors = { ...safeProps, ...colorProps }; // Create the material instance only once when 'app' changes const material = useMemo(() => new StandardMaterial(), [app]); // Update material properties when 'props' change useLayoutEffect(() => { if (material) { // Filter the props to only include those in the standard material const filteredProps = Object.fromEntries(Object.entries(propsWithColors).filter(([key]) => key in material)); Object.assign(material, filteredProps); material.update(); } }, [app, material, propsWithColors]); // Clean up the material when the component unmounts useLayoutEffect(() => { return () => { if (material) { material.destroy(); } }; }, [material]); return material; }; // dynamically build a list of property names that are colors const tmpMaterial = new StandardMaterial(); const colors = getColorPropertyNames(tmpMaterial); tmpMaterial.destroy(); // create a schema for the material props const componentDefinition = createComponentDefinition("Material", () => new StandardMaterial(), (material) => material.destroy(), "StandardMaterial"); //# sourceMappingURL=use-material.js.map