chore: implement preview refresh (#893)

* chore: implement refresh for ScaleAdjusterPreview

* chore: implement refresh in ShapeChangerPreview
This commit is contained in:
bd_ 2024-06-23 10:09:51 +09:00 committed by GitHub
parent ae3e163bd4
commit 76d5f882eb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 78 additions and 18 deletions

View File

@ -82,8 +82,21 @@ namespace nadena.dev.modular_avatar.core.editor
{
}
public RenderAspects Reads => RenderAspects.Shapes;
public RenderAspects WhatChanged => RenderAspects.Shapes;
public RenderAspects Reads => 0;
// We only change things in OnFrame, so downstream nodes will need to keep track of changes to these bones and
// blendshapes themselves.
public RenderAspects WhatChanged => 0;
public Task<IRenderFilterNode> Refresh
(
IEnumerable<(Renderer, Renderer)> proxyPairs,
ComputeContext context,
RenderAspects updatedAspects
)
{
return Task.FromResult((IRenderFilterNode)this);
}
public void OnFrame(Renderer original, Renderer proxy)
{

View File

@ -57,11 +57,11 @@ namespace nadena.dev.modular_avatar.core.editor
IEnumerable<(Renderer, Renderer)> proxyPairs,
ComputeContext context)
{
var node = new Node();
var node = new Node(group);
try
{
await node.Init(group, proxyPairs, context);
await node.Init(proxyPairs, context);
}
catch (Exception e)
{
@ -74,8 +74,16 @@ namespace nadena.dev.modular_avatar.core.editor
private class Node : IRenderFilterNode
{
private readonly RenderGroup _group;
private Mesh _generatedMesh = null;
private ImmutableList<ModularAvatarShapeChanger> _changers;
private HashSet<int> _toDelete;
internal Node(RenderGroup group)
{
_group = group;
}
private bool IsChangerActive(ModularAvatarShapeChanger changer, ComputeContext context)
{
@ -91,34 +99,74 @@ namespace nadena.dev.modular_avatar.core.editor
}
}
public async Task Init(RenderGroup group, IEnumerable<(Renderer, Renderer)> renderers,
ComputeContext context)
private HashSet<int> GetToDeleteSet(SkinnedMeshRenderer proxy, ComputeContext context)
{
var (original, proxy) = renderers.First();
_changers = _group.GetData<ImmutableList<ModularAvatarShapeChanger>>();
if (original == null || proxy == null) return;
if (!(proxy is SkinnedMeshRenderer smr)) return;
_changers = group.GetData<ImmutableList<ModularAvatarShapeChanger>>();
HashSet<int> toDelete = new HashSet<int>();
var mesh = smr.sharedMesh;
var toDelete = new HashSet<int>();
var mesh = context.Observe(proxy.sharedMesh);
foreach (var changer in _changers)
{
context.Observe(changer);
if (!IsChangerActive(changer, context)) continue;
foreach (var shape in changer.Shapes)
{
if (shape.ChangeType == ShapeChangeType.Delete)
{
var index = mesh.GetBlendShapeIndex(shape.ShapeName);
if (index < 0) continue;
toDelete.Add(index);
}
}
}
return toDelete;
}
public async Task Init(
IEnumerable<(Renderer, Renderer)> renderers,
ComputeContext context
)
{
var (original, proxy) = renderers.First();
if (original == null || proxy == null) return;
if (!(proxy is SkinnedMeshRenderer smr)) return;
await Init(smr, context, GetToDeleteSet(smr, context));
}
public async Task<IRenderFilterNode> Refresh(IEnumerable<(Renderer, Renderer)> proxyPairs,
ComputeContext context, RenderAspects updatedAspects)
{
if ((updatedAspects & RenderAspects.Mesh) != 0) return null;
var (original, proxy) = proxyPairs.First();
if (original == null || proxy == null) return null;
if (!(proxy is SkinnedMeshRenderer smr)) return null;
var toDelete = GetToDeleteSet(smr, context);
if (toDelete.Count == _toDelete.Count && toDelete.All(_toDelete.Contains))
{
return this;
}
var node = new Node(_group);
await node.Init(smr, context, toDelete);
return node;
}
public async Task Init(
SkinnedMeshRenderer proxy,
ComputeContext context,
HashSet<int> toDelete
)
{
_toDelete = toDelete;
var mesh = proxy.sharedMesh;
if (toDelete.Count > 0)
{
mesh = Object.Instantiate(mesh);
@ -163,7 +211,6 @@ namespace nadena.dev.modular_avatar.core.editor
mesh.SetTriangles(tris, subMesh, false, baseVertex: baseVertex);
}
smr.sharedMesh = mesh;
_generatedMesh = mesh;
}
}