2024-06-03 08:52:08 +08:00
|
|
|
|
#region
|
|
|
|
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Collections.Immutable;
|
|
|
|
|
using System.Linq;
|
2024-06-07 11:58:08 +08:00
|
|
|
|
using System.Threading.Tasks;
|
2024-06-03 08:52:08 +08:00
|
|
|
|
using nadena.dev.modular_avatar.core.editor.ScaleAdjuster;
|
|
|
|
|
using nadena.dev.ndmf.preview;
|
|
|
|
|
using nadena.dev.ndmf.rq;
|
|
|
|
|
using nadena.dev.ndmf.rq.unity.editor;
|
|
|
|
|
using UnityEditor;
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
namespace nadena.dev.modular_avatar.core.editor
|
|
|
|
|
{
|
|
|
|
|
internal class ScaleAdjusterPreview : IRenderFilter
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
[InitializeOnLoadMethod]
|
|
|
|
|
private static void StaticInit()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static GameObject FindAvatarRootObserving(ComputeContext ctx, GameObject ptr)
|
|
|
|
|
{
|
|
|
|
|
while (ptr != null)
|
|
|
|
|
{
|
|
|
|
|
ctx.Observe(ptr);
|
|
|
|
|
var xform = ptr.transform;
|
|
|
|
|
if (RuntimeUtil.IsAvatarRoot(xform)) return ptr;
|
|
|
|
|
|
|
|
|
|
ptr = xform.parent?.gameObject;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-17 10:47:54 +08:00
|
|
|
|
public ReactiveValue<ImmutableList<RenderGroup>> TargetGroups { get; } =
|
|
|
|
|
ReactiveValue<ImmutableList<RenderGroup>>.Create(
|
2024-06-03 08:52:08 +08:00
|
|
|
|
"Scale Adjuster: Find targets",
|
|
|
|
|
async ctx =>
|
|
|
|
|
{
|
|
|
|
|
var scaleAdjusters = await ctx.Observe(CommonQueries.GetComponentsByType<ModularAvatarScaleAdjuster>());
|
|
|
|
|
|
2024-06-17 10:47:54 +08:00
|
|
|
|
ImmutableList<RenderGroup>.Builder result = ImmutableList.CreateBuilder<RenderGroup>();
|
|
|
|
|
|
2024-06-03 08:52:08 +08:00
|
|
|
|
foreach (var adjuster in scaleAdjusters)
|
|
|
|
|
{
|
|
|
|
|
// Find parent object
|
|
|
|
|
// TODO: Reactive helper
|
|
|
|
|
var root = FindAvatarRootObserving(ctx, adjuster.gameObject);
|
|
|
|
|
if (root == null) continue;
|
|
|
|
|
|
|
|
|
|
var renderers = ctx.GetComponentsInChildren<Renderer>(root, true);
|
|
|
|
|
|
|
|
|
|
foreach (var renderer in renderers)
|
|
|
|
|
{
|
2024-06-17 10:47:54 +08:00
|
|
|
|
if (renderer is SkinnedMeshRenderer smr)
|
|
|
|
|
{
|
|
|
|
|
result.Add(RenderGroup.For(renderer));
|
|
|
|
|
}
|
2024-06-03 08:52:08 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-17 10:47:54 +08:00
|
|
|
|
return result.ToImmutable();
|
2024-06-03 08:52:08 +08:00
|
|
|
|
});
|
|
|
|
|
|
2024-06-17 10:47:54 +08:00
|
|
|
|
public Task<IRenderFilterNode> Instantiate(RenderGroup group, IEnumerable<(Renderer, Renderer)> proxyPairs,
|
|
|
|
|
ComputeContext context)
|
2024-06-07 11:58:08 +08:00
|
|
|
|
{
|
|
|
|
|
return Task.FromResult((IRenderFilterNode)new ScaleAdjusterPreviewNode());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal class ScaleAdjusterPreviewNode : IRenderFilterNode
|
|
|
|
|
{
|
|
|
|
|
private static ScaleAdjustedBones _bones = new ScaleAdjustedBones();
|
|
|
|
|
|
|
|
|
|
public ScaleAdjusterPreviewNode()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-17 10:47:54 +08:00
|
|
|
|
public RenderAspects Reads => RenderAspects.Shapes;
|
|
|
|
|
public RenderAspects WhatChanged => RenderAspects.Shapes;
|
2024-06-07 11:58:08 +08:00
|
|
|
|
|
2024-06-03 08:52:08 +08:00
|
|
|
|
public void OnFrame(Renderer original, Renderer proxy)
|
|
|
|
|
{
|
|
|
|
|
if (proxy is SkinnedMeshRenderer p_smr && original is SkinnedMeshRenderer o_smr)
|
|
|
|
|
{
|
|
|
|
|
p_smr.rootBone = _bones.GetBone(o_smr.rootBone)?.proxy ?? o_smr.rootBone;
|
|
|
|
|
p_smr.bones = o_smr.bones.Select(b =>
|
|
|
|
|
{
|
|
|
|
|
var sa = (Component)b?.GetComponent<ModularAvatarScaleAdjuster>();
|
|
|
|
|
return _bones.GetBone(sa ?? b, true)?.proxy ?? b;
|
|
|
|
|
}).ToArray();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_bones.Update();
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-07 11:58:08 +08:00
|
|
|
|
public void Dispose()
|
|
|
|
|
{
|
|
|
|
|
_bones.Clear();
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-06-03 08:52:08 +08:00
|
|
|
|
}
|