2024-10-20 09:58:41 +08:00
|
|
|
|
#if MA_VRCSDK3_AVATARS
|
|
|
|
|
using System.Collections.Generic;
|
2024-08-04 10:56:07 +08:00
|
|
|
|
using System.Collections.Immutable;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Threading.Tasks;
|
2024-08-26 11:19:04 +08:00
|
|
|
|
using nadena.dev.modular_avatar.core.editor.Simulator;
|
2024-08-04 10:56:07 +08:00
|
|
|
|
using nadena.dev.ndmf.preview;
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
|
|
|
|
namespace nadena.dev.modular_avatar.core.editor
|
|
|
|
|
{
|
|
|
|
|
internal class ObjectSwitcherPreview : IRenderFilter
|
|
|
|
|
{
|
2024-08-19 09:32:56 +08:00
|
|
|
|
public bool CanEnableRenderers => true;
|
|
|
|
|
|
2024-08-04 12:05:10 +08:00
|
|
|
|
static TogglablePreviewNode EnableNode = TogglablePreviewNode.Create(
|
|
|
|
|
() => "Object Switcher",
|
|
|
|
|
qualifiedName: "nadena.dev.modular-avatar/ObjectSwitcherPreview",
|
|
|
|
|
true
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
public IEnumerable<TogglablePreviewNode> GetPreviewControlNodes()
|
|
|
|
|
{
|
|
|
|
|
yield return EnableNode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool IsEnabled(ComputeContext context)
|
|
|
|
|
{
|
|
|
|
|
return context.Observe(EnableNode.IsEnabled);
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-26 11:19:04 +08:00
|
|
|
|
private IEnumerable<RenderGroup> RootsForAvatar(ComputeContext context, GameObject avatarRoot)
|
2024-08-04 10:56:07 +08:00
|
|
|
|
{
|
2024-08-26 11:19:04 +08:00
|
|
|
|
if (!context.ActiveInHierarchy(avatarRoot))
|
2024-08-04 10:56:07 +08:00
|
|
|
|
{
|
2024-08-26 11:19:04 +08:00
|
|
|
|
yield break;
|
2024-08-04 10:56:07 +08:00
|
|
|
|
}
|
|
|
|
|
|
2024-08-26 11:19:04 +08:00
|
|
|
|
var analysis = ReactiveObjectAnalyzer.CachedAnalyze(context, avatarRoot);
|
|
|
|
|
var initialStates = analysis.InitialStates;
|
2024-08-05 10:31:43 +08:00
|
|
|
|
|
2024-08-26 11:19:04 +08:00
|
|
|
|
var renderers = context.GetComponentsInChildren<Renderer>(avatarRoot, true);
|
|
|
|
|
|
|
|
|
|
foreach (var renderer in renderers)
|
2024-08-04 10:56:07 +08:00
|
|
|
|
{
|
2024-09-14 08:52:45 +08:00
|
|
|
|
// For now, the preview system only supports MeshRenderer and SkinnedMeshRenderer
|
|
|
|
|
if (renderer is not MeshRenderer and not SkinnedMeshRenderer) continue;
|
|
|
|
|
|
2024-08-26 11:19:04 +08:00
|
|
|
|
bool currentlyEnabled = context.ActiveInHierarchy(renderer.gameObject);
|
2024-08-05 10:31:43 +08:00
|
|
|
|
|
2024-08-26 11:19:04 +08:00
|
|
|
|
bool overrideEnabled = true;
|
|
|
|
|
Transform cursor = renderer.transform;
|
|
|
|
|
while (cursor != null && !RuntimeUtil.IsAvatarRoot(cursor))
|
|
|
|
|
{
|
|
|
|
|
if (initialStates.TryGetValue(TargetProp.ForObjectActive(cursor.gameObject), out var initialState) && initialState is float f)
|
2024-08-05 10:31:43 +08:00
|
|
|
|
{
|
2024-08-26 11:19:04 +08:00
|
|
|
|
if (f < 0.5f)
|
|
|
|
|
{
|
|
|
|
|
overrideEnabled = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2024-08-05 10:31:43 +08:00
|
|
|
|
}
|
2024-08-26 11:19:04 +08:00
|
|
|
|
else if (!cursor.gameObject.activeSelf)
|
2024-08-05 10:31:43 +08:00
|
|
|
|
{
|
2024-08-26 11:19:04 +08:00
|
|
|
|
overrideEnabled = false;
|
2024-08-05 10:31:43 +08:00
|
|
|
|
break;
|
|
|
|
|
}
|
2024-08-26 11:19:04 +08:00
|
|
|
|
|
|
|
|
|
cursor = cursor.parent;
|
2024-08-04 10:56:07 +08:00
|
|
|
|
}
|
|
|
|
|
|
2024-08-26 11:19:04 +08:00
|
|
|
|
if (overrideEnabled != currentlyEnabled)
|
|
|
|
|
{
|
|
|
|
|
yield return RenderGroup.For(renderer).WithData(overrideEnabled);
|
|
|
|
|
}
|
2024-08-04 10:56:07 +08:00
|
|
|
|
}
|
2024-08-26 11:19:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public ImmutableList<RenderGroup> GetTargetGroups(ComputeContext context)
|
|
|
|
|
{
|
|
|
|
|
var roots = context.GetAvatarRoots();
|
|
|
|
|
|
|
|
|
|
return roots.SelectMany(av => RootsForAvatar(context, av)).ToImmutableList();
|
2024-08-04 10:56:07 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Task<IRenderFilterNode> Instantiate(RenderGroup group, IEnumerable<(Renderer, Renderer)> proxyPairs,
|
|
|
|
|
ComputeContext context)
|
|
|
|
|
{
|
2024-08-08 09:19:49 +08:00
|
|
|
|
return Task.FromResult<IRenderFilterNode>(new Node(group.GetData<bool>()));
|
2024-08-04 10:56:07 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private class Node : IRenderFilterNode
|
|
|
|
|
{
|
|
|
|
|
public RenderAspects WhatChanged => 0;
|
2024-08-08 09:19:49 +08:00
|
|
|
|
private readonly bool _shouldEnable;
|
2024-08-04 10:56:07 +08:00
|
|
|
|
|
2024-08-08 09:19:49 +08:00
|
|
|
|
public Node(bool shouldEnable)
|
|
|
|
|
{
|
|
|
|
|
_shouldEnable = shouldEnable;
|
|
|
|
|
}
|
2024-08-05 10:31:43 +08:00
|
|
|
|
|
2024-08-04 10:56:07 +08:00
|
|
|
|
public void OnFrame(Renderer original, Renderer proxy)
|
|
|
|
|
{
|
2024-08-19 09:32:56 +08:00
|
|
|
|
proxy.enabled = _shouldEnable;
|
2024-08-04 10:56:07 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-10-20 09:58:41 +08:00
|
|
|
|
}
|
|
|
|
|
#endif
|