using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.Scripting;
namespace NecromancerTome
{
///
/// necrobones - разведка к жестам (BACKLOG «Заклинания с руки и жесты», 1.6.0). Свой хват -
/// это неподвижная поза рук от первого лица, как у браслета (кулак к противнику, без движения
/// при действии): кости рига ставятся в нужную комбинацию после аниматора. Сначала надо знать
/// кости: команда пишет в лог дерево рига рук от первого лица (EModelSDCS.baseRigFP, его создаёт
/// SDCSUtils.CreateVizFP под Camera/UFPSRoot) с локальными поворотами и позициями, и параметры
/// аниматора FPPlayerController (WeaponHoldType и прочие) с текущими значениями.
///
[Preserve]
public class ConsoleCmdNecroBones : ConsoleCmdAbstract
{
const string Tag = "[NecromancerTome] necrobones: ";
public override string[] getCommands() => new[] { "necrobones" };
public override string getDescription() => "NecromancerTome: дерево костей рук от первого лица и параметры аниматора - в лог";
public override void Execute(List _params, CommandSenderInfo _senderInfo)
{
EntityPlayerLocal player = GameManager.Instance.World?.GetPrimaryPlayer();
if (player == null)
{
return;
}
if (!(player.emodel is EModelSDCS sdcs) || sdcs.baseRigFP == null)
{
SdtdConsole.Instance.Output("риг рук от первого лица не найден (EModelSDCS.baseRigFP)");
return;
}
Transform root = sdcs.baseRigFP.transform;
ItemClass held = player.inventory?.holdingItem;
Debug.Log(Tag + "в руке " + (held != null ? held.GetItemName() + ", HoldType " + held.HoldType.Value : "ничего") + ", вид от первого лица " + sdcs.IsFPV);
Debug.Log(Tag + "путь рига: " + PathOf(root));
int count = 0;
var sb = new StringBuilder();
Dump(root, 0, sb, ref count);
foreach (string line in sb.ToString().Split('\n'))
{
if (line.Length > 0)
{
Debug.Log(Tag + line);
}
}
Animator anim = root.GetComponentInChildren(true) ?? root.GetComponentInParent();
if (anim != null)
{
Debug.Log(Tag + "аниматор на " + anim.name + ", контроллер " + (anim.runtimeAnimatorController != null ? anim.runtimeAnimatorController.name : "нет"));
foreach (AnimatorControllerParameter p in anim.parameters)
{
string v = p.type == AnimatorControllerParameterType.Float ? anim.GetFloat(p.nameHash).ToString("0.###")
: p.type == AnimatorControllerParameterType.Int ? anim.GetInteger(p.nameHash).ToString()
: p.type == AnimatorControllerParameterType.Bool ? anim.GetBool(p.nameHash).ToString()
: "trigger";
Debug.Log(Tag + " параметр " + p.name + " (" + p.type + ") = " + v);
}
for (int l = 0; l < anim.layerCount; l++)
{
AnimatorClipInfo[] clips = anim.GetCurrentAnimatorClipInfo(l);
string names = "";
foreach (AnimatorClipInfo c in clips)
{
names += (names.Length > 0 ? ", " : "") + (c.clip != null ? c.clip.name : "?") + " x" + c.weight.ToString("0.##");
}
Debug.Log(Tag + " слой " + l + " " + anim.GetLayerName(l) + " вес " + anim.GetLayerWeight(l).ToString("0.##") + ": " + names);
}
}
else
{
Debug.Log(Tag + "аниматор не найден");
}
SdtdConsole.Instance.Output("костей рук: " + count + " - дерево и параметры аниматора в логе (строки necrobones)");
}
static void Dump(Transform _t, int _depth, StringBuilder _sb, ref int _count)
{
_count++;
Vector3 e = _t.localEulerAngles;
Vector3 p = _t.localPosition;
_sb.Append(new string(' ', _depth * 2)).Append(_t.name)
.Append(_t.gameObject.activeSelf ? "" : " [выкл]")
.Append(" пов. ").Append(e.x.ToString("0.#")).Append(' ').Append(e.y.ToString("0.#")).Append(' ').Append(e.z.ToString("0.#"))
.Append(" поз. ").Append(p.x.ToString("0.###")).Append(' ').Append(p.y.ToString("0.###")).Append(' ').Append(p.z.ToString("0.###"))
.Append('\n');
for (int i = 0; i < _t.childCount; i++)
{
Dump(_t.GetChild(i), _depth + 1, _sb, ref _count);
}
}
static string PathOf(Transform _t)
{
string s = _t.name;
for (Transform p = _t.parent; p != null; p = p.parent)
{
s = p.name + "/" + s;
}
return s;
}
}
}