Core - Add AbstractModel.cs, AbstractModelContainer.cs & AbstractModelPart.cs

This commit is contained in:
miku-666
2025-12-12 05:13:28 +01:00
parent 288e54a5f0
commit e361a29b82
4 changed files with 154 additions and 0 deletions

View File

@@ -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<Image> DefaultTexture { get; }
public IReadOnlyDictionary<string, Image> Textures { get; }
private IDictionary<string, AbstractModelPart> _parts;
public AbstractModel(string name, Size textureSize, NamedData<Image> defaultTexture, IReadOnlyDictionary<string, Image> 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<AbstractModelPart> abstractModelParts)
{
foreach (AbstractModelPart abstractModelPart in abstractModelParts)
{
AddPart(abstractModelPart);
}
}
}
}

View File

@@ -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<string, JsonModelMetaData> _metaData = JsonConvert.DeserializeObject<Dictionary<string, JsonModelMetaData>>(Resources.modelMetaData);
private IDictionary<string, AbstractModel> _models = new Dictionary<string, AbstractModel>();
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<string, Image> 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<string, ModelPart> parts = model.GetParts().ToDictionary(part => part.Name);
IReadOnlyDictionary<string, Image> 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<AbstractModelPart> GetRootAbstractModelPart(ModelMetaDataPart[] dataParts, IDictionary<string, ModelPart> 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;
}
}
}
}

View File

@@ -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<Box> _boxes;
private List<AbstractModelPart> _subParts;
public AbstractModelPart(string name, AbstractModelPart parent, Vector3 translation, Vector3 rotation, IEnumerable<Box> boxes)
{
Name = name;
Parent = parent;
Translation = translation;
Rotation = rotation;
_boxes = new List<Box>(boxes);
_subParts = new List<AbstractModelPart>();
}
public void AddBox(Box box) => _boxes.Add(box);
internal void AddParts(IEnumerable<AbstractModelPart> parts) => _subParts.AddRange(parts);
}
}

View File

@@ -162,7 +162,10 @@
<Compile Include="MapReader.cs" />
<Compile Include="Misc\FileCacher.cs" />
<Compile Include="Misc\OpenFolderDialog.cs" />
<Compile Include="Model\AbstractModel.cs" />
<Compile Include="Model\AbstractModelContainer.cs" />
<Compile Include="Box.cs" />
<Compile Include="Model\AbstractModelPart.cs" />
<Compile Include="NamedData.cs" />
<Compile Include="DLC\DLCPackageType.cs" />
<Compile Include="Properties\Resources.Designer.cs">