mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2025-12-15 05:04:16 +01:00
Rework debug tab.
This commit is contained in:
parent
a04b7cd1db
commit
4b92eae723
31 changed files with 2450 additions and 1790 deletions
286
Glamourer/Gui/Tabs/DebugTab/ModelEvaluationPanel.cs
Normal file
286
Glamourer/Gui/Tabs/DebugTab/ModelEvaluationPanel.cs
Normal file
|
|
@ -0,0 +1,286 @@
|
|||
using System;
|
||||
using System.Numerics;
|
||||
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
||||
using Glamourer.Customization;
|
||||
using Glamourer.Interop;
|
||||
using Glamourer.Interop.Structs;
|
||||
using Glamourer.Structs;
|
||||
using ImGuiNET;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
|
||||
namespace Glamourer.Gui.Tabs.DebugTab;
|
||||
|
||||
public unsafe class ModelEvaluationPanel(
|
||||
ObjectManager _objectManager,
|
||||
VisorService _visorService,
|
||||
UpdateSlotService _updateSlotService,
|
||||
ChangeCustomizeService _changeCustomizeService,
|
||||
CrestService _crestService) : IDebugTabTree
|
||||
{
|
||||
public string Label
|
||||
=> "Model Evaluation";
|
||||
|
||||
public bool Disabled
|
||||
=> false;
|
||||
|
||||
private int _gameObjectIndex;
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
ImGui.InputInt("Game Object Index", ref _gameObjectIndex, 0, 0);
|
||||
var actor = (Actor)_objectManager.Objects.GetObjectAddress(_gameObjectIndex);
|
||||
var model = actor.Model;
|
||||
using var table = ImRaii.Table("##evaluationTable", 4, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.RowBg);
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.TableHeader("Actor");
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.TableHeader("Model");
|
||||
ImGui.TableNextColumn();
|
||||
|
||||
ImGuiUtil.DrawTableColumn("Address");
|
||||
ImGui.TableNextColumn();
|
||||
ImGuiUtil.CopyOnClickSelectable(actor.ToString());
|
||||
ImGui.TableNextColumn();
|
||||
ImGuiUtil.CopyOnClickSelectable(model.ToString());
|
||||
ImGui.TableNextColumn();
|
||||
if (actor.IsCharacter)
|
||||
{
|
||||
ImGui.TextUnformatted(actor.AsCharacter->CharacterData.ModelCharaId.ToString());
|
||||
if (actor.AsCharacter->CharacterData.TransformationId != 0)
|
||||
ImGui.TextUnformatted($"Transformation Id: {actor.AsCharacter->CharacterData.TransformationId}");
|
||||
if (actor.AsCharacter->CharacterData.ModelCharaId_2 != -1)
|
||||
ImGui.TextUnformatted($"ModelChara2 {actor.AsCharacter->CharacterData.ModelCharaId_2}");
|
||||
if (actor.AsCharacter->CharacterData.StatusEffectVFXId != 0)
|
||||
ImGui.TextUnformatted($"Status Id: {actor.AsCharacter->CharacterData.StatusEffectVFXId}");
|
||||
}
|
||||
|
||||
ImGuiUtil.DrawTableColumn("Mainhand");
|
||||
ImGuiUtil.DrawTableColumn(actor.IsCharacter ? actor.GetMainhand().ToString() : "No Character");
|
||||
|
||||
var (mainhand, offhand, mainModel, offModel) = model.GetWeapons(actor);
|
||||
ImGuiUtil.DrawTableColumn(mainModel.ToString());
|
||||
ImGui.TableNextColumn();
|
||||
ImGuiUtil.CopyOnClickSelectable(mainhand.ToString());
|
||||
|
||||
ImGuiUtil.DrawTableColumn("Offhand");
|
||||
ImGuiUtil.DrawTableColumn(actor.IsCharacter ? actor.GetOffhand().ToString() : "No Character");
|
||||
ImGuiUtil.DrawTableColumn(offModel.ToString());
|
||||
ImGui.TableNextColumn();
|
||||
ImGuiUtil.CopyOnClickSelectable(offhand.ToString());
|
||||
|
||||
DrawVisor(actor, model);
|
||||
DrawHatState(actor, model);
|
||||
DrawWeaponState(actor, model);
|
||||
DrawWetness(actor, model);
|
||||
DrawEquip(actor, model);
|
||||
DrawCustomize(actor, model);
|
||||
DrawCrests(actor, model);
|
||||
}
|
||||
|
||||
private void DrawVisor(Actor actor, Model model)
|
||||
{
|
||||
using var id = ImRaii.PushId("Visor");
|
||||
ImGuiUtil.DrawTableColumn("Visor State");
|
||||
ImGuiUtil.DrawTableColumn(actor.IsCharacter ? actor.AsCharacter->DrawData.IsVisorToggled.ToString() : "No Character");
|
||||
ImGuiUtil.DrawTableColumn(model.IsHuman ? VisorService.GetVisorState(model).ToString() : "No Human");
|
||||
ImGui.TableNextColumn();
|
||||
if (!model.IsHuman)
|
||||
return;
|
||||
|
||||
if (ImGui.SmallButton("Set True"))
|
||||
_visorService.SetVisorState(model, true);
|
||||
ImGui.SameLine();
|
||||
if (ImGui.SmallButton("Set False"))
|
||||
_visorService.SetVisorState(model, false);
|
||||
ImGui.SameLine();
|
||||
if (ImGui.SmallButton("Toggle"))
|
||||
_visorService.SetVisorState(model, !VisorService.GetVisorState(model));
|
||||
}
|
||||
|
||||
private void DrawHatState(Actor actor, Model model)
|
||||
{
|
||||
using var id = ImRaii.PushId("HatState");
|
||||
ImGuiUtil.DrawTableColumn("Hat State");
|
||||
ImGuiUtil.DrawTableColumn(actor.IsCharacter
|
||||
? actor.AsCharacter->DrawData.IsHatHidden ? "Hidden" : actor.GetArmor(EquipSlot.Head).ToString()
|
||||
: "No Character");
|
||||
ImGuiUtil.DrawTableColumn(model.IsHuman
|
||||
? model.AsHuman->Head.Value == 0 ? "No Hat" : model.GetArmor(EquipSlot.Head).ToString()
|
||||
: "No Human");
|
||||
ImGui.TableNextColumn();
|
||||
if (!model.IsHuman)
|
||||
return;
|
||||
|
||||
if (ImGui.SmallButton("Hide"))
|
||||
_updateSlotService.UpdateSlot(model, EquipSlot.Head, CharacterArmor.Empty);
|
||||
ImGui.SameLine();
|
||||
if (ImGui.SmallButton("Show"))
|
||||
_updateSlotService.UpdateSlot(model, EquipSlot.Head, actor.GetArmor(EquipSlot.Head));
|
||||
ImGui.SameLine();
|
||||
if (ImGui.SmallButton("Toggle"))
|
||||
_updateSlotService.UpdateSlot(model, EquipSlot.Head,
|
||||
model.AsHuman->Head.Value == 0 ? actor.GetArmor(EquipSlot.Head) : CharacterArmor.Empty);
|
||||
}
|
||||
|
||||
private void DrawWeaponState(Actor actor, Model model)
|
||||
{
|
||||
using var id = ImRaii.PushId("WeaponState");
|
||||
ImGuiUtil.DrawTableColumn("Weapon State");
|
||||
ImGuiUtil.DrawTableColumn(actor.IsCharacter
|
||||
? actor.AsCharacter->DrawData.IsWeaponHidden ? "Hidden" : "Visible"
|
||||
: "No Character");
|
||||
var text = string.Empty;
|
||||
|
||||
if (!model.IsHuman)
|
||||
{
|
||||
text = "No Model";
|
||||
}
|
||||
else if (model.AsDrawObject->Object.ChildObject == null)
|
||||
{
|
||||
text = "No Weapon";
|
||||
}
|
||||
else
|
||||
{
|
||||
var weapon = (DrawObject*)model.AsDrawObject->Object.ChildObject;
|
||||
if ((weapon->Flags & 0x09) == 0x09)
|
||||
text = "Visible";
|
||||
else
|
||||
text = "Hidden";
|
||||
}
|
||||
|
||||
ImGuiUtil.DrawTableColumn(text);
|
||||
ImGui.TableNextColumn();
|
||||
if (!model.IsHuman)
|
||||
return;
|
||||
}
|
||||
|
||||
private void DrawWetness(Actor actor, Model model)
|
||||
{
|
||||
using var id = ImRaii.PushId("Wetness");
|
||||
ImGuiUtil.DrawTableColumn("Wetness");
|
||||
ImGuiUtil.DrawTableColumn(actor.IsCharacter ? actor.AsCharacter->IsGPoseWet ? "GPose" : "None" : "No Character");
|
||||
var modelString = model.IsCharacterBase
|
||||
? $"{model.AsCharacterBase->SwimmingWetness:F4} Swimming\n"
|
||||
+ $"{model.AsCharacterBase->WeatherWetness:F4} Weather\n"
|
||||
+ $"{model.AsCharacterBase->ForcedWetness:F4} Forced\n"
|
||||
+ $"{model.AsCharacterBase->WetnessDepth:F4} Depth\n"
|
||||
: "No CharacterBase";
|
||||
ImGuiUtil.DrawTableColumn(modelString);
|
||||
ImGui.TableNextColumn();
|
||||
if (!actor.IsCharacter)
|
||||
return;
|
||||
|
||||
if (ImGui.SmallButton("GPose On"))
|
||||
actor.AsCharacter->IsGPoseWet = true;
|
||||
ImGui.SameLine();
|
||||
if (ImGui.SmallButton("GPose Off"))
|
||||
actor.AsCharacter->IsGPoseWet = false;
|
||||
ImGui.SameLine();
|
||||
if (ImGui.SmallButton("GPose Toggle"))
|
||||
actor.AsCharacter->IsGPoseWet = !actor.AsCharacter->IsGPoseWet;
|
||||
}
|
||||
|
||||
private void DrawEquip(Actor actor, Model model)
|
||||
{
|
||||
using var id = ImRaii.PushId("Equipment");
|
||||
foreach (var slot in EquipSlotExtensions.EqdpSlots)
|
||||
{
|
||||
using var id2 = ImRaii.PushId((int)slot);
|
||||
ImGuiUtil.DrawTableColumn(slot.ToName());
|
||||
ImGuiUtil.DrawTableColumn(actor.IsCharacter ? actor.GetArmor(slot).ToString() : "No Character");
|
||||
ImGuiUtil.DrawTableColumn(model.IsHuman ? model.GetArmor(slot).ToString() : "No Human");
|
||||
ImGui.TableNextColumn();
|
||||
if (!model.IsHuman)
|
||||
continue;
|
||||
|
||||
if (ImGui.SmallButton("Change Piece"))
|
||||
_updateSlotService.UpdateArmor(model, slot,
|
||||
new CharacterArmor((SetId)(slot == EquipSlot.Hands ? 6064 : slot == EquipSlot.Head ? 6072 : 1), 1, 0));
|
||||
ImGui.SameLine();
|
||||
if (ImGui.SmallButton("Change Stain"))
|
||||
_updateSlotService.UpdateStain(model, slot, 5);
|
||||
ImGui.SameLine();
|
||||
if (ImGui.SmallButton("Reset"))
|
||||
_updateSlotService.UpdateSlot(model, slot, actor.GetArmor(slot));
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawCustomize(Actor actor, Model model)
|
||||
{
|
||||
using var id = ImRaii.PushId("Customize");
|
||||
var actorCustomize = new Customize(actor.IsCharacter
|
||||
? *(Penumbra.GameData.Structs.CustomizeData*)&actor.AsCharacter->DrawData.CustomizeData
|
||||
: new Penumbra.GameData.Structs.CustomizeData());
|
||||
var modelCustomize = new Customize(model.IsHuman
|
||||
? *(Penumbra.GameData.Structs.CustomizeData*)model.AsHuman->Customize.Data
|
||||
: new Penumbra.GameData.Structs.CustomizeData());
|
||||
foreach (var type in Enum.GetValues<CustomizeIndex>())
|
||||
{
|
||||
using var id2 = ImRaii.PushId((int)type);
|
||||
ImGuiUtil.DrawTableColumn(type.ToDefaultName());
|
||||
ImGuiUtil.DrawTableColumn(actor.IsCharacter ? actorCustomize[type].Value.ToString("X2") : "No Character");
|
||||
ImGuiUtil.DrawTableColumn(model.IsHuman ? modelCustomize[type].Value.ToString("X2") : "No Human");
|
||||
ImGui.TableNextColumn();
|
||||
if (!model.IsHuman || type.ToFlag().RequiresRedraw())
|
||||
continue;
|
||||
|
||||
if (ImGui.SmallButton("++"))
|
||||
{
|
||||
var value = modelCustomize[type].Value;
|
||||
var (_, mask) = type.ToByteAndMask();
|
||||
var shift = BitOperations.TrailingZeroCount(mask);
|
||||
var newValue = value + (1 << shift);
|
||||
modelCustomize.Set(type, (CustomizeValue)newValue);
|
||||
_changeCustomizeService.UpdateCustomize(model, modelCustomize.Data);
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
if (ImGui.SmallButton("--"))
|
||||
{
|
||||
var value = modelCustomize[type].Value;
|
||||
var (_, mask) = type.ToByteAndMask();
|
||||
var shift = BitOperations.TrailingZeroCount(mask);
|
||||
var newValue = value - (1 << shift);
|
||||
modelCustomize.Set(type, (CustomizeValue)newValue);
|
||||
_changeCustomizeService.UpdateCustomize(model, modelCustomize.Data);
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
if (ImGui.SmallButton("Reset"))
|
||||
{
|
||||
modelCustomize.Set(type, actorCustomize[type]);
|
||||
_changeCustomizeService.UpdateCustomize(model, modelCustomize.Data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawCrests(Actor actor, Model model)
|
||||
{
|
||||
using var id = ImRaii.PushId("Crests");
|
||||
CrestFlag whichToggle = 0;
|
||||
CrestFlag totalModelFlags = 0;
|
||||
foreach (var crestFlag in CrestExtensions.AllRelevantSet)
|
||||
{
|
||||
id.Push((int)crestFlag);
|
||||
var modelCrest = CrestService.GetModelCrest(actor, crestFlag);
|
||||
if (modelCrest)
|
||||
totalModelFlags |= crestFlag;
|
||||
ImGuiUtil.DrawTableColumn($"{crestFlag.ToLabel()} Crest");
|
||||
ImGuiUtil.DrawTableColumn(actor.IsCharacter ? actor.GetCrest(crestFlag).ToString() : "No Character");
|
||||
ImGuiUtil.DrawTableColumn(modelCrest.ToString());
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
if (model.IsHuman && ImGui.SmallButton("Toggle"))
|
||||
whichToggle = crestFlag;
|
||||
|
||||
id.Pop();
|
||||
}
|
||||
|
||||
if (whichToggle != 0)
|
||||
_crestService.UpdateCrests(actor, totalModelFlags ^ whichToggle);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue