Code commit

This commit is contained in:
RisaDev
2024-01-06 01:21:41 +03:00
parent a7d7297c59
commit a486dd2c96
90 changed files with 11576 additions and 0 deletions

View File

@@ -0,0 +1,288 @@
using CustomizePlus.Core.Data;
using CustomizePlus.Game.Events;
using CustomizePlus.Game.Services;
using CustomizePlus.Profiles.Data;
using CustomizePlus.Templates.Data;
using CustomizePlus.Templates.Events;
using OtterGui.Log;
using System;
using System.Collections.Generic;
using System.Numerics;
namespace CustomizePlus.Templates;
public class TemplateEditorManager : IDisposable
{
private readonly TemplateChanged _event;
private readonly GPoseStateChanged _gposeStateChanged;
private readonly Logger _logger;
private readonly GameObjectService _gameObjectService;
private readonly TemplateManager _templateManager;
/// <summary>
/// Reference to the original template which is currently being edited, should not be edited!
/// </summary>
private Template _currentlyEditedTemplateOriginal;
/// <summary>
/// Internal profile for the editor
/// </summary>
public Profile EditorProfile { get; private set; }
/// <summary>
/// Original ID of the template which is currently being edited
/// </summary>
public Guid CurrentlyEditedTemplateId { get; private set; }
/// <summary>
/// A copy of currently edited template, all changes must be done on this template
/// </summary>
public Template? CurrentlyEditedTemplate { get; private set; }
public bool IsEditorActive { get; private set; }
/// <summary>
/// Is editor currently paused? Happens automatically when editor is not compatible with the current game state.
/// Keeps editor state frozen and prevents any changes to it, also sets editor profile as disabled.
/// </summary>
public bool IsEditorPaused { get; private set; }
/// <summary>
/// Indicates if there are any changes in current editing session or not
/// </summary>
public bool HasChanges { get; private set; }
public bool IsKeepOnlyEditorProfileActive { get; set; } //todo
public TemplateEditorManager(
TemplateChanged @event,
GPoseStateChanged gposeStateChanged,
Logger logger,
TemplateManager templateManager,
GameObjectService gameObjectService)
{
_event = @event;
_gposeStateChanged = gposeStateChanged;
_logger = logger;
_templateManager = templateManager;
_gameObjectService = gameObjectService;
_gposeStateChanged.Subscribe(OnGPoseStateChanged, GPoseStateChanged.Priority.TemplateEditorManager);
EditorProfile = new Profile() { Templates = new List<Template>(), Enabled = false, Name = "Template editor profile" };
}
public void Dispose()
{
_gposeStateChanged.Unsubscribe(OnGPoseStateChanged);
}
/// <summary>
/// Turn on editing of a specific template. If character name not set will default to local player.
/// </summary>
internal bool EnableEditor(Template template, string? characterName = null) //todo: editor is borked
{
if (IsEditorActive || IsEditorPaused)
return false;
_logger.Debug($"Enabling editor profile for {template.Name} via character {characterName}");
CurrentlyEditedTemplateId = template.UniqueId;
_currentlyEditedTemplateOriginal = template;
CurrentlyEditedTemplate = new Template(template)
{
CreationDate = DateTimeOffset.UtcNow,
ModifiedDate = DateTimeOffset.UtcNow,
UniqueId = Guid.NewGuid(),
Name = "Template editor temporary template"
};
if (characterName != null)
EditorProfile.CharacterName = characterName;
else //safeguard
EditorProfile.CharacterName = _gameObjectService.GetCurrentPlayerName();
EditorProfile.Templates.Clear(); //safeguard
EditorProfile.Templates.Add(CurrentlyEditedTemplate);
EditorProfile.Enabled = true;
HasChanges = false;
IsEditorActive = true;
_event.Invoke(TemplateChanged.Type.EditorEnabled, template, characterName);
return true;
}
/// <summary>
/// Turn off editing of a specific template
/// </summary>
internal bool DisableEditor()
{
if (!IsEditorActive || IsEditorPaused)
return false;
_logger.Debug($"Disabling editor profile");
string characterName = EditorProfile.CharacterName;
CurrentlyEditedTemplateId = Guid.Empty;
CurrentlyEditedTemplate = null;
EditorProfile.Enabled = false;
EditorProfile.CharacterName = "";
EditorProfile.Templates.Clear();
IsEditorActive = false;
HasChanges = false;
_event.Invoke(TemplateChanged.Type.EditorDisabled, null, characterName);
return true;
}
public void SaveChanges(bool asCopy = false)
{
var targetTemplate = _templateManager.GetTemplate(CurrentlyEditedTemplateId);
if (targetTemplate == null)
throw new Exception($"Fatal editor error: Template with ID {CurrentlyEditedTemplateId} not found in template manager");
if (asCopy)
targetTemplate = _templateManager.Clone(targetTemplate, $"{targetTemplate.Name} - Copy {Guid.NewGuid().ToString().Substring(0, 4)}", false);
_templateManager.ApplyBoneChangesAndSave(targetTemplate, CurrentlyEditedTemplate!);
}
public bool ChangeEditorCharacter(string characterName)
{
if (!IsEditorActive || EditorProfile.CharacterName == characterName || IsEditorPaused)
return false;
_logger.Debug($"Changing character name for editor profile from {EditorProfile.CharacterName} to {characterName}");
EditorProfile.CharacterName = characterName;
_event.Invoke(TemplateChanged.Type.EditorCharacterChanged, CurrentlyEditedTemplate, (characterName, EditorProfile));
return true;
}
/// <summary>
/// Resets changes in currently edited template to default values
/// </summary>
public bool ResetBoneAttributeChanges(string boneName, BoneAttribute attribute)
{
if (!IsEditorActive || IsEditorPaused)
return false;
if (!CurrentlyEditedTemplate!.Bones.ContainsKey(boneName))
return false;
var resetValue = GetResetValueForAttribute(attribute);
switch (attribute)
{
case BoneAttribute.Position:
if (resetValue == CurrentlyEditedTemplate!.Bones[boneName].Translation)
return false;
break;
case BoneAttribute.Rotation:
if (resetValue == CurrentlyEditedTemplate!.Bones[boneName].Rotation)
return false;
break;
case BoneAttribute.Scale:
if (resetValue == CurrentlyEditedTemplate!.Bones[boneName].Scaling)
return false;
break;
}
CurrentlyEditedTemplate!.Bones[boneName].UpdateAttribute(attribute, resetValue);
if (!HasChanges)
HasChanges = true;
return true;
}
/// <summary>
/// Reverts changes in currently edited template to values set in saved copy of the template.
/// Resets to default value if saved copy doesn't have that bone edited
/// </summary>
public bool RevertBoneAttributeChanges(string boneName, BoneAttribute attribute)
{
if (!IsEditorActive || IsEditorPaused)
return false;
if (!CurrentlyEditedTemplate!.Bones.ContainsKey(boneName))
return false;
Vector3? originalValue = null!;
if (_currentlyEditedTemplateOriginal.Bones.ContainsKey(boneName))
{
switch (attribute)
{
case BoneAttribute.Position:
originalValue = _currentlyEditedTemplateOriginal.Bones[boneName].Translation;
if (originalValue == CurrentlyEditedTemplate!.Bones[boneName].Translation)
return false;
break;
case BoneAttribute.Rotation:
originalValue = _currentlyEditedTemplateOriginal.Bones[boneName].Rotation;
if (originalValue == CurrentlyEditedTemplate!.Bones[boneName].Rotation)
return false;
break;
case BoneAttribute.Scale:
originalValue = _currentlyEditedTemplateOriginal.Bones[boneName].Scaling;
if (originalValue == CurrentlyEditedTemplate!.Bones[boneName].Scaling)
return false;
break;
}
}
else
originalValue = GetResetValueForAttribute(attribute);
CurrentlyEditedTemplate!.Bones[boneName].UpdateAttribute(attribute, originalValue.Value);
if (!HasChanges)
HasChanges = true;
return true;
}
public bool ModifyBoneTransform(string boneName, BoneTransform transform)
{
if (!IsEditorActive || IsEditorPaused)
return false;
if (!_templateManager.ModifyBoneTransform(CurrentlyEditedTemplate!, boneName, transform))
return false;
if (!HasChanges)
HasChanges = true;
return true;
}
private Vector3 GetResetValueForAttribute(BoneAttribute attribute)
{
switch (attribute)
{
case BoneAttribute.Scale:
return Vector3.One;
default:
return Vector3.Zero;
}
}
private void OnGPoseStateChanged(GPoseStateChanged.Type type)
{
switch (type)
{
case GPoseStateChanged.Type.Entered:
IsEditorPaused = true;
EditorProfile.Enabled = false;
break;
case GPoseStateChanged.Type.Exited:
EditorProfile.Enabled = true;
IsEditorPaused = false;
break;
}
}
}