From e38373dccfbf5917856cdf67db2681f0ed6be49f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20L=C3=BCbe=C3=9F?= Date: Sun, 8 Jan 2023 19:31:01 +0100 Subject: [PATCH] Serialize Mesh and MeshRenderer in scene + fixed Light serialization --- GlitchyEditor/content/Scenes/physics2D.scene | 79 ++++++++++++++++++- .../src/Assets/MaterialAssetLoader.bf | 15 ++-- .../src/EditWindows/ComponentEditWindow.bf | 8 +- GlitchyEngine/src/Content/Asset.bf | 45 +++++++++++ GlitchyEngine/src/Math/Color.bf | 2 + GlitchyEngine/src/Math/ColorRGB.bf | 2 + GlitchyEngine/src/World/Components.bf | 17 +++- GlitchyEngine/src/World/SceneSerializer.bf | 78 ++++++++++++------ 8 files changed, 204 insertions(+), 42 deletions(-) diff --git a/GlitchyEditor/content/Scenes/physics2D.scene b/GlitchyEditor/content/Scenes/physics2D.scene index 3decb20..8f19e80 100644 --- a/GlitchyEditor/content/Scenes/physics2D.scene +++ b/GlitchyEditor/content/Scenes/physics2D.scene @@ -14,7 +14,7 @@ A = 1 }, IsCircle = false, - Sprite = null, + Sprite = "\\Textures\\TestMat\\rustediron2_albedo.png", UvTransform = { X = 0, Y = 0, @@ -164,7 +164,7 @@ OrthographicHeight = 10, OrthographicNearPlane = 0, OrthographicFarPlane = 10, - AspectRatio = 2.156692, + AspectRatio = 2.969697, FixedAspectRatio = false } }, @@ -181,7 +181,7 @@ A = 1 }, IsCircle = true, - Sprite = "Textures/rocket.png", + Sprite = "\\Textures\\rocket.png", UvTransform = { X = 0, Y = 0, @@ -227,6 +227,79 @@ Restitution = 0, RestitutionThreshold = 0.5 } + }, + { + Id = 935640822766280888, + NameComponent = { + Name = "Light" + }, + TransformComponent = { + Position = { + X = 3.883276, + Y = 0, + Z = -0.808795 + }, + Rotation = { + X = 0.497987, + Y = -0.103421, + Z = 0.15538, + W = 0.846859 + }, + Scale = { + X = 0.999998, + Y = 1, + Z = 1 + }, + EditorEulerRotation = { + X = 1.090894, + Y = -0.340794, + Z = 0.160858 + } + }, + LightComponent = { + LightType = .Directional, + Illuminance = 12.9, + Color = { + R = 0.985467, + G = 1, + B = 0.569979 + } + } + }, + { + Id = 721949523193525565, + NameComponent = { + Name = "Sphere" + }, + TransformComponent = { + Position = { + X = 0, + Y = 0, + Z = -1.523338 + }, + Rotation = { + X = 0, + Y = 0, + Z = 0, + W = 1 + }, + Scale = { + X = 1, + Y = 1, + Z = 1 + }, + EditorEulerRotation = { + X = 0, + Y = 0, + Z = 0 + } + }, + MeshComponent = { + Mesh = "\\Models\\sphere.glb" + }, + MeshRendererComponent = { + Material = "\\Textures\\TestMaterial.mat" + } } ] } \ No newline at end of file diff --git a/GlitchyEditor/src/Assets/MaterialAssetLoader.bf b/GlitchyEditor/src/Assets/MaterialAssetLoader.bf index d348179..3ad888a 100644 --- a/GlitchyEditor/src/Assets/MaterialAssetLoader.bf +++ b/GlitchyEditor/src/Assets/MaterialAssetLoader.bf @@ -77,15 +77,16 @@ class MaterialAssetLoader : IAssetLoader //, IReloadingAssetLoader for (let (slotName, textureIdentifier) in materialFile.Textures) { - Texture texture = contentManager.LoadAsset(textureIdentifier) as Texture; - - if (texture == null) + using (Texture texture = contentManager.LoadAsset(textureIdentifier) as Texture) { - Log.EngineLogger.Error("Failed to load texture."); - // TODO: LoadAsset should return an error texture. - } + if (texture == null) + { + Log.EngineLogger.Error("Failed to load texture."); + // TODO: LoadAsset should return an error texture. + } - material.SetTexture(slotName, texture); + material.SetTexture(slotName, texture); + } } fx.ReleaseRef(); diff --git a/GlitchyEditor/src/EditWindows/ComponentEditWindow.bf b/GlitchyEditor/src/EditWindows/ComponentEditWindow.bf index cb4f62d..110eb5e 100644 --- a/GlitchyEditor/src/EditWindows/ComponentEditWindow.bf +++ b/GlitchyEditor/src/EditWindows/ComponentEditWindow.bf @@ -268,10 +268,10 @@ namespace GlitchyEditor.EditWindows StringView path = .((char8*)payload.Data, (int)payload.DataSize); - Texture2D texture = Content.LoadAsset(path);//new Texture2D(path, true); - - spriteRendererComponent.Sprite?.ReleaseRef(); - spriteRendererComponent.Sprite = texture; + using (Texture2D texture = Content.LoadAsset(path)) + { + spriteRendererComponent.Sprite = texture; + } } ImGui.EndDragDropTarget(); diff --git a/GlitchyEngine/src/Content/Asset.bf b/GlitchyEngine/src/Content/Asset.bf index 48b5b49..67a09fd 100644 --- a/GlitchyEngine/src/Content/Asset.bf +++ b/GlitchyEngine/src/Content/Asset.bf @@ -1,8 +1,12 @@ using GlitchyEngine.Core; using System; +using Bon; +using Bon.Integrated; +using System.Reflection; namespace GlitchyEngine.Content; +[BonTarget] class Asset : RefCounter { private append String _identifier; @@ -28,10 +32,51 @@ class Asset : RefCounter /// Gets the content manager that manages this asset; or null if this asset isn't managed. public IContentManager ContentManager => _contentManager; + static this + { + gBonEnv.typeHandlers.Add(typeof(Asset), + ((.)new => AssetSerialize, new => AssetDeserialize)); + } + protected ~this() { // TODO: crash when _contentManager is deleted first... // TODO: unregister from content manager _contentManager?.UnmanageAsset(this); } + + static void AssetSerialize(BonWriter writer, ValueView value, BonEnvironment environment) + { + Log.EngineLogger.Assert(value.type == typeof(Asset)); + + let identifier = value.Get().Identifier; + writer.String(identifier); + } + + static Result AssetDeserialize(BonReader reader, ValueView value, BonEnvironment environment)//, DeserializeFieldState state) + { + Log.EngineLogger.Assert(value.type == typeof(Asset)); + + String identifier = scope .(); + + Deserialize.String!(reader, ref identifier, environment); + + Asset asset = Application.Get().ContentManager.LoadAsset(identifier); + + if (asset != null) + { + Asset oldAsset = value.Get(); + oldAsset.ReleaseRef(); + + value.Assign(asset); + return .Ok; + } + else + { + Deserialize.Error!("Invalid resource path", reader, value.type); + } + } + + //gBonEnv.typeHandlers.Add(typeof(Resource<>), + // ((.)new => ResourceSerialize, (.)new => ResourceDeserialize)); } \ No newline at end of file diff --git a/GlitchyEngine/src/Math/Color.bf b/GlitchyEngine/src/Math/Color.bf index 69ceb13..3bb38bf 100644 --- a/GlitchyEngine/src/Math/Color.bf +++ b/GlitchyEngine/src/Math/Color.bf @@ -1,9 +1,11 @@ +using Bon; using System; namespace GlitchyEngine.Math { /// Represents a four component color with 8 bit per channel [CRepr] + [BonTarget] public struct Color { // from DirectXColors.h diff --git a/GlitchyEngine/src/Math/ColorRGB.bf b/GlitchyEngine/src/Math/ColorRGB.bf index 3247c8f..be07e7c 100644 --- a/GlitchyEngine/src/Math/ColorRGB.bf +++ b/GlitchyEngine/src/Math/ColorRGB.bf @@ -1,3 +1,4 @@ +using Bon; using System; using internal GlitchyEngine.Math; @@ -6,6 +7,7 @@ namespace GlitchyEngine.Math { /// Represents an RGB color. [CRepr] + [BonTarget] public struct ColorRGB { /** diff --git a/GlitchyEngine/src/World/Components.bf b/GlitchyEngine/src/World/Components.bf index 4acece6..3e166c7 100644 --- a/GlitchyEngine/src/World/Components.bf +++ b/GlitchyEngine/src/World/Components.bf @@ -46,7 +46,20 @@ namespace GlitchyEngine.World [Component("Sprite Renderer")] struct SpriterRendererComponent : IDisposableComponent { - public Texture2D Sprite = null; + private Texture2D _sprite = null; + + public Texture2D Sprite + { + get => _sprite; + set mut + { + if (_sprite == value) + return; + + SetReference!(_sprite, value); + } + } + public ColorRGBA Color = .White; public Vector4 UvTransform = .(0, 0, 1, 1); @@ -63,7 +76,7 @@ namespace GlitchyEngine.World public void Dispose() { - Sprite?.ReleaseRef(); + _sprite?.ReleaseRef(); } } diff --git a/GlitchyEngine/src/World/SceneSerializer.bf b/GlitchyEngine/src/World/SceneSerializer.bf index 2a5d86f..70e75d6 100644 --- a/GlitchyEngine/src/World/SceneSerializer.bf +++ b/GlitchyEngine/src/World/SceneSerializer.bf @@ -88,7 +88,7 @@ namespace GlitchyEngine.World { Serialize.Value(writer, "Color", component.Color); Serialize.Value(writer, "IsCircle", component.IsCircle); - Serialize.Value(writer, "Sprite", component.Sprite); + Serialize.Value(writer, "Sprite", component.Sprite?.Identifier); Serialize.Value(writer, "UvTransform", component.UvTransform); }); @@ -169,6 +169,16 @@ namespace GlitchyEngine.World Serialize.Value(writer, "Restitution", component.Restitution); Serialize.Value(writer, "RestitutionThreshold", component.RestitutionThreshold); }); + + SerializeComponent(writer, entity, "MeshComponent", scope (component) => + { + Serialize.Value(writer, "Mesh", component.Mesh.Identifier); + }); + + SerializeComponent(writer, entity, "MeshRendererComponent", scope (component) => + { + Serialize.Value(writer, "Material", component.Material.Identifier); + }); } writer.EntryEnd(); @@ -260,6 +270,21 @@ namespace GlitchyEngine.World private Result DeserializeEntity(BonReader reader) { + mixin DeserializeAsset(StringView identifier) where T : Asset + { + Asset asset = null; + + Try!(Deserialize.Value(reader, identifier, out asset)); + + if (asset != null && !(asset is T)) + { + Log.EngineLogger.Error($"Asset {asset.Identifier} is not a {nameof(T)}."); + return .Err; + } + + (T)asset + } + Try!(reader.ObjectBlock()); Deserialize.Value(reader, "Id", let uuid); @@ -287,40 +312,22 @@ namespace GlitchyEngine.World delete name; - return .Ok; - })); - case "NameComponent": - Try!(DeserializeComponent(reader, entity, scope (component) => - { - String name; - - Deserialize.Value(reader, "Name", out name); - - component.SetName(name); - - delete name; - return .Ok; })); case "SpriterRendererComponent": Try!(DeserializeComponent(reader, entity, scope (component) => { - // TODO: Texture - Try!(Deserialize.Value(reader, "Color", out component.Color)); reader.EntryEnd(); Try!(Deserialize.Value(reader, "IsCircle", out component.IsCircle)); reader.EntryEnd(); - String spriteName; - Try!(Deserialize.Value(reader, "Sprite", out spriteName)); - - if (spriteName != null) - component.Sprite = Content.LoadAsset(spriteName); - - delete spriteName; - + using (Texture2D sprite = DeserializeAsset!("Sprite")) + { + component.Sprite = (Texture2D)sprite; + } reader.EntryEnd(); + Try!(Deserialize.Value(reader, "UvTransform", out component.UvTransform)); return .Ok; @@ -407,7 +414,7 @@ namespace GlitchyEngine.World case "LightComponent": Try!(DeserializeComponent(reader, entity, scope (component) => { - SceneLight light = component.SceneLight; + ref SceneLight light = ref component.SceneLight; Deserialize.Value(reader, "LightType", out light.[Friend]_type); reader.EntryEnd(); @@ -464,7 +471,26 @@ namespace GlitchyEngine.World return .Ok; })); - + case "MeshComponent": + Try!(DeserializeComponent(reader, entity, scope (component) => + { + using (GeometryBinding mesh = DeserializeAsset!("Mesh")) + { + component.Mesh = mesh; + } + + return .Ok; + })); + case "MeshRendererComponent": + Try!(DeserializeComponent(reader, entity, scope (component) => + { + using (Material material = DeserializeAsset!("Material")) + { + component.Material = material; + } + + return .Ok; + })); default: Log.EngineLogger.AssertDebug(false, "Unknown component type"); //return .Err;