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)
136 lines
3.9 KiB
C#
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;
|
|
}
|
|
}
|