mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/PCK-Studio.git
synced 2026-07-04 01:44:18 +00:00
Update modelMetaData part hierarchy structure
This commit is contained in:
@@ -62,7 +62,6 @@ namespace PckStudio.Internal
|
||||
BlockBenchModel blockBenchModel = BlockBenchModel.Create(BlockBenchFormatInfos.BedrockEntity, modelInfo.Model.Name, modelInfo.Model.TextureSize, modelInfo.Textures.Select(nt => (Texture)nt));
|
||||
blockBenchModel.ModelIdentifier = modelInfo.Model.Name;
|
||||
|
||||
Dictionary<string, Outline> outliners = new Dictionary<string, Outline>(5);
|
||||
List<Element> elements = new List<Element>(modelInfo.Model.PartCount);
|
||||
|
||||
if (!ModelMetaData.TryGetValue(modelInfo.Model.Name, out JsonModelMetaData modelMetaData))
|
||||
@@ -71,28 +70,9 @@ namespace PckStudio.Internal
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (ModelPart part in modelInfo.Model.GetParts())
|
||||
{
|
||||
Debug.Assert(!outliners.ContainsKey(part.Name), $"'{part.Name}' is already present.");
|
||||
var outline = new Outline(part.Name);
|
||||
|
||||
Vector3 partTranslation = part.Translation;
|
||||
outline.Origin = TransformSpace(partTranslation, Vector3.Zero, bbModelTransformAxis);
|
||||
outline.Origin += _heightOffset;
|
||||
|
||||
Vector3 rotation = part.Rotation;
|
||||
outline.Rotation = rotation * TransformSpace(Vector3.One, Vector3.Zero, bbModelTransformAxis);
|
||||
|
||||
Element[] elements1 = part.GetBoxes().Select(box => ToElement(part.Name, box, partTranslation)).ToArray();
|
||||
elements.AddRange(elements1);
|
||||
outline.Children.Add(elements1.Select(element => element.Uuid));
|
||||
outliners.Add(part.Name, outline);
|
||||
}
|
||||
|
||||
TraverseChildren(modelMetaData.RootParts, ref outliners);
|
||||
IEnumerable<Outline> outlines = ConvertToOutlines(modelInfo.Model, Vector3.Zero, modelMetaData.RootParts, elements.AddRange);
|
||||
|
||||
blockBenchModel.Elements = elements.ToArray();
|
||||
IEnumerable<Outline> outlines = outliners.Values.Where(value => modelMetaData.RootParts.Count == 0 || modelMetaData.RootParts.ContainsKey(value.Name));
|
||||
if (ExportSettings.CreateModelOutline)
|
||||
outlines = new Outline[1]
|
||||
{
|
||||
@@ -113,44 +93,49 @@ namespace PckStudio.Internal
|
||||
return element;
|
||||
}
|
||||
|
||||
// TODO: return a new object instead of modifying a reference. (make immutable) -miku
|
||||
private static void TraverseChildren(IReadOnlyDictionary<string, JArray> keyValues, ref Dictionary<string, Outline> outliners)
|
||||
private Outline[] ConvertToOutlines(Model model, Vector3 parentRotation, IReadOnlyCollection<ModelMetaDataPart> keyValues, Action<Element[]> addElements, int depth = 0)
|
||||
{
|
||||
foreach (KeyValuePair<string, JArray> item in keyValues)
|
||||
Outline CreateOutline(ModelPart modelPart)
|
||||
{
|
||||
if (!outliners.ContainsKey(item.Key))
|
||||
Outline outline = new Outline(modelPart.Name);
|
||||
|
||||
Vector3 partTranslation = modelPart.Translation;
|
||||
outline.Origin = TransformSpace(partTranslation, Vector3.Zero, bbModelTransformAxis);
|
||||
outline.Origin += _heightOffset;
|
||||
|
||||
Vector3 rotation = modelPart.Rotation;
|
||||
outline.Rotation = rotation * TransformSpace(Vector3.One, Vector3.Zero, bbModelTransformAxis);
|
||||
outline.Rotation += parentRotation;
|
||||
|
||||
Element[] elements1 = modelPart.GetBoxes().Select(box => ToElement(modelPart.Name, box, partTranslation)).ToArray();
|
||||
addElements(elements1);
|
||||
|
||||
outline.Children.Add(elements1.Select(element => element.Uuid).ToArray());
|
||||
return outline;
|
||||
}
|
||||
|
||||
if (depth == 0 && keyValues.Count == 0)
|
||||
{
|
||||
Debug.WriteLine($"{nameof(item.Key)}: '{item.Key}' not in {nameof(outliners)}.");
|
||||
return model.GetParts().Select(CreateOutline).ToArray();
|
||||
}
|
||||
|
||||
List<Outline> outlines = new List<Outline>();
|
||||
foreach (ModelMetaDataPart item in keyValues)
|
||||
{
|
||||
if (!model.TryGetPart(item.Name, out ModelPart modelPart))
|
||||
{
|
||||
Debug.WriteLine($"{nameof(item.Name)}: '{item.Name}' not in {nameof(model)}.");
|
||||
continue;
|
||||
}
|
||||
Outline partentOutline = outliners[item.Key];
|
||||
foreach (JToken child in item.Value)
|
||||
{
|
||||
if (child.Type == JTokenType.String && outliners.TryGetValue(child.ToString(), out Outline childOutline))
|
||||
{
|
||||
childOutline.Rotation -= partentOutline.Rotation;
|
||||
partentOutline.Children.Add(JToken.FromObject(childOutline));
|
||||
}
|
||||
if (child.Type == JTokenType.Object)
|
||||
{
|
||||
IReadOnlyDictionary<string, JArray> childKeyValues = child.ToObject<ReadOnlyDictionary<string, JArray>>();
|
||||
TraverseChildren(childKeyValues, ref outliners);
|
||||
foreach (var key in childKeyValues.Keys)
|
||||
{
|
||||
if (!outliners.ContainsKey(key))
|
||||
{
|
||||
Debug.WriteLine($"{nameof(key)}: '{key}' not in {nameof(outliners)}.");
|
||||
continue;
|
||||
}
|
||||
childOutline = outliners[key];
|
||||
childOutline.Rotation -= partentOutline.Rotation;
|
||||
partentOutline.Children.Add(JToken.FromObject(childOutline));
|
||||
}
|
||||
}
|
||||
}
|
||||
Outline partentOutline = CreateOutline(modelPart);
|
||||
JToken[] s = ConvertToOutlines(model, modelPart.Rotation, item.Children, addElements, depth + 1).Select(JToken.FromObject).ToArray();
|
||||
partentOutline.Children.Add(s);
|
||||
outlines.Add(partentOutline);
|
||||
}
|
||||
return outlines.ToArray();
|
||||
}
|
||||
|
||||
|
||||
private static Element CreateElement(string name, ModelBox box, Vector3 origin, Vector3 translationUnit, Vector3 offset)
|
||||
{
|
||||
Vector3 pos = box.Position;
|
||||
|
||||
@@ -10,12 +10,21 @@ using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace PckStudio.Internal.Json
|
||||
{
|
||||
internal class ModelMetaDataPart
|
||||
{
|
||||
[JsonProperty("name", Required = Required.Always)]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonProperty("children", NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public ModelMetaDataPart[] Children { get; set; } = Array.Empty<ModelMetaDataPart>();
|
||||
}
|
||||
|
||||
internal class JsonModelMetaData
|
||||
{
|
||||
[JsonProperty("textureLocations", Required = Required.Always)]
|
||||
public string[] TextureLocations { get; set; }
|
||||
|
||||
[JsonProperty("root", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public ReadOnlyDictionary<string, JArray> RootParts { get; set; } = new ReadOnlyDictionary<string, JArray>(new Dictionary<string, JArray>());
|
||||
[JsonProperty("parts", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public ModelMetaDataPart[] RootParts { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,22 +3,32 @@
|
||||
"textureLocations": [
|
||||
"res/mob/bat"
|
||||
],
|
||||
"root": {
|
||||
"head": [
|
||||
"rightEar",
|
||||
"leftEar"
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"rightWing": [
|
||||
"rightWingTip"
|
||||
],
|
||||
"leftWing": [
|
||||
"leftWingTip"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
"parts": [
|
||||
{
|
||||
"name": "head",
|
||||
"children": [
|
||||
{ "name": "rightEar" },
|
||||
{ "name": "leftEar" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "body",
|
||||
"children": [
|
||||
{
|
||||
"name": "rightWing",
|
||||
"children": [
|
||||
{ "name": "rightWingTip" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "leftWing",
|
||||
"children": [
|
||||
{ "name": "leftWingTip" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"bed": {
|
||||
"textureLocations": [
|
||||
@@ -64,40 +74,90 @@
|
||||
"textureLocations": [
|
||||
"res/mob/dolphin"
|
||||
],
|
||||
"root": {
|
||||
"body": [
|
||||
{
|
||||
"head": [ "nose" ],
|
||||
"tail": [ "tail_fin" ]
|
||||
},
|
||||
"left_fin",
|
||||
"right_fin",
|
||||
"back_fin"
|
||||
]
|
||||
}
|
||||
"parts": [
|
||||
{
|
||||
"name": "body",
|
||||
"children": [
|
||||
{
|
||||
"name": "head",
|
||||
"children": [
|
||||
{ "name": "nose" },
|
||||
{ "name": "tail_fin" }
|
||||
]
|
||||
},
|
||||
{ "name": "right_fin" },
|
||||
{ "name": "left_fin" },
|
||||
{ "name": "back_fin" }
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"dragon": {
|
||||
"textureLocations": [
|
||||
"res/mob/enderdragon/ender"
|
||||
],
|
||||
"root": {
|
||||
"head": [ "jaw" ],
|
||||
"body": [],
|
||||
"wing": [ "wingtip" ],
|
||||
"wing1": [ "wingtip1" ],
|
||||
"rearleg": [ { "rearlegtip": [ "rearfoot" ] } ],
|
||||
"rearleg1": [ { "rearlegtip1": [ "rearfoot1" ] } ],
|
||||
"frontleg": [ { "frontlegtip": [ "frontfoot" ] } ],
|
||||
"frontleg1": [ { "frontlegtip1": [ "frontfoot1" ] } ]
|
||||
}
|
||||
"parts": [
|
||||
{
|
||||
"name": "head",
|
||||
"children": [ { "name": "jaw" } ]
|
||||
},
|
||||
{ "name": "body" },
|
||||
{
|
||||
"name": "wing",
|
||||
"children": [ { "name": "wingtip" } ]
|
||||
},
|
||||
{
|
||||
"name": "wing1",
|
||||
"children": [ { "name": "wingtip1" } ]
|
||||
},
|
||||
{
|
||||
"name": "rearleg",
|
||||
"children": [
|
||||
{
|
||||
"name": "rearlegtip",
|
||||
"children": [ { "name": "rearfoot" } ]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "rearleg1",
|
||||
"children": [
|
||||
{
|
||||
"name": "rearlegtip1",
|
||||
"children": [ { "name": "rearfoot1" } ]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "frontleg",
|
||||
"children": [
|
||||
{
|
||||
"name": "frontlegtip",
|
||||
"children": [ { "name": "frontfoot" } ]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "frontleg1",
|
||||
"children": [
|
||||
{
|
||||
"name": "frontlegtip1",
|
||||
"children": [ { "name": "frontfoot1" } ]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"dragon_head": {
|
||||
"textureLocations": [
|
||||
"res/mob/enderdragon/ender"
|
||||
],
|
||||
"root": {
|
||||
"head": [ "jaw" ]
|
||||
}
|
||||
"parts": [
|
||||
{
|
||||
"name": "head",
|
||||
"children": [ { "name": "jaw" } ]
|
||||
}
|
||||
]
|
||||
},
|
||||
"enderman": {
|
||||
"textureLocations": [
|
||||
@@ -115,14 +175,23 @@
|
||||
"res/mob/guardian",
|
||||
"res/mob/guardian_elder"
|
||||
],
|
||||
"root": {
|
||||
"head": [
|
||||
"eye",
|
||||
{
|
||||
"tailpart0": [ { "tailpart1": [ "tailpart2" ] } ]
|
||||
}
|
||||
]
|
||||
}
|
||||
"parts": [
|
||||
{
|
||||
"name": "head",
|
||||
"children": [
|
||||
{ "name": "eye" },
|
||||
{
|
||||
"name": "tailpart0",
|
||||
"children": [
|
||||
{
|
||||
"name": "tailpart1",
|
||||
"children": [ { "name": "tailpart2" } ]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"irongolem": {
|
||||
"textureLocations": [
|
||||
@@ -167,28 +236,48 @@
|
||||
"res/mob/parrot/parrot_red_blue",
|
||||
"res/mob/parrot/parrot_yellow_blue"
|
||||
],
|
||||
"root": {
|
||||
"head": [ "head2", "beak1", "beak2", "feather" ],
|
||||
"body": [],
|
||||
"tail": [],
|
||||
"wing0": [],
|
||||
"wing1": [],
|
||||
"leg0": [],
|
||||
"leg1": []
|
||||
}
|
||||
"parts": [
|
||||
{
|
||||
"name": "head",
|
||||
"children": [
|
||||
{ "name": "head2" },
|
||||
{ "name": "beak1" },
|
||||
{ "name": "beak2" },
|
||||
{ "name": "feather" }
|
||||
]
|
||||
},
|
||||
{ "name": "body" },
|
||||
{ "name": "tail" },
|
||||
{ "name": "wing0" },
|
||||
{ "name": "wing1" },
|
||||
{ "name": "leg0" },
|
||||
{ "name": "leg1" }
|
||||
]
|
||||
},
|
||||
"phantom": {
|
||||
"textureLocations": [
|
||||
"res/mob/phantom"
|
||||
],
|
||||
"root": {
|
||||
"body": [
|
||||
"head",
|
||||
{ "wing0": [ "wingtip0" ] },
|
||||
{ "wing1": [ "wingtip1" ] },
|
||||
{ "tail": [ "tailtip" ] }
|
||||
]
|
||||
}
|
||||
"parts": [
|
||||
{
|
||||
"name": "body",
|
||||
"children": [
|
||||
{ "name": "head" },
|
||||
{
|
||||
"name": "wing0",
|
||||
"children": [ { "name": "wingtip0" } ]
|
||||
},
|
||||
{
|
||||
"name": "wing1",
|
||||
"children": [ { "name": "wingtip1" } ]
|
||||
},
|
||||
{
|
||||
"name": "tail",
|
||||
"children": [ { "name": "tailtip" } ]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"pig": {
|
||||
"textureLocations": [
|
||||
@@ -369,19 +458,42 @@
|
||||
"res/mob/horse/horse_zombie",
|
||||
"res/mob/horse/mule"
|
||||
],
|
||||
"root": {
|
||||
"Neck": [ { "Head": [ "UMouth", "Ear1", "Ear2", "MuleEarL", "MuleEarR", "SaddleMouthL", "SaddleMouthR", "HeadSaddle" ] } ],
|
||||
"Body": [ "TailA", "Saddle" ],
|
||||
"Mane": [],
|
||||
"Leg1A": [],
|
||||
"Leg2A": [],
|
||||
"Leg3A": [],
|
||||
"Leg4A": [],
|
||||
"Bag1": [],
|
||||
"Bag2": [],
|
||||
"SaddleMouthLine": [],
|
||||
"SaddleMouthLineR": []
|
||||
}
|
||||
"parts": [
|
||||
{
|
||||
"name": "Neck",
|
||||
"children": [
|
||||
{
|
||||
"name": "Head",
|
||||
"children": [
|
||||
{ "name": "HeadSaddle" },
|
||||
{ "name": "UMouth" },
|
||||
{ "name": "Ear1" },
|
||||
{ "name": "Ear2" },
|
||||
{ "name": "MuleEarL" },
|
||||
{ "name": "MuleEarR" },
|
||||
{ "name": "SaddleMouthL" },
|
||||
{ "name": "SaddleMouthR" }
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Body",
|
||||
"children": [
|
||||
{ "name": "TailA" },
|
||||
{ "name": "Saddle" }
|
||||
]
|
||||
},
|
||||
{ "name": "Mane" },
|
||||
{ "name": "Leg1A" },
|
||||
{ "name": "Leg2A" },
|
||||
{ "name": "Leg3A" },
|
||||
{ "name": "Leg4A" },
|
||||
{ "name": "Bag1" },
|
||||
{ "name": "Bag2" },
|
||||
{ "name": "SaddleMouthLine" },
|
||||
{ "name": "SaddleMouthLineR" }
|
||||
]
|
||||
},
|
||||
"cat": {
|
||||
"textureLocations": [
|
||||
|
||||
Reference in New Issue
Block a user