Files
CustomizeTool/CustomizePlus/Api/Data/IPCCharacterProfile.cs
RisaDev 2d40fff844 More work on profile character assignment rewrite.
Added ability to apply profile to any currently logged in character
Functional UI for player character, retainers and mannequins
Almost completely switched to using ActorIdentifier instead of character name
Migration code for ActorIdentifier instead of character names
IPC is not functional for now (see todos)
2024-10-07 01:11:20 +03:00

136 lines
3.9 KiB
C#

using CustomizePlus.Configuration.Data.Version3;
using CustomizePlus.Core.Data;
using CustomizePlus.GameData.Extensions;
using CustomizePlus.Profiles.Data;
using CustomizePlus.Templates.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;
namespace CustomizePlus.Api.Data;
/// <summary>
/// Bare essentials version of character profile
/// </summary>
public class IPCCharacterProfile
{
public string CharacterName { get; set; } = "Invalid";
public Dictionary<string, IPCBoneTransform> Bones { get; init; } = new();
public static IPCCharacterProfile FromFullProfile(Profile profile)
{
var ipcProfile = new IPCCharacterProfile
{
CharacterName = profile.Character.ToNameWithoutOwnerName(), //todo: proper update to v5
Bones = new Dictionary<string, IPCBoneTransform>()
};
foreach (var template in profile.Templates)
{
foreach (var kvPair in template.Bones) //not super optimal but whatever
{
ipcProfile.Bones[kvPair.Key] = new IPCBoneTransform
{
Translation = kvPair.Value.Translation,
Rotation = kvPair.Value.Rotation,
Scaling = kvPair.Value.Scaling
};
}
}
return ipcProfile;
}
public static (Profile, Template) ToFullProfile(IPCCharacterProfile profile, bool isTemporary = true)
{
var fullProfile = new Profile
{
Name = $"{profile.CharacterName}'s IPC profile",
// CharacterName = profile.CharacterName, //todo: proper update to v5
CreationDate = DateTimeOffset.UtcNow,
ModifiedDate = DateTimeOffset.UtcNow,
Enabled = true,
LimitLookupToOwnedObjects = false,
UniqueId = Guid.NewGuid(),
Templates = new List<Template>(1),
ProfileType = isTemporary ? Profiles.Enums.ProfileType.Temporary : Profiles.Enums.ProfileType.Normal
};
var template = new Template
{
Name = $"{fullProfile.Name}'s template",
CreationDate = fullProfile.CreationDate,
ModifiedDate = fullProfile.ModifiedDate,
UniqueId = Guid.NewGuid(),
Bones = new Dictionary<string, BoneTransform>(profile.Bones.Count)
};
foreach (var kvPair in profile.Bones)
template.Bones.Add(kvPair.Key,
new BoneTransform { Translation = kvPair.Value.Translation, Rotation = kvPair.Value.Rotation, Scaling = kvPair.Value.Scaling });
fullProfile.Templates.Add(template);
return (fullProfile, template);
}
}
public class IPCBoneTransform
{
private Vector3 _translation;
public Vector3 Translation
{
get => _translation;
set => _translation = ClampVector(value);
}
private Vector3 _rotation;
public Vector3 Rotation
{
get => _rotation;
set => _rotation = ClampAngles(value);
}
private Vector3 _scaling;
public Vector3 Scaling
{
get => _scaling;
set => _scaling = ClampVector(value);
}
/// <summary>
/// Clamp all vector values to be within allowed limits.
/// </summary>
private Vector3 ClampVector(Vector3 vector)
{
return new Vector3
{
X = Math.Clamp(vector.X, -512, 512),
Y = Math.Clamp(vector.Y, -512, 512),
Z = Math.Clamp(vector.Z, -512, 512)
};
}
private static Vector3 ClampAngles(Vector3 rotVec)
{
static float Clamp(float angle)
{
if (angle > 180)
angle -= 360;
else if (angle < -180)
angle += 360;
return angle;
}
rotVec.X = Clamp(rotVec.X);
rotVec.Y = Clamp(rotVec.Y);
rotVec.Z = Clamp(rotVec.Z);
return rotVec;
}
}