diff --git a/PckStudio.Core/Model/AbstractModel.cs b/PckStudio.Core/Model/AbstractModel.cs new file mode 100644 index 00000000..73e4e82b --- /dev/null +++ b/PckStudio.Core/Model/AbstractModel.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using DiscordRPC; + +namespace PckStudio.Core.Model +{ + public class AbstractModel + { + public string Name { get; } + + public Size TextureSize { get; } + public NamedData DefaultTexture { get; } + public IReadOnlyDictionary Textures { get; } + + private IDictionary _parts; + + public AbstractModel(string name, Size textureSize, NamedData defaultTexture, IReadOnlyDictionary textures) + { + Name = name; + TextureSize = textureSize; + DefaultTexture = defaultTexture; + Textures = textures; + } + + internal bool AddPart(AbstractModelPart abstractModelPart) + { + if (abstractModelPart is null || _parts.ContainsKey(abstractModelPart.Name)) + return false; + _parts.Add(abstractModelPart.Name, abstractModelPart); + return true; + } + + internal void AddParts(IEnumerable abstractModelParts) + { + foreach (AbstractModelPart abstractModelPart in abstractModelParts) + { + AddPart(abstractModelPart); + } + } + } +} diff --git a/PckStudio.Core/Model/AbstractModelContainer.cs b/PckStudio.Core/Model/AbstractModelContainer.cs new file mode 100644 index 00000000..0daed766 --- /dev/null +++ b/PckStudio.Core/Model/AbstractModelContainer.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Newtonsoft.Json; +using OMI.Formats.Model; +using PckStudio.Core.Extensions; +using PckStudio.Core.Json; +using PckStudio.Core.Properties; +using PckStudio.Interfaces; + +namespace PckStudio.Core.Model +{ + public class AbstractModelContainer + { + static Dictionary _metaData = JsonConvert.DeserializeObject>(Resources.modelMetaData); + + private IDictionary _models = new Dictionary(); + + public AbstractModel GetModelByName(string name) => _models[name]; + public bool AddModel(AbstractModel model) + { + if (model == null || _models.ContainsKey(model.Name)) + return false; + _models.Add(model.Name, model); + return true; + } + + public bool RemoveModel(AbstractModel model) => model is not null && _models.Remove(model.Name); + + public static AbstractModelContainer FromModelContainer(OMI.Formats.Model.ModelContainer models, ITryGet texture) + { + var abstractModelContainer = new AbstractModelContainer(); + if (models is null) + return abstractModelContainer; + foreach (OMI.Formats.Model.Model model in models.GetModels().Where(m => _metaData.ContainsKey(m.Name) && m.Name.EqualsAny(_metaData[m.Name].RootParts.Select(mdp => mdp.Name).ToArray()))) + { + if (!_metaData.TryGetValue(model.Name, out JsonModelMetaData modelMetaData)) + { + Trace.TraceWarning($"No model meta data found for: '{model.Name}'."); + continue; + } + + IDictionary parts = model.GetParts().ToDictionary(part => part.Name); + + IReadOnlyDictionary textures = modelMetaData.TextureLocations.Where(s => texture.TryGet(s, out _)).ToDictionary(Path.GetFileNameWithoutExtension, s => + { + texture.TryGet(s, out Image img); + return img; + }); + AbstractModel abstractModel = new AbstractModel(model.Name, model.TextureSize, textures.FirstOrDefault(), textures); + abstractModel.AddParts(GetRootAbstractModelPart(modelMetaData.RootParts, parts, null)); + abstractModelContainer.AddModel(abstractModel); + } + return abstractModelContainer; + } + + private static IEnumerable GetRootAbstractModelPart(ModelMetaDataPart[] dataParts, IDictionary parts, AbstractModelPart parent) + { + foreach (ModelMetaDataPart rootPart in dataParts) + { + if (!parts.TryGetValue(rootPart.Name, out ModelPart part)) + continue; + var abstractModelPart = new AbstractModelPart(part.Name, parent, part.Translation, part.Rotation + part.AdditionalRotation, part.GetBoxes().Select(mb => new Box(mb.Position, mb.Size, mb.Uv, mb.Inflate, mb.Mirror))); + abstractModelPart.AddParts(GetRootAbstractModelPart(rootPart.Children, parts, abstractModelPart)); + yield return abstractModelPart; + } + } + } +} \ No newline at end of file diff --git a/PckStudio.Core/Model/AbstractModelPart.cs b/PckStudio.Core/Model/AbstractModelPart.cs new file mode 100644 index 00000000..b1a9fa60 --- /dev/null +++ b/PckStudio.Core/Model/AbstractModelPart.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Numerics; + +namespace PckStudio.Core.Model +{ + public class AbstractModelPart + { + public string Name { get; } + public AbstractModelPart Parent { get; } + public Vector3 Translation { get; } + public Vector3 Rotation { get; } + + private IList _boxes; + private List _subParts; + + public AbstractModelPart(string name, AbstractModelPart parent, Vector3 translation, Vector3 rotation, IEnumerable boxes) + { + Name = name; + Parent = parent; + Translation = translation; + Rotation = rotation; + _boxes = new List(boxes); + _subParts = new List(); + } + + public void AddBox(Box box) => _boxes.Add(box); + + internal void AddParts(IEnumerable parts) => _subParts.AddRange(parts); + } +} diff --git a/PckStudio.Core/PckStudio.Core.csproj b/PckStudio.Core/PckStudio.Core.csproj index 24fea733..c872a71b 100644 --- a/PckStudio.Core/PckStudio.Core.csproj +++ b/PckStudio.Core/PckStudio.Core.csproj @@ -162,7 +162,10 @@ + + +