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 Reads => 0;
public RenderAspects WhatChanged => RenderAspects.Shapes;
// 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) public void OnFrame(Renderer original, Renderer proxy)
{ {

View File

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