using System; namespace BansheeEngine { /// /// Renderable represents any visible object in the scene. It has a mesh, bounds and a set of materials. Renderer will /// render any Renderable objects visible by a camera. /// [RunInEditor] public sealed class Renderable : Component { private NativeRenderable _native; [SerializeField] private SerializableData serializableData = new SerializableData(); /// /// Returns the non-component version of Renderable that is wrapped by this component. /// internal NativeRenderable Native { get { return _native; } } /// /// Mesh to render. /// public Mesh Mesh { get { return _native.Mesh; } set { _native.Mesh = value; serializableData.mesh = value; int subMeshCount = 0; if (value != null) subMeshCount = value.SubMeshCount; Material[] newMaterials = new Material[subMeshCount]; int numToCopy = MathEx.Min(newMaterials.Length, serializableData.materials.Length); Array.Copy(serializableData.materials, newMaterials, numToCopy); serializableData.materials = newMaterials; } } /// /// Material to use when rendering the mesh. If the mesh contains multiple sub-meshes then you may set individual /// materials for each sub-mesh. /// public Material Material { get { return _native.GetMaterial(0); } set { _native.SetMaterial(value); serializableData.materials[0] = value; } } /// /// Materials to use when rendering the mesh. /// public Material[] Materials { get { return _native.Materials; } set { _native.Materials = value; serializableData.materials = new Material[value.Length]; Array.Copy(value, serializableData.materials, value.Length); } } /// /// Returns a material for a specific sub-mesh. /// /// Index of the sub-mesh. /// Material used for rendering the sub-mesh at the specified index. public Material GetMaterial(int index = 0) { return _native.GetMaterial(index); } /// /// Sets a material for a specific sub-mesh. /// /// Material to use for rendering the sub-mesh at the specified index. /// Index of the sub-mesh. public void SetMaterial(Material material, int index = 0) { _native.SetMaterial(material, index); serializableData.materials[index] = material; } /// /// Layer bitfield that controls whether a renderable is considered visible in a specific camera. Renderable layer /// must match camera layer in order for the camera to render the component. /// public UInt64 Layers { get { return _native.Layers; } set { _native.Layers = value; serializableData.layers = value; } } /// /// Gets world bounds of the mesh rendered by this object. /// public Bounds Bounds { get { return _native.GetBounds(SceneObject); } } private void OnReset() { if (_native != null) _native.OnDestroy(); _native = new NativeRenderable(SceneObject); // Restore saved values after reset _native.Mesh = serializableData.mesh; if (serializableData.materials != null) { for (int i = 0; i < serializableData.materials.Length; i++) _native.SetMaterial(serializableData.materials[i], i); } _native.Layers = serializableData.layers; } private void OnUpdate() { _native.UpdateTransform(SceneObject); } private void OnDestroy() { _native.OnDestroy(); } /// internal protected override bool CalculateBounds(out AABox box, out Sphere sphere) { Bounds bounds = Bounds; box = bounds.Box; sphere = bounds.Sphere; return true; } /// /// Holds all data the renderable component needs to persist through serialization. /// [SerializeObject] private class SerializableData { public Mesh mesh; public Material[] materials = new Material[0]; public UInt64 layers = 1; } } }