diff --git a/GlitchyEngine/src/Renderer/Material.bf b/GlitchyEngine/src/Renderer/Material.bf index 6b5ab84..4ff972b 100644 --- a/GlitchyEngine/src/Renderer/Material.bf +++ b/GlitchyEngine/src/Renderer/Material.bf @@ -10,6 +10,15 @@ namespace GlitchyEngine.Renderer; public class Material : Asset { + /** + * If true, this material is a runtime instance and can be changed by scripts. + * If false, it is the actual material from the harddrive and should not be modified by scripts. + * If a script tries to modify it, a runtime instance will be created. + */ + private bool _isRuntimeInstance = false; + + private Material _parent ~ _?.ReleaseRef(); + private Effect _effect ~ _?.ReleaseRef(); private Dictionary Handle, TextureDimension Dimension, int32? groupTarget)> _textures = new .() ~ DeleteDictionaryAndKeys!(_); @@ -32,6 +41,11 @@ public class Material : Asset } } + // TODO: allow changing + public Material Parent => _parent; + + public bool IsRuntimeInstance => _isRuntimeInstance; + public this() { @@ -42,6 +56,13 @@ public class Material : Asset Effect = effect; } + public this(Material parentMaterial, bool isRuntimeInstance) + { + _parent = parentMaterial..AddRef(); + Effect = _parent.Effect; + _isRuntimeInstance = isRuntimeInstance; + } + private void Init() { decltype(_textures) newTextures = new .(); @@ -99,7 +120,9 @@ public class Material : Asset } } - for (let (bufferName, buffer) in _effect.Buffers) + BufferCollection parentBuffers = _parent?._bufferCollection ?? _effect.Buffers; + + for (let (bufferName, buffer) in parentBuffers) { if (buffer == null) continue; @@ -171,28 +194,12 @@ public class Material : Asset { if(_textures.TryGetValue(name, var entry)) { - /*switch (texture.Get().GetType()) - { - //case .Texture1D: - // _textures[name].Dimension = .Texture1D; - case typeof(Texture2D): - _textures[name].Dimension = .Texture2D; - case typeof(TextureCube): - _textures[name].Dimension = .TextureCube; - //case .Texture3D: - // _textures[name].Dimension = .Texture3D; - default: - _textures[name].Dimension = .Unknown; - }*/ - //entry?.ReleaseRef(); _textures[name].Handle = texture; _textures[name].groupTarget = groupTargetIndex; - //texture?.AddRef(); } else { Log.EngineLogger.Error($"Material doesn't have the texture slot \"{name}\""); - //Log.EngineLogger.Assert(false); } } diff --git a/GlitchyEngine/src/Scripting/ScriptGlue.bf b/GlitchyEngine/src/Scripting/ScriptGlue.bf index 99f57e4..79a9321 100644 --- a/GlitchyEngine/src/Scripting/ScriptGlue.bf +++ b/GlitchyEngine/src/Scripting/ScriptGlue.bf @@ -1054,6 +1054,17 @@ static class ScriptGlue static void SpriteRenderer_GetMaterial(UUID entityId, out AssetHandle assetId) { SpriteRendererComponent* spriteRenderer = GetComponentSafe(entityId); + + Material material = GetAssetOrThrow!((AssetHandle)spriteRenderer.Material); + + if (!material.IsRuntimeInstance) + { + material = new Material(material, true); + material.Identifier = scope $"(Instance) {material.Identifier}"; + Content.ManageAsset(material); + spriteRenderer.Material = material.Handle; + } + assetId = spriteRenderer.Material; } @@ -1162,6 +1173,17 @@ static class ScriptGlue static void MeshRenderer_GetMaterial(UUID entityId, out AssetHandle assetId) { MeshRendererComponent* meshRenderer = GetComponentSafe(entityId); + + Material material = GetAssetOrThrow!((AssetHandle)meshRenderer.Material); + + if (!material.IsRuntimeInstance) + { + material = new Material(material, true); + material.Identifier = scope $"(Instance) {material.Identifier}"; + Content.ManageAsset(material); + meshRenderer.Material = material.Handle; + } + assetId = meshRenderer.Material; } diff --git a/ScriptCore/Core/EngineObject.cs b/ScriptCore/Core/EngineObject.cs index 49933bd..73a7f80 100644 --- a/ScriptCore/Core/EngineObject.cs +++ b/ScriptCore/Core/EngineObject.cs @@ -25,4 +25,13 @@ public abstract class EngineObject { _uuid = uuid; } + + /// Determines whether the specified is equal to the current . + /// The object to compare with the current object. + /// true if the specified object is equal to the current object; otherwise, false. + public bool Equals(EngineObject other) + { + // TODO: Are we really only interested in what equates to reference equality on the engine side? + return _uuid == other._uuid; + } } diff --git a/ScriptCore/Graphics/Material.cs b/ScriptCore/Graphics/Material.cs index 98d11e0..6b7e94b 100644 --- a/ScriptCore/Graphics/Material.cs +++ b/ScriptCore/Graphics/Material.cs @@ -3,6 +3,9 @@ using GlitchyEngine.Math; namespace GlitchyEngine.Graphics; +/// +/// An that represents how a surface should be rendered. +/// public class Material : Asset { public void SetVariable(string name, float4 value) diff --git a/ScriptCore/Graphics/MeshRenderer.cs b/ScriptCore/Graphics/MeshRenderer.cs index 6f655ea..edd8b73 100644 --- a/ScriptCore/Graphics/MeshRenderer.cs +++ b/ScriptCore/Graphics/MeshRenderer.cs @@ -10,6 +10,10 @@ public class MeshRenderer : Component /// /// Gets or sets the Material of this . /// + /// + /// If you get the and it is not yet a runtime-instance, + /// a new runtime-instance will be created and returned in its place. + /// public Material Material { get diff --git a/ScriptCore/Graphics/SpriteRenderer.cs b/ScriptCore/Graphics/SpriteRenderer.cs index 920f969..e267a71 100644 --- a/ScriptCore/Graphics/SpriteRenderer.cs +++ b/ScriptCore/Graphics/SpriteRenderer.cs @@ -39,6 +39,10 @@ public class SpriteRenderer : Component /// /// Gets or sets the Material of this SpriteRenderer. /// + /// + /// If you get the and it is not yet a runtime-instance, + /// a new runtime-instance will be created and returned in its place. + /// public Material Material { get