mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/PCK-Studio.git
synced 2026-07-18 10:38:12 +00:00
Split up model and skin importer into seperate classes and improved api
This commit is contained in:
37
PCK-Studio/External/Format/BlockBenchModel.cs
vendored
37
PCK-Studio/External/Format/BlockBenchModel.cs
vendored
@@ -155,6 +155,25 @@ namespace PckStudio.External.Format
|
||||
|
||||
[JsonProperty("uuid")]
|
||||
internal Guid Uuid;
|
||||
|
||||
internal static Element CreateCube(string name, Vector2 uvOffset, Vector3 pos, Vector3 size, float inflate, bool mirror)
|
||||
{
|
||||
return new Element
|
||||
{
|
||||
Name = name,
|
||||
UseBoxUv = true,
|
||||
Locked = false,
|
||||
Rescale = false,
|
||||
Type = "cube",
|
||||
Uuid = Guid.NewGuid(),
|
||||
UvOffset = uvOffset,
|
||||
MirrorUv = mirror,
|
||||
Inflate = inflate,
|
||||
From = pos,
|
||||
To = pos + size
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal class Texture
|
||||
@@ -321,6 +340,22 @@ namespace PckStudio.External.Format
|
||||
|
||||
[JsonProperty("textures")]
|
||||
internal Texture[] Textures;
|
||||
|
||||
|
||||
internal static BlockBenchModel Create(string name, Size textureResolution, IEnumerable<Texture> textures)
|
||||
{
|
||||
return new BlockBenchModel()
|
||||
{
|
||||
Name = name,
|
||||
Textures = textures.ToArray(),
|
||||
TextureResolution = textureResolution,
|
||||
ModelIdentifier = "",
|
||||
Metadata = new Meta()
|
||||
{
|
||||
FormatVersion = "4.5",
|
||||
ModelFormat = "free",
|
||||
UseBoxUv = true,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,20 +181,20 @@ namespace PckStudio.Forms.Editor
|
||||
{
|
||||
SaveFileDialog saveFileDialog = new SaveFileDialog();
|
||||
saveFileDialog.Title = "Save Model File";
|
||||
saveFileDialog.Filter = SkinModelImporter.SupportedModelFileFormatsFilter;
|
||||
saveFileDialog.Filter = SkinModelImporter.Default.SupportedModelFileFormatsFilter;
|
||||
saveFileDialog.FileName = _skin.MetaData.Name.TrimEnd(new char[] { '\n', '\r' }).Replace(' ', '_');
|
||||
if (saveFileDialog.ShowDialog() == DialogResult.OK)
|
||||
SkinModelImporter.Export(saveFileDialog.FileName, _skin.Model);
|
||||
SkinModelImporter.Default.Export(saveFileDialog.FileName, _skin.Model);
|
||||
}
|
||||
|
||||
private void importSkinButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
OpenFileDialog openFileDialog = new OpenFileDialog();
|
||||
openFileDialog.Title = "Select Model File";
|
||||
openFileDialog.Filter = SkinModelImporter.SupportedModelFileFormatsFilter;
|
||||
openFileDialog.Filter = SkinModelImporter.Default.SupportedModelFileFormatsFilter;
|
||||
if (MessageBox.Show("Import custom model project file? Your current work will be lost!", "", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1) == DialogResult.Yes && openFileDialog.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
SkinModelInfo modelInfo = SkinModelImporter.Import(openFileDialog.FileName);
|
||||
SkinModelInfo modelInfo = SkinModelImporter.Default.Import(openFileDialog.FileName);
|
||||
if (modelInfo is not null)
|
||||
{
|
||||
_skin.Model = modelInfo;
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using PckStudio.Internal;
|
||||
using PckStudio.Internal.Skin;
|
||||
|
||||
namespace PckStudio.Interfaces
|
||||
{
|
||||
internal interface ISkinModelImportProvider : IModelImportProvider<SkinModelInfo>
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -46,7 +46,6 @@ namespace PckStudio.Internal.App
|
||||
_ = Tiles.MoonPhaseImageList;
|
||||
_ = Tiles.PaintingImageList;
|
||||
SettingsManager.Initialize();
|
||||
SkinModelImporter.Initialize();
|
||||
CultureInfo.CurrentCulture = CultureInfo.InvariantCulture;
|
||||
Task.Run(GetContributors);
|
||||
}
|
||||
|
||||
78
PCK-Studio/Internal/GameModelImporter.cs
Normal file
78
PCK-Studio/Internal/GameModelImporter.cs
Normal file
@@ -0,0 +1,78 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using OMI.Formats.Model;
|
||||
using PckStudio.External.Format;
|
||||
using System.Numerics;
|
||||
using System.IO;
|
||||
|
||||
namespace PckStudio.Internal
|
||||
{
|
||||
internal sealed class GameModelImporter : ModelImporter<GameModelInfo>
|
||||
{
|
||||
public static GameModelImporter Default { get; } = new GameModelImporter();
|
||||
|
||||
private GameModelImporter()
|
||||
{
|
||||
InternalAddProvider(new FileDialogFilter("", "*.bbmodel"), null, ExportBlockBenchModel);
|
||||
}
|
||||
|
||||
internal static void ExportBlockBenchModel(string fileName, GameModelInfo modelInfo)
|
||||
{
|
||||
BlockBenchModel blockBenchModel = BlockBenchModel.Create(Path.GetFileNameWithoutExtension(fileName), modelInfo.Model.TextureSize, modelInfo.Textures.Select(nt => (Texture)nt));
|
||||
|
||||
Dictionary<string, Outline> outliners = new Dictionary<string, Outline>(5);
|
||||
List<Element> elements = new List<Element>(modelInfo.Model.Parts.Count);
|
||||
|
||||
Vector3 transformAxis = new Vector3(1, 1, 0);
|
||||
|
||||
Outline GetOrCreateOutline(string partName)
|
||||
{
|
||||
if (!outliners.ContainsKey(partName))
|
||||
outliners.Add(partName, new Outline(partName));
|
||||
return outliners[partName];
|
||||
}
|
||||
|
||||
foreach (ModelPart part in modelInfo.Model.Parts.Values)
|
||||
{
|
||||
//Outline outline = GetOrCreateOutline(part.Name);
|
||||
|
||||
var outline = new Outline(part.Name);
|
||||
|
||||
Vector3 partTranslation = part.Translation;
|
||||
outline.Origin = TransformSpace(partTranslation, Vector3.Zero, transformAxis);
|
||||
outline.Origin += Vector3.UnitY * 24f;
|
||||
|
||||
Vector3 rotation = part.Rotation + part.AdditionalRotation;
|
||||
outline.Rotation = rotation * TransformSpace(Vector3.One, Vector3.Zero, transformAxis);
|
||||
|
||||
foreach (ModelBox box in part.Boxes)
|
||||
{
|
||||
Element element = CreateElement(box, partTranslation, part.Name);
|
||||
element.Origin = outline.Origin;
|
||||
elements.Add(element);
|
||||
outline.Children.Add(element.Uuid);
|
||||
}
|
||||
outliners.Add(part.Name, outline);
|
||||
}
|
||||
|
||||
blockBenchModel.Elements = elements.ToArray();
|
||||
blockBenchModel.Outliner = JArray.FromObject(outliners);
|
||||
|
||||
string content = JsonConvert.SerializeObject(blockBenchModel);
|
||||
File.WriteAllText(fileName, content);
|
||||
}
|
||||
|
||||
private static Element CreateElement(ModelBox box, Vector3 origin, string name)
|
||||
{
|
||||
Vector3 pos = box.Position;
|
||||
Vector3 size = box.Size;
|
||||
Vector3 transformPos = TransformSpace(pos + origin, size, new Vector3(1, 1, 0)) + 24f * Vector3.UnitY;
|
||||
return Element.CreateCube(name, box.Uv, transformPos, size, box.Scale, box.Mirror);
|
||||
}
|
||||
}
|
||||
}
|
||||
23
PCK-Studio/Internal/GameModelInfo.cs
Normal file
23
PCK-Studio/Internal/GameModelInfo.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using OMI.Formats.Model;
|
||||
|
||||
namespace PckStudio.Internal
|
||||
{
|
||||
internal class GameModelInfo
|
||||
{
|
||||
public Model Model { get; }
|
||||
|
||||
public IEnumerable<NamedTexture> Textures { get; }
|
||||
|
||||
public GameModelInfo(Model model, IEnumerable<NamedTexture> textures)
|
||||
{
|
||||
Model = model;
|
||||
Textures = textures;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
138
PCK-Studio/Internal/ModelImporter.cs
Normal file
138
PCK-Studio/Internal/ModelImporter.cs
Normal file
@@ -0,0 +1,138 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using PckStudio.Interfaces;
|
||||
|
||||
namespace PckStudio.Internal
|
||||
{
|
||||
internal abstract class ModelImporter<T> where T : class
|
||||
{
|
||||
private Dictionary<string, IModelImportProvider<T>> _importProviders = new Dictionary<string, IModelImportProvider<T>>();
|
||||
|
||||
private sealed class SimpleSkinImportProvider : IModelImportProvider<T>
|
||||
{
|
||||
public string Name => nameof(SimpleSkinImportProvider);
|
||||
|
||||
public FileDialogFilter DialogFilter => _dialogFilter;
|
||||
|
||||
private FileDialogFilter _dialogFilter;
|
||||
private Func<string, T> _import;
|
||||
private Action<string, T> _export;
|
||||
|
||||
public SimpleSkinImportProvider(FileDialogFilter dialogFilter, Func<string, T> import, Action<string, T> export)
|
||||
{
|
||||
_dialogFilter = dialogFilter;
|
||||
_import = import;
|
||||
_export = export;
|
||||
}
|
||||
|
||||
public void Export(string filename, T model)
|
||||
{
|
||||
_ = _export ?? throw new NotImplementedException();
|
||||
_export(filename, model);
|
||||
}
|
||||
|
||||
public T Import(string filename)
|
||||
{
|
||||
_ = _import ?? throw new NotImplementedException();
|
||||
return _import(filename);
|
||||
}
|
||||
|
||||
public void Export(ref Stream stream, T model)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public T Import(Stream stream)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
internal string SupportedModelFileFormatsFilter => string.Join("|", _importProviders.Values.Select(p => p.DialogFilter));
|
||||
|
||||
public T Import(string filename)
|
||||
{
|
||||
if (HasProvider(filename))
|
||||
return GetProvider(filename).Import(filename);
|
||||
|
||||
Trace.TraceWarning($"[{nameof(SkinModelImporter)}:Import] No provider found for '{Path.GetExtension(filename)}'.");
|
||||
return default;
|
||||
}
|
||||
|
||||
public void Export(string filename, T model)
|
||||
{
|
||||
if (model is null)
|
||||
{
|
||||
Trace.TraceError($"[{nameof(SkinModelImporter)}:Export] Model is null.");
|
||||
return;
|
||||
}
|
||||
if (!HasProvider(filename))
|
||||
{
|
||||
string fileExtension = Path.GetExtension(filename);
|
||||
Trace.TraceWarning($"[{nameof(SkinModelImporter)}:Export] No provider found for '{fileExtension}'.");
|
||||
return;
|
||||
}
|
||||
GetProvider(filename).Export(filename, model);
|
||||
}
|
||||
|
||||
internal bool AddProvider(IModelImportProvider<T> provider)
|
||||
{
|
||||
if (_importProviders.ContainsKey(provider.DialogFilter.Extension))
|
||||
return false;
|
||||
|
||||
_importProviders.Add(provider.DialogFilter.Extension, provider);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected bool HasProvider(string filename)
|
||||
{
|
||||
string fileExtension = Path.GetExtension(filename);
|
||||
return _importProviders.ContainsKey(fileExtension) && _importProviders[fileExtension] is not null;
|
||||
}
|
||||
|
||||
protected IModelImportProvider<T> GetProvider(string filename)
|
||||
{
|
||||
string fileExtension = Path.GetExtension(filename);
|
||||
return _importProviders.ContainsKey(fileExtension) ? _importProviders[fileExtension] : null;
|
||||
}
|
||||
|
||||
protected bool InternalAddProvider(FileDialogFilter dialogFilter, Func<string, T> import, Action<string, T> export)
|
||||
{
|
||||
if (import == null || export == null)
|
||||
return false;
|
||||
|
||||
return AddProvider(new SimpleSkinImportProvider(dialogFilter, import, export));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Translates coordinate unit system into our coordinate system
|
||||
/// </summary>
|
||||
/// <param name="origin">Position/Origin of the Object(Cube).</param>
|
||||
/// <param name="size">The Size of the Object(Cube).</param>
|
||||
/// <param name="translationUnit">Describes what axises need translation.</param>
|
||||
/// <returns>The translated position</returns>
|
||||
protected static Vector3 TransformSpace(Vector3 origin, Vector3 size, Vector3 translationUnit)
|
||||
{
|
||||
// The translation unit describes what axises need to be swapped
|
||||
// Example:
|
||||
// translation unit = (1, 0, 0) => This translation unit will ONLY swap the X axis
|
||||
translationUnit = Vector3.Clamp(translationUnit, Vector3.Zero, Vector3.One);
|
||||
// To better understand see:
|
||||
// https://sharplab.io/#v2:C4LgTgrgdgNAJiA1AHwAICYCMBYAUKgBgAJVMA6AOQgFsBTMASwGMBnAbj1QGYT0iBhIgG88RMb3SjxI3OLlEAbgEMwRBlAAOEYEQC8RKLQDuRAGq0mwAPZguACkwwijogQCUHWfLHLVtAB4aFsC0cHoGxmbBNvYAtC7xTpgeUt6+RGC0LOEAKmBKUCwAYjbU/FY2cOpKISx26lrAKV7epACcdpkszd5i7Z1ZevoBQZahPeIAvqlEM9wkmABsUZYxRHkFxaXlldW1duartmqa2m4zMr2KKhmD+ofWtmT8ADZK1Br1p8BODzFkAC16FZftEngB5QwTbxdIgAKn06E8V1hsXuYK4ZEhtGRvVQAHYiLEurixNNcJMgA
|
||||
Vector3 transformUnit = -((translationUnit * 2) - Vector3.One);
|
||||
|
||||
Vector3 pos = origin;
|
||||
// The next line essentialy does uses the fomular below just on all axis.
|
||||
// x = -(pos.x + size.x)
|
||||
pos *= transformUnit;
|
||||
pos -= size * translationUnit;
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,78 +18,35 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Drawing;
|
||||
using System.Numerics;
|
||||
using System.Diagnostics;
|
||||
using System.Windows.Forms;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
using PckStudio.Extensions;
|
||||
using PckStudio.External.Format;
|
||||
using PckStudio.Interfaces;
|
||||
using PckStudio.Properties;
|
||||
using PckStudio.Internal.Skin;
|
||||
using PckStudio.Internal.Json;
|
||||
using PckStudio.Internal.IO.PSM;
|
||||
using PckStudio.External.Format;
|
||||
using PckStudio.Internal.FileFormats;
|
||||
using PckStudio.Forms.Additional_Popups;
|
||||
using System.Drawing;
|
||||
using PckStudio.Internal.Skin;
|
||||
using OMI.Formats.Model;
|
||||
using PckStudio.Internal.Json;
|
||||
using System.Collections.ObjectModel;
|
||||
using PckStudio.Properties;
|
||||
using PckStudio.Interfaces;
|
||||
|
||||
namespace PckStudio.Internal
|
||||
{
|
||||
internal static class SkinModelImporter
|
||||
internal sealed class SkinModelImporter : ModelImporter<SkinModelInfo>
|
||||
{
|
||||
private static Dictionary<string, ISkinModelImportProvider> _importProviders = new Dictionary<string, ISkinModelImportProvider>();
|
||||
|
||||
private sealed class SimpleSkinImportProvider : ISkinModelImportProvider
|
||||
{
|
||||
public string Name => nameof(SimpleSkinImportProvider);
|
||||
|
||||
public FileDialogFilter DialogFilter => _dialogFilter;
|
||||
|
||||
private FileDialogFilter _dialogFilter;
|
||||
private Func<string, SkinModelInfo> _import;
|
||||
private Action<string, SkinModelInfo> _export;
|
||||
|
||||
public SimpleSkinImportProvider(FileDialogFilter dialogFilter, Func<string, SkinModelInfo> import, Action<string, SkinModelInfo> export)
|
||||
{
|
||||
_dialogFilter = dialogFilter;
|
||||
_import = import;
|
||||
_export = export;
|
||||
}
|
||||
|
||||
public void Export(string filename, SkinModelInfo model)
|
||||
{
|
||||
_ = _export ?? throw new NotImplementedException();
|
||||
_export(filename, model);
|
||||
}
|
||||
|
||||
public SkinModelInfo Import(string filename)
|
||||
{
|
||||
_ = _import ?? throw new NotImplementedException();
|
||||
return _import(filename);
|
||||
}
|
||||
|
||||
public void Export(ref Stream stream, SkinModelInfo model)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public SkinModelInfo Import(Stream stream)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
internal static string SupportedModelFileFormatsFilter => string.Join("|", _importProviders.Values.Select(p => p.DialogFilter));
|
||||
public static SkinModelImporter Default { get; } = new SkinModelImporter();
|
||||
|
||||
internal static ReadOnlyDictionary<string, JsonModelMetaData> ModelTextureLocations { get; private set; }
|
||||
|
||||
internal static void Initialize()
|
||||
internal SkinModelImporter()
|
||||
{
|
||||
ModelTextureLocations = JsonConvert.DeserializeObject<ReadOnlyDictionary<string, JsonModelMetaData>>(Resources.modelTextureLocations);
|
||||
InternalAddProvider(new("Pck skin model(*.psm)", "*.psm"), ImportPsm, ExportPsm);
|
||||
@@ -97,47 +54,6 @@ namespace PckStudio.Internal
|
||||
InternalAddProvider(new("Bedrock (Legacy) Model(*.geo.json;*.json)", "*.geo.json;*.json"), ImportBedrockJson, ExportBedrockJson);
|
||||
}
|
||||
|
||||
internal static bool AddProvider(ISkinModelImportProvider provider)
|
||||
{
|
||||
if (_importProviders.ContainsKey(provider.DialogFilter.Extension))
|
||||
return false;
|
||||
|
||||
_importProviders.Add(provider.DialogFilter.Extension, provider);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool InternalAddProvider(FileDialogFilter dialogFilter, Func<string, SkinModelInfo> import, Action<string, SkinModelInfo> export)
|
||||
{
|
||||
if (import == null || export == null)
|
||||
return false;
|
||||
|
||||
return AddProvider(new SimpleSkinImportProvider(dialogFilter, import, export));
|
||||
}
|
||||
|
||||
internal static SkinModelInfo Import(string fileName)
|
||||
{
|
||||
string fileExtension = Path.GetExtension(fileName);
|
||||
if (_importProviders.ContainsKey(fileExtension) && _importProviders[fileExtension] is not null)
|
||||
return _importProviders[fileExtension].Import(fileName);
|
||||
|
||||
Trace.TraceWarning($"[{nameof(SkinModelImporter)}:Import] No provider found for '{fileExtension}'.");
|
||||
return null;
|
||||
}
|
||||
|
||||
internal static void Export(string fileName, SkinModelInfo model)
|
||||
{
|
||||
if (model is null)
|
||||
{
|
||||
Trace.TraceError($"[{nameof(SkinModelImporter)}:Export] Model is null.");
|
||||
return;
|
||||
}
|
||||
string fileExtension = Path.GetExtension(fileName);
|
||||
if (_importProviders.ContainsKey(fileExtension) && _importProviders[fileExtension] is not null)
|
||||
_importProviders[fileExtension].Export(fileName, model);
|
||||
|
||||
Trace.TraceWarning($"[{nameof(SkinModelImporter)}:Export] No provider found for '{fileExtension}'.");
|
||||
}
|
||||
|
||||
internal static SkinModelInfo ImportPsm(string fileName)
|
||||
{
|
||||
var reader = new PSMFileReader();
|
||||
@@ -250,7 +166,7 @@ namespace PckStudio.Internal
|
||||
internal static void ExportBlockBenchModel(string fileName, SkinModelInfo modelInfo)
|
||||
{
|
||||
Image exportTexture = FixTexture(modelInfo);
|
||||
BlockBenchModel blockBenchModel = CreateBlockBenchModel(Path.GetFileNameWithoutExtension(fileName), new Size(64, exportTexture.Width == exportTexture.Height ? 64 : 32), [exportTexture]);
|
||||
BlockBenchModel blockBenchModel = BlockBenchModel.Create(Path.GetFileNameWithoutExtension(fileName), new Size(64, exportTexture.Width == exportTexture.Height ? 64 : 32), [exportTexture]);
|
||||
|
||||
Dictionary<string, Outline> outliners = new Dictionary<string, Outline>(5);
|
||||
List<Element> elements = new List<Element>(modelInfo.AdditionalBoxes.Count);
|
||||
@@ -290,69 +206,6 @@ namespace PckStudio.Internal
|
||||
File.WriteAllText(fileName, content);
|
||||
}
|
||||
|
||||
internal static void ExportBlockBenchModel(string fileName, Model model, IEnumerable<NamedTexture> textures)
|
||||
{
|
||||
BlockBenchModel blockBenchModel = CreateBlockBenchModel(Path.GetFileNameWithoutExtension(fileName), model.TextureSize, textures.Select(nt => (Texture)nt));
|
||||
|
||||
Dictionary<string, Outline> outliners = new Dictionary<string, Outline>(5);
|
||||
List<Element> elements = new List<Element>(model.Parts.Count);
|
||||
|
||||
Vector3 transformAxis = new Vector3(1, 1, 0);
|
||||
|
||||
Outline GetOrCreateOutline(string partName)
|
||||
{
|
||||
if (!outliners.ContainsKey(partName))
|
||||
outliners.Add(partName, new Outline(partName));
|
||||
return outliners[partName];
|
||||
}
|
||||
|
||||
foreach (ModelPart part in model.Parts.Values)
|
||||
{
|
||||
//Outline outline = GetOrCreateOutline(part.Name);
|
||||
|
||||
var outline = new Outline(part.Name);
|
||||
|
||||
Vector3 partTranslation = part.Translation;
|
||||
outline.Origin = TransformSpace(partTranslation, Vector3.Zero, transformAxis);
|
||||
outline.Origin += Vector3.UnitY * 24f;
|
||||
|
||||
Vector3 rotation = part.Rotation + part.AdditionalRotation;
|
||||
outline.Rotation = rotation * TransformSpace(Vector3.One, Vector3.Zero, transformAxis);
|
||||
|
||||
foreach (ModelBox box in part.Boxes)
|
||||
{
|
||||
Element element = CreateElement(box, partTranslation, part.Name);
|
||||
element.Origin = outline.Origin;
|
||||
elements.Add(element);
|
||||
outline.Children.Add(element.Uuid);
|
||||
}
|
||||
outliners.Add(part.Name, outline);
|
||||
}
|
||||
|
||||
blockBenchModel.Elements = elements.ToArray();
|
||||
blockBenchModel.Outliner = JArray.FromObject(outliners);
|
||||
|
||||
string content = JsonConvert.SerializeObject(blockBenchModel);
|
||||
File.WriteAllText(fileName, content);
|
||||
}
|
||||
|
||||
private static BlockBenchModel CreateBlockBenchModel(string name, Size textureResolution, IEnumerable<Texture> textures)
|
||||
{
|
||||
return new BlockBenchModel()
|
||||
{
|
||||
Name = name,
|
||||
Textures = textures.ToArray(),
|
||||
TextureResolution = textureResolution,
|
||||
ModelIdentifier = "",
|
||||
Metadata = new Meta()
|
||||
{
|
||||
FormatVersion = "4.5",
|
||||
ModelFormat = "free",
|
||||
UseBoxUv = true,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static Element CreateElement(SkinBOX box)
|
||||
{
|
||||
Vector3 transformPos = TranslateFromInternalPosistion(box, new Vector3(1, 1, 0));
|
||||
@@ -362,35 +215,9 @@ namespace PckStudio.Internal
|
||||
return element;
|
||||
}
|
||||
|
||||
private static Element CreateElement(ModelBox box, Vector3 origin, string name)
|
||||
{
|
||||
Vector3 pos = box.Position;
|
||||
Vector3 size = box.Size;
|
||||
Vector3 transformPos = TranslateToInternalPosition("", pos + origin, size, new Vector3(1, 1, 0));
|
||||
return CreateElement(name, box.Uv, transformPos, size, box.Scale, box.Mirror);
|
||||
}
|
||||
|
||||
private static Element CreateElement(Vector2 uvOffset, Vector3 pos, Vector3 size, float inflate, bool mirror)
|
||||
{
|
||||
return CreateElement("cube", uvOffset, pos, size, inflate, mirror);
|
||||
}
|
||||
|
||||
private static Element CreateElement(string name, Vector2 uvOffset, Vector3 pos, Vector3 size, float inflate, bool mirror)
|
||||
{
|
||||
return new Element
|
||||
{
|
||||
Name = name,
|
||||
UseBoxUv = true,
|
||||
Locked = false,
|
||||
Rescale = false,
|
||||
Type = "cube",
|
||||
Uuid = Guid.NewGuid(),
|
||||
UvOffset = uvOffset,
|
||||
MirrorUv = mirror,
|
||||
Inflate = inflate,
|
||||
From = pos,
|
||||
To = pos + size
|
||||
};
|
||||
return Element.CreateCube("cube", uvOffset, pos, size, inflate, mirror);
|
||||
}
|
||||
|
||||
internal static SkinModelInfo ImportBedrockJson(string fileName)
|
||||
@@ -698,7 +525,7 @@ namespace PckStudio.Internal
|
||||
return result;
|
||||
}
|
||||
|
||||
private static Vector3 GetOffset(string name, ref Dictionary<string, SkinPartOffset> offsetLookUp, IReadOnlyList<SkinPartOffset> partOffsets)
|
||||
private static Vector3 GetOffset(string name, ref Dictionary<string, SkinPartOffset> offsetLookUp, IEnumerable<SkinPartOffset> partOffsets)
|
||||
{
|
||||
if (offsetLookUp.ContainsKey(name))
|
||||
{
|
||||
@@ -737,30 +564,5 @@ namespace PckStudio.Internal
|
||||
{
|
||||
return TranslateToInternalPosition(skinBox.Type, skinBox.Pos, skinBox.Size, translationUnit);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Translates coordinate unit system into our coordinate system
|
||||
/// </summary>
|
||||
/// <param name="origin">Position/Origin of the Object(Cube).</param>
|
||||
/// <param name="size">The Size of the Object(Cube).</param>
|
||||
/// <param name="translationUnit">Describes what axises need translation.</param>
|
||||
/// <returns>The translated position</returns>
|
||||
private static Vector3 TransformSpace(Vector3 origin, Vector3 size, Vector3 translationUnit)
|
||||
{
|
||||
// The translation unit describes what axises need to be swapped
|
||||
// Example:
|
||||
// translation unit = (1, 0, 0) => This translation unit will ONLY swap the X axis
|
||||
translationUnit = Vector3.Clamp(translationUnit, Vector3.Zero, Vector3.One);
|
||||
// To better understand see:
|
||||
// https://sharplab.io/#v2:C4LgTgrgdgNAJiA1AHwAICYCMBYAUKgBgAJVMA6AOQgFsBTMASwGMBnAbj1QGYT0iBhIgG88RMb3SjxI3OLlEAbgEMwRBlAAOEYEQC8RKLQDuRAGq0mwAPZguACkwwijogQCUHWfLHLVtAB4aFsC0cHoGxmbBNvYAtC7xTpgeUt6+RGC0LOEAKmBKUCwAYjbU/FY2cOpKISx26lrAKV7epACcdpkszd5i7Z1ZevoBQZahPeIAvqlEM9wkmABsUZYxRHkFxaXlldW1duartmqa2m4zMr2KKhmD+ofWtmT8ADZK1Br1p8BODzFkAC16FZftEngB5QwTbxdIgAKn06E8V1hsXuYK4ZEhtGRvVQAHYiLEurixNNcJMgA
|
||||
Vector3 transformUnit = -((translationUnit * 2) - Vector3.One);
|
||||
|
||||
Vector3 pos = origin;
|
||||
// The next line essentialy does uses the fomular below just on all axis.
|
||||
// x = -(pos.x + size.x)
|
||||
pos *= transformUnit;
|
||||
pos -= size * translationUnit;
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -648,7 +648,7 @@ namespace PckStudio
|
||||
|
||||
if (openFileDialog.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
SkinModelImporter.ExportBlockBenchModel(openFileDialog.FileName, model, textures);
|
||||
GameModelImporter.Default.Export(openFileDialog.FileName, new GameModelInfo(model, textures));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,7 +151,7 @@
|
||||
</Compile>
|
||||
<Compile Include="Extensions\OpenTkMatrixExtensions.cs" />
|
||||
<Compile Include="Interfaces\IModelImportProvider.cs" />
|
||||
<Compile Include="Interfaces\ISkinModelImportProvider.cs" />
|
||||
<Compile Include="Internal\GameModelInfo.cs" />
|
||||
<Compile Include="Internal\IO\PSM\PSMFileReader.cs" />
|
||||
<Compile Include="Internal\IO\PSM\PSMFileWriter.cs" />
|
||||
<Compile Include="Internal\GameConstants.cs" />
|
||||
@@ -169,6 +169,8 @@
|
||||
<Compile Include="Internal\FileDialogFilter.cs" />
|
||||
<Compile Include="Internal\Deserializer\ImageDeserializer.cs" />
|
||||
<Compile Include="Internal\Misc\RichPresenceClient.cs" />
|
||||
<Compile Include="Internal\GameModelImporter.cs" />
|
||||
<Compile Include="Internal\ModelImporter.cs" />
|
||||
<Compile Include="Internal\SkinModelImporter.cs" />
|
||||
<Compile Include="Internal\ModelPartSpecifics.cs" />
|
||||
<Compile Include="Internal\Json\JsonModelMetaData.cs" />
|
||||
|
||||
Reference in New Issue
Block a user