diff options
Diffstat (limited to 'Thronefall_1_57/Decompile/NGS.MeshFusionPro')
84 files changed, 5323 insertions, 0 deletions
diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/AfterCombineAction.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/AfterCombineAction.cs new file mode 100644 index 0000000..f586b15 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/AfterCombineAction.cs @@ -0,0 +1,8 @@ +namespace NGS.MeshFusionPro; + +public enum AfterCombineAction +{ + DisableComponents, + DestroyGameObject, + DoNothing +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/BinaryTree.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/BinaryTree.cs new file mode 100644 index 0000000..b7eddf1 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/BinaryTree.cs @@ -0,0 +1,156 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public abstract class BinaryTree<TNode, TData> where TNode : BinaryTreeNode<TData> +{ + private Dictionary<TData, List<TNode>> _dataToNodes; + + public IBinaryTreeNode Root => RootInternal; + + public int Height { get; private set; } + + protected TNode RootInternal { get; private set; } + + public BinaryTree() + { + Height = 0; + _dataToNodes = new Dictionary<TData, List<TNode>>(); + } + + public void Add(TData data) + { + if (Root == null) + { + RootInternal = CreateRoot(data); + Height = 1; + } + if (!Includes(RootInternal, data)) + { + GrowTreeUp(data); + } + AddData(RootInternal, data, 1); + } + + public bool Remove(TData data) + { + if (!_dataToNodes.TryGetValue(data, out var value)) + { + return false; + } + foreach (TNode item in value) + { + item.Remove(data); + } + return _dataToNodes.Remove(data); + } + + protected void GrowTreeUp(TData target) + { + if (!Includes(RootInternal, target)) + { + RootInternal = ExpandRoot(RootInternal, target); + Height++; + GrowTreeUp(target); + } + } + + protected void GrowTreeDown(TNode node, TData target, int depth) + { + if (node.HasChilds) + { + throw new Exception("GrowTreeDown::" + depth + " node already has childs"); + } + Bounds bounds = node.Bounds; + Vector3 vector; + Vector3 size; + if (bounds.size.x > bounds.size.y || bounds.size.x > bounds.size.z) + { + vector = new Vector3(bounds.size.x / 4f, 0f, 0f); + size = new Vector3(bounds.size.x / 2f, bounds.size.y, bounds.size.z); + } + else if (bounds.size.y > bounds.size.x || bounds.size.y > bounds.size.z) + { + vector = new Vector3(0f, bounds.size.y / 4f, 0f); + size = new Vector3(bounds.size.x, bounds.size.y / 2f, bounds.size.z); + } + else + { + vector = new Vector3(0f, 0f, bounds.size.z / 4f); + size = new Vector3(bounds.size.x, bounds.size.y, bounds.size.z / 2f); + } + bool flag = depth == Height; + TNode val = CreateNode(bounds.center - vector, size, flag); + TNode val2 = CreateNode(bounds.center + vector, size, flag); + node.SetChilds(val, val2); + if (!flag) + { + if (Intersects(val, target)) + { + GrowTreeDown(val, target, depth + 1); + } + if (Intersects(val2, target)) + { + GrowTreeDown(val2, target, depth + 1); + } + } + } + + protected void AddData(TNode node, TData data, int depth) + { + if (node.IsLeaf) + { + node.Add(data); + if (!_dataToNodes.TryGetValue(data, out var value)) + { + value = new List<TNode>(); + _dataToNodes.Add(data, value); + } + if (!value.Contains(node)) + { + value.Add(node); + } + return; + } + if (!node.HasChilds) + { + GrowTreeDown(node, data, depth + 1); + } + TNode node2 = (TNode)node.Left; + TNode node3 = (TNode)node.Right; + if (Intersects(node2, data)) + { + AddData(node2, data, depth + 1); + } + if (Intersects(node3, data)) + { + AddData(node3, data, depth + 1); + } + } + + protected void TreeTraversal(Func<TNode, int, bool> func) + { + TreeTraversal(RootInternal, 1, func); + } + + protected void TreeTraversal(TNode current, int depth, Func<TNode, int, bool> func) + { + if (func(current, depth) && current.HasChilds) + { + TreeTraversal((TNode)current.Left, depth + 1, func); + TreeTraversal((TNode)current.Right, depth + 1, func); + } + } + + protected abstract TNode CreateRoot(TData data); + + protected abstract TNode ExpandRoot(TNode root, TData target); + + protected abstract TNode CreateNode(Vector3 center, Vector3 size, bool isLeaf); + + protected abstract bool Intersects(TNode node, TData data); + + protected abstract bool Includes(TNode node, TData data); +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/BinaryTreeDrawer.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/BinaryTreeDrawer.cs new file mode 100644 index 0000000..87776a2 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/BinaryTreeDrawer.cs @@ -0,0 +1,22 @@ +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public class BinaryTreeDrawer<TData> +{ + public void DrawGizmo(IBinaryTreeNode root, Color color) + { + Gizmos.color = color; + DrawNode(root); + } + + private void DrawNode(IBinaryTreeNode node) + { + Gizmos.DrawWireCube(node.Center, node.Size); + if (node.HasChilds) + { + DrawNode(node.GetLeft()); + DrawNode(node.GetRight()); + } + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/BinaryTreeNode.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/BinaryTreeNode.cs new file mode 100644 index 0000000..4558519 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/BinaryTreeNode.cs @@ -0,0 +1,48 @@ +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public abstract class BinaryTreeNode<TData> : IBinaryTreeNode +{ + public BinaryTreeNode<TData> Left { get; private set; } + + public BinaryTreeNode<TData> Right { get; private set; } + + public bool IsLeaf { get; private set; } + + public bool HasChilds => Left != null; + + public Vector3 Center { get; private set; } + + public Vector3 Size { get; private set; } + + public Bounds Bounds { get; private set; } + + public BinaryTreeNode(Vector3 center, Vector3 size, bool isLeaf) + { + Center = center; + Size = size; + Bounds = new Bounds(center, size); + IsLeaf = isLeaf; + } + + public IBinaryTreeNode GetLeft() + { + return Left; + } + + public IBinaryTreeNode GetRight() + { + return Right; + } + + public void SetChilds(BinaryTreeNode<TData> left, BinaryTreeNode<TData> right) + { + Left = left; + Right = right; + } + + public abstract void Add(TData data); + + public abstract void Remove(TData data); +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/BoundsHelper.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/BoundsHelper.cs new file mode 100644 index 0000000..012a350 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/BoundsHelper.cs @@ -0,0 +1,39 @@ +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public static class BoundsHelper +{ + public static Bounds Transform(this Bounds bounds, Matrix4x4 transform) + { + Vector3 min = bounds.min; + Vector3 max = bounds.max; + Vector4 column = transform.GetColumn(3); + Vector3 vector = column; + Vector3 vector2 = column; + for (int i = 0; i < 3; i++) + { + for (int j = 0; j < 3; j++) + { + float num = transform[i, j]; + float num2 = num * min[j]; + float num3 = num * max[j]; + vector[i] += ((num2 < num3) ? num2 : num3); + vector2[i] += ((num2 < num3) ? num3 : num2); + } + } + Bounds result = default(Bounds); + result.center = transform.MultiplyPoint3x4(bounds.center); + result.size = vector2 - vector; + return result; + } + + public static bool Contains(this Bounds bounds, Bounds target) + { + if (bounds.Contains(target.min)) + { + return bounds.Contains(target.max); + } + return false; + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombineErrorStrategy.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombineErrorStrategy.cs new file mode 100644 index 0000000..89cfbe3 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombineErrorStrategy.cs @@ -0,0 +1,7 @@ +namespace NGS.MeshFusionPro; + +public enum CombineErrorStrategy +{ + UndoCombining, + Ignore +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombineMethod.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombineMethod.cs new file mode 100644 index 0000000..e30d53e --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombineMethod.cs @@ -0,0 +1,6 @@ +namespace NGS.MeshFusionPro; + +public enum CombineMethod +{ + Simple +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombineSource.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombineSource.cs new file mode 100644 index 0000000..f010062 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombineSource.cs @@ -0,0 +1,92 @@ +using System; +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public class CombineSource : ICombineSource<CombinedObject, CombinedObjectPart>, ICombineSource +{ + public Vector3 Position { get; private set; } + + public Bounds Bounds { get; private set; } + + public MeshCombineInfo CombineInfo { get; private set; } + + public RendererSettings RendererSettings { get; private set; } + + public event Action<ICombinedObject, ICombinedObjectPart> onCombined; + + public event Action<ICombinedObject, string> onCombineError; + + public event Action<ICombinedObject> onCombineFailed; + + public event Action<CombinedObject, CombinedObjectPart> onCombinedTyped; + + public event Action<CombinedObject, string> onCombineErrorTyped; + + public event Action<CombinedObject> onCombineFailedTyped; + + public CombineSource(GameObject go, int submeshIndex = 0) + : this(go.GetComponent<MeshFilter>().mesh, go.GetComponent<MeshRenderer>(), submeshIndex) + { + } + + public CombineSource(Mesh mesh, MeshRenderer renderer, int submeshIndex = 0) + { + if (mesh == null) + { + throw new ArgumentException("Mesh is null"); + } + if (renderer == null) + { + throw new ArgumentException("Mesh Renderer is null"); + } + if (submeshIndex >= mesh.subMeshCount) + { + throw new ArgumentException("Submesh index is greater the submeshCount"); + } + MeshCombineInfo info = new MeshCombineInfo(mesh, renderer.localToWorldMatrix, renderer.lightmapScaleOffset, renderer.realtimeLightmapScaleOffset, submeshIndex); + RendererSettings settings = new RendererSettings(renderer, submeshIndex); + Construct(info, settings, renderer.bounds); + } + + public CombineSource(MeshCombineInfo info, RendererSettings settings) + : this(info, settings, info.mesh.bounds.Transform(info.transformMatrix)) + { + } + + public CombineSource(MeshCombineInfo info, RendererSettings settings, Bounds bounds) + { + Construct(info, settings, bounds); + } + + private void Construct(MeshCombineInfo info, RendererSettings settings, Bounds bounds) + { + CombineInfo = info; + RendererSettings = settings; + Position = info.transformMatrix.GetTranslation(); + Bounds = bounds; + } + + public void Combined(CombinedObject root, CombinedObjectPart part) + { + this.onCombined?.Invoke(root, part); + this.onCombinedTyped?.Invoke(root, part); + } + + public void CombineError(CombinedObject root, string errorMessage) + { + if (this.onCombineError == null && this.onCombinedTyped == null) + { + Debug.Log("Error during combine " + root.name + ", reason :" + errorMessage); + return; + } + this.onCombineError?.Invoke(root, errorMessage); + this.onCombineErrorTyped?.Invoke(root, errorMessage); + } + + public void CombineFailed(CombinedObject root) + { + this.onCombineFailed?.Invoke(root); + this.onCombineFailedTyped?.Invoke(root); + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombineTree.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombineTree.cs new file mode 100644 index 0000000..2fd39af --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombineTree.cs @@ -0,0 +1,112 @@ +using System; +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public class CombineTree : BinaryTree<CombineTreeNode, ICombineSource> +{ + private ICombinedMeshFactory _factory; + + private float _leafSize; + + private int _vertexLimit; + + public float LeafSize => _leafSize; + + public int VertexLimit => _vertexLimit; + + public ICombinedMeshFactory CombinedMeshFactory => _factory; + + public event Action<CombinedObject> onStaticCombinedObjectCreated; + + public event Action<DynamicCombinedObject> onDynamicCombinedObjectCreated; + + public event Action<CombinedLODGroup> onCombinedLODGroupCreated; + + public CombineTree(ICombinedMeshFactory factory, float leafSize, int vertexLimit) + { + _factory = factory; + _leafSize = leafSize; + _vertexLimit = vertexLimit; + } + + public void Combine() + { + TreeTraversal(delegate(CombineTreeNode node, int depth) + { + node.Combine(); + return true; + }); + } + + protected override CombineTreeNode CreateRoot(ICombineSource source) + { + return CreateNode(source.Position, Vector3.one * _leafSize, isLeaf: true); + } + + protected override CombineTreeNode CreateNode(Vector3 center, Vector3 size, bool isLeaf) + { + CombineTreeNode combineTreeNode = new CombineTreeNode(this, center, size, isLeaf); + combineTreeNode.onStaticCombinedObjectCreated += this.onStaticCombinedObjectCreated; + combineTreeNode.onDynamicCombinedObjectCreated += this.onDynamicCombinedObjectCreated; + combineTreeNode.onCombinedLODGroupCreated += this.onCombinedLODGroupCreated; + return combineTreeNode; + } + + protected override CombineTreeNode ExpandRoot(CombineTreeNode root, ICombineSource target) + { + Bounds bounds = root.Bounds; + Bounds bounds2 = target.Bounds; + Vector3 center = Vector3.zero; + Vector3 size = Vector3.zero; + Vector3 center2 = Vector3.zero; + bool flag = false; + for (int i = 0; i < 3; i++) + { + if (bounds2.min[i] < bounds.min[i]) + { + size = bounds.size; + size[i] *= 2f; + center = bounds.center; + center[i] -= bounds.size[i] / 2f; + center2 = bounds.center; + center2[i] -= bounds.size[i]; + break; + } + if (bounds2.max[i] > bounds.max[i]) + { + size = bounds.size; + size[i] *= 2f; + center = bounds.center; + center[i] += bounds.size[i] / 2f; + center2 = bounds.center; + center2[i] += bounds.size[i]; + flag = true; + break; + } + } + CombineTreeNode combineTreeNode = CreateNode(center, size, isLeaf: false); + CombineTreeNode combineTreeNode2 = CreateNode(center2, bounds.size, root.IsLeaf); + if (flag) + { + combineTreeNode.SetChilds(base.RootInternal, combineTreeNode2); + } + else + { + combineTreeNode.SetChilds(combineTreeNode2, base.RootInternal); + } + return combineTreeNode; + } + + protected override bool Includes(CombineTreeNode node, ICombineSource source) + { + Bounds bounds = node.Bounds; + Bounds bounds2 = source.Bounds; + return bounds.Contains(bounds2); + } + + protected override bool Intersects(CombineTreeNode node, ICombineSource source) + { + return node.Bounds.Contains(source.Position); + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombineTreeNode.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombineTreeNode.cs new file mode 100644 index 0000000..ca4c318 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombineTreeNode.cs @@ -0,0 +1,45 @@ +using System; +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public class CombineTreeNode : BinaryTreeNode<ICombineSource> +{ + private CombineTree _tree; + + private UniversalObjectsCombiner _combiner; + + public event Action<CombinedObject> onStaticCombinedObjectCreated; + + public event Action<DynamicCombinedObject> onDynamicCombinedObjectCreated; + + public event Action<CombinedLODGroup> onCombinedLODGroupCreated; + + public CombineTreeNode(CombineTree tree, Vector3 center, Vector3 size, bool isLeaf) + : base(center, size, isLeaf) + { + _tree = tree; + } + + public override void Add(ICombineSource source) + { + if (_combiner == null) + { + _combiner = new UniversalObjectsCombiner(_tree.CombinedMeshFactory, _tree.VertexLimit); + _combiner.onStaticCombinedObjectCreated += this.onStaticCombinedObjectCreated; + _combiner.onDynamicCombinedObjectCreated += this.onDynamicCombinedObjectCreated; + _combiner.onCombinedLODGroupCreated += this.onCombinedLODGroupCreated; + } + _combiner.AddSource(source); + } + + public override void Remove(ICombineSource source) + { + _combiner.RemoveSource(source); + } + + public void Combine() + { + _combiner?.Combine(); + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombinedLODGroup.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombinedLODGroup.cs new file mode 100644 index 0000000..e5f2a93 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombinedLODGroup.cs @@ -0,0 +1,265 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public class CombinedLODGroup : MonoBehaviour, ICombinedObject<CombinedLODGroupPart, LODGroupCombineSource>, ICombinedObject +{ + private class LevelOfDetailCombiner : StaticObjectsCombiner + { + private Transform _transform; + + private CombinedLODGroup _group; + + private Renderer[] _renderers; + + private int _level; + + public LevelOfDetailCombiner(int level, CombinedLODGroup group, ICombinedMeshFactory factory, int vertexLimit) + : base(factory, vertexLimit) + { + _level = level; + _group = group; + _transform = new GameObject("LOD" + _level).transform; + _transform.parent = group.transform; + _transform.localPosition = Vector3.zero; + } + + public Renderer[] GetRenderers() + { + if (_renderers == null || _renderers.Length != base.CombinedObjects.Count) + { + UpdateRenderersList(); + } + return _renderers; + } + + public Bounds CalculateBounds() + { + Bounds result = new Bounds(_group.transform.position, Vector3.zero); + GetRenderers(); + for (int i = 0; i < _renderers.Length; i++) + { + if (base.CombinedObjects[i].Parts.Count > 0) + { + result.Encapsulate(_renderers[i].bounds); + } + } + return result; + } + + protected override CombinedObject CreateCombinedObject(CombineSource source) + { + CombinedObject combinedObject = base.CreateCombinedObject(source); + combinedObject.transform.parent = _transform; + _group._updateLODs = true; + return combinedObject; + } + + private void UpdateRenderersList() + { + _renderers = base.CombinedObjects.Select((CombinedObject r) => r.GetComponent<Renderer>()).ToArray(); + } + } + + private LODGroup _group; + + private List<CombinedLODGroupPart> _parts; + + private LevelOfDetailCombiner[] _levelCombiners; + + private LOD[] _lods; + + private Bounds _localBounds; + + private int _lodCount; + + private LODGroupSettings _originalSettings; + + private float _originalBoundsSize; + + private bool _updateLODs; + + IReadOnlyList<ICombinedObjectPart> ICombinedObject.Parts => _parts; + + public IReadOnlyList<CombinedLODGroupPart> Parts => _parts; + + public LODGroupSettings Settings => _originalSettings; + + public Bounds Bounds + { + get + { + Bounds localBounds = _localBounds; + localBounds.center += base.transform.position; + return localBounds; + } + } + + public static CombinedLODGroup Create(MeshType meshType, CombineMethod combineMethod, LODGroupSettings settings, int vertexLimit = 45000) + { + return Create(new CombinedMeshFactory(meshType, combineMethod), settings, vertexLimit); + } + + public static CombinedLODGroup Create(ICombinedMeshFactory factory, LODGroupSettings settings, int vertexLimit = 45000) + { + CombinedLODGroup combinedLODGroup = new GameObject("CombinedLODGroup").AddComponent<CombinedLODGroup>(); + combinedLODGroup.Construct(settings, factory, vertexLimit); + return combinedLODGroup; + } + + private void Construct(LODGroupSettings settings, ICombinedMeshFactory factory, int vertexLimit) + { + if (factory == null) + { + throw new ArgumentException("CombinedLODGroup::factory is null"); + } + _group = base.gameObject.AddComponent<LODGroup>(); + _parts = new List<CombinedLODGroupPart>(); + _group.fadeMode = settings.fadeMode; + _group.animateCrossFading = settings.animateCrossFading; + _originalSettings = settings; + _lodCount = _originalSettings.lodCount; + _levelCombiners = new LevelOfDetailCombiner[_lodCount]; + _lods = new LOD[_originalSettings.lodCount]; + for (int i = 0; i < _originalSettings.lodCount; i++) + { + _levelCombiners[i] = new LevelOfDetailCombiner(i, this, factory, vertexLimit); + _lods[i] = new LOD + { + fadeTransitionWidth = _originalSettings.fadeTransitionsWidth[i], + screenRelativeTransitionHeight = _originalSettings.screenTransitionsHeight[i], + renderers = null + }; + } + } + + public void Combine(IEnumerable<ICombineSource> sources) + { + Combine(sources.Select((ICombineSource s) => (LODGroupCombineSource)s)); + } + + public void Combine(IEnumerable<LODGroupCombineSource> sourceGroups) + { + if (sourceGroups == null || sourceGroups.Count() == 0) + { + throw new ArgumentException("CombinedLODGroup::sources is null"); + } + LODGroupCombineSource[] array = sourceGroups.ToArray(); + if (_parts.Count == 0) + { + InitBeforeFirstCombine(array); + } + List<CombinedObjectPart>[] combinedParts = FillCombinersAndCreateBaseParts(array); + for (int i = 0; i < _lodCount; i++) + { + _levelCombiners[i].Combine(); + } + RecalculateBounds(); + if (_updateLODs) + { + UpdateLODs(); + _updateLODs = false; + } + CreatePartsAndNotifySources(array, combinedParts); + } + + public void Destroy(CombinedLODGroupPart part, IList<CombinedObjectPart> baseParts) + { + if (_parts.Remove(part)) + { + for (int i = 0; i < baseParts.Count; i++) + { + baseParts[i].Destroy(); + } + RecalculateBounds(); + } + } + + private void InitBeforeFirstCombine(LODGroupCombineSource[] sources) + { + Vector3 zero = Vector3.zero; + for (int i = 0; i < sources.Length; i++) + { + zero += sources[i].Position; + } + base.transform.position = zero / sources.Length; + _originalBoundsSize = sources[0].Bounds.size.magnitude; + } + + private List<CombinedObjectPart>[] FillCombinersAndCreateBaseParts(LODGroupCombineSource[] sourceGroups) + { + List<CombinedObjectPart>[] parts = new List<CombinedObjectPart>[sourceGroups.Length]; + for (int i = 0; i < sourceGroups.Length; i++) + { + LODGroupCombineSource sourceGroup = sourceGroups[i]; + parts[i] = new List<CombinedObjectPart>(); + for (int j = 0; j < _lodCount; j++) + { + CombineSource[] array = sourceGroup.BaseSources[j]; + foreach (CombineSource obj in array) + { + int g = i; + obj.onCombinedTyped += delegate(CombinedObject o, CombinedObjectPart p) + { + parts[g].Add(p); + }; + obj.onCombineErrorTyped += delegate(CombinedObject root, string msg) + { + sourceGroup.CombineError(this, msg); + }; + } + _levelCombiners[j].AddSources(array); + } + } + return parts; + } + + private void RecalculateBounds() + { + _localBounds = new Bounds(base.transform.position, Vector3.zero); + for (int i = 0; i < _levelCombiners.Length; i++) + { + _localBounds.Encapsulate(_levelCombiners[i].CalculateBounds()); + } + _localBounds.center -= base.transform.position; + } + + private void UpdateLODs() + { + float value = _localBounds.size.magnitude / _originalBoundsSize; + float num = 1f; + value = Mathf.Clamp(value, 1f, 100f); + for (int i = 0; i < _lodCount; i++) + { + LOD lOD = _lods[i]; + lOD.renderers = _levelCombiners[i].GetRenderers(); + lOD.screenRelativeTransitionHeight = _originalSettings.screenTransitionsHeight[i] * value; + if (lOD.screenRelativeTransitionHeight >= num) + { + num = (lOD.screenRelativeTransitionHeight = num - 0.03f); + } + _lods[i] = lOD; + } + _group.SetLODs(_lods); + } + + private void CreatePartsAndNotifySources(LODGroupCombineSource[] sourceGroups, List<CombinedObjectPart>[] combinedParts) + { + for (int i = 0; i < sourceGroups.Length; i++) + { + LODGroupCombineSource lODGroupCombineSource = sourceGroups[i]; + List<CombinedObjectPart> list = combinedParts[i]; + if (list.Count == 0) + { + lODGroupCombineSource.CombineFailed(this); + continue; + } + CombinedLODGroupPart combinedLODGroupPart = new CombinedLODGroupPart(this, list); + _parts.Add(combinedLODGroupPart); + lODGroupCombineSource.Combined(this, combinedLODGroupPart); + } + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombinedLODGroupMatcher.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombinedLODGroupMatcher.cs new file mode 100644 index 0000000..ef1b3c7 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombinedLODGroupMatcher.cs @@ -0,0 +1,20 @@ +namespace NGS.MeshFusionPro; + +public class CombinedLODGroupMatcher : CombinedObjectMatcher<CombinedLODGroup, LODGroupCombineSource> +{ + private LODGroupSettings _settings; + + public override void StartMatching(CombinedLODGroup combinedObject) + { + _settings = combinedObject.Settings; + } + + public override bool CanAddSource(LODGroupCombineSource source) + { + return source.Settings.IsEqual(_settings, 0.01f, 0.01f); + } + + public override void SourceAdded(LODGroupCombineSource source) + { + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombinedLODGroupPart.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombinedLODGroupPart.cs new file mode 100644 index 0000000..95c9c00 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombinedLODGroupPart.cs @@ -0,0 +1,49 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public class CombinedLODGroupPart : ICombinedObjectPart<CombinedLODGroup>, ICombinedObjectPart +{ + private List<CombinedObjectPart> _baseParts; + + private Bounds _localBounds; + + ICombinedObject ICombinedObjectPart.Root => Root; + + public CombinedLODGroup Root { get; private set; } + + public Bounds LocalBounds => _localBounds; + + public Bounds Bounds + { + get + { + Bounds localBounds = _localBounds; + localBounds.center += Root.transform.position; + return localBounds; + } + } + + public CombinedLODGroupPart(CombinedLODGroup root, List<CombinedObjectPart> baseParts) + { + Root = root; + _baseParts = baseParts; + CalculateLocalBounds(); + } + + public void Destroy() + { + Root.Destroy(this, _baseParts); + } + + private void CalculateLocalBounds() + { + _localBounds = _baseParts[0].Bounds; + for (int i = 1; i < _baseParts.Count; i++) + { + _localBounds.Encapsulate(_baseParts[i].Bounds); + } + _localBounds.center -= Root.transform.position; + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombinedMesh.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombinedMesh.cs new file mode 100644 index 0000000..fd9933b --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombinedMesh.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public class CombinedMesh : IDisposable +{ + private Mesh _mesh; + + private CombinedMeshDataInternal _meshData; + + private IMeshCombiner _combiner; + + private IMeshCutter _cutter; + + public Mesh Mesh => _mesh; + + public CombinedMeshData MeshData => _meshData; + + public CombinedMesh(IMeshCombiner combiner, IMeshCutter cutter) + { + if (combiner == null) + { + throw new ArgumentNullException("MeshCombiner not assigned"); + } + if (cutter == null) + { + throw new ArgumentNullException("MeshCutter not assigned"); + } + _mesh = new Mesh(); + _mesh.MarkDynamic(); + _combiner = combiner; + _cutter = cutter; + _meshData = CreateMeshData(); + _meshData.Initialize(this); + } + + public CombinedMeshPart[] Combine(IList<MeshCombineInfo> infos) + { + _combiner.Combine(_mesh, infos); + return _meshData.CreateParts(infos); + } + + public void Cut(IList<CombinedMeshPart> parts) + { + MeshCuttingInfo[] array = new MeshCuttingInfo[parts.Count]; + for (int i = 0; i < parts.Count; i++) + { + CombinedMeshPart combinedMeshPart = parts[i]; + array[i] = new MeshCuttingInfo + { + vertexStart = combinedMeshPart.VertexStart, + vertexCount = combinedMeshPart.VertexCount, + triangleStart = combinedMeshPart.TrianglesStart, + triangleCount = combinedMeshPart.TrianglesCount + }; + } + _cutter.Cut(_mesh, array); + _meshData.RemoveParts(parts); + } + + public void Dispose() + { + _meshData.Dispose(); + } + + protected virtual CombinedMeshDataInternal CreateMeshData() + { + return new CombinedMeshDataInternal(); + } +} +public class CombinedMesh<TCombinedMeshData> : CombinedMesh where TCombinedMeshData : CombinedMeshDataInternal, new() +{ + public TCombinedMeshData MeshDataInternal => (TCombinedMeshData)base.MeshData; + + public CombinedMesh(IMeshCombiner combiner, IMeshCutter cutter) + : base(combiner, cutter) + { + } + + protected override CombinedMeshDataInternal CreateMeshData() + { + return new TCombinedMeshData(); + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombinedMeshData.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombinedMeshData.cs new file mode 100644 index 0000000..06afc2b --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombinedMeshData.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public abstract class CombinedMeshData +{ + public abstract int PartsCount { get; } + + public abstract int VertexCount { get; } + + public abstract Bounds GetBounds(); + + public abstract Bounds GetBounds(CombinedMeshPart part); + + public abstract IEnumerable<CombinedMeshPart> GetParts(); +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombinedMeshDataInternal.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombinedMeshDataInternal.cs new file mode 100644 index 0000000..c055f95 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombinedMeshDataInternal.cs @@ -0,0 +1,124 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public class CombinedMeshDataInternal : CombinedMeshData, IDisposable +{ + private CombinedMesh _root; + + private List<CombinedMeshPartInternal> _parts; + + private int _vertexCount; + + private int _trianglesCount; + + private List<Bounds> _partsBounds; + + private Bounds _boundingBox; + + public override int PartsCount => _parts.Count; + + public override int VertexCount => _vertexCount; + + protected CombinedMesh Root => _root; + + public void Initialize(CombinedMesh root) + { + _root = root; + _parts = new List<CombinedMeshPartInternal>(); + OnInitialized(); + } + + public override Bounds GetBounds() + { + return _boundingBox; + } + + public override Bounds GetBounds(CombinedMeshPart part) + { + return _partsBounds[part.Index]; + } + + public override IEnumerable<CombinedMeshPart> GetParts() + { + for (int i = 0; i < _parts.Count; i++) + { + yield return _parts[i]; + } + } + + public void Dispose() + { + OnDispose(); + } + + public CombinedMeshPart[] CreateParts(IList<MeshCombineInfo> infos) + { + CombinedMeshPart[] array = new CombinedMeshPart[infos.Count]; + for (int i = 0; i < array.Length; i++) + { + MeshCombineInfo meshCombineInfo = infos[i]; + Mesh mesh = meshCombineInfo.mesh; + Matrix4x4 transformMatrix = meshCombineInfo.transformMatrix; + int vertexCount = _vertexCount; + int vertexCount2 = meshCombineInfo.vertexCount; + int trianglesCount = _trianglesCount; + int trianglesCount2 = meshCombineInfo.trianglesCount; + CombinedMeshPartInternal combinedMeshPartInternal = new CombinedMeshPartInternal(_root, _parts.Count, vertexCount, vertexCount2, trianglesCount, trianglesCount2); + _parts.Add(combinedMeshPartInternal); + array[i] = combinedMeshPartInternal; + _vertexCount += vertexCount2; + _trianglesCount += trianglesCount2; + OnAddPart(combinedMeshPartInternal, mesh, transformMatrix); + } + OnMeshUpdated(); + return array; + } + + public void RemoveParts(IList<CombinedMeshPart> parts) + { + for (int i = 0; i < parts.Count; i++) + { + CombinedMeshPartInternal combinedMeshPartInternal = (CombinedMeshPartInternal)parts[i]; + OnRemovePart(combinedMeshPartInternal); + int num = _parts.IndexOf(combinedMeshPartInternal); + int vertexCount = combinedMeshPartInternal.VertexCount; + int trianglesCount = combinedMeshPartInternal.TrianglesCount; + for (int j = num + 1; j < _parts.Count; j++) + { + CombinedMeshPartInternal combinedMeshPartInternal2 = _parts[j]; + combinedMeshPartInternal2.Offset(newVertexStart: combinedMeshPartInternal2.VertexStart - vertexCount, newTrianglesStart: combinedMeshPartInternal2.TrianglesStart - trianglesCount, newIndex: combinedMeshPartInternal2.Index - 1); + } + _parts.Remove(combinedMeshPartInternal); + _vertexCount -= combinedMeshPartInternal.VertexCount; + _trianglesCount -= combinedMeshPartInternal.TrianglesCount; + } + OnMeshUpdated(); + } + + protected virtual void OnInitialized() + { + _partsBounds = new List<Bounds>(); + } + + protected virtual void OnAddPart(CombinedMeshPart part, Mesh mesh, Matrix4x4 transform) + { + _partsBounds.Add(mesh.bounds.Transform(transform)); + } + + protected virtual void OnRemovePart(CombinedMeshPart part) + { + _partsBounds.RemoveAt(part.Index); + } + + protected virtual void OnMeshUpdated() + { + _boundingBox = _root.Mesh.bounds; + } + + protected virtual void OnDispose() + { + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombinedMeshFactory.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombinedMeshFactory.cs new file mode 100644 index 0000000..850efd8 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombinedMeshFactory.cs @@ -0,0 +1,43 @@ +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public class CombinedMeshFactory : ICombinedMeshFactory +{ + private IMeshToolsFactory _tools; + + private IMovableCombinedMeshFactory _movableMeshFactory; + + public CombinedMeshFactory(MeshType meshType, CombineMethod combineMethod, MoveMethod moveMethod = MoveMethod.Simple) + { + if (meshType == MeshType.Standard) + { + _tools = new SimpleToolsSTDFactory(); + if (moveMethod == MoveMethod.Simple) + { + _movableMeshFactory = new SimpleMovableMeshSTDFactory(_tools); + } + else + { + _movableMeshFactory = new JobsMovableMeshSTDFactory(_tools); + } + return; + } + _tools = new SimpleToolsLWFactory(); + if (moveMethod == MoveMethod.Simple) + { + Debug.Log("Simple mover not implemented yet for lightweight meshes. Jobs mover will be used instead"); + } + _movableMeshFactory = new JobsMovableMeshLWFactory(_tools); + } + + public CombinedMesh CreateCombinedMesh() + { + return new CombinedMesh(_tools.CreateMeshCombiner(), _tools.CreateMeshCutter()); + } + + public CombinedMesh CreateMovableCombinedMesh(out ICombinedMeshMover mover) + { + return _movableMeshFactory.CreateMovableMesh(out mover); + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombinedMeshPart.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombinedMeshPart.cs new file mode 100644 index 0000000..9034a26 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombinedMeshPart.cs @@ -0,0 +1,26 @@ +namespace NGS.MeshFusionPro; + +public class CombinedMeshPart +{ + public CombinedMesh Root { get; private set; } + + public int Index { get; protected set; } + + public int VertexStart { get; protected set; } + + public int VertexCount { get; protected set; } + + public int TrianglesStart { get; protected set; } + + public int TrianglesCount { get; protected set; } + + public CombinedMeshPart(CombinedMesh root, int index, int vertexStart, int vertexCount, int trianglesStart, int trianglesCount) + { + Root = root; + Index = index; + VertexStart = vertexStart; + VertexCount = vertexCount; + TrianglesStart = trianglesStart; + TrianglesCount = trianglesCount; + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombinedMeshPartInternal.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombinedMeshPartInternal.cs new file mode 100644 index 0000000..9bc07cd --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombinedMeshPartInternal.cs @@ -0,0 +1,16 @@ +namespace NGS.MeshFusionPro; + +public class CombinedMeshPartInternal : CombinedMeshPart +{ + public CombinedMeshPartInternal(CombinedMesh root, int index, int vertexStart, int vertexCount, int trianglesStart, int trianglesCount) + : base(root, index, vertexStart, vertexCount, trianglesStart, trianglesCount) + { + } + + public void Offset(int newIndex, int newVertexStart, int newTrianglesStart) + { + base.Index = newIndex; + base.VertexStart = newVertexStart; + base.TrianglesStart = newTrianglesStart; + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombinedObject.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombinedObject.cs new file mode 100644 index 0000000..5a7bc43 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombinedObject.cs @@ -0,0 +1,209 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public class CombinedObject : MonoBehaviour, ICombinedObject<CombinedObjectPart, CombineSource>, ICombinedObject +{ + private CombinedMesh _combinedMesh; + + private CombinedMeshDataInternal _meshData; + + private List<CombinedObjectPart> _parts; + + private List<CombinedMeshPart> _destroyedMeshParts; + + private RendererSettings _rendererSettings; + + private bool _updating; + + IReadOnlyList<ICombinedObjectPart> ICombinedObject.Parts => _parts; + + public IReadOnlyList<CombinedObjectPart> Parts => _parts; + + public RendererSettings RendererSettings => _rendererSettings; + + public Bounds Bounds + { + get + { + Bounds localBounds = LocalBounds; + localBounds.center += base.transform.position; + return localBounds; + } + } + + public Bounds LocalBounds => _combinedMesh.MeshData.GetBounds(); + + public int VertexCount => _combinedMesh.MeshData.VertexCount; + + public bool Updating + { + get + { + return _updating; + } + set + { + _updating = value; + base.enabled = value; + } + } + + private void Update() + { + if (!Updating) + { + base.enabled = false; + return; + } + ForceUpdate(); + base.enabled = false; + } + + private void OnDestroy() + { + _combinedMesh.Dispose(); + } + + public static CombinedObject Create(MeshType meshType, CombineMethod combineType, RendererSettings settings) + { + return Create(new CombinedMeshFactory(meshType, combineType), settings); + } + + public static CombinedObject Create(ICombinedMeshFactory factory, RendererSettings settings) + { + return Create(factory.CreateCombinedMesh(), settings); + } + + public static CombinedObject Create(CombinedMesh combinedMesh, RendererSettings settings) + { + CombinedObject combinedObject = new GameObject("Combined Object").AddComponent<CombinedObject>(); + combinedObject.Construct(combinedMesh, settings); + return combinedObject; + } + + private void Construct(CombinedMesh combinedMesh, RendererSettings settings) + { + _combinedMesh = combinedMesh; + _meshData = (CombinedMeshDataInternal)_combinedMesh.MeshData; + _parts = new List<CombinedObjectPart>(); + _destroyedMeshParts = new List<CombinedMeshPart>(); + _rendererSettings = settings; + _updating = true; + if (combinedMesh.MeshData.PartsCount > 0) + { + foreach (CombinedMeshPart part in combinedMesh.MeshData.GetParts()) + { + _parts.Add(new CombinedObjectPart(this, part)); + } + } + CreateMeshFilter(_combinedMesh.Mesh); + CreateMeshRenderer(settings); + } + + public void ForceUpdate() + { + if (_destroyedMeshParts.Count > 0) + { + _combinedMesh.Cut(_destroyedMeshParts); + _destroyedMeshParts.Clear(); + } + } + + public Bounds GetLocalBounds(CombinedObjectPart part) + { + return _meshData.GetBounds(part.MeshPart); + } + + public Bounds GetBounds(CombinedObjectPart part) + { + Bounds localBounds = GetLocalBounds(part); + localBounds.center += base.transform.position; + return localBounds; + } + + public void Combine(IEnumerable<ICombineSource> sources) + { + Combine(sources.Select((ICombineSource s) => (CombineSource)s)); + } + + public void Combine(IEnumerable<CombineSource> sources) + { + if (_parts.Count == 0) + { + base.transform.position = GetAveragePosition(sources); + } + Vector3 position = base.transform.position; + int num = sources.Count(); + int num2 = 0; + MeshCombineInfo[] array = new MeshCombineInfo[num]; + foreach (CombineSource source in sources) + { + MeshCombineInfo combineInfo = source.CombineInfo; + combineInfo.transformMatrix = combineInfo.transformMatrix.SetTranslation(source.Position - position); + array[num2++] = combineInfo; + } + try + { + CombinedMeshPart[] array2 = _combinedMesh.Combine(array); + num2 = 0; + foreach (CombineSource source2 in sources) + { + CombinedObjectPart combinedObjectPart = new CombinedObjectPart(this, array2[num2]); + _parts.Add(combinedObjectPart); + source2.Combined(this, combinedObjectPart); + num2++; + } + } + catch (Exception ex) + { + string errorMessage = ex.Message + ex.StackTrace; + foreach (CombineSource source3 in sources) + { + source3.CombineError(this, errorMessage); + source3.CombineFailed(this); + } + } + } + + public void Destroy(CombinedObjectPart part) + { + if (_parts.Remove(part)) + { + _destroyedMeshParts.Add(part.MeshPart); + base.enabled = true; + } + } + + private void CreateMeshFilter(Mesh mesh) + { + base.gameObject.AddComponent<MeshFilter>().sharedMesh = mesh; + } + + private void CreateMeshRenderer(RendererSettings settings) + { + MeshRenderer meshRenderer = base.gameObject.AddComponent<MeshRenderer>(); + meshRenderer.sharedMaterial = settings.material; + meshRenderer.shadowCastingMode = settings.shadowMode; + meshRenderer.receiveShadows = settings.receiveShadows; + meshRenderer.lightmapIndex = settings.lightmapIndex; + meshRenderer.realtimeLightmapIndex = settings.realtimeLightmapIndex; + meshRenderer.tag = settings.tag; + meshRenderer.gameObject.layer = settings.layer; + } + + private Vector3 GetAveragePosition(IEnumerable<CombineSource> sources) + { + Vector3 zero = Vector3.zero; + int num = 0; + foreach (CombineSource source in sources) + { + zero += source.Position; + num++; + } + return zero / num; + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombinedObjectMatcher.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombinedObjectMatcher.cs new file mode 100644 index 0000000..57e39b7 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombinedObjectMatcher.cs @@ -0,0 +1,10 @@ +namespace NGS.MeshFusionPro; + +public abstract class CombinedObjectMatcher<TCombinedObject, TCombineSource> where TCombinedObject : ICombinedObject where TCombineSource : ICombineSource +{ + public abstract void StartMatching(TCombinedObject combinedObject); + + public abstract bool CanAddSource(TCombineSource source); + + public abstract void SourceAdded(TCombineSource source); +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombinedObjectPart.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombinedObjectPart.cs new file mode 100644 index 0000000..ca434ff --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/CombinedObjectPart.cs @@ -0,0 +1,35 @@ +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public class CombinedObjectPart : ICombinedObjectPart<CombinedObject>, ICombinedObjectPart +{ + private bool _destroyed; + + ICombinedObject ICombinedObjectPart.Root => Root; + + public CombinedObject Root { get; private set; } + + public CombinedMeshPart MeshPart { get; private set; } + + public Bounds LocalBounds => Root.GetLocalBounds(this); + + public Bounds Bounds => Root.GetBounds(this); + + public CombinedObjectPart(CombinedObject root, CombinedMeshPart meshPart) + { + Root = root; + MeshPart = meshPart; + } + + public void Destroy() + { + if (_destroyed) + { + Debug.Log("CombinedPart already destroyed"); + return; + } + Root.Destroy(this); + _destroyed = true; + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/DynamicCombineSource.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/DynamicCombineSource.cs new file mode 100644 index 0000000..dcbf244 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/DynamicCombineSource.cs @@ -0,0 +1,70 @@ +using System; +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public class DynamicCombineSource : ICombineSource<DynamicCombinedObject, DynamicCombinedObjectPart>, ICombineSource +{ + private CombineSource _base; + + public CombineSource Base => _base; + + public Vector3 Position => _base.Position; + + public Bounds Bounds => _base.Bounds; + + public event Action<ICombinedObject, ICombinedObjectPart> onCombined; + + public event Action<ICombinedObject, string> onCombineError; + + public event Action<ICombinedObject> onCombineFailed; + + public event Action<DynamicCombinedObject, DynamicCombinedObjectPart> onCombinedTyped; + + public event Action<DynamicCombinedObject, string> onCombineErrorTyped; + + public event Action<DynamicCombinedObject> onCombineFailedTyped; + + public DynamicCombineSource(GameObject go, int submeshIndex = 0) + { + _base = new CombineSource(go, submeshIndex); + } + + public DynamicCombineSource(Mesh mesh, MeshRenderer renderer, int submeshIndex = 0) + { + _base = new CombineSource(mesh, renderer, submeshIndex); + } + + public DynamicCombineSource(MeshCombineInfo info, RendererSettings settings) + { + _base = new CombineSource(info, settings); + } + + public DynamicCombineSource(MeshCombineInfo info, RendererSettings settings, Bounds bounds) + { + _base = new CombineSource(info, settings, bounds); + } + + public void Combined(DynamicCombinedObject root, DynamicCombinedObjectPart part) + { + this.onCombined?.Invoke(root, part); + this.onCombinedTyped?.Invoke(root, part); + } + + public void CombineError(DynamicCombinedObject root, string errorMessage) + { + if (this.onCombineError == null && this.onCombineErrorTyped == null) + { + Debug.Log("Error during combine " + root.name + ", reason :" + errorMessage); + return; + } + this.onCombineError?.Invoke(root, errorMessage); + this.onCombineErrorTyped?.Invoke(root, errorMessage); + } + + public void CombineFailed(DynamicCombinedObject root) + { + this.onCombineFailed?.Invoke(root); + this.onCombineFailedTyped?.Invoke(root); + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/DynamicCombinedObject.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/DynamicCombinedObject.cs new file mode 100644 index 0000000..464bee8 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/DynamicCombinedObject.cs @@ -0,0 +1,155 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public class DynamicCombinedObject : MonoBehaviour, ICombinedObject<DynamicCombinedObjectPart, DynamicCombineSource>, ICombinedObject +{ + private CombinedObject _baseObject; + + private List<DynamicCombinedObjectPart> _parts; + + private ICombinedMeshMover _meshMover; + + private List<DynamicCombinedObjectPartInternal> _movedParts; + + private List<PartMoveInfo> _movedPartsData; + + private bool _partsMoved; + + IReadOnlyList<ICombinedObjectPart> ICombinedObject.Parts => _parts; + + public IReadOnlyList<DynamicCombinedObjectPart> Parts => _parts; + + public RendererSettings RendererSettings => _baseObject.RendererSettings; + + public Bounds Bounds => _baseObject.Bounds; + + public Bounds LocalBounds => _baseObject.LocalBounds; + + public int VertexCount => _baseObject.VertexCount; + + private void Update() + { + if (_movedParts.Count > 0) + { + if (_meshMover is IAsyncCombinedMeshMover asyncCombinedMeshMover) + { + asyncCombinedMeshMover.MovePartsAsync(_movedPartsData); + } + else + { + _meshMover.MoveParts(_movedPartsData); + } + for (int i = 0; i < _movedParts.Count; i++) + { + _movedParts[i].PositionUpdated(); + } + _movedParts.Clear(); + _movedPartsData.Clear(); + _partsMoved = true; + } + } + + private void LateUpdate() + { + if (_partsMoved) + { + if (_meshMover is IAsyncCombinedMeshMover asyncCombinedMeshMover) + { + asyncCombinedMeshMover.FinishAsyncMoving(); + } + _meshMover.ApplyData(); + _partsMoved = false; + } + _baseObject.ForceUpdate(); + if (_movedParts.Count == 0) + { + base.enabled = false; + } + } + + private void OnDestroy() + { + if (_meshMover is IDisposable disposable) + { + disposable.Dispose(); + } + } + + public static DynamicCombinedObject Create(MeshType meshType, CombineMethod combineMethod, MoveMethod moveMethod, RendererSettings settings) + { + return Create(new CombinedMeshFactory(meshType, combineMethod, moveMethod), settings); + } + + public static DynamicCombinedObject Create(ICombinedMeshFactory factory, RendererSettings settings) + { + ICombinedMeshMover mover; + CombinedObject combinedObject = CombinedObject.Create(factory.CreateMovableCombinedMesh(out mover), settings); + DynamicCombinedObject dynamicCombinedObject = combinedObject.gameObject.AddComponent<DynamicCombinedObject>(); + dynamicCombinedObject.Construct(combinedObject, mover); + return dynamicCombinedObject; + } + + private void Construct(CombinedObject baseObject, ICombinedMeshMover mover) + { + base.gameObject.name = "Dynamic Combined Object"; + _baseObject = baseObject; + _meshMover = mover; + _parts = new List<DynamicCombinedObjectPart>(); + _movedParts = new List<DynamicCombinedObjectPartInternal>(); + _movedPartsData = new List<PartMoveInfo>(); + _baseObject.Updating = false; + } + + public void Combine(IEnumerable<ICombineSource> sources) + { + Combine(sources.Select((ICombineSource s) => (DynamicCombineSource)s)); + } + + public void Combine(IEnumerable<DynamicCombineSource> sources) + { + int num = sources.Count(); + CombineSource[] array = new CombineSource[num]; + _ = new DynamicCombinedObjectPart[num]; + int num2 = 0; + foreach (DynamicCombineSource source in sources) + { + CombineSource baseSource = source.Base; + array[num2++] = baseSource; + baseSource.onCombinedTyped += delegate(CombinedObject root, CombinedObjectPart part) + { + DynamicCombinedObjectPart dynamicCombinedObjectPart = new DynamicCombinedObjectPartInternal(this, part, baseSource.CombineInfo.transformMatrix); + _parts.Add(dynamicCombinedObjectPart); + source.Combined(this, dynamicCombinedObjectPart); + }; + baseSource.onCombineErrorTyped += delegate(CombinedObject root, string message) + { + source.CombineError(this, message); + }; + baseSource.onCombineFailedTyped += delegate + { + source.CombineFailed(this); + }; + } + _baseObject.Combine(array); + } + + public void UpdatePart(DynamicCombinedObjectPartInternal part) + { + _movedParts.Add(part); + _movedPartsData.Add(part.CreateMoveInfo()); + base.enabled = true; + } + + public void Destroy(DynamicCombinedObjectPart dynamicPart, CombinedObjectPart basePart) + { + if (_parts.Remove(dynamicPart)) + { + basePart.Destroy(); + base.enabled = true; + } + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/DynamicCombinedObjectMatcher.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/DynamicCombinedObjectMatcher.cs new file mode 100644 index 0000000..cf76052 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/DynamicCombinedObjectMatcher.cs @@ -0,0 +1,39 @@ +namespace NGS.MeshFusionPro; + +public class DynamicCombinedObjectMatcher : CombinedObjectMatcher<DynamicCombinedObject, DynamicCombineSource> +{ + private RendererSettings _settings; + + private int _vertexCount; + + private int _vertexLimit; + + public DynamicCombinedObjectMatcher(int vertexLimit) + { + _vertexLimit = vertexLimit; + } + + public override void StartMatching(DynamicCombinedObject combinedObject) + { + _settings = combinedObject.RendererSettings; + _vertexCount = combinedObject.VertexCount; + } + + public override bool CanAddSource(DynamicCombineSource source) + { + if (!_settings.Equals(source.Base.RendererSettings)) + { + return false; + } + if (_vertexCount + source.Base.CombineInfo.vertexCount > _vertexLimit) + { + return false; + } + return true; + } + + public override void SourceAdded(DynamicCombineSource source) + { + _vertexCount += source.Base.CombineInfo.vertexCount; + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/DynamicCombinedObjectPart.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/DynamicCombinedObjectPart.cs new file mode 100644 index 0000000..c2ff95d --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/DynamicCombinedObjectPart.cs @@ -0,0 +1,44 @@ +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public abstract class DynamicCombinedObjectPart : ICombinedObjectPart<DynamicCombinedObject>, ICombinedObjectPart +{ + protected DynamicCombinedObject _root; + + protected CombinedObjectPart _basePart; + + private bool _destroyed; + + ICombinedObject ICombinedObjectPart.Root => Root; + + public DynamicCombinedObject Root => _root; + + public Bounds LocalBounds => _basePart.LocalBounds; + + public Bounds Bounds => _basePart.Bounds; + + public DynamicCombinedObjectPart(DynamicCombinedObject root, CombinedObjectPart basePart, Matrix4x4 transformMatrix) + { + _root = root; + _basePart = basePart; + } + + public abstract void Move(Vector3 position, Quaternion rotation, Vector3 scale); + + public abstract void Move(Matrix4x4 transform); + + public abstract void MoveLocal(Matrix4x4 localTransform); + + public void Destroy() + { + if (_destroyed) + { + Debug.Log("Part already destroyed"); + } + else + { + _root.Destroy(this, _basePart); + } + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/DynamicCombinedObjectPartInternal.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/DynamicCombinedObjectPartInternal.cs new file mode 100644 index 0000000..d7a0c1c --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/DynamicCombinedObjectPartInternal.cs @@ -0,0 +1,61 @@ +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public class DynamicCombinedObjectPartInternal : DynamicCombinedObjectPart +{ + private Matrix4x4 _localTransform; + + private Matrix4x4 _targetLocalTransform; + + private Matrix4x4 _worldToLocalMatrix; + + private bool _inMove; + + public DynamicCombinedObjectPartInternal(DynamicCombinedObject root, CombinedObjectPart basePart, Matrix4x4 transformMatrix) + : base(root, basePart, transformMatrix) + { + Vector3 pos = transformMatrix.GetTranslation() - root.transform.position; + _localTransform = transformMatrix.SetTranslation(pos); + _worldToLocalMatrix = base.Root.transform.worldToLocalMatrix; + } + + public override void Move(Vector3 position, Quaternion rotation, Vector3 scale) + { + Move(Matrix4x4.TRS(position, rotation, scale)); + } + + public override void Move(Matrix4x4 transform) + { + Matrix4x4 localTransform = _worldToLocalMatrix * transform; + MoveLocal(localTransform); + } + + public override void MoveLocal(Matrix4x4 localTransform) + { + if (!_inMove) + { + _targetLocalTransform = localTransform; + _root.UpdatePart(this); + _inMove = true; + } + } + + public PartMoveInfo CreateMoveInfo() + { + CombinedMeshPart meshPart = _basePart.MeshPart; + PartMoveInfo result = default(PartMoveInfo); + result.partIndex = meshPart.Index; + result.vertexStart = meshPart.VertexStart; + result.vertexCount = meshPart.VertexCount; + result.currentTransform = _localTransform; + result.targetTransform = _targetLocalTransform; + return result; + } + + public void PositionUpdated() + { + _localTransform = _targetLocalTransform; + _inMove = false; + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/DynamicMeshFusionSource.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/DynamicMeshFusionSource.cs new file mode 100644 index 0000000..bf92aec --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/DynamicMeshFusionSource.cs @@ -0,0 +1,130 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public class DynamicMeshFusionSource : MeshFusionSource +{ + [SerializeField] + [HideInInspector] + private MeshRenderer _renderer; + + [SerializeField] + [HideInInspector] + private MeshFilter _filter; + + [SerializeField] + [HideInInspector] + private Mesh _mesh; + + private DynamicCombineSource[] _sources; + + private DynamicCombinedObjectPart[] _parts; + + public override bool TryGetBounds(ref Bounds bounds) + { + if (_renderer != null) + { + bounds = _renderer.bounds; + return true; + } + return false; + } + + protected override void OnSourceCombinedInternal(ICombinedObject root, ICombinedObjectPart part) + { + for (int i = 0; i < _parts.Length; i++) + { + if (_parts[i] == null) + { + _parts[i] = (DynamicCombinedObjectPart)part; + return; + } + } + throw new Exception("Unexpected Behaviour"); + } + + protected override bool CheckCompatibilityAndGetComponents(out string incompatibilityReason) + { + incompatibilityReason = ""; + return CanCreateCombineSource(base.gameObject, ref incompatibilityReason, ref _renderer, ref _filter, ref _mesh); + } + + protected override void CreateSources() + { + if (_sources == null) + { + _sources = new DynamicCombineSource[_mesh.subMeshCount]; + } + if (_parts == null) + { + _parts = new DynamicCombinedObjectPart[_mesh.subMeshCount]; + } + for (int i = 0; i < _sources.Length; i++) + { + _sources[i] = new DynamicCombineSource(_mesh, _renderer, i); + } + } + + protected override IEnumerable<ICombineSource> GetCombineSources() + { + if (_sources == null) + { + yield break; + } + for (int i = 0; i < _sources.Length; i++) + { + DynamicCombineSource dynamicCombineSource = _sources[i]; + if (dynamicCombineSource == null) + { + break; + } + yield return dynamicCombineSource; + } + } + + protected override IEnumerable<ICombinedObjectPart> GetCombinedParts() + { + if (_parts == null) + { + yield break; + } + for (int i = 0; i < _parts.Length; i++) + { + DynamicCombinedObjectPart dynamicCombinedObjectPart = _parts[i]; + if (dynamicCombinedObjectPart == null) + { + break; + } + yield return dynamicCombinedObjectPart; + } + } + + protected override void ClearSources() + { + if (_sources != null) + { + for (int i = 0; i < _sources.Length && _sources[i] != null; i++) + { + _sources[i] = null; + } + } + } + + protected override void ClearParts() + { + if (_parts != null) + { + for (int i = 0; i < _parts.Length; i++) + { + _parts[i] = null; + } + } + } + + protected override void ToggleComponents(bool enabled) + { + _renderer.enabled = enabled; + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/DynamicObjectsCombiner.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/DynamicObjectsCombiner.cs new file mode 100644 index 0000000..a7d6115 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/DynamicObjectsCombiner.cs @@ -0,0 +1,42 @@ +using System.Collections.Generic; + +namespace NGS.MeshFusionPro; + +public class DynamicObjectsCombiner : ObjectsCombiner<DynamicCombinedObject, DynamicCombineSource> +{ + private ICombinedMeshFactory _factory; + + private DynamicCombinedObjectMatcher _matcher; + + private int _vertexLimit; + + public DynamicObjectsCombiner(ICombinedMeshFactory factory, int vertexLimit) + { + _factory = factory; + _matcher = new DynamicCombinedObjectMatcher(vertexLimit); + _vertexLimit = vertexLimit; + } + + public override void AddSource(DynamicCombineSource source) + { + if (source.Base.CombineInfo.vertexCount < _vertexLimit) + { + base.AddSource(source); + } + } + + protected override void CombineSources(DynamicCombinedObject root, IList<DynamicCombineSource> sources) + { + root.Combine(sources); + } + + protected override DynamicCombinedObject CreateCombinedObject(DynamicCombineSource source) + { + return DynamicCombinedObject.Create(_factory, source.Base.RendererSettings); + } + + protected override CombinedObjectMatcher<DynamicCombinedObject, DynamicCombineSource> GetMatcher() + { + return _matcher; + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/IAsyncCombinedMeshMover.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/IAsyncCombinedMeshMover.cs new file mode 100644 index 0000000..07f0de8 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/IAsyncCombinedMeshMover.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; + +namespace NGS.MeshFusionPro; + +public interface IAsyncCombinedMeshMover : ICombinedMeshMover +{ + void MovePartsAsync(IList<PartMoveInfo> moveInfos); + + void FinishAsyncMoving(); +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/IBinaryTreeNode.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/IBinaryTreeNode.cs new file mode 100644 index 0000000..c25beae --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/IBinaryTreeNode.cs @@ -0,0 +1,20 @@ +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public interface IBinaryTreeNode +{ + Vector3 Center { get; } + + Vector3 Size { get; } + + Bounds Bounds { get; } + + bool HasChilds { get; } + + bool IsLeaf { get; } + + IBinaryTreeNode GetLeft(); + + IBinaryTreeNode GetRight(); +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/ICombineSource.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/ICombineSource.cs new file mode 100644 index 0000000..2b147b7 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/ICombineSource.cs @@ -0,0 +1,25 @@ +using System; +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public interface ICombineSource +{ + Vector3 Position { get; } + + Bounds Bounds { get; } + + event Action<ICombinedObject, ICombinedObjectPart> onCombined; + + event Action<ICombinedObject, string> onCombineError; + + event Action<ICombinedObject> onCombineFailed; +} +public interface ICombineSource<TCombinedObject, TCombinedPart> : ICombineSource where TCombinedObject : ICombinedObject where TCombinedPart : ICombinedObjectPart +{ + event Action<TCombinedObject, TCombinedPart> onCombinedTyped; + + event Action<TCombinedObject, string> onCombineErrorTyped; + + event Action<TCombinedObject> onCombineFailedTyped; +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/ICombinedMeshFactory.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/ICombinedMeshFactory.cs new file mode 100644 index 0000000..98d71f7 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/ICombinedMeshFactory.cs @@ -0,0 +1,8 @@ +namespace NGS.MeshFusionPro; + +public interface ICombinedMeshFactory +{ + CombinedMesh CreateCombinedMesh(); + + CombinedMesh CreateMovableCombinedMesh(out ICombinedMeshMover mover); +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/ICombinedMeshMover.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/ICombinedMeshMover.cs new file mode 100644 index 0000000..05560a1 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/ICombinedMeshMover.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; + +namespace NGS.MeshFusionPro; + +public interface ICombinedMeshMover +{ + void MoveParts(IList<PartMoveInfo> moveInfos); + + void ApplyData(); +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/ICombinedObject.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/ICombinedObject.cs new file mode 100644 index 0000000..5c2bb55 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/ICombinedObject.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; + +namespace NGS.MeshFusionPro; + +public interface ICombinedObject +{ + IReadOnlyList<ICombinedObjectPart> Parts { get; } + + void Combine(IEnumerable<ICombineSource> sources); +} +public interface ICombinedObject<TCombinedPart, TCombinedSource> : ICombinedObject where TCombinedPart : ICombinedObjectPart where TCombinedSource : ICombineSource +{ + new IReadOnlyList<TCombinedPart> Parts { get; } + + void Combine(IEnumerable<TCombinedSource> sources); +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/ICombinedObjectPart.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/ICombinedObjectPart.cs new file mode 100644 index 0000000..b5a0f08 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/ICombinedObjectPart.cs @@ -0,0 +1,18 @@ +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public interface ICombinedObjectPart +{ + ICombinedObject Root { get; } + + Bounds Bounds { get; } + + Bounds LocalBounds { get; } + + void Destroy(); +} +public interface ICombinedObjectPart<TCombinedObject> : ICombinedObjectPart where TCombinedObject : ICombinedObject +{ + new TCombinedObject Root { get; } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/IMeshCombiner.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/IMeshCombiner.cs new file mode 100644 index 0000000..ccd84ce --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/IMeshCombiner.cs @@ -0,0 +1,9 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public interface IMeshCombiner +{ + void Combine(Mesh mesh, IList<MeshCombineInfo> combineInfos); +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/IMeshCutter.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/IMeshCutter.cs new file mode 100644 index 0000000..f9af704 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/IMeshCutter.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public interface IMeshCutter +{ + void Cut(Mesh mesh, MeshCuttingInfo cuttingInfo); + + void Cut(Mesh mesh, IList<MeshCuttingInfo> cuttingInfos); +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/IMeshToolsFactory.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/IMeshToolsFactory.cs new file mode 100644 index 0000000..2d670e2 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/IMeshToolsFactory.cs @@ -0,0 +1,8 @@ +namespace NGS.MeshFusionPro; + +public interface IMeshToolsFactory +{ + IMeshCombiner CreateMeshCombiner(); + + IMeshCutter CreateMeshCutter(); +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/IMovableCombinedMeshFactory.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/IMovableCombinedMeshFactory.cs new file mode 100644 index 0000000..555d632 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/IMovableCombinedMeshFactory.cs @@ -0,0 +1,6 @@ +namespace NGS.MeshFusionPro; + +public interface IMovableCombinedMeshFactory +{ + CombinedMesh CreateMovableMesh(out ICombinedMeshMover mover); +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/ISourceTrackingStrategy.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/ISourceTrackingStrategy.cs new file mode 100644 index 0000000..ba5db36 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/ISourceTrackingStrategy.cs @@ -0,0 +1,6 @@ +namespace NGS.MeshFusionPro; + +public interface ISourceTrackingStrategy +{ + bool OnUpdate(); +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/JobsMeshMoverLW.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/JobsMeshMoverLW.cs new file mode 100644 index 0000000..b2ea31d --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/JobsMeshMoverLW.cs @@ -0,0 +1,139 @@ +using System; +using System.Collections.Generic; +using Unity.Burst; +using Unity.Collections; +using Unity.Jobs; +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public class JobsMeshMoverLW : IAsyncCombinedMeshMover, ICombinedMeshMover, IDisposable +{ + [BurstCompile] + private struct MovePartsJob : IJobParallelFor + { + [NativeDisableParallelForRestriction] + public NativeArray<LightweightVertex> vertices; + + [ReadOnly] + public NativeArray<LightweightVertex> localVertices; + + [WriteOnly] + [NativeDisableParallelForRestriction] + public NativeArray<Bounds> bounds; + + [ReadOnly] + [NativeDisableParallelForRestriction] + public NativeArray<Bounds> localBounds; + + [ReadOnly] + public NativeList<PartMoveInfo> moveInfos; + + public void Execute(int idx) + { + PartMoveInfo partMoveInfo = moveInfos[idx]; + int partIndex = partMoveInfo.partIndex; + int vertexStart = partMoveInfo.vertexStart; + int num = vertexStart + partMoveInfo.vertexCount; + Matrix4x4 targetTransform = partMoveInfo.targetTransform; + for (int i = vertexStart; i < num; i++) + { + LightweightVertex lightweightVertex = localVertices[i]; + float w = lightweightVertex.tanW; + Vector3 normalized = targetTransform.MultiplyVector(lightweightVertex.Normal).normalized; + Vector4 tangent = targetTransform.MultiplyVector(lightweightVertex.Tangent).normalized; + tangent.w = w; + LightweightVertex lightweightVertex2 = default(LightweightVertex); + lightweightVertex2.Position = targetTransform.MultiplyPoint3x4(lightweightVertex.Position); + lightweightVertex2.Normal = normalized; + lightweightVertex2.Tangent = tangent; + lightweightVertex2.uv = lightweightVertex.uv; + lightweightVertex2.uv2 = lightweightVertex.uv2; + LightweightVertex value = lightweightVertex2; + vertices[i] = value; + } + bounds[partIndex] = localBounds[partIndex].Transform(targetTransform); + } + } + + [BurstCompile] + private struct RecalculateBoundsJob : IJob + { + public NativeArray<Bounds> bounds; + + public NativeArray<Bounds> boundingBox; + + public void Execute() + { + Bounds value = boundingBox[0]; + value.size = Vector3.zero; + for (int i = 0; i < bounds.Length; i++) + { + value.Encapsulate(bounds[i]); + } + boundingBox[0] = value; + } + } + + private MeshDataNativeArraysLW _meshData; + + private NativeList<PartMoveInfo> _moveInfos; + + private JobHandle _handle; + + public JobsMeshMoverLW(MeshDataNativeArraysLW meshData) + { + _meshData = meshData; + _moveInfos = new NativeList<PartMoveInfo>(Allocator.Persistent); + } + + public void MoveParts(IList<PartMoveInfo> moveInfos) + { + MovePartsAsync(moveInfos); + FinishAsyncMoving(); + } + + public void MovePartsAsync(IList<PartMoveInfo> moveInfos) + { + NativeArray<Bounds> bounds = _meshData.Bounds; + bounds[0] = new Bounds(_meshData.GetBounds().center, Vector3.zero); + _moveInfos.Clear(); + for (int i = 0; i < moveInfos.Count; i++) + { + ref NativeList<PartMoveInfo> moveInfos2 = ref _moveInfos; + PartMoveInfo value = moveInfos[i]; + moveInfos2.Add(in value); + } + MovePartsJob movePartsJob = default(MovePartsJob); + movePartsJob.vertices = _meshData.Vertices; + movePartsJob.bounds = _meshData.PartsBounds; + movePartsJob.localVertices = _meshData.VerticesLocal; + movePartsJob.localBounds = _meshData.PartsBoundsLocal; + movePartsJob.moveInfos = _moveInfos; + MovePartsJob jobData = movePartsJob; + RecalculateBoundsJob recalculateBoundsJob = default(RecalculateBoundsJob); + recalculateBoundsJob.bounds = _meshData.PartsBounds; + recalculateBoundsJob.boundingBox = bounds; + RecalculateBoundsJob jobData2 = recalculateBoundsJob; + _handle = jobData2.Schedule(IJobParallelForExtensions.Schedule(jobData, _moveInfos.Length, 4)); + } + + public void FinishAsyncMoving() + { + _handle.Complete(); + } + + public void ApplyData() + { + if (!_handle.IsCompleted) + { + FinishAsyncMoving(); + } + _meshData.ApplyDataToMesh(); + } + + public void Dispose() + { + _moveInfos.Dispose(); + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/JobsMeshMoverSTD.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/JobsMeshMoverSTD.cs new file mode 100644 index 0000000..535b8af --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/JobsMeshMoverSTD.cs @@ -0,0 +1,144 @@ +using System; +using System.Collections.Generic; +using Unity.Burst; +using Unity.Collections; +using Unity.Jobs; +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public class JobsMeshMoverSTD : IAsyncCombinedMeshMover, ICombinedMeshMover, IDisposable +{ + [BurstCompile] + private struct MovePartsJob : IJobParallelFor + { + [NativeDisableParallelForRestriction] + public NativeArray<Vector3> vertices; + + [NativeDisableParallelForRestriction] + public NativeArray<Vector3> normals; + + [NativeDisableParallelForRestriction] + public NativeArray<Vector4> tangents; + + [WriteOnly] + [NativeDisableParallelForRestriction] + public NativeArray<Bounds> bounds; + + [ReadOnly] + [NativeDisableParallelForRestriction] + public NativeArray<Bounds> localBounds; + + [ReadOnly] + public NativeList<PartMoveInfo> moveInfos; + + public void Execute(int idx) + { + PartMoveInfo partMoveInfo = moveInfos[idx]; + int partIndex = partMoveInfo.partIndex; + int vertexStart = partMoveInfo.vertexStart; + int num = vertexStart + partMoveInfo.vertexCount; + Matrix4x4 targetTransform = partMoveInfo.targetTransform; + Matrix4x4 inverse = partMoveInfo.currentTransform.inverse; + for (int i = vertexStart; i < num; i++) + { + Vector3 point = vertices[i]; + Vector3 vector = normals[i]; + Vector4 vector2 = tangents[i]; + float w = vector2.w; + point = inverse.MultiplyPoint3x4(point); + point = targetTransform.MultiplyPoint3x4(point); + vector = inverse.MultiplyVector(vector); + vector = targetTransform.MultiplyVector(vector); + vector2 = inverse.MultiplyVector(vector2); + vector2 = targetTransform.MultiplyVector(vector2); + vector2.w = w; + vertices[i] = point; + normals[i] = vector; + tangents[i] = vector2; + } + bounds[partIndex] = localBounds[partIndex].Transform(targetTransform); + } + } + + [BurstCompile] + private struct RecalculateBoundsJob : IJob + { + public NativeArray<Bounds> bounds; + + public NativeArray<Bounds> boundingBox; + + public void Execute() + { + Bounds value = boundingBox[0]; + for (int i = 0; i < bounds.Length; i++) + { + value.Encapsulate(bounds[i]); + } + boundingBox[0] = value; + } + } + + private MeshDataNativeArraysSTD _meshData; + + private NativeList<PartMoveInfo> _moveInfos; + + private JobHandle _handle; + + public JobsMeshMoverSTD(MeshDataNativeArraysSTD meshData) + { + _meshData = meshData; + _moveInfos = new NativeList<PartMoveInfo>(Allocator.Persistent); + } + + public void MoveParts(IList<PartMoveInfo> moveInfos) + { + MovePartsAsync(moveInfos); + FinishAsyncMoving(); + } + + public void MovePartsAsync(IList<PartMoveInfo> moveInfos) + { + NativeArray<Bounds> bounds = _meshData.Bounds; + bounds[0] = new Bounds(_meshData.GetBounds().center, Vector3.zero); + _moveInfos.Clear(); + for (int i = 0; i < moveInfos.Count; i++) + { + ref NativeList<PartMoveInfo> moveInfos2 = ref _moveInfos; + PartMoveInfo value = moveInfos[i]; + moveInfos2.Add(in value); + } + MovePartsJob movePartsJob = default(MovePartsJob); + movePartsJob.vertices = _meshData.Vertices; + movePartsJob.normals = _meshData.Normals; + movePartsJob.tangents = _meshData.Tangents; + movePartsJob.bounds = _meshData.PartsBounds; + movePartsJob.localBounds = _meshData.PartsBoundsLocal; + movePartsJob.moveInfos = _moveInfos; + MovePartsJob jobData = movePartsJob; + RecalculateBoundsJob recalculateBoundsJob = default(RecalculateBoundsJob); + recalculateBoundsJob.bounds = _meshData.PartsBounds; + recalculateBoundsJob.boundingBox = bounds; + RecalculateBoundsJob jobData2 = recalculateBoundsJob; + _handle = jobData2.Schedule(IJobParallelForExtensions.Schedule(jobData, _moveInfos.Length, 4)); + } + + public void FinishAsyncMoving() + { + _handle.Complete(); + } + + public void ApplyData() + { + if (!_handle.IsCompleted) + { + FinishAsyncMoving(); + } + _meshData.ApplyDataToMesh(); + } + + public void Dispose() + { + _moveInfos.Dispose(); + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/JobsMovableMeshLWFactory.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/JobsMovableMeshLWFactory.cs new file mode 100644 index 0000000..4790976 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/JobsMovableMeshLWFactory.cs @@ -0,0 +1,18 @@ +namespace NGS.MeshFusionPro; + +public class JobsMovableMeshLWFactory : IMovableCombinedMeshFactory +{ + private IMeshToolsFactory _tools; + + public JobsMovableMeshLWFactory(IMeshToolsFactory tools) + { + _tools = tools; + } + + public CombinedMesh CreateMovableMesh(out ICombinedMeshMover mover) + { + CombinedMesh<MeshDataNativeArraysLW> combinedMesh = new CombinedMesh<MeshDataNativeArraysLW>(_tools.CreateMeshCombiner(), _tools.CreateMeshCutter()); + mover = new JobsMeshMoverLW(combinedMesh.MeshDataInternal); + return combinedMesh; + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/JobsMovableMeshSTDFactory.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/JobsMovableMeshSTDFactory.cs new file mode 100644 index 0000000..36402f5 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/JobsMovableMeshSTDFactory.cs @@ -0,0 +1,18 @@ +namespace NGS.MeshFusionPro; + +public class JobsMovableMeshSTDFactory : IMovableCombinedMeshFactory +{ + private IMeshToolsFactory _tools; + + public JobsMovableMeshSTDFactory(IMeshToolsFactory tools) + { + _tools = tools; + } + + public CombinedMesh CreateMovableMesh(out ICombinedMeshMover mover) + { + CombinedMesh<MeshDataNativeArraysSTD> combinedMesh = new CombinedMesh<MeshDataNativeArraysSTD>(_tools.CreateMeshCombiner(), _tools.CreateMeshCutter()); + mover = new JobsMeshMoverSTD(combinedMesh.MeshDataInternal); + return combinedMesh; + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/LODGroupCombineSource.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/LODGroupCombineSource.cs new file mode 100644 index 0000000..66c640b --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/LODGroupCombineSource.cs @@ -0,0 +1,106 @@ +using System; +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public class LODGroupCombineSource : ICombineSource<CombinedLODGroup, CombinedLODGroupPart>, ICombineSource +{ + private Bounds _bounds; + + private LODGroupSettings _settings; + + private CombineSource[][] _sources; + + public Vector3 Position { get; private set; } + + public Bounds Bounds => _bounds; + + public LODGroup LODGroup { get; private set; } + + public LODGroupSettings Settings => _settings; + + public CombineSource[][] BaseSources => _sources; + + public event Action<ICombinedObject, ICombinedObjectPart> onCombined; + + public event Action<ICombinedObject, string> onCombineError; + + public event Action<ICombinedObject> onCombineFailed; + + public event Action<CombinedLODGroup, CombinedLODGroupPart> onCombinedTyped; + + public event Action<CombinedLODGroup, string> onCombineErrorTyped; + + public event Action<CombinedLODGroup> onCombineFailedTyped; + + public LODGroupCombineSource(LODGroup group) + { + LODGroup = group; + Position = group.transform.position; + LOD[] lODs = group.GetLODs(); + _settings = new LODGroupSettings(group); + _sources = new CombineSource[_settings.lodCount][]; + _bounds = new Bounds(group.localReferencePoint + Position, Vector3.zero); + for (int i = 0; i < lODs.Length; i++) + { + Renderer[] renderers = lODs[i].renderers; + CreateSourcesArray(i, renderers); + FillSources(i, renderers); + } + } + + public void Combined(CombinedLODGroup root, CombinedLODGroupPart part) + { + this.onCombined?.Invoke(root, part); + this.onCombinedTyped?.Invoke(root, part); + } + + public void CombineError(CombinedLODGroup root, string errorMessage) + { + if (this.onCombineError == null && this.onCombineErrorTyped == null) + { + Debug.Log("Combine error occured : " + root.name + ", reason : " + errorMessage); + return; + } + this.onCombineError?.Invoke(root, errorMessage); + this.onCombineErrorTyped?.Invoke(root, errorMessage); + } + + public void CombineFailed(CombinedLODGroup root) + { + this.onCombineFailed?.Invoke(root); + this.onCombineFailedTyped?.Invoke(root); + } + + private void CreateSourcesArray(int level, Renderer[] renderers) + { + int num = 0; + for (int i = 0; i < renderers.Length; i++) + { + if (!(renderers[i] == null)) + { + num += renderers[i].sharedMaterials.Length; + } + } + _sources[level] = new CombineSource[num]; + } + + private void FillSources(int level, Renderer[] renderers) + { + int num = 0; + for (int i = 0; i < renderers.Length; i++) + { + MeshRenderer meshRenderer = (MeshRenderer)renderers[i]; + if (!(meshRenderer == null)) + { + Mesh sharedMesh = meshRenderer.GetComponent<MeshFilter>().sharedMesh; + for (int j = 0; j < sharedMesh.subMeshCount; j++) + { + _sources[level][num] = new CombineSource(sharedMesh, meshRenderer, j); + num++; + } + _bounds.Encapsulate(meshRenderer.bounds); + } + } + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/LODGroupSettings.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/LODGroupSettings.cs new file mode 100644 index 0000000..b0d123f --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/LODGroupSettings.cs @@ -0,0 +1,63 @@ +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public struct LODGroupSettings +{ + public float size; + + public int lodCount; + + public LODFadeMode fadeMode; + + public bool animateCrossFading; + + public float[] screenTransitionsHeight; + + public float[] fadeTransitionsWidth; + + public LODGroupSettings(LODGroup group) + { + size = group.size; + lodCount = group.lodCount; + fadeMode = group.fadeMode; + animateCrossFading = group.animateCrossFading; + screenTransitionsHeight = new float[lodCount]; + fadeTransitionsWidth = new float[lodCount]; + LOD[] lODs = group.GetLODs(); + for (int i = 0; i < lodCount; i++) + { + LOD lOD = lODs[i]; + screenTransitionsHeight[i] = lOD.screenRelativeTransitionHeight; + fadeTransitionsWidth[i] = lOD.fadeTransitionWidth; + } + } + + public bool IsEqual(LODGroupSettings settings, float screenHeightThreshold = 0.0001f, float fadeWidthThreshold = 0.0001f) + { + if (lodCount != settings.lodCount) + { + return false; + } + if (fadeMode != settings.fadeMode) + { + return false; + } + if (animateCrossFading != settings.animateCrossFading) + { + return false; + } + for (int i = 0; i < lodCount; i++) + { + if (Mathf.Abs(screenTransitionsHeight[i] - settings.screenTransitionsHeight[i]) > screenHeightThreshold) + { + return false; + } + if (Mathf.Abs(fadeTransitionsWidth[i] - settings.fadeTransitionsWidth[i]) > fadeWidthThreshold) + { + return false; + } + } + return true; + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/LODGroupsCombiner.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/LODGroupsCombiner.cs new file mode 100644 index 0000000..961bf28 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/LODGroupsCombiner.cs @@ -0,0 +1,34 @@ +using System.Collections.Generic; + +namespace NGS.MeshFusionPro; + +public class LODGroupsCombiner : ObjectsCombiner<CombinedLODGroup, LODGroupCombineSource> +{ + private ICombinedMeshFactory _factory; + + private CombinedLODGroupMatcher _matcher; + + private int _vertexLimit; + + public LODGroupsCombiner(ICombinedMeshFactory factory, int vertexLimit) + { + _factory = factory; + _matcher = new CombinedLODGroupMatcher(); + _vertexLimit = vertexLimit; + } + + protected override CombinedLODGroup CreateCombinedObject(LODGroupCombineSource source) + { + return CombinedLODGroup.Create(_factory, source.Settings, _vertexLimit); + } + + protected override void CombineSources(CombinedLODGroup root, IList<LODGroupCombineSource> sources) + { + root.Combine(sources); + } + + protected override CombinedObjectMatcher<CombinedLODGroup, LODGroupCombineSource> GetMatcher() + { + return _matcher; + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/LODMeshFusionSource.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/LODMeshFusionSource.cs new file mode 100644 index 0000000..4b941b9 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/LODMeshFusionSource.cs @@ -0,0 +1,141 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public class LODMeshFusionSource : MeshFusionSource +{ + [SerializeField] + [HideInInspector] + private LODGroup _group; + + private LODGroupCombineSource _source; + + private CombinedLODGroupPart _part; + + private Bounds? _savedBounds; + + public override bool TryGetBounds(ref Bounds bounds) + { + if (_source != null) + { + bounds = _source.Bounds; + return true; + } + if (_part != null) + { + bounds = _part.Bounds; + return true; + } + if (_savedBounds.HasValue) + { + bounds = _savedBounds.Value; + return true; + } + if (base.IsIncompatible) + { + return false; + } + LOD[] lODs = _group.GetLODs(); + bounds = new Bounds(base.transform.position, Vector3.zero); + for (int i = 0; i < lODs.Length; i++) + { + Renderer[] renderers = lODs[i].renderers; + for (int j = 0; j < renderers.Length; j++) + { + if (!(renderers[j] == null)) + { + bounds.Encapsulate(renderers[j].bounds); + } + } + } + _savedBounds = bounds; + return true; + } + + protected override void OnSourceCombinedInternal(ICombinedObject root, ICombinedObjectPart part) + { + _part = (CombinedLODGroupPart)part; + } + + protected override bool CheckCompatibilityAndGetComponents(out string incompatibilityReason) + { + if (_group == null) + { + _group = GetComponent<LODGroup>(); + } + if (_group == null) + { + incompatibilityReason = "LODGroup not found"; + return false; + } + incompatibilityReason = ""; + MeshFilter filter = null; + Mesh mesh = null; + LOD[] lODs = _group.GetLODs(); + for (int i = 0; i < lODs.Length; i++) + { + Renderer[] renderers = lODs[i].renderers; + for (int j = 0; j < renderers.Length; j++) + { + MeshRenderer renderer = renderers[j] as MeshRenderer; + if (!(renderer == null) && !CanCreateCombineSource(renderer.gameObject, ref incompatibilityReason, ref renderer, ref filter, ref mesh)) + { + return false; + } + } + } + return true; + } + + protected override void CreateSources() + { + _source = new LODGroupCombineSource(_group); + } + + protected override IEnumerable<ICombineSource> GetCombineSources() + { + if (_source != null) + { + yield return _source; + } + } + + protected override IEnumerable<ICombinedObjectPart> GetCombinedParts() + { + if (_part != null) + { + yield return _part; + } + } + + protected override void ClearSources() + { + if (_source != null) + { + _source = null; + } + } + + protected override void ClearParts() + { + if (_part != null) + { + _part = null; + } + } + + protected override void ToggleComponents(bool enabled) + { + LOD[] lODs = _group.GetLODs(); + for (int i = 0; i < lODs.Length; i++) + { + Renderer[] renderers = lODs[i].renderers; + for (int j = 0; j < renderers.Length; j++) + { + renderers[j].enabled = enabled; + } + } + _group.enabled = enabled; + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/LightweightVertex.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/LightweightVertex.cs new file mode 100644 index 0000000..5c5de9e --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/LightweightVertex.cs @@ -0,0 +1,95 @@ +using Unity.Mathematics; +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public struct LightweightVertex +{ + public float3 pos; + + public sbyte normX; + + public sbyte normY; + + public sbyte normZ; + + public sbyte normW; + + public sbyte tanX; + + public sbyte tanY; + + public sbyte tanZ; + + public sbyte tanW; + + public half2 uv; + + public half2 uv2; + + public Vector3 Position + { + get + { + return pos; + } + set + { + pos = value; + } + } + + public Vector3 Normal + { + get + { + return new Vector3((float)normX / 127f, (float)normY / 127f, (float)normZ / 127f); + } + set + { + normX = (sbyte)(value.x * 127f); + normY = (sbyte)(value.y * 127f); + normZ = (sbyte)(value.z * 127f); + normW = 1; + } + } + + public Vector4 Tangent + { + get + { + return new Vector4((float)tanX / 127f, (float)tanY / 127f, (float)tanZ / 127f, (float)tanW / 127f); + } + set + { + tanX = (sbyte)(value.x * 127f); + tanY = (sbyte)(value.y * 127f); + tanZ = (sbyte)(value.z * 127f); + tanW = (sbyte)(value.w * 127f); + } + } + + public Vector2 UV + { + get + { + return new Vector2(uv.x, uv.y); + } + set + { + uv = new half2((half)value.x, (half)value.y); + } + } + + public Vector2 UV2 + { + get + { + return new Vector2(uv2.x, uv2.y); + } + set + { + uv2 = new half2((half)value.x, (half)value.y); + } + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MatrixHelper.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MatrixHelper.cs new file mode 100644 index 0000000..feb92b1 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MatrixHelper.cs @@ -0,0 +1,18 @@ +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public static class MatrixHelper +{ + public static Vector3 GetTranslation(this Matrix4x4 matrix) + { + return matrix.GetColumn(3); + } + + public static Matrix4x4 SetTranslation(this Matrix4x4 matrix, Vector3 pos) + { + Matrix4x4 result = matrix; + result.SetColumn(3, new Vector4(pos.x, pos.y, pos.z, 1f)); + return result; + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MeshCombineInfo.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MeshCombineInfo.cs new file mode 100644 index 0000000..ed879cb --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MeshCombineInfo.cs @@ -0,0 +1,43 @@ +using UnityEngine; +using UnityEngine.Rendering; + +namespace NGS.MeshFusionPro; + +public struct MeshCombineInfo +{ + public Mesh mesh; + + public Matrix4x4 transformMatrix; + + public Vector4 lightmapScaleOffset; + + public Vector4 realtimeLightmapScaleOffset; + + public int submeshIndex; + + public readonly int vertexCount; + + public readonly int trianglesCount; + + public MeshCombineInfo(Mesh mesh, int submeshIndex = 0) + : this(mesh, Matrix4x4.identity, submeshIndex) + { + } + + public MeshCombineInfo(Mesh mesh, Matrix4x4 transformMatrix, int submeshIndex = 0) + : this(mesh, transformMatrix, new Vector4(1f, 1f, 0f, 0f), new Vector4(1f, 1f, 0f, 0f), submeshIndex) + { + } + + public MeshCombineInfo(Mesh mesh, Matrix4x4 transformMatrix, Vector4 lightmapScaleOffset, Vector4 realtimeLightmapScaleOffset, int submeshIndex = 0) + { + this.mesh = mesh; + this.transformMatrix = transformMatrix; + this.lightmapScaleOffset = lightmapScaleOffset; + this.realtimeLightmapScaleOffset = realtimeLightmapScaleOffset; + this.submeshIndex = submeshIndex; + SubMeshDescriptor subMesh = mesh.GetSubMesh(submeshIndex); + vertexCount = subMesh.vertexCount; + trianglesCount = subMesh.indexCount; + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MeshCombinerBase.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MeshCombinerBase.cs new file mode 100644 index 0000000..34804fd --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MeshCombinerBase.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public abstract class MeshCombinerBase : IMeshCombiner +{ + public void Combine(Mesh mesh, IList<MeshCombineInfo> infos) + { + ValidateMesh(mesh); + ValidateCombineInfos(infos); + CombineInternal(mesh, infos); + } + + protected abstract void CombineInternal(Mesh mesh, IList<MeshCombineInfo> infos); + + protected virtual void ValidateMesh(Mesh mesh) + { + if (mesh == null) + { + throw new ArgumentNullException("mesh"); + } + if (mesh.subMeshCount > 1) + { + throw new ArgumentException("BaseMeshCombiner::input 'mesh' should have 1 submesh"); + } + } + + protected virtual void ValidateCombineInfos(IList<MeshCombineInfo> infos) + { + if (infos == null) + { + throw new ArgumentNullException("MeshCombineInfos is null"); + } + for (int i = 0; i < infos.Count; i++) + { + if (infos[i].mesh == null) + { + throw new ArgumentNullException("MeshCombineInfo.mesh is null"); + } + } + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MeshCombinerSimpleLW.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MeshCombinerSimpleLW.cs new file mode 100644 index 0000000..50e6031 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MeshCombinerSimpleLW.cs @@ -0,0 +1,29 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public class MeshCombinerSimpleLW : MeshCombinerBase +{ + private MeshCombinerSimpleSTD _stdCombiner; + + public MeshCombinerSimpleLW() + { + _stdCombiner = new MeshCombinerSimpleSTD(); + } + + protected override void CombineInternal(Mesh mesh, IList<MeshCombineInfo> infos) + { + VertexBufferUtil.ToStandardBuffer(mesh); + try + { + _stdCombiner.Combine(mesh, infos); + VertexBufferUtil.ToLightweightBuffer(mesh); + } + catch + { + VertexBufferUtil.ToLightweightBuffer(mesh); + throw; + } + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MeshCombinerSimpleSTD.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MeshCombinerSimpleSTD.cs new file mode 100644 index 0000000..3e9fb86 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MeshCombinerSimpleSTD.cs @@ -0,0 +1,42 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public class MeshCombinerSimpleSTD : MeshCombinerBase +{ + private MeshSeparatorSimple _meshSeparator; + + public MeshCombinerSimpleSTD() + { + _meshSeparator = new MeshSeparatorSimple(); + } + + protected override void CombineInternal(Mesh mesh, IList<MeshCombineInfo> infos) + { + CombineInstance[] array = new CombineInstance[infos.Count + 1]; + Mesh mesh2 = Object.Instantiate(mesh); + array[0] = CreateCombineInstance(new MeshCombineInfo(mesh2)); + for (int i = 0; i < infos.Count; i++) + { + array[i + 1] = CreateCombineInstance(infos[i]); + } + mesh.CombineMeshes(array, mergeSubMeshes: true, useMatrices: true, hasLightmapData: true); + } + + private CombineInstance CreateCombineInstance(MeshCombineInfo info) + { + Mesh mesh = info.mesh; + if (mesh.subMeshCount > 1) + { + mesh = _meshSeparator.GetSubmesh(mesh, info.submeshIndex); + } + CombineInstance result = default(CombineInstance); + result.mesh = mesh; + result.subMeshIndex = 0; + result.transform = info.transformMatrix; + result.lightmapScaleOffset = info.lightmapScaleOffset; + result.realtimeLightmapScaleOffset = info.realtimeLightmapScaleOffset; + return result; + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MeshCutterSimpleLW.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MeshCutterSimpleLW.cs new file mode 100644 index 0000000..4a70c56 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MeshCutterSimpleLW.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Unity.Collections; +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public class MeshCutterSimpleLW : IMeshCutter +{ + private static List<int> _triangles; + + static MeshCutterSimpleLW() + { + _triangles = new List<int>(); + } + + public void Cut(Mesh mesh, MeshCuttingInfo info) + { + Cut(mesh, new MeshCuttingInfo[1] { info }); + } + + public void Cut(Mesh mesh, IList<MeshCuttingInfo> infos) + { + ValidateMeshOrThrowException(mesh); + mesh.GetTriangles(_triangles, 0); + using (Mesh.MeshDataArray meshDataArray = Mesh.AcquireReadOnlyMeshData(mesh)) + { + NativeArray<LightweightVertex> other = meshDataArray[0].GetVertexData<LightweightVertex>(); + NativeList<LightweightVertex> nativeList = new NativeList<LightweightVertex>(Allocator.Temp); + nativeList.CopyFrom(in other); + foreach (MeshCuttingInfo item in infos.OrderByDescending((MeshCuttingInfo i) => i.triangleStart)) + { + nativeList.RemoveRange(item.vertexStart, item.vertexCount); + _triangles.RemoveRange(item.triangleStart, item.triangleCount); + OffsetTriangles(item); + } + mesh.SetTriangles(_triangles, 0); + mesh.SetVertexBufferData<LightweightVertex>(nativeList, 0, 0, nativeList.Length); + } + _triangles.Clear(); + } + + private void ValidateMeshOrThrowException(Mesh mesh) + { + if (mesh == null) + { + throw new ArgumentNullException("mesh"); + } + if (mesh.subMeshCount > 1) + { + throw new ArgumentException("SimpleMeshCutter::'mesh' should has only 1 submesh"); + } + } + + private void OffsetTriangles(MeshCuttingInfo info) + { + int vertexCount = info.vertexCount; + int triangleStart = info.triangleStart; + int count = _triangles.Count; + for (int i = triangleStart; i < count; i++) + { + _triangles[i] -= vertexCount; + } + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MeshCutterSimpleSTD.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MeshCutterSimpleSTD.cs new file mode 100644 index 0000000..950f0e9 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MeshCutterSimpleSTD.cs @@ -0,0 +1,138 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public class MeshCutterSimpleSTD : IMeshCutter +{ + private static List<Vector3> _vertices; + + private static List<Vector3> _normals; + + private static List<Vector4> _tangents; + + private static List<int> _triangles; + + private static List<Vector2>[] _uvs; + + private static int _maxUVsCount; + + static MeshCutterSimpleSTD() + { + _maxUVsCount = 4; + _vertices = new List<Vector3>(); + _normals = new List<Vector3>(); + _tangents = new List<Vector4>(); + _triangles = new List<int>(); + _uvs = new List<Vector2>[_maxUVsCount]; + for (int i = 0; i < _maxUVsCount; i++) + { + _uvs[i] = new List<Vector2>(); + } + } + + public void Cut(Mesh mesh, MeshCuttingInfo info) + { + Cut(mesh, new MeshCuttingInfo[1] { info }); + } + + public void Cut(Mesh mesh, IList<MeshCuttingInfo> infos) + { + ValidateMeshOrThrowException(mesh); + CollectData(mesh); + foreach (MeshCuttingInfo item in infos.OrderByDescending((MeshCuttingInfo i) => i.triangleStart)) + { + RemoveData(item); + OffsetTriangles(item); + } + ApplyDataToMesh(mesh); + ClearData(); + } + + private void ValidateMeshOrThrowException(Mesh mesh) + { + if (mesh == null) + { + throw new ArgumentNullException("mesh is null"); + } + if (mesh.subMeshCount > 1) + { + throw new ArgumentException("SimpleMeshCutter::'mesh' should has only 1 submesh"); + } + } + + private void CollectData(Mesh mesh) + { + mesh.GetVertices(_vertices); + mesh.GetNormals(_normals); + mesh.GetTangents(_tangents); + mesh.GetTriangles(_triangles, 0); + for (int i = 0; i < _maxUVsCount; i++) + { + mesh.GetUVs(i, _uvs[i]); + } + } + + private void RemoveData(MeshCuttingInfo cuttingInfo) + { + int vertexStart = cuttingInfo.vertexStart; + int vertexCount = cuttingInfo.vertexCount; + _vertices.RemoveRange(vertexStart, vertexCount); + if (_normals.Count > 0) + { + _normals.RemoveRange(vertexStart, vertexCount); + } + if (_tangents.Count > 0) + { + _tangents.RemoveRange(vertexStart, vertexCount); + } + _triangles.RemoveRange(cuttingInfo.triangleStart, cuttingInfo.triangleCount); + for (int i = 0; i < _uvs.Length; i++) + { + if (_uvs[i].Count > 0) + { + _uvs[i].RemoveRange(vertexStart, vertexCount); + } + } + } + + private void OffsetTriangles(MeshCuttingInfo info) + { + int vertexCount = info.vertexCount; + int triangleStart = info.triangleStart; + int count = _triangles.Count; + for (int i = triangleStart; i < count; i++) + { + _triangles[i] -= vertexCount; + } + } + + private void ApplyDataToMesh(Mesh mesh) + { + mesh.SetTriangles(_triangles, 0); + mesh.SetVertices(_vertices); + mesh.SetNormals(_normals); + mesh.SetTangents(_tangents); + for (int i = 0; i < _maxUVsCount; i++) + { + if (_uvs[i].Count > 0) + { + mesh.SetUVs(i, _uvs[i]); + } + } + } + + private void ClearData() + { + _vertices.Clear(); + _normals.Clear(); + _tangents.Clear(); + _triangles.Clear(); + for (int i = 0; i < _maxUVsCount; i++) + { + _uvs[i].Clear(); + } + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MeshCuttingInfo.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MeshCuttingInfo.cs new file mode 100644 index 0000000..a295571 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MeshCuttingInfo.cs @@ -0,0 +1,20 @@ +namespace NGS.MeshFusionPro; + +public struct MeshCuttingInfo +{ + public int vertexStart; + + public int vertexCount; + + public int triangleStart; + + public int triangleCount; + + public MeshCuttingInfo(int vertexStart, int vertexCount, int triangleStart, int triangleCount) + { + this.vertexStart = vertexStart; + this.vertexCount = vertexCount; + this.triangleStart = triangleStart; + this.triangleCount = triangleCount; + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MeshDataListsSTD.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MeshDataListsSTD.cs new file mode 100644 index 0000000..1bf34eb --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MeshDataListsSTD.cs @@ -0,0 +1,83 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public class MeshDataListsSTD : CombinedMeshDataInternal +{ + private CombinedMesh _root; + + private List<Vector3> _vertices; + + private List<Vector3> _normals; + + private List<Vector4> _tangents; + + private List<Bounds> _partsBounds; + + private List<Bounds> _partsBoundsLocal; + + public List<Vector3> Vertices => _vertices; + + public List<Vector3> Normals => _normals; + + public List<Vector4> Tangents => _tangents; + + public List<Bounds> PartsBounds => _partsBounds; + + public List<Bounds> PartsBoundsLocal => _partsBoundsLocal; + + public Bounds Bounds { get; set; } + + public override Bounds GetBounds() + { + return Bounds; + } + + public override Bounds GetBounds(CombinedMeshPart part) + { + return _partsBounds[part.Index]; + } + + public void ApplyDataToMesh() + { + Mesh mesh = _root.Mesh; + mesh.SetVertices(_vertices); + mesh.SetNormals(_normals); + mesh.SetTangents(_tangents); + mesh.bounds = Bounds; + } + + protected override void OnInitialized() + { + _root = base.Root; + _vertices = new List<Vector3>(); + _normals = new List<Vector3>(); + _tangents = new List<Vector4>(); + _partsBounds = new List<Bounds>(); + _partsBoundsLocal = new List<Bounds>(); + } + + protected override void OnAddPart(CombinedMeshPart part, Mesh mesh, Matrix4x4 transform) + { + Bounds bounds = mesh.bounds; + Bounds item = bounds.Transform(transform); + _partsBounds.Add(item); + _partsBoundsLocal.Add(bounds); + } + + protected override void OnRemovePart(CombinedMeshPart part) + { + _partsBounds.RemoveAt(part.Index); + _partsBoundsLocal.RemoveAt(part.Index); + } + + protected override void OnMeshUpdated() + { + Mesh mesh = _root.Mesh; + mesh.GetVertices(_vertices); + mesh.GetNormals(_normals); + mesh.GetTangents(_tangents); + Bounds = mesh.bounds; + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MeshDataNativeArraysLW.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MeshDataNativeArraysLW.cs new file mode 100644 index 0000000..939d022 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MeshDataNativeArraysLW.cs @@ -0,0 +1,131 @@ +using System.Collections.Generic; +using Unity.Collections; +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public class MeshDataNativeArraysLW : CombinedMeshDataInternal +{ + private CombinedMesh _root; + + private NativeList<LightweightVertex> _vertices; + + private NativeList<Bounds> _partsBounds; + + private NativeArray<Bounds> _bounds; + + private NativeList<LightweightVertex> _verticesLocal; + + private NativeList<Bounds> _partsBoundsLocal; + + private List<Vector3> _tempVertices; + + private List<Vector3> _tempNormals; + + private List<Vector4> _tempTangents; + + private List<Vector2> _tempUV; + + private List<Vector2> _tempUV2; + + public NativeArray<LightweightVertex> Vertices => _vertices; + + public NativeArray<Bounds> PartsBounds => _partsBounds; + + public NativeArray<Bounds> Bounds => _bounds; + + public NativeArray<LightweightVertex> VerticesLocal => _verticesLocal; + + public NativeArray<Bounds> PartsBoundsLocal => _partsBoundsLocal; + + public override Bounds GetBounds() + { + return _bounds[0]; + } + + public override Bounds GetBounds(CombinedMeshPart part) + { + return _partsBounds[part.Index]; + } + + public void ApplyDataToMesh() + { + Mesh mesh = _root.Mesh; + mesh.SetVertexBufferData(Vertices, 0, 0, _vertices.Length); + mesh.bounds = _bounds[0]; + } + + protected override void OnInitialized() + { + _root = base.Root; + VertexBufferUtil.ToLightweightBuffer(_root.Mesh); + _vertices = new NativeList<LightweightVertex>(Allocator.Persistent); + _partsBounds = new NativeList<Bounds>(Allocator.Persistent); + _bounds = new NativeArray<Bounds>(1, Allocator.Persistent); + _verticesLocal = new NativeList<LightweightVertex>(Allocator.Persistent); + _partsBoundsLocal = new NativeList<Bounds>(Allocator.Persistent); + _tempVertices = new List<Vector3>(); + _tempNormals = new List<Vector3>(); + _tempTangents = new List<Vector4>(); + _tempUV = new List<Vector2>(); + _tempUV2 = new List<Vector2>(); + } + + protected override void OnAddPart(CombinedMeshPart part, Mesh mesh, Matrix4x4 transform) + { + Bounds value = mesh.bounds; + Bounds value2 = value.Transform(transform); + _partsBounds.Add(in value2); + _partsBoundsLocal.Add(in value); + mesh.GetVertices(_tempVertices); + mesh.GetNormals(_tempNormals); + mesh.GetTangents(_tempTangents); + mesh.GetUVs(0, _tempUV); + mesh.GetUVs(1, _tempUV2); + int vertexCount = mesh.vertexCount; + for (int i = 0; i < vertexCount; i++) + { + LightweightVertex value3 = default(LightweightVertex); + value3.Position = _tempVertices[i]; + value3.Normal = _tempNormals[i]; + value3.Tangent = _tempTangents[i]; + if (_tempUV.Count > 0) + { + value3.UV = _tempUV[i]; + } + if (_tempUV2.Count > 0) + { + value3.UV2 = _tempUV2[i]; + } + _verticesLocal.Add(in value3); + } + } + + protected override void OnRemovePart(CombinedMeshPart part) + { + _partsBounds.RemoveAt(part.Index); + _verticesLocal.RemoveRange(part.VertexStart, part.VertexCount); + _partsBoundsLocal.RemoveAt(part.Index); + } + + protected override void OnMeshUpdated() + { + Mesh mesh = _root.Mesh; + using (Mesh.MeshDataArray meshDataArray = Mesh.AcquireReadOnlyMeshData(mesh)) + { + Mesh.MeshData meshData = meshDataArray[0]; + _vertices.Clear(); + _vertices.AddRange(meshData.GetVertexData<LightweightVertex>()); + } + _bounds[0] = mesh.bounds; + } + + protected override void OnDispose() + { + _vertices.Dispose(); + _partsBounds.Dispose(); + _bounds.Dispose(); + _verticesLocal.Dispose(); + _partsBoundsLocal.Dispose(); + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MeshDataNativeArraysSTD.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MeshDataNativeArraysSTD.cs new file mode 100644 index 0000000..3063894 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MeshDataNativeArraysSTD.cs @@ -0,0 +1,104 @@ +using Unity.Collections; +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public class MeshDataNativeArraysSTD : CombinedMeshDataInternal +{ + private CombinedMesh _root; + + private NativeList<Vector3> _vertices; + + private NativeList<Vector3> _normals; + + private NativeList<Vector4> _tangents; + + private NativeList<Bounds> _partsBounds; + + private NativeList<Bounds> _partsBoundsLocal; + + private NativeArray<Bounds> _bounds; + + public NativeArray<Vector3> Vertices => _vertices; + + public NativeArray<Vector3> Normals => _normals; + + public NativeArray<Vector4> Tangents => _tangents; + + public NativeArray<Bounds> PartsBounds => _partsBounds; + + public NativeArray<Bounds> PartsBoundsLocal => _partsBoundsLocal; + + public NativeArray<Bounds> Bounds => _bounds; + + public override Bounds GetBounds() + { + return _bounds[0]; + } + + public override Bounds GetBounds(CombinedMeshPart part) + { + return _partsBounds[part.Index]; + } + + public void ApplyDataToMesh() + { + Mesh mesh = _root.Mesh; + mesh.SetVertices(Vertices); + mesh.SetNormals(Normals); + mesh.SetTangents(Tangents); + mesh.bounds = _bounds[0]; + } + + protected override void OnInitialized() + { + _root = base.Root; + _vertices = new NativeList<Vector3>(Allocator.Persistent); + _normals = new NativeList<Vector3>(Allocator.Persistent); + _tangents = new NativeList<Vector4>(Allocator.Persistent); + _partsBounds = new NativeList<Bounds>(Allocator.Persistent); + _partsBoundsLocal = new NativeList<Bounds>(Allocator.Persistent); + _bounds = new NativeArray<Bounds>(1, Allocator.Persistent); + } + + protected override void OnAddPart(CombinedMeshPart part, Mesh mesh, Matrix4x4 transform) + { + Bounds value = mesh.bounds; + Bounds value2 = value.Transform(transform); + _partsBounds.Add(in value2); + _partsBoundsLocal.Add(in value); + } + + protected override void OnRemovePart(CombinedMeshPart part) + { + _partsBounds.RemoveAt(part.Index); + _partsBoundsLocal.RemoveAt(part.Index); + } + + protected override void OnMeshUpdated() + { + Mesh mesh = _root.Mesh; + int vertexCount = mesh.vertexCount; + _vertices.ResizeUninitialized(vertexCount); + _normals.ResizeUninitialized(vertexCount); + _tangents.ResizeUninitialized(vertexCount); + using (Mesh.MeshDataArray meshDataArray = Mesh.AcquireReadOnlyMeshData(mesh)) + { + Mesh.MeshData meshData = meshDataArray[0]; + meshData.GetVertices(_vertices); + meshData.GetNormals(_normals); + meshData.GetTangents(_tangents); + } + _bounds[0] = mesh.bounds; + } + + protected override void OnDispose() + { + _vertices.Dispose(); + _normals.Dispose(); + _tangents.Dispose(); + _partsBounds.Dispose(); + _partsBoundsLocal.Dispose(); + _bounds.Dispose(); + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MeshFusionSource.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MeshFusionSource.cs new file mode 100644 index 0000000..555f9e8 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MeshFusionSource.cs @@ -0,0 +1,333 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace NGS.MeshFusionPro; + +[DisallowMultipleComponent] +public abstract class MeshFusionSource : MonoBehaviour +{ + private RuntimeMeshFusion _controller; + + private int _combinedSourcesCount; + + private int _failedSourcesCount; + + private int _totalSourcesCount; + + [field: SerializeField] + public SourceCombineStatus CombineStatus { get; private set; } + + [field: SerializeField] + public int ControllerIndex { get; set; } + + [field: SerializeField] + [field: HideInInspector] + public bool CombineAtStart { get; set; } = true; + + + [field: SerializeField] + [field: HideInInspector] + public CombineErrorStrategy CombineErrorStrategy { get; set; } + + [field: SerializeField] + public AfterCombineAction AfterCombineAction { get; set; } + + [field: SerializeField] + public bool IsIncompatible { get; private set; } + + [field: SerializeField] + public string IncompatibilityReason { get; private set; } + + [field: SerializeField] + public bool HasCombineErrors { get; private set; } + + [field: SerializeField] + public string CombineErrors { get; private set; } + + public event Action<MeshFusionSource, IEnumerable<ICombinedObjectPart>> onCombineFinished; + + private void Reset() + { + CheckCompatibility(); + } + + private void Start() + { + if (CombineAtStart) + { + AssignToController(); + } + } + + private void OnDestroy() + { + Unfreeze(); + } + + public void Unfreeze() + { + if (CombineStatus == SourceCombineStatus.AssignedToController) + { + UnassignFromController(); + } + ClearSourcesAndUnsubscribe(); + } + + public abstract bool TryGetBounds(ref Bounds bounds); + + public bool CheckCompatibility() + { + try + { + string incompatibilityReason; + bool flag = CheckCompatibilityAndGetComponents(out incompatibilityReason); + IsIncompatible = !flag; + IncompatibilityReason = incompatibilityReason; + return flag; + } + catch (Exception ex) + { + IsIncompatible = true; + IncompatibilityReason += $"\n{ex.Message}{ex.StackTrace}"; + return false; + } + } + + public bool AssignToController() + { + try + { + if (CombineStatus != 0) + { + return false; + } + if (!CheckCompatibility()) + { + return false; + } + _controller = RuntimeMeshFusion.FindByIndex(ControllerIndex); + if (_controller == null) + { + throw new NullReferenceException("RuntimeMeshFusion with index " + ControllerIndex + " not found"); + } + CreateSourcesAndSubscribe(); + HasCombineErrors = false; + CombineErrors = ""; + _combinedSourcesCount = 0; + _failedSourcesCount = 0; + _totalSourcesCount = 0; + foreach (ICombineSource combineSource in GetCombineSources()) + { + _totalSourcesCount++; + _controller.AddSource(combineSource); + } + CombineStatus = SourceCombineStatus.AssignedToController; + return true; + } + catch (Exception ex) + { + HasCombineErrors = true; + CombineErrors += $"\n{ex.Message}\n{ex.StackTrace}"; + UnassignFromController(); + CombineStatus = SourceCombineStatus.FailedToCombine; + return false; + } + } + + public void UndoCombine() + { + try + { + foreach (ICombinedObjectPart combinedPart in GetCombinedParts()) + { + combinedPart.Destroy(); + } + foreach (ICombineSource combineSource in GetCombineSources()) + { + combineSource.onCombined += delegate(ICombinedObject root, ICombinedObjectPart part) + { + part.Destroy(); + }; + } + UnassignFromController(); + ClearSourcesAndUnsubscribe(); + ClearParts(); + _combinedSourcesCount = 0; + _failedSourcesCount = 0; + ToggleComponents(enabled: true); + CombineStatus = SourceCombineStatus.NotCombined; + } + catch (Exception ex) + { + HasCombineErrors = true; + CombineErrors += $"\n{ex.Message}\n{ex.StackTrace}"; + CombineStatus = SourceCombineStatus.FailedToCombine; + } + } + + private void CreateSourcesAndSubscribe() + { + CreateSources(); + foreach (ICombineSource combineSource in GetCombineSources()) + { + combineSource.onCombined += OnSourceCombinedHandler; + combineSource.onCombineError += OnCombineErrorHandler; + combineSource.onCombineFailed += OnFailedCombineSourceHandler; + } + } + + private void ClearSourcesAndUnsubscribe() + { + foreach (ICombineSource combineSource in GetCombineSources()) + { + combineSource.onCombined -= OnSourceCombinedHandler; + combineSource.onCombineError -= OnCombineErrorHandler; + combineSource.onCombineFailed -= OnFailedCombineSourceHandler; + } + ClearSources(); + } + + private void UnassignFromController() + { + if (_controller != null) + { + foreach (ICombineSource combineSource in GetCombineSources()) + { + _controller.RemoveSource(combineSource); + } + } + _controller = null; + } + + private void OnSourceCombinedHandler(ICombinedObject root, ICombinedObjectPart part) + { + CombineStatus = SourceCombineStatus.CombinedPartially; + _combinedSourcesCount++; + OnSourceCombinedInternal(root, part); + if (_combinedSourcesCount + _failedSourcesCount == _totalSourcesCount) + { + OnCombineFinishedHandler(); + } + } + + private void OnCombineErrorHandler(ICombinedObject root, string errorMessage) + { + HasCombineErrors = true; + CombineErrors = CombineErrors + errorMessage + "\n"; + OnCombineErrorInternal(root, errorMessage); + if (CombineErrorStrategy == CombineErrorStrategy.UndoCombining) + { + UndoCombine(); + } + } + + private void OnFailedCombineSourceHandler(ICombinedObject root) + { + _failedSourcesCount++; + OnFailedCombineSourceInternal(root); + if (_combinedSourcesCount + _failedSourcesCount == _totalSourcesCount) + { + OnCombineFinishedHandler(); + } + } + + private void OnCombineFinishedHandler() + { + ClearSourcesAndUnsubscribe(); + if (_combinedSourcesCount == _totalSourcesCount) + { + CombineStatus = SourceCombineStatus.Combined; + } + else if (_failedSourcesCount == _totalSourcesCount) + { + CombineStatus = SourceCombineStatus.FailedToCombine; + return; + } + OnCombineFinishedInternal(); + this.onCombineFinished?.Invoke(this, GetCombinedParts()); + if (AfterCombineAction == AfterCombineAction.DisableComponents) + { + ToggleComponents(enabled: false); + } + else if (AfterCombineAction == AfterCombineAction.DestroyGameObject) + { + UnityEngine.Object.Destroy(base.gameObject); + } + } + + protected virtual void OnSourceCombinedInternal(ICombinedObject root, ICombinedObjectPart part) + { + } + + protected virtual void OnCombineErrorInternal(ICombinedObject root, string errorMessage) + { + } + + protected virtual void OnFailedCombineSourceInternal(ICombinedObject root) + { + } + + protected virtual void OnCombineFinishedInternal() + { + } + + protected bool CanCreateCombineSource(GameObject go, ref string incompatibilityReason, ref MeshRenderer renderer, ref MeshFilter filter, ref Mesh mesh) + { + if (renderer == null) + { + renderer = go.GetComponent<MeshRenderer>(); + } + if (renderer == null) + { + incompatibilityReason = "MeshRenderer not found"; + return false; + } + if (renderer.isPartOfStaticBatch) + { + incompatibilityReason = "MeshRenderer is PartOfStaticBatching\nDisable Static Batching"; + return false; + } + if (filter == null) + { + filter = go.GetComponent<MeshFilter>(); + } + if (filter == null) + { + incompatibilityReason = "MeshFilter not found"; + return false; + } + mesh = filter.sharedMesh; + if (mesh == null) + { + incompatibilityReason = "Mesh not found"; + return false; + } + if (!mesh.isReadable) + { + incompatibilityReason = "Mesh is not readable. Enable Read/Write in import settings"; + return false; + } + if (mesh.subMeshCount != renderer.sharedMaterials.Length) + { + incompatibilityReason = "Submesh count and Materials count isn't equal"; + return false; + } + incompatibilityReason = ""; + return true; + } + + protected abstract bool CheckCompatibilityAndGetComponents(out string incompatibilityReason); + + protected abstract void CreateSources(); + + protected abstract void ClearSources(); + + protected abstract void ClearParts(); + + protected abstract IEnumerable<ICombineSource> GetCombineSources(); + + protected abstract IEnumerable<ICombinedObjectPart> GetCombinedParts(); + + protected abstract void ToggleComponents(bool enabled); +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MeshSeparatorSimple.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MeshSeparatorSimple.cs new file mode 100644 index 0000000..6c79a16 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MeshSeparatorSimple.cs @@ -0,0 +1,130 @@ +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Rendering; + +namespace NGS.MeshFusionPro; + +public class MeshSeparatorSimple +{ + private const int MAX_UV_CHANNELS = 4; + + private static Dictionary<Mesh, Mesh[]> _meshToSubmeshes; + + private static List<Vector3> _srcVertices; + + private static List<Vector3> _srcNormals; + + private static List<Vector4> _srcTangents; + + private static List<Vector2> _srcUV; + + private static List<int> _triangles; + + private static List<Vector3> _vertices; + + private static List<Vector3> _normals; + + private static List<Vector4> _tangents; + + private static List<Vector2> _uv; + + static MeshSeparatorSimple() + { + _meshToSubmeshes = new Dictionary<Mesh, Mesh[]>(); + _srcVertices = new List<Vector3>(); + _srcNormals = new List<Vector3>(); + _srcTangents = new List<Vector4>(); + _srcUV = new List<Vector2>(); + _triangles = new List<int>(); + _vertices = new List<Vector3>(); + _normals = new List<Vector3>(); + _tangents = new List<Vector4>(); + _uv = new List<Vector2>(); + } + + public Mesh GetSubmesh(Mesh source, int submesh) + { + if (!_meshToSubmeshes.TryGetValue(source, out var value)) + { + value = Separate(source); + _meshToSubmeshes.Add(source, value); + } + return value[submesh]; + } + + private Mesh[] Separate(Mesh mesh) + { + int subMeshCount = mesh.subMeshCount; + Mesh[] array = new Mesh[subMeshCount]; + CollectMeshData(mesh); + for (int i = 0; i < subMeshCount; i++) + { + array[i] = CreateFromSubmesh(mesh, i); + } + ClearData(); + return array; + } + + private void CollectMeshData(Mesh mesh) + { + mesh.GetVertices(_srcVertices); + mesh.GetNormals(_srcNormals); + mesh.GetTangents(_srcTangents); + } + + private Mesh CreateFromSubmesh(Mesh mesh, int submesh) + { + SubMeshDescriptor subMesh = mesh.GetSubMesh(submesh); + Mesh mesh2 = new Mesh(); + int indexCount = subMesh.indexCount; + int vertexCount = subMesh.vertexCount; + int firstVertex = subMesh.firstVertex; + int num = firstVertex + vertexCount; + _vertices.Clear(); + _normals.Clear(); + _tangents.Clear(); + mesh.GetIndices(_triangles, submesh); + for (int i = firstVertex; i < num; i++) + { + _vertices.Add(_srcVertices[i]); + _normals.Add(_srcNormals[i]); + _tangents.Add(_srcTangents[i]); + } + for (int j = 0; j < indexCount; j++) + { + _triangles[j] -= firstVertex; + } + mesh2.SetVertices(_vertices); + mesh2.SetNormals(_normals); + mesh2.SetTangents(_tangents); + mesh2.SetTriangles(_triangles, 0, calculateBounds: false); + mesh2.bounds = subMesh.bounds; + for (int k = 0; k < 4; k++) + { + mesh.GetUVs(k, _srcUV); + if (_srcUV.Count != 0) + { + _uv.Clear(); + for (int l = firstVertex; l < num; l++) + { + _uv.Add(_srcUV[l]); + } + mesh2.SetUVs(k, _uv); + } + } + return mesh2; + } + + private void ClearData() + { + _srcVertices.Clear(); + _srcNormals.Clear(); + _srcTangents.Clear(); + _srcUV.Clear(); + _triangles.Clear(); + _vertices.Clear(); + _normals.Clear(); + _tangents.Clear(); + _uv.Clear(); + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MeshType.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MeshType.cs new file mode 100644 index 0000000..63cafe1 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MeshType.cs @@ -0,0 +1,7 @@ +namespace NGS.MeshFusionPro; + +public enum MeshType +{ + Standard, + Lightweight +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MoveMethod.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MoveMethod.cs new file mode 100644 index 0000000..27d690f --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/MoveMethod.cs @@ -0,0 +1,7 @@ +namespace NGS.MeshFusionPro; + +public enum MoveMethod +{ + Simple, + Jobs +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/ObjectsCombiner.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/ObjectsCombiner.cs new file mode 100644 index 0000000..6cf2299 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/ObjectsCombiner.cs @@ -0,0 +1,155 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public abstract class ObjectsCombiner<TCombinedObject, TCombineSource> where TCombinedObject : ICombinedObject where TCombineSource : ICombineSource +{ + private List<TCombinedObject> _combinedObjects; + + private List<TCombineSource> _sources; + + private List<TCombineSource> _sourcesForCombine; + + public IReadOnlyList<TCombinedObject> CombinedObjects => _combinedObjects; + + public bool ContainSources => _sources.Count > 0; + + public event Action<TCombinedObject> onCombinedObjectCreated; + + protected ObjectsCombiner() + { + _sources = new List<TCombineSource>(); + _combinedObjects = new List<TCombinedObject>(); + _sourcesForCombine = new List<TCombineSource>(); + } + + public virtual void AddSource(TCombineSource source) + { + _sources.Add(source); + } + + public void AddSources(IEnumerable<TCombineSource> sources) + { + foreach (TCombineSource source in sources) + { + AddSource(source); + } + } + + public void RemoveSource(TCombineSource source) + { + _sources.Remove(source); + } + + public void Combine() + { + if (_sources.Count != 0) + { + CleanEmptyData(); + CombineInternal(); + _sources.Clear(); + } + } + + private void CleanEmptyData() + { + int num = 0; + while (num < _combinedObjects.Count) + { + if (_combinedObjects[num] == null) + { + _combinedObjects.RemoveAt(num); + } + else + { + num++; + } + } + num = 0; + while (num < _sources.Count) + { + if (_sources[num] == null) + { + _sources.RemoveAt(num); + } + else + { + num++; + } + } + } + + private void CombineInternal() + { + _sourcesForCombine.Clear(); + int num = 0; + while (num <= _combinedObjects.Count && _sources.Count != 0) + { + bool flag = false; + TCombinedObject val; + if (num == _combinedObjects.Count) + { + try + { + val = CreateCombinedObject(_sources[0]); + _combinedObjects.Add(val); + flag = true; + } + catch (Exception ex) + { + Debug.Log("Unable to create CombinedObject : " + ex.Message + ex.StackTrace); + _sources.RemoveAt(0); + continue; + } + } + else + { + val = _combinedObjects[num]; + } + CombinedObjectMatcher<TCombinedObject, TCombineSource> matcher = GetMatcher(); + matcher.StartMatching(val); + int num2 = 0; + while (num2 < _sources.Count) + { + TCombineSource val2 = _sources[num2]; + if (matcher.CanAddSource(val2)) + { + _sourcesForCombine.Add(val2); + matcher.SourceAdded(val2); + _sources.RemoveAt(num2); + } + else + { + num2++; + } + } + if (_sourcesForCombine.Count > 0) + { + try + { + CombineSources(val, _sourcesForCombine); + _sourcesForCombine.Clear(); + } + catch (Exception ex2) + { + Debug.Log("Unable to combine sources in ObjectsCombiner : " + ex2.Message + ex2.StackTrace); + _sourcesForCombine.Clear(); + continue; + } + } + if (flag) + { + this.onCombinedObjectCreated?.Invoke(val); + } + num++; + } + } + + protected abstract CombinedObjectMatcher<TCombinedObject, TCombineSource> GetMatcher(); + + protected abstract TCombinedObject CreateCombinedObject(TCombineSource source); + + protected abstract void CombineSources(TCombinedObject root, IList<TCombineSource> sources); +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/PartMoveInfo.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/PartMoveInfo.cs new file mode 100644 index 0000000..776f8ad --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/PartMoveInfo.cs @@ -0,0 +1,16 @@ +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public struct PartMoveInfo +{ + public int partIndex; + + public int vertexStart; + + public int vertexCount; + + public Matrix4x4 currentTransform; + + public Matrix4x4 targetTransform; +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/RendererHelper.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/RendererHelper.cs new file mode 100644 index 0000000..f513a90 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/RendererHelper.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public static class RendererHelper +{ + private static List<Material> _materials; + + static RendererHelper() + { + _materials = new List<Material>(); + } + + public static Material GetSharedMaterialWithoutAlloc(this Renderer renderer, int index) + { + renderer.GetSharedMaterials(_materials); + return _materials[index]; + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/RendererSettings.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/RendererSettings.cs new file mode 100644 index 0000000..8d29b8c --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/RendererSettings.cs @@ -0,0 +1,43 @@ +using UnityEngine; +using UnityEngine.Rendering; + +namespace NGS.MeshFusionPro; + +public struct RendererSettings +{ + public string tag; + + public int layer; + + public Material material; + + public ShadowCastingMode shadowMode; + + public bool receiveShadows; + + public int lightmapIndex; + + public int realtimeLightmapIndex; + + public RendererSettings(Material material, ShadowCastingMode shadowMode = ShadowCastingMode.On, bool receiveShadows = true, int lightmapIndex = -1, int realtimeLightmapIndex = -1, string tag = "Untagged", int layer = 0) + { + this.material = material; + this.shadowMode = shadowMode; + this.receiveShadows = receiveShadows; + this.lightmapIndex = lightmapIndex; + this.realtimeLightmapIndex = realtimeLightmapIndex; + this.tag = tag; + this.layer = layer; + } + + public RendererSettings(Renderer renderer, int materialIndex = 0) + { + material = renderer.GetSharedMaterialWithoutAlloc(materialIndex); + shadowMode = renderer.shadowCastingMode; + receiveShadows = renderer.receiveShadows; + lightmapIndex = renderer.lightmapIndex; + realtimeLightmapIndex = renderer.realtimeLightmapIndex; + tag = renderer.tag; + layer = renderer.gameObject.layer; + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/RigidbodyTrackingStrategy.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/RigidbodyTrackingStrategy.cs new file mode 100644 index 0000000..763f666 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/RigidbodyTrackingStrategy.cs @@ -0,0 +1,62 @@ +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public class RigidbodyTrackingStrategy : ISourceTrackingStrategy +{ + private Rigidbody _rigidbody; + + private Transform _transform; + + private DynamicCombinedObjectPart[] _parts; + + private float _velocityThreashold = 0.5f; + + private float _angularVelocityThreashold = 0.3f; + + public float VelocityThreashold + { + get + { + return _velocityThreashold; + } + set + { + _velocityThreashold = Mathf.Max(0f, value); + } + } + + public float AngularVelocityThreashold + { + get + { + return _angularVelocityThreashold; + } + set + { + _angularVelocityThreashold = Mathf.Max(0f, value); + } + } + + public RigidbodyTrackingStrategy(Rigidbody target, DynamicCombinedObjectPart[] parts) + { + _rigidbody = target; + _transform = target.transform; + _parts = parts; + } + + public bool OnUpdate() + { + float magnitude = _rigidbody.velocity.magnitude; + float magnitude2 = _rigidbody.angularVelocity.magnitude; + if (magnitude > _velocityThreashold || magnitude2 > _angularVelocityThreashold) + { + for (int i = 0; i < _parts.Length; i++) + { + _parts[i].Move(_transform.localToWorldMatrix); + } + return true; + } + return false; + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/RuntimeMeshFusion.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/RuntimeMeshFusion.cs new file mode 100644 index 0000000..38c811b --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/RuntimeMeshFusion.cs @@ -0,0 +1,197 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public class RuntimeMeshFusion : MonoBehaviour +{ + private static List<RuntimeMeshFusion> _Instances; + + [SerializeField] + [HideInInspector] + private int _controllerIndex; + + [SerializeField] + [HideInInspector] + private bool _drawGizmo; + + [SerializeField] + [HideInInspector] + private int _cellSize = 80; + + [SerializeField] + [HideInInspector] + private int _maxVerticesPerObject = 40000; + + [SerializeField] + [HideInInspector] + private MeshType _meshType; + + [SerializeField] + [HideInInspector] + private MoveMethod _moveMethod = MoveMethod.Jobs; + + private CombineTree _combineTree; + + private bool _sourceAdded; + + private BinaryTreeDrawer<ICombineSource> _treeDrawer; + + public int ControllerIndex + { + get + { + return _controllerIndex; + } + set + { + if (!Application.isPlaying) + { + _controllerIndex = value; + } + } + } + + public bool DrawGizmo + { + get + { + return _drawGizmo; + } + set + { + _drawGizmo = value; + } + } + + public int CellSize + { + get + { + return _cellSize; + } + set + { + if (!Application.isPlaying) + { + _cellSize = Mathf.Max(1, value); + } + } + } + + public int MaxVertices + { + get + { + return _maxVerticesPerObject; + } + set + { + if (!Application.isPlaying) + { + _maxVerticesPerObject = Mathf.Clamp(value, 500, 65000); + } + } + } + + public MeshType MeshType + { + get + { + return _meshType; + } + set + { + if (!Application.isPlaying) + { + _meshType = value; + } + } + } + + public MoveMethod MoveMethod + { + get + { + return _moveMethod; + } + set + { + if (!Application.isPlaying) + { + _moveMethod = value; + } + } + } + + private void Awake() + { + if (_Instances == null) + { + _Instances = new List<RuntimeMeshFusion>(); + } + _Instances.Add(this); + ICombinedMeshFactory factory = new CombinedMeshFactory(_meshType, CombineMethod.Simple, _moveMethod); + _combineTree = new CombineTree(factory, _cellSize, _maxVerticesPerObject); + _treeDrawer = new BinaryTreeDrawer<ICombineSource>(); + Transform parent = new GameObject("CombinedObjects").transform; + _combineTree.onStaticCombinedObjectCreated += delegate(CombinedObject r) + { + r.transform.parent = parent; + }; + _combineTree.onDynamicCombinedObjectCreated += delegate(DynamicCombinedObject r) + { + r.transform.parent = parent; + }; + _combineTree.onCombinedLODGroupCreated += delegate(CombinedLODGroup r) + { + r.transform.parent = parent; + }; + } + + private void Update() + { + if (_sourceAdded) + { + _combineTree.Combine(); + _sourceAdded = false; + } + } + + private void OnDrawGizmos() + { + if (Application.isPlaying && _drawGizmo && _combineTree != null && _combineTree.Root != null) + { + _treeDrawer.DrawGizmo(_combineTree.Root, Color.white); + } + } + + private void OnDestroy() + { + _Instances.Remove(this); + } + + public static RuntimeMeshFusion FindByIndex(int index) + { + for (int i = 0; i < _Instances.Count; i++) + { + RuntimeMeshFusion runtimeMeshFusion = _Instances[i]; + if (runtimeMeshFusion.ControllerIndex == index) + { + return runtimeMeshFusion; + } + } + throw new KeyNotFoundException("MeshFusionController with index : " + index + " not found"); + } + + public void AddSource(ICombineSource source) + { + _combineTree.Add(source); + _sourceAdded = true; + } + + public void RemoveSource(ICombineSource source) + { + _combineTree.Remove(source); + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/SimpleMeshMoverSTD.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/SimpleMeshMoverSTD.cs new file mode 100644 index 0000000..5a56ec3 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/SimpleMeshMoverSTD.cs @@ -0,0 +1,62 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public class SimpleMeshMoverSTD : ICombinedMeshMover +{ + private MeshDataListsSTD _meshData; + + public SimpleMeshMoverSTD(MeshDataListsSTD meshData) + { + _meshData = meshData; + } + + public void MoveParts(IList<PartMoveInfo> moveInfos) + { + List<Vector3> vertices = _meshData.Vertices; + List<Vector3> normals = _meshData.Normals; + List<Vector4> tangents = _meshData.Tangents; + List<Bounds> partsBounds = _meshData.PartsBounds; + List<Bounds> partsBoundsLocal = _meshData.PartsBoundsLocal; + Bounds bounds = _meshData.GetBounds(); + bounds.size = Vector3.zero; + for (int i = 0; i < moveInfos.Count; i++) + { + PartMoveInfo partMoveInfo = moveInfos[i]; + int partIndex = partMoveInfo.partIndex; + int vertexStart = partMoveInfo.vertexStart; + int num = vertexStart + partMoveInfo.vertexCount; + Matrix4x4 targetTransform = partMoveInfo.targetTransform; + Matrix4x4 inverse = partMoveInfo.currentTransform.inverse; + for (int j = vertexStart; j < num; j++) + { + Vector3 point = vertices[j]; + Vector3 vector = normals[j]; + Vector4 vector2 = tangents[j]; + float w = vector2.w; + point = inverse.MultiplyPoint3x4(point); + point = targetTransform.MultiplyPoint3x4(point); + vector = inverse.MultiplyVector(vector); + vector = targetTransform.MultiplyVector(vector); + vector2 = inverse.MultiplyVector(vector2); + vector2 = targetTransform.MultiplyVector(vector2); + vector2.w = w; + vertices[j] = point; + normals[j] = vector; + tangents[j] = vector2; + } + partsBounds[partIndex] = partsBoundsLocal[partIndex].Transform(targetTransform); + } + for (int k = 0; k < partsBounds.Count; k++) + { + bounds.Encapsulate(partsBounds[k]); + } + _meshData.Bounds = bounds; + } + + public void ApplyData() + { + _meshData.ApplyDataToMesh(); + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/SimpleMovableMeshSTDFactory.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/SimpleMovableMeshSTDFactory.cs new file mode 100644 index 0000000..3454e5e --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/SimpleMovableMeshSTDFactory.cs @@ -0,0 +1,18 @@ +namespace NGS.MeshFusionPro; + +public class SimpleMovableMeshSTDFactory : IMovableCombinedMeshFactory +{ + private IMeshToolsFactory _tools; + + public SimpleMovableMeshSTDFactory(IMeshToolsFactory tools) + { + _tools = tools; + } + + public CombinedMesh CreateMovableMesh(out ICombinedMeshMover mover) + { + CombinedMesh<MeshDataListsSTD> combinedMesh = new CombinedMesh<MeshDataListsSTD>(_tools.CreateMeshCombiner(), _tools.CreateMeshCutter()); + mover = new SimpleMeshMoverSTD(combinedMesh.MeshDataInternal); + return combinedMesh; + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/SimpleToolsLWFactory.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/SimpleToolsLWFactory.cs new file mode 100644 index 0000000..cedbde2 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/SimpleToolsLWFactory.cs @@ -0,0 +1,14 @@ +namespace NGS.MeshFusionPro; + +public class SimpleToolsLWFactory : IMeshToolsFactory +{ + public IMeshCombiner CreateMeshCombiner() + { + return new MeshCombinerSimpleLW(); + } + + public IMeshCutter CreateMeshCutter() + { + return new MeshCutterSimpleLW(); + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/SimpleToolsSTDFactory.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/SimpleToolsSTDFactory.cs new file mode 100644 index 0000000..ee1ce77 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/SimpleToolsSTDFactory.cs @@ -0,0 +1,14 @@ +namespace NGS.MeshFusionPro; + +public class SimpleToolsSTDFactory : IMeshToolsFactory +{ + public IMeshCombiner CreateMeshCombiner() + { + return new MeshCombinerSimpleSTD(); + } + + public IMeshCutter CreateMeshCutter() + { + return new MeshCutterSimpleSTD(); + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/SourceCombineStatus.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/SourceCombineStatus.cs new file mode 100644 index 0000000..8aab0cd --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/SourceCombineStatus.cs @@ -0,0 +1,10 @@ +namespace NGS.MeshFusionPro; + +public enum SourceCombineStatus +{ + NotCombined, + AssignedToController, + CombinedPartially, + Combined, + FailedToCombine +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/SourceTracker.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/SourceTracker.cs new file mode 100644 index 0000000..571d46d --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/SourceTracker.cs @@ -0,0 +1,161 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace NGS.MeshFusionPro; + +[DisallowMultipleComponent] +[RequireComponent(typeof(MeshFusionSource))] +public class SourceTracker : MonoBehaviour +{ + [SerializeField] + private MeshFusionSource _source; + + [SerializeField] + private bool _isDynamicObject; + + [SerializeField] + private Rigidbody _rigidbody; + + private IEnumerable<ICombinedObjectPart> _parts; + + private ISourceTrackingStrategy _trackingStrategy; + + private float _idleTime; + + private Action _updateFunc; + + public bool IsDynamicObject => _isDynamicObject; + + [field: SerializeField] + public TrackingTarget TrackingTarget { get; set; } + + [field: SerializeField] + public bool DisableWhenIdle { get; set; } = true; + + + [field: SerializeField] + [field: Min(0.01f)] + public float MaxIdleTime { get; set; } = 5f; + + + [field: SerializeField] + public bool WakeUpWhenCollision { get; set; } = true; + + + [field: SerializeField] + public bool TrackingDestroy { get; set; } = true; + + + public void WakeUp() + { + base.enabled = true; + _idleTime = 0f; + } + + private void Reset() + { + _source = GetComponent<MeshFusionSource>(); + _isDynamicObject = _source is DynamicMeshFusionSource; + if (TryGetComponent<Rigidbody>(out _rigidbody)) + { + TrackingTarget = TrackingTarget.Rigidbody; + } + } + + private void Awake() + { + if (_source == null) + { + _source = GetComponent<MeshFusionSource>(); + _isDynamicObject = _source is DynamicMeshFusionSource; + } + _source.onCombineFinished += OnCombineFinished; + base.enabled = false; + } + + private void Update() + { + try + { + _updateFunc?.Invoke(); + } + catch + { + if (!_isDynamicObject) + { + base.enabled = false; + return; + } + throw; + } + } + + private void OnCollisionEnter(Collision collision) + { + if (_isDynamicObject && WakeUpWhenCollision && _parts != null) + { + WakeUp(); + } + } + + private void OnDestroy() + { + if (!base.gameObject.scene.isLoaded || !TrackingDestroy || _parts == null) + { + return; + } + foreach (ICombinedObjectPart part in _parts) + { + if (part != null && part.Root != null) + { + part.Destroy(); + } + } + } + + private void OnCombineFinished(MeshFusionSource source, IEnumerable<ICombinedObjectPart> parts) + { + _parts = parts; + _source.onCombineFinished -= OnCombineFinished; + if (!_isDynamicObject) + { + return; + } + _updateFunc = UpdateMoveTracker; + if (TrackingTarget == TrackingTarget.Rigidbody && _rigidbody != null) + { + _trackingStrategy = new RigidbodyTrackingStrategy(_rigidbody, parts.Select((ICombinedObjectPart p) => (DynamicCombinedObjectPart)p).ToArray()); + if (DisableWhenIdle) + { + _updateFunc = UpdateMoveTrackerAndCheckIdle; + } + } + else + { + _trackingStrategy = new TransformTrackingStrategy(base.transform, parts.Select((ICombinedObjectPart p) => (DynamicCombinedObjectPart)p).ToArray()); + } + base.enabled = true; + } + + private void UpdateMoveTracker() + { + _trackingStrategy.OnUpdate(); + } + + private void UpdateMoveTrackerAndCheckIdle() + { + if (_trackingStrategy.OnUpdate()) + { + _idleTime = 0f; + return; + } + _idleTime += Time.deltaTime; + if (_idleTime > MaxIdleTime) + { + _idleTime = 0f; + base.enabled = false; + } + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/StaticCombinedObjectMatcher.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/StaticCombinedObjectMatcher.cs new file mode 100644 index 0000000..60ea49c --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/StaticCombinedObjectMatcher.cs @@ -0,0 +1,39 @@ +namespace NGS.MeshFusionPro; + +public class StaticCombinedObjectMatcher : CombinedObjectMatcher<CombinedObject, CombineSource> +{ + private RendererSettings _settings; + + private int _vertexCount; + + private int _vertexLimit; + + public StaticCombinedObjectMatcher(int vertexLimit) + { + _vertexLimit = vertexLimit; + } + + public override void StartMatching(CombinedObject combinedObject) + { + _settings = combinedObject.RendererSettings; + _vertexCount = combinedObject.VertexCount; + } + + public override bool CanAddSource(CombineSource source) + { + if (!_settings.Equals(source.RendererSettings)) + { + return false; + } + if (_vertexCount + source.CombineInfo.vertexCount > _vertexLimit) + { + return false; + } + return true; + } + + public override void SourceAdded(CombineSource source) + { + _vertexCount += source.CombineInfo.vertexCount; + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/StaticMeshFusionSource.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/StaticMeshFusionSource.cs new file mode 100644 index 0000000..fbd86b3 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/StaticMeshFusionSource.cs @@ -0,0 +1,131 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public class StaticMeshFusionSource : MeshFusionSource +{ + [SerializeField] + [HideInInspector] + private MeshRenderer _renderer; + + [SerializeField] + [HideInInspector] + private MeshFilter _filter; + + [SerializeField] + [HideInInspector] + private Mesh _mesh; + + private CombineSource[] _sources; + + private CombinedObjectPart[] _parts; + + public override bool TryGetBounds(ref Bounds bounds) + { + if (_renderer != null) + { + bounds = _renderer.bounds; + return true; + } + return false; + } + + protected override void OnSourceCombinedInternal(ICombinedObject root, ICombinedObjectPart part) + { + for (int i = 0; i < _parts.Length; i++) + { + if (_parts[i] == null) + { + _parts[i] = (CombinedObjectPart)part; + return; + } + } + throw new Exception("Unexpected Behaviour"); + } + + protected override bool CheckCompatibilityAndGetComponents(out string incompatibilityReason) + { + incompatibilityReason = ""; + return CanCreateCombineSource(base.gameObject, ref incompatibilityReason, ref _renderer, ref _filter, ref _mesh); + } + + protected override void CreateSources() + { + if (_sources == null) + { + _sources = new CombineSource[_mesh.subMeshCount]; + } + if (_parts == null) + { + _parts = new CombinedObjectPart[_mesh.subMeshCount]; + } + for (int i = 0; i < _sources.Length; i++) + { + CombineSource combineSource = new CombineSource(_mesh, _renderer, i); + _sources[i] = combineSource; + } + } + + protected override IEnumerable<ICombineSource> GetCombineSources() + { + if (_sources == null) + { + yield break; + } + for (int i = 0; i < _sources.Length; i++) + { + CombineSource combineSource = _sources[i]; + if (combineSource == null) + { + break; + } + yield return combineSource; + } + } + + protected override IEnumerable<ICombinedObjectPart> GetCombinedParts() + { + if (_parts == null) + { + yield break; + } + for (int i = 0; i < _parts.Length; i++) + { + CombinedObjectPart combinedObjectPart = _parts[i]; + if (combinedObjectPart == null) + { + break; + } + yield return combinedObjectPart; + } + } + + protected override void ClearSources() + { + if (_sources != null) + { + for (int i = 0; i < _sources.Length; i++) + { + _sources[i] = null; + } + } + } + + protected override void ClearParts() + { + if (_parts != null) + { + for (int i = 0; i < _parts.Length; i++) + { + _parts[i] = null; + } + } + } + + protected override void ToggleComponents(bool enabled) + { + _renderer.enabled = enabled; + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/StaticObjectsCombiner.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/StaticObjectsCombiner.cs new file mode 100644 index 0000000..e1cc19a --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/StaticObjectsCombiner.cs @@ -0,0 +1,42 @@ +using System.Collections.Generic; + +namespace NGS.MeshFusionPro; + +public class StaticObjectsCombiner : ObjectsCombiner<CombinedObject, CombineSource> +{ + private ICombinedMeshFactory _factory; + + private StaticCombinedObjectMatcher _matcher; + + private int _vertexLimit; + + public StaticObjectsCombiner(ICombinedMeshFactory factory, int vertexLimit) + { + _factory = factory; + _matcher = new StaticCombinedObjectMatcher(vertexLimit); + _vertexLimit = vertexLimit; + } + + public override void AddSource(CombineSource source) + { + if (source.CombineInfo.vertexCount < _vertexLimit) + { + base.AddSource(source); + } + } + + protected override void CombineSources(CombinedObject root, IList<CombineSource> sources) + { + root.Combine(sources); + } + + protected override CombinedObject CreateCombinedObject(CombineSource source) + { + return CombinedObject.Create(_factory, source.RendererSettings); + } + + protected override CombinedObjectMatcher<CombinedObject, CombineSource> GetMatcher() + { + return _matcher; + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/TrackingTarget.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/TrackingTarget.cs new file mode 100644 index 0000000..3c2276b --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/TrackingTarget.cs @@ -0,0 +1,7 @@ +namespace NGS.MeshFusionPro; + +public enum TrackingTarget +{ + Transform, + Rigidbody +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/TransformTrackingStrategy.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/TransformTrackingStrategy.cs new file mode 100644 index 0000000..2a5f282 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/TransformTrackingStrategy.cs @@ -0,0 +1,30 @@ +using UnityEngine; + +namespace NGS.MeshFusionPro; + +public class TransformTrackingStrategy : ISourceTrackingStrategy +{ + private Transform _transform; + + private DynamicCombinedObjectPart[] _parts; + + public TransformTrackingStrategy(Transform target, DynamicCombinedObjectPart[] parts) + { + _transform = target; + _parts = parts; + } + + public bool OnUpdate() + { + if (_transform.hasChanged) + { + for (int i = 0; i < _parts.Length; i++) + { + _parts[i].Move(_transform.localToWorldMatrix); + } + _transform.hasChanged = false; + return true; + } + return false; + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/UniversalObjectsCombiner.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/UniversalObjectsCombiner.cs new file mode 100644 index 0000000..ae5189f --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/UniversalObjectsCombiner.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections.Generic; + +namespace NGS.MeshFusionPro; + +public class UniversalObjectsCombiner +{ + private StaticObjectsCombiner _staticCombiner; + + private DynamicObjectsCombiner _dynamicCombiner; + + private LODGroupsCombiner _lodCombiner; + + public event Action<CombinedObject> onStaticCombinedObjectCreated; + + public event Action<DynamicCombinedObject> onDynamicCombinedObjectCreated; + + public event Action<CombinedLODGroup> onCombinedLODGroupCreated; + + public UniversalObjectsCombiner(ICombinedMeshFactory factory, int vertexLimit) + { + _staticCombiner = new StaticObjectsCombiner(factory, vertexLimit); + _dynamicCombiner = new DynamicObjectsCombiner(factory, vertexLimit); + _lodCombiner = new LODGroupsCombiner(factory, vertexLimit); + _staticCombiner.onCombinedObjectCreated += delegate(CombinedObject r) + { + this.onStaticCombinedObjectCreated?.Invoke(r); + }; + _dynamicCombiner.onCombinedObjectCreated += delegate(DynamicCombinedObject r) + { + this.onDynamicCombinedObjectCreated?.Invoke(r); + }; + _lodCombiner.onCombinedObjectCreated += delegate(CombinedLODGroup r) + { + this.onCombinedLODGroupCreated?.Invoke(r); + }; + } + + public void AddSource(ICombineSource source) + { + if (source is CombineSource source2) + { + _staticCombiner.AddSource(source2); + return; + } + if (source is DynamicCombineSource source3) + { + _dynamicCombiner.AddSource(source3); + return; + } + if (source is LODGroupCombineSource source4) + { + _lodCombiner.AddSource(source4); + return; + } + throw new NotImplementedException("Unknown Combine Source"); + } + + public void AddSources(IEnumerable<ICombineSource> sources) + { + foreach (ICombineSource source in sources) + { + AddSource(source); + } + } + + public void RemoveSource(ICombineSource source) + { + if (source is CombineSource source2) + { + _staticCombiner.RemoveSource(source2); + return; + } + if (source is DynamicCombineSource source3) + { + _dynamicCombiner.RemoveSource(source3); + return; + } + if (source is LODGroupCombineSource source4) + { + _lodCombiner.RemoveSource(source4); + return; + } + throw new NotImplementedException("Unknown Combine Source"); + } + + public void Combine() + { + if (_staticCombiner.ContainSources) + { + _staticCombiner.Combine(); + } + if (_dynamicCombiner.ContainSources) + { + _dynamicCombiner.Combine(); + } + if (_lodCombiner.ContainSources) + { + _lodCombiner.Combine(); + } + } +} diff --git a/Thronefall_1_57/Decompile/NGS.MeshFusionPro/VertexBufferUtil.cs b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/VertexBufferUtil.cs new file mode 100644 index 0000000..e409ce5 --- /dev/null +++ b/Thronefall_1_57/Decompile/NGS.MeshFusionPro/VertexBufferUtil.cs @@ -0,0 +1,124 @@ +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Rendering; + +namespace NGS.MeshFusionPro; + +public static class VertexBufferUtil +{ + private static readonly Dictionary<VertexAttribute, VertexAttributeDescriptor> StandardAttributesMap; + + private static readonly VertexAttributeDescriptor[] LightweightAttributesLayout; + + private static List<VertexAttributeDescriptor> _meshAttributes; + + static VertexBufferUtil() + { + LightweightAttributesLayout = new VertexAttributeDescriptor[5] + { + new VertexAttributeDescriptor(VertexAttribute.Position, VertexAttributeFormat.Float32, 3, 0), + new VertexAttributeDescriptor(VertexAttribute.Normal, VertexAttributeFormat.SNorm8, 4), + new VertexAttributeDescriptor(VertexAttribute.Tangent, VertexAttributeFormat.SNorm8, 4), + new VertexAttributeDescriptor(VertexAttribute.TexCoord0, VertexAttributeFormat.Float16, 2), + new VertexAttributeDescriptor(VertexAttribute.TexCoord1, VertexAttributeFormat.Float16, 2) + }; + StandardAttributesMap = new Dictionary<VertexAttribute, VertexAttributeDescriptor> + { + { + VertexAttribute.Position, + new VertexAttributeDescriptor(VertexAttribute.Position, VertexAttributeFormat.Float32, 3, 0) + }, + { + VertexAttribute.Normal, + new VertexAttributeDescriptor(VertexAttribute.Normal) + }, + { + VertexAttribute.Tangent, + new VertexAttributeDescriptor(VertexAttribute.Tangent, VertexAttributeFormat.Float32, 4) + }, + { + VertexAttribute.TexCoord0, + new VertexAttributeDescriptor(VertexAttribute.TexCoord0, VertexAttributeFormat.Float32, 2) + }, + { + VertexAttribute.TexCoord1, + new VertexAttributeDescriptor(VertexAttribute.TexCoord1, VertexAttributeFormat.Float32, 2) + }, + { + VertexAttribute.TexCoord2, + new VertexAttributeDescriptor(VertexAttribute.TexCoord2, VertexAttributeFormat.Float32, 2) + }, + { + VertexAttribute.TexCoord3, + new VertexAttributeDescriptor(VertexAttribute.TexCoord3, VertexAttributeFormat.Float32, 2) + } + }; + _meshAttributes = new List<VertexAttributeDescriptor>(); + } + + public static bool IsStandardBuffer(Mesh mesh) + { + mesh.GetVertexAttributes(_meshAttributes); + for (int i = 0; i < _meshAttributes.Count; i++) + { + VertexAttributeDescriptor vertexAttributeDescriptor = _meshAttributes[i]; + VertexAttributeDescriptor vertexAttributeDescriptor2 = StandardAttributesMap[vertexAttributeDescriptor.attribute]; + if (vertexAttributeDescriptor.format != vertexAttributeDescriptor2.format) + { + return false; + } + if (vertexAttributeDescriptor.dimension != vertexAttributeDescriptor2.dimension) + { + return false; + } + } + return true; + } + + public static bool IsLightweightBuffer(Mesh mesh) + { + mesh.GetVertexAttributes(_meshAttributes); + if (_meshAttributes.Count != LightweightAttributesLayout.Length) + { + return false; + } + for (int i = 0; i < _meshAttributes.Count; i++) + { + VertexAttributeDescriptor vertexAttributeDescriptor = _meshAttributes[i]; + VertexAttributeDescriptor vertexAttributeDescriptor2 = LightweightAttributesLayout[i]; + if (vertexAttributeDescriptor.attribute != vertexAttributeDescriptor2.attribute) + { + return false; + } + if (vertexAttributeDescriptor.format != vertexAttributeDescriptor2.format) + { + return false; + } + if (vertexAttributeDescriptor.dimension != vertexAttributeDescriptor2.dimension) + { + return false; + } + } + return true; + } + + public static void ToStandardBuffer(Mesh mesh) + { + if (!IsStandardBuffer(mesh)) + { + for (int i = 0; i < _meshAttributes.Count; i++) + { + _meshAttributes[i] = StandardAttributesMap[_meshAttributes[i].attribute]; + } + mesh.SetVertexBufferParams(mesh.vertexCount, _meshAttributes.ToArray()); + } + } + + public static void ToLightweightBuffer(Mesh mesh) + { + if (!IsLightweightBuffer(mesh)) + { + mesh.SetVertexBufferParams(mesh.vertexCount, LightweightAttributesLayout); + } + } +} |
