Add using game base state as base for fixed design sets.

This commit is contained in:
Ottermandias 2023-07-19 16:43:54 +02:00
parent 8f9beed6f8
commit c909510edc
11 changed files with 69 additions and 18 deletions

View file

@ -1,6 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Game.ClientState.Objects.Types;
using Dalamud.Plugin; using Dalamud.Plugin;
using Glamourer.Events;
using Penumbra.Api.Helpers; using Penumbra.Api.Helpers;
using Penumbra.GameData.Actors; using Penumbra.GameData.Actors;
@ -31,9 +32,7 @@ public partial class GlamourerIpc
foreach (var id in actors) foreach (var id in actors)
{ {
if (_stateManager.TryGetValue(id, out var state)) if (_stateManager.TryGetValue(id, out var state))
{ _stateManager.ResetState(state, StateChanged.Source.Ipc, 0xDEADBEEF);
_stateManager.ResetState(state, 0xDEADBEEF);
}
} }
} }
} }

View file

@ -116,11 +116,12 @@ public class AutoDesignApplier : IDisposable
break; break;
case AutomationChanged.Type.ChangeIdentifier when set.Enabled: case AutomationChanged.Type.ChangeIdentifier when set.Enabled:
// Remove fixed state from the old identifiers assigned and the old enabled set, if any. // Remove fixed state from the old identifiers assigned and the old enabled set, if any.
var (oldIds, _, oldSet) = ((ActorIdentifier[], ActorIdentifier, AutoDesignSet?)) bonusData!; var (oldIds, _, oldSet) = ((ActorIdentifier[], ActorIdentifier, AutoDesignSet?))bonusData!;
RemoveOld(oldIds); RemoveOld(oldIds);
ApplyNew(set); // Does not need to disable oldSet because same identifiers. ApplyNew(set); // Does not need to disable oldSet because same identifiers.
break; break;
case AutomationChanged.Type.ToggleSet: // Does not need to disable old states because same identifiers. case AutomationChanged.Type.ToggleSet: // Does not need to disable old states because same identifiers.
case AutomationChanged.Type.ChangedBase:
case AutomationChanged.Type.AddedDesign: case AutomationChanged.Type.AddedDesign:
case AutomationChanged.Type.MovedDesign: case AutomationChanged.Type.MovedDesign:
case AutomationChanged.Type.ChangedDesign: case AutomationChanged.Type.ChangedDesign:
@ -193,7 +194,9 @@ public class AutoDesignApplier : IDisposable
EquipFlag totalEquipFlags = 0; EquipFlag totalEquipFlags = 0;
CustomizeFlag totalCustomizeFlags = 0; CustomizeFlag totalCustomizeFlags = 0;
byte totalMetaFlags = 0; byte totalMetaFlags = 0;
if (!respectManual) if (set.BaseState == AutoDesignSet.Base.Game)
_state.ResetState(state, StateChanged.Source.Fixed);
else if (!respectManual)
state.RemoveFixedDesignSources(); state.RemoveFixedDesignSources();
foreach (var design in set.Designs) foreach (var design in set.Designs)
{ {

View file

@ -209,6 +209,22 @@ public class AutoDesignManager : ISavable, IReadOnlyList<AutoDesignSet>
_event.Invoke(AutomationChanged.Type.ToggleSet, set, oldEnabled); _event.Invoke(AutomationChanged.Type.ToggleSet, set, oldEnabled);
} }
public void ChangeBaseState(int whichSet, AutoDesignSet.Base newBase)
{
if (whichSet >= _data.Count || whichSet < 0)
return;
var set = _data[whichSet];
if (newBase == set.BaseState)
return;
var old = set.BaseState;
set.BaseState = newBase;
Save();
Glamourer.Log.Debug($"Changed base state of set {whichSet + 1} from {old} to {newBase}.");
_event.Invoke(AutomationChanged.Type.ChangedBase, set, (old, newBase));
}
public void AddDesign(AutoDesignSet set, Design design) public void AddDesign(AutoDesignSet set, Design design)
{ {
var newDesign = new AutoDesign() var newDesign = new AutoDesign()
@ -375,6 +391,7 @@ public class AutoDesignManager : ISavable, IReadOnlyList<AutoDesignSet>
var set = new AutoDesignSet(name, id) var set = new AutoDesignSet(name, id)
{ {
Enabled = obj["Enabled"]?.ToObject<bool>() ?? false, Enabled = obj["Enabled"]?.ToObject<bool>() ?? false,
BaseState = obj["BaseState"]?.ToObject<AutoDesignSet.Base>() ?? AutoDesignSet.Base.Current,
}; };
if (set.Enabled) if (set.Enabled)

View file

@ -1,4 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection.Metadata.Ecma335;
using Glamourer.Designs;
using Glamourer.State;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using Penumbra.GameData.Actors; using Penumbra.GameData.Actors;
@ -11,6 +14,7 @@ public class AutoDesignSet
public string Name; public string Name;
public ActorIdentifier[] Identifiers; public ActorIdentifier[] Identifiers;
public bool Enabled; public bool Enabled;
public Base BaseState = Base.Current;
public JObject Serialize() public JObject Serialize()
{ {
@ -23,6 +27,7 @@ public class AutoDesignSet
["Name"] = Name, ["Name"] = Name,
["Identifier"] = Identifiers[0].ToJson(), ["Identifier"] = Identifiers[0].ToJson(),
["Enabled"] = Enabled, ["Enabled"] = Enabled,
["BaseState"] = BaseState.ToString(),
["Designs"] = list, ["Designs"] = list,
}; };
} }
@ -37,4 +42,10 @@ public class AutoDesignSet
Identifiers = identifiers; Identifiers = identifiers;
Designs = designs; Designs = designs;
} }
public enum Base : byte
{
Current,
Game,
}
} }

View file

@ -35,6 +35,9 @@ public sealed class AutomationChanged : EventWrapper<Action<AutomationChanged.Ty
/// <summary> Toggle the enabled state of a given set. Additional data is the thus disabled other set, if any [AutoDesignSet?]. </summary> /// <summary> Toggle the enabled state of a given set. Additional data is the thus disabled other set, if any [AutoDesignSet?]. </summary>
ToggleSet, ToggleSet,
/// <summary> Change the used base state of a given set. Additional data is prior and new base. [(AutoDesignSet.Base, AutoDesignSet.Base)]. </summary>
ChangedBase,
/// <summary> Add a new associated design to a given set. Additional data is the index it got added at [int]. </summary> /// <summary> Add a new associated design to a given set. Additional data is the index it got added at [int]. </summary>
AddedDesign, AddedDesign,

View file

@ -344,7 +344,7 @@ public class ActorPanel
{ {
if (ImGuiUtil.DrawDisabledButton("Revert to Game", Vector2.Zero, "Revert the character to its actual state in the game.", if (ImGuiUtil.DrawDisabledButton("Revert to Game", Vector2.Zero, "Revert the character to its actual state in the game.",
_state!.IsLocked)) _state!.IsLocked))
_stateManager.ResetState(_state!); _stateManager.ResetState(_state!, StateChanged.Source.Manual);
ImGui.SameLine(); ImGui.SameLine();
if (ImGuiUtil.DrawDisabledButton("Reapply State", Vector2.Zero, "Try to reapply the configured state if something went wrong.", if (ImGuiUtil.DrawDisabledButton("Reapply State", Vector2.Zero, "Try to reapply the configured state if something went wrong.",

View file

@ -73,8 +73,17 @@ public class SetPanel
if (!child || !_selector.HasSelection) if (!child || !_selector.HasSelection)
return; return;
var enabled = Selection.Enabled;
if (ImGui.Checkbox("Enabled", ref enabled))
_manager.SetState(_selector.SelectionIndex, enabled);
var useGame = _selector.Selection!.BaseState is AutoDesignSet.Base.Game;
if (ImGui.Checkbox("Use Game State as Base", ref useGame))
_manager.ChangeBaseState(_selector.SelectionIndex, useGame ? AutoDesignSet.Base.Game : AutoDesignSet.Base.Current);
var name = _tempName ?? Selection.Name; var name = _tempName ?? Selection.Name;
var flags = _selector.IncognitoMode ? ImGuiInputTextFlags.ReadOnly | ImGuiInputTextFlags.Password : ImGuiInputTextFlags.None; var flags = _selector.IncognitoMode ? ImGuiInputTextFlags.ReadOnly | ImGuiInputTextFlags.Password : ImGuiInputTextFlags.None;
ImGui.SetNextItemWidth(220 * ImGuiHelpers.GlobalScale);
if (ImGui.InputText("##Name", ref name, 128, flags)) if (ImGui.InputText("##Name", ref name, 128, flags))
_tempName = name; _tempName = name;
@ -84,11 +93,6 @@ public class SetPanel
_tempName = null; _tempName = null;
} }
ImGui.SameLine();
var enabled = Selection.Enabled;
if (ImGui.Checkbox("Enabled", ref enabled))
_manager.SetState(_selector.SelectionIndex, enabled);
ImGui.Separator(); ImGui.Separator();
DrawIdentifierSelection(_selector.SelectionIndex); DrawIdentifierSelection(_selector.SelectionIndex);

View file

@ -1083,7 +1083,7 @@ public unsafe class DebugTab : ITab
ImGuiUtil.DrawTableColumn(state.Identifier.ToString()); ImGuiUtil.DrawTableColumn(state.Identifier.ToString());
ImGui.TableNextColumn(); ImGui.TableNextColumn();
if (ImGui.Button("Reset")) if (ImGui.Button("Reset"))
_state.ResetState(state); _state.ResetState(state, StateChanged.Source.Manual);
ImGui.TableNextRow(); ImGui.TableNextRow();

View file

@ -150,7 +150,7 @@ public class CommandService : IDisposable
return false; return false;
if (_stateManager.TryGetValue(identifier, out var state)) if (_stateManager.TryGetValue(identifier, out var state))
_stateManager.ResetState(state); _stateManager.ResetState(state, StateChanged.Source.Manual);
return true; return true;
} }

View file

@ -50,7 +50,11 @@ public class StateApplier
{ {
var data = GetData(state); var data = GetData(state);
if (apply) if (apply)
{
state.TempLock();
ForceRedraw(data); ForceRedraw(data);
}
return data; return data;
} }
@ -58,7 +62,7 @@ public class StateApplier
/// Change the customization values of actors either by applying them via update or redrawing, /// Change the customization values of actors either by applying them via update or redrawing,
/// this depends on whether the changes include changes to Race, Gender, Body Type or Face. /// this depends on whether the changes include changes to Race, Gender, Body Type or Face.
/// </summary> /// </summary>
public void ChangeCustomize(ActorData data, in Customize customize) public void ChangeCustomize(ActorData data, in Customize customize, ActorState? state = null)
{ {
foreach (var actor in data.Objects) foreach (var actor in data.Objects)
{ {
@ -68,9 +72,14 @@ public class StateApplier
var flags = Customize.Compare(mdl.GetCustomize(), customize); var flags = Customize.Compare(mdl.GetCustomize(), customize);
if (!flags.RequiresRedraw() || !mdl.IsHuman) if (!flags.RequiresRedraw() || !mdl.IsHuman)
{
_changeCustomize.UpdateCustomize(mdl, customize.Data); _changeCustomize.UpdateCustomize(mdl, customize.Data);
}
else else
{
state?.TempLock();
_penumbra.RedrawObject(actor, RedrawType.Redraw); _penumbra.RedrawObject(actor, RedrawType.Redraw);
}
} }
} }
@ -79,7 +88,8 @@ public class StateApplier
{ {
var data = GetData(state); var data = GetData(state);
if (apply) if (apply)
ChangeCustomize(data, state.ModelData.Customize); ChangeCustomize(data, state.ModelData.Customize, state);
return data; return data;
} }
@ -111,6 +121,7 @@ public class StateApplier
var data = GetData(state); var data = GetData(state);
if (apply) if (apply)
ChangeArmor(data, slot, state.ModelData.Armor(slot), state.ModelData.IsHatVisible()); ChangeArmor(data, slot, state.ModelData.Armor(slot), state.ModelData.IsHatVisible());
return data; return data;
} }
@ -145,6 +156,7 @@ public class StateApplier
var data = GetData(state); var data = GetData(state);
if (apply) if (apply)
ChangeStain(data, slot, state.ModelData.Stain(slot)); ChangeStain(data, slot, state.ModelData.Stain(slot));
return data; return data;
} }
@ -164,6 +176,7 @@ public class StateApplier
var data = GetData(state); var data = GetData(state);
if (apply) if (apply)
ChangeWeapon(data, slot, state.ModelData.Item(slot), state.ModelData.Stain(slot)); ChangeWeapon(data, slot, state.ModelData.Item(slot), state.ModelData.Stain(slot));
return data; return data;
} }
@ -183,6 +196,7 @@ public class StateApplier
var data = GetData(state); var data = GetData(state);
if (apply) if (apply)
ChangeMainhand(data, state.ModelData.Item(EquipSlot.MainHand), state.ModelData.Stain(EquipSlot.MainHand)); ChangeMainhand(data, state.ModelData.Item(EquipSlot.MainHand), state.ModelData.Stain(EquipSlot.MainHand));
return data; return data;
} }

View file

@ -399,7 +399,7 @@ public class StateManager : IReadOnlyDictionary<ActorIdentifier, ActorState>
return actors; return actors;
} }
public void ResetState(ActorState state, uint key = 0) public void ResetState(ActorState state, StateChanged.Source source, uint key = 0)
{ {
if (!state.Unlock(key)) if (!state.Unlock(key))
return; return;
@ -419,10 +419,10 @@ public class StateManager : IReadOnlyDictionary<ActorIdentifier, ActorState>
foreach (var type in Enum.GetValues<ActorState.MetaIndex>()) foreach (var type in Enum.GetValues<ActorState.MetaIndex>())
state[type] = StateChanged.Source.Game; state[type] = StateChanged.Source.Game;
var actors = ApplyAll(state, redraw); var actors = source is StateChanged.Source.Manual or StateChanged.Source.Ipc ? ApplyAll(state, redraw) : ActorData.Invalid;
Glamourer.Log.Verbose( Glamourer.Log.Verbose(
$"Reset entire state of {state.Identifier.Incognito(null)} to game base. [Affecting {actors.ToLazyString("nothing")}.]"); $"Reset entire state of {state.Identifier.Incognito(null)} to game base. [Affecting {actors.ToLazyString("nothing")}.]");
_event.Invoke(StateChanged.Type.Design, state[ActorState.MetaIndex.Wetness], state, actors, null); _event.Invoke(StateChanged.Type.Design, StateChanged.Source.Manual, state, actors, null);
} }
public void ReapplyState(Actor actor) public void ReapplyState(Actor actor)