Skip to content

Commit

Permalink
Added replacement in animations and added a checkbox to replace all o…
Browse files Browse the repository at this point in the history
…r only ones that actualy get used twice
  • Loading branch information
bigibas123 committed Jun 9, 2024
1 parent ea863a2 commit 62df5b0
Show file tree
Hide file tree
Showing 16 changed files with 351 additions and 113 deletions.
37 changes: 16 additions & 21 deletions Editor/MatSlotExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,27 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using cc.dingemans.bigibas123.MaterialDedup.Editor.Animation;
using cc.dingemans.bigibas123.MaterialDedup.Editor.Model;
using cc.dingemans.bigibas123.MaterialDedup.Runtime;
using UnityEngine;
using VRC.SDK3.Avatars.Components;

namespace cc.dingemans.bigibas123.MaterialDedup.Editor
{
public static class MatSlotExtensions
{
public static IEnumerable<MaterialReference> AsMaterialRefs(this MaterialDeduplicatorBehavior dup)
public static IEnumerable<MaterialTarget> AsMaterialRefs(this MaterialDeduplicatorBehavior dup,
VRCAvatarDescriptor contextAvatarDescriptor)
{
//TODO add materials referenced in animations as well
return dup.Renderers.AsMaterialRefs();
IEnumerable<MaterialTarget> rendererMaterials = dup.Renderers.AsMaterialRefs();
IEnumerable<MaterialTarget> animationLayerMats =
contextAvatarDescriptor.GetMaterialTargetFromAnimationLayers();
return rendererMaterials.Concat(animationLayerMats);
}

public static IEnumerable<MaterialReference> AsMaterialRefs(this IEnumerable<Renderer> renders) =>
public static IEnumerable<RendererMaterialReference> AsMaterialRefs(this IEnumerable<Renderer> renders) =>
renders.SelectMany(renderer => renderer.AsMaterialRefs());

public static IEnumerable<MaterialReference> AsMaterialRefs(this Renderer rend) =>
rend.sharedMaterials.Select((_, b) => new MaterialReference(rend, b));
public static IEnumerable<RendererMaterialReference> AsMaterialRefs(this Renderer rend) =>
rend.sharedMaterials.Select((_, b) => new RendererMaterialReference(rend, b));

public static List<DeduplicatedMaterial> AsDedupList(this IEnumerable<MaterialReference> avatarMaterials)
public static List<DeduplicatedMaterial> AsDedupList(this IEnumerable<MaterialTarget> avatarMaterials)
{
var resolvedMaterials = new List<DeduplicatedMaterial>();
foreach (var avatarMat in avatarMaterials)
Expand All @@ -31,15 +36,10 @@ public static List<DeduplicatedMaterial> AsDedupList(this IEnumerable<MaterialRe
var found = false;
foreach (var resolved in resolvedMaterials)
{
if (
avatarMat.HasPropertiesSameAs(resolved)
&& IsAnimatedTheSame(resolved,avatarMat)
)
{
found = true;
resolved.AddRefForReplacement(avatarMat);
break;
}
if (!avatarMat.HasPropertiesSameAs(resolved)) continue;
found = true;
resolved.AddRefForReplacement(avatarMat);
break;
}

if (found) continue;
Expand All @@ -50,10 +50,5 @@ public static List<DeduplicatedMaterial> AsDedupList(this IEnumerable<MaterialRe

return resolvedMaterials;
}

private static bool IsAnimatedTheSame(DeduplicatedMaterial dedupped, MaterialReference mat)
{
return true; //TODO
}
}
}
2 changes: 1 addition & 1 deletion Editor/MaterialDedup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ protected override void Configure()
var roots = ctx.AvatarRootTransform.GetComponentsInChildren<MaterialDeduplicatorBehavior>();
foreach (var root in roots)
{
root.AsMaterialRefs().AsDedupList().ForEach(d => d.ApplyToDests());
root.AsMaterialRefs(ctx.AvatarDescriptor).AsDedupList().ForEach(d => d.ApplyToDests(root.replaceEvenIfOnlyOne));
UnityEngine.Object.DestroyImmediate(root);
}
});
Expand Down
106 changes: 81 additions & 25 deletions Editor/MaterialDeduplicatorBehaviorEditor.cs
Original file line number Diff line number Diff line change
@@ -1,44 +1,100 @@
using System.Linq;
using System.Collections.Generic;
using System.Linq;
using cc.dingemans.bigibas123.MaterialDedup.Editor.Model;
using cc.dingemans.bigibas123.MaterialDedup.Runtime;
using JetBrains.Annotations;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
using VRC;
using VRC.SDK3.Avatars.Components;

namespace cc.dingemans.bigibas123.MaterialDedup.Editor
{
[CustomEditor(typeof(MaterialDeduplicatorBehavior))]
public class MaterialDeduplicatorBehaviorEditor : UnityEditor.Editor
{
SerializedProperty _replaceEvenIfOnlyOneProp;

[CanBeNull] private GroupBox _box;

void OnEnable()
{
_replaceEvenIfOnlyOneProp =
serializedObject.FindProperty(nameof(MaterialDeduplicatorBehavior.replaceEvenIfOnlyOne));
}

private void ReDrawMaterials(MaterialDeduplicatorBehavior behavior)
{
_box.contentContainer.Clear();
var list = behavior
.AsMaterialRefs(behavior.gameObject.GetComponentInParent<VRCAvatarDescriptor>())
.AsDedupList();
var matBlock = GetMaterialFoldouts(list, behavior.replaceEvenIfOnlyOne);
foreach (var foldout in matBlock)
{
_box.contentContainer.Add(foldout);
}
}

public override VisualElement CreateInspectorGUI()
{
VisualElement inspector = new VisualElement();
var list = ((MaterialDeduplicatorBehavior)target).AsMaterialRefs().AsDedupList().ToList();

list.ForEach(dedup =>
var behavior = (MaterialDeduplicatorBehavior)target;

var checkBox = new PropertyField(_replaceEvenIfOnlyOneProp, "Always replace materials");
checkBox.RegisterValueChangeCallback(evt => { ReDrawMaterials(behavior); });

inspector.Add(checkBox);

var list = behavior
.AsMaterialRefs(behavior.gameObject.GetComponentInParent<VRCAvatarDescriptor>())
.AsDedupList();

var matBlock = GetMaterialFoldouts(list, behavior.replaceEvenIfOnlyOne);
_box ??= new GroupBox();
foreach (var foldout in matBlock)
{
var rendererFold = new Foldout
{
text = dedup.Name,
};
var gb = new GroupBox() { focusable = false };
gb.SetEnabled(false);
var of = new ObjectField() { focusable = false, objectType = typeof(Material) };
of.value = dedup.Material;
gb.contentContainer.Add(of);
foreach (var dest in dedup.Destinations)
{
var rendObjField = new ObjectField() { focusable = false, objectType = typeof(Renderer) };
rendObjField.label = dest.Slot.ToString();
rendObjField.value = dest.Renderer;
gb.contentContainer.Add(rendObjField);
}
rendererFold.contentContainer.Add(gb);
inspector.Add(rendererFold);
});


_box.contentContainer.Add(foldout);
}
inspector.Add(_box);

return inspector;
}

public IEnumerable<Foldout> GetMaterialFoldouts(IEnumerable<DeduplicatedMaterial> list,
bool replaceEvenIfOnlyOne)
{
return list
.Where(dedup => replaceEvenIfOnlyOne || dedup.DestinationCount > 1)
.ToList()
.Select(dedup =>
{
var rendererFold = new Foldout
{
text = dedup.Name,
};
var gb = new GroupBox() { focusable = false };
gb.SetEnabled(false);
var of = new ObjectField() { focusable = false, objectType = typeof(Material) };
of.value = dedup.Material;
gb.contentContainer.Add(of);
foreach (var dest in dedup.Destinations)
{
var rendObjField = new ObjectField
{
focusable = false,
objectType = dest.Target.GetType(),
label = dest.Name,
value = dest.Target
};
gb.contentContainer.Add(rendObjField);
}

rendererFold.contentContainer.Add(gb);
return rendererFold;
});
}
}
}
35 changes: 35 additions & 0 deletions Editor/Model/AnimationMaterialTarget.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using UnityEditor;
using UnityEngine;

namespace cc.dingemans.bigibas123.MaterialDedup.Editor.Model
{
public class AnimationMaterialTarget : MaterialTarget
{
private readonly AnimationClip _clip;
private readonly EditorCurveBinding _binding;
private readonly int _keyFrameId;

public AnimationMaterialTarget(AnimationClip clip, EditorCurveBinding binding, int keyFrame)
{
_clip = clip;
_binding = binding;
_keyFrameId = keyFrame;
}

private ObjectReferenceKeyframe Keyframe =>
AnimationUtility.GetObjectReferenceCurve(_clip, _binding)[_keyFrameId];

public override Material Material => Keyframe.value as Material;
public override string Name => $"{_clip.name}:{_binding.propertyName}[{_keyFrameId}]";

public override TargetType Type => TargetType.AnimationClip;
public override Object Target => _clip;

public override void SetNewMat(Material mat)
{
var curve = AnimationUtility.GetObjectReferenceCurve(_clip, _binding);
curve[_keyFrameId].value = mat;
AnimationUtility.SetObjectReferenceCurve(_clip, _binding, curve);
}
}
}
3 changes: 3 additions & 0 deletions Editor/Model/AnimationMaterialTarget.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 13 additions & 12 deletions Editor/Model/DeduplicatedMaterial.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ namespace cc.dingemans.bigibas123.MaterialDedup.Editor.Model
public class DeduplicatedMaterial : MaterialContainer
{
private string _prefix = "Dedup:";
private List<MaterialReference> _destinations;
public ImmutableList<MaterialReference> Destinations => _destinations.ToImmutableList();
private List<MaterialTarget> _destinations;
public ImmutableList<MaterialTarget> Destinations => _destinations.ToImmutableList();
public int DestinationCount => _destinations.Count;

private Material _material;
[CanBeNull] private string _destName;

Expand All @@ -33,27 +35,26 @@ public override string Name

public DeduplicatedMaterial(Material sourceMaterial)
{
_destinations = new List<MaterialReference>();
_destinations = new List<MaterialTarget>();
_material = new Material(sourceMaterial);
}

public void AddRefForReplacement(MaterialReference avatarMat)
public void AddRefForReplacement(MaterialTarget avatarMat)
{
_destinations.Add(avatarMat);
_destName = null;
}

public void ApplyToDests()
public void ApplyToDests(bool bypassCountCheck = false)
{
if (_destinations.Count <= 1)
if (bypassCountCheck || DestinationCount > 1)
{
//Let the material be instead of replacing it
return;
}
var finalMaterial = Material;
foreach (var dest in _destinations)
{
dest.SetNewMat(finalMaterial);
var finalMaterial = Material;
foreach (var dest in _destinations)
{
dest.SetNewMat(finalMaterial);
}
}
}
}
Expand Down
49 changes: 0 additions & 49 deletions Editor/Model/MaterialReference.cs

This file was deleted.

11 changes: 11 additions & 0 deletions Editor/Model/MaterialTarget.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using UnityEngine;

namespace cc.dingemans.bigibas123.MaterialDedup.Editor.Model
{
public abstract class MaterialTarget : MaterialContainer
{
public abstract TargetType Type { get; }
public abstract Object Target { get; }
public abstract void SetNewMat(Material mat);
}
}
3 changes: 3 additions & 0 deletions Editor/Model/MaterialTarget.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 62df5b0

Please sign in to comment.