Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate from unused bones by reference #430

Merged
merged 13 commits into from
Sep 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .docs/content/docs/reference/trace-and-optimize/index.ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ aliases:
アニメーションなどで使われていないBlendShapeを自動的に固定・除去します。
- `使われていないObjectを自動的に削除する`
アニメーションなどを走査して、使われていないObjectを自動的に削除します。
- `endボーンを残す`
親が削除されていないendボーン[^endbone]を削除しないようにします。

また、以下の設定で自動設定を調節できます。
- `MMDワールドとの互換性`
Expand All @@ -28,3 +30,5 @@ aliases:
それらの機能については英語のTooltipやソースコード、または開発者の指示を参考にしてください。

![component.png](component.png)

[^endbone]: AAOは名前が`end`(大文字小文字の区別なし)で終わるボーンをendボーンとして扱います。
4 changes: 4 additions & 0 deletions .docs/content/docs/reference/trace-and-optimize/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ Currently the following optimizations are applied automatically.
Automatically freezes unused BlendShapes in animation or else.
- `Remove unused Objects`
By scanning animation, etc., Automatically removes unused Objects.
- `Preserve EndBone`
Prevents removing end bones[^endbone] whose parent is not removed.

Also, You can adjust optimization with the following settings
- `MMD World Compatibility`
Expand All @@ -28,3 +30,5 @@ In addition, there is `Advanced Settings` which is for workaround bugs but it's
See tooltips or implementation for more details.

![component.png](component.png)

[^endbone]: AAO currently assumes any bones whose name ends with `end` (ignoring case) are end bones.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ EditorOnlyなメッシュからしか参照がないボーンをEditorOnlyにし

このコンポーネントは[Avatar Global Component](../../component-kind/avatar-global-components)であるため、アバターのルートに追加してください。

{{< hint warning >}}

このコンポーネントは非推奨です。代わりに[Trace and Optimize](../trace-and-optimize)の`使われていないObjectを自動的に削除する`を使用してください。
このコンポーネントの動作が改善されることはありません。

{{< /hint >}}

これはNarazakaさんの[UnusedBonesByReferencesTool][UnusedBonesByReferencesTool]を移植したものですが、ビルド時に実行します。

[UnusedBonesByReferencesTool]: https://narazaka.booth.pm/items/3831781
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ Marks it as EditorOnly that bones referenced only from EditorOnly meshes.

This component is [Avatar Global Component](../../component-kind/avatar-global-components), so this should be added to an avatar root.

{{< hint warning >}}

This component is obsolete. You should use `Remove unused Objects` of [Trace and Optimize](../trace-and-optimize) instead.
This component will never get algorithm improvements.

{{< /hint >}}

This is port of [UnusedBonesByReferencesTool by Narazaka][UnusedBonesByReferencesTool] but run at build time.

[UnusedBonesByReferencesTool]: https://narazaka.booth.pm/items/3831781
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG-PRERELEASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,15 @@ The format is based on [Keep a Changelog].
## [Unreleased]
### Added
- Automatic MergeBone in Remove Unused Objects `#433`
- Preserve end bones in Remove Unused Objects `#430`
- This does same thing as `Preserve end bones` in UnusedBonesByReferenceTool.

### Changed

### Deprecated
- UnusedBonesByReferenceTool component is now obsolete `#430`
- Newly introduced algorithm of`Remove Unused Objects` does same thing!
- You can migrate to `Remove Unused Objects` only with one click!

### Removed

Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,14 @@ The format is based on [Keep a Changelog].
### Changed
- Improved 'Remove Unused Objects' `#401`
- Remove Unused Objects now removes unnecessary Components & Bones!
- With new algorithm, you can preserve end bones (`#430`)
- You may use `Use Legacy GC` to use legacy algotythm for Remove Unused Objects in `Advanced Settings` (`#419`)
- Performance: Share MeshInfo2 between SkinnedMesh processing and MergeBone `#421`

### Deprecated
- UnusedBonesByReferenceTool component is now obsolete `#430`
- Newly introduced algorithm of`Remove Unused Objects` does same thing!
- You can migrate to `Remove Unused Objects` only with one click!

### Removed

Expand Down
8 changes: 8 additions & 0 deletions Editor/AutomaticConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ internal class TraceAndOptimizeEditor : AvatarGlobalComponentEditorBase
{
private SerializedProperty _freezeBlendShape;
private SerializedProperty _removeUnusedObjects;
private SerializedProperty _preserveEndBone;
private SerializedProperty _mmdWorldCompatibility;
private SerializedProperty _advancedAnimatorParser;
private SerializedProperty _advancedSettings;
Expand All @@ -18,6 +19,7 @@ private void OnEnable()
{
_freezeBlendShape = serializedObject.FindProperty(nameof(TraceAndOptimize.freezeBlendShape));
_removeUnusedObjects = serializedObject.FindProperty(nameof(TraceAndOptimize.removeUnusedObjects));
_preserveEndBone = serializedObject.FindProperty(nameof(TraceAndOptimize.preserveEndBone));
_mmdWorldCompatibility = serializedObject.FindProperty(nameof(TraceAndOptimize.mmdWorldCompatibility));
_advancedAnimatorParser = serializedObject.FindProperty(nameof(TraceAndOptimize.advancedAnimatorParser));
_advancedSettings = serializedObject.FindProperty(nameof(TraceAndOptimize.advancedSettings));
Expand All @@ -33,6 +35,12 @@ protected override void OnInspectorGUIInner()
GUILayout.Label("Features", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(_freezeBlendShape);
EditorGUILayout.PropertyField(_removeUnusedObjects);
if (_removeUnusedObjects.boolValue)
{
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(_preserveEndBone);
EditorGUI.indentLevel--;
}

_advancedSettingsLabel.text = CL4EE.Tr("TraceAndOptimize:prop:advancedSettings");
if (EditorGUILayout.PropertyField(_advancedSettings, _advancedSettingsLabel, false))
Expand Down
18 changes: 14 additions & 4 deletions Editor/Processors/TraceAndOptimize/ComponentDependencyCollector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,17 @@ static ComponentDependencyCollector()
InitByTypeParsers();
}

private readonly Dictionary<Component, ComponentDependencies> _dependencies =
new Dictionary<Component, ComponentDependencies>();

private readonly bool _preserveEndBone;
private readonly OptimizerSession _session;

public ComponentDependencyCollector(OptimizerSession session)
public ComponentDependencyCollector(OptimizerSession session, bool preserveEndBone)
{
_preserveEndBone = preserveEndBone;
_session = session;
}

private readonly Dictionary<Component, ComponentDependencies> _dependencies =
new Dictionary<Component, ComponentDependencies>();

public class ComponentDependencies
{
Expand Down Expand Up @@ -234,6 +235,15 @@ private static void InitByTypeParsers()
AddParser<Transform>((collector, deps, transform) =>
{
deps.AddAlwaysDependency(transform.parent, kind: DependencyType.Parent);

// For compatibility with UnusedBonesByReferenceTool
// https://github.com/anatawa12/AvatarOptimizer/issues/429
if (collector._preserveEndBone &&
transform.name.EndsWith("end", StringComparison.OrdinalIgnoreCase))
{
collector.GetDependencies(transform.parent)
.AddAlwaysDependency(transform);
}
});
// Animator does not do much for motion, just changes states of other components.
// All State Changes are collected separately
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,19 @@ class FindUnusedObjectsProcessor
private readonly ImmutableModificationsContainer _modifications;
private readonly OptimizerSession _session;
private readonly HashSet<GameObject> _exclusions;
private readonly bool _preserveEndBone;
private readonly bool _useLegacyGC;
private readonly bool _noConfigureMergeBone;

public FindUnusedObjectsProcessor(ImmutableModificationsContainer modifications, OptimizerSession session,
bool preserveEndBone,
bool useLegacyGC,
bool noConfigureMergeBone,
HashSet<GameObject> exclusions)
{
_modifications = modifications;
_session = session;
_preserveEndBone = preserveEndBone;
_useLegacyGC = useLegacyGC;
_noConfigureMergeBone = noConfigureMergeBone;
_exclusions = exclusions;
Expand Down Expand Up @@ -92,7 +95,7 @@ private void ProcessNew()
private void MarkAndSweep()
{
// first, collect usages
var collector = new ComponentDependencyCollector(_session);
var collector = new ComponentDependencyCollector(_session, _preserveEndBone);
collector.CollectAllUsages();

// then, mark and sweep.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,10 @@ public void ProcessLater(OptimizerSession session)

if (_config.removeUnusedObjects)
new FindUnusedObjectsProcessor(_modifications, session,
_config.advancedSettings.useLegacyGc,
_config.advancedSettings.noConfigureMergeBone,
_exclusions).Process();
preserveEndBone: _config.preserveEndBone,
useLegacyGC: _config.advancedSettings.useLegacyGc,
noConfigureMergeBone: _config.advancedSettings.noConfigureMergeBone,
exclusions: _exclusions).Process();

}
}
Expand Down
64 changes: 64 additions & 0 deletions Editor/UnusedBonesByReferencesToolEditor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using Anatawa12.AvatarOptimizer.Processors;
using CustomLocalization4EditorExtension;
using UnityEditor;
using UnityEngine;

namespace Anatawa12.AvatarOptimizer
{
[CustomEditor(typeof(UnusedBonesByReferencesTool))]
class UnusedBonesByReferencesToolEditor : AvatarGlobalComponentEditorBase
{
private SerializedProperty _preserveEndBone;
private SerializedProperty _detectExtraChild;

private void OnEnable()
{
_preserveEndBone = serializedObject.FindProperty(nameof(UnusedBonesByReferencesTool.preserveEndBone));
_detectExtraChild = serializedObject.FindProperty(nameof(UnusedBonesByReferencesTool.detectExtraChild));
}

protected override void OnInspectorGUIInner()
{
EditorGUILayout.PropertyField(_preserveEndBone);
EditorGUILayout.PropertyField(_detectExtraChild);

EditorGUILayout.HelpBox(CL4EE.Tr("UnusedBonesByReferencesTool:suggestMigrate"), MessageType.Info);
if (GUILayout.Button(CL4EE.Tr("UnusedBonesByReferencesTool:migrate")))
{
const string CONTENT_UNDO_NAME = "Migrate UnusedBonesByReferencesTool to Trace and Optimize";

var component = (UnusedBonesByReferencesTool)target;

// first, migrate configuration
var traceAndOptimize = component.GetComponent<TraceAndOptimize>();
if (!traceAndOptimize)
traceAndOptimize = Undo.AddComponent<TraceAndOptimize>(component.gameObject);
Undo.RecordObject(traceAndOptimize, CONTENT_UNDO_NAME);

traceAndOptimize.removeUnusedObjects = true;
traceAndOptimize.advancedSettings.useLegacyGc = false;
traceAndOptimize.preserveEndBone = component.preserveEndBone;
PrefabUtility.RecordPrefabInstancePropertyModifications(traceAndOptimize);

// then, remove EditorOnly from bones
foreach (var boneReference in UnusedBonesByReferencesToolEarlyProcessor.BoneReference
.Make(component.transform))
{
if (boneReference.Bone.CompareTag("EditorOnly"))
{
Undo.RecordObject(boneReference.Bone, CONTENT_UNDO_NAME);
boneReference.Bone.tag = "Untagged";
PrefabUtility.RecordPrefabInstancePropertyModifications(boneReference.Bone);
}
}

Undo.DestroyObjectImmediate(component);
Undo.SetCurrentGroupName(CONTENT_UNDO_NAME);

EditorUtility.DisplayDialog(CL4EE.Tr("UnusedBonesByReferencesTool:migrationFinished:title"),
CL4EE.Tr("UnusedBonesByReferencesTool:migrationFinished:description"),
"Ok");
}
}
}
}
3 changes: 3 additions & 0 deletions Editor/UnusedBonesByReferencesToolEditor.cs.meta

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

21 changes: 21 additions & 0 deletions Localization/en.po
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,21 @@ msgstr "Detect Extra Children"
msgid "UnusedBonesByReferencesTool:tooltip:detectExtraChild"
msgstr "If checked, this tool does not remove bones with non-bone children."

msgid "UnusedBonesByReferencesTool:suggestMigrate"
msgstr ""
"UnusedBonesByReferencesTool is obsoleted by more intelligent Trace and Optimize!\n"
"Would you like to migrate to Trace and Optimize by clicking the button below?"

msgid "UnusedBonesByReferencesTool:migrate"
msgstr "Migrate to Trace and Optimize"

msgid "UnusedBonesByReferencesTool:migrationFinished:title"
msgstr "Migration Finished!"

msgid "UnusedBonesByReferencesTool:migrationFinished:description"
msgstr "Migrating to Trace and Optimize is finished!"


# endregion

# region TraceAndOptimize
Expand Down Expand Up @@ -381,6 +396,12 @@ msgid "TraceAndOptimize:warn:unknown-type"
msgstr "Unknown Component Type '{0}' Found. This will reduce optimization performance and may break your Avatar."
"If your avatar got broken, Please report this error to AvatarOptimizer!"

msgid "TraceAndOptimize:prop:preserveEndBone"
msgstr "Preserve EndBone"

msgid "TraceAndOptimize:tooltip:preserveEndBone"
msgstr "Prevents removing end bones whose parent is not removed."

# endregion

#region ApplyObjectMapping
Expand Down
20 changes: 20 additions & 0 deletions Localization/ja.po
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,20 @@ msgstr "他の子オブジェクトを認識する"
msgid "UnusedBonesByReferencesTool:tooltip:detectExtraChild"
msgstr "チェックされている場合、子にボーン以外を持つボーンを削除しません。"

msgid "UnusedBonesByReferencesTool:suggestMigrate"
msgstr ""
"UnusedBonesByReferencesToolは、使用されていないボーンなどに対してより賢い処理を行うTrace and Optimizeに置き換えられました!\n"
Sayamame-beans marked this conversation as resolved.
Show resolved Hide resolved
"下のボタンを押し、Trace and Optimizeに移行しませんか? (設定は引き継がれます)"

msgid "UnusedBonesByReferencesTool:migrate"
msgstr "Trace and Optimizeに移行する"

msgid "UnusedBonesByReferencesTool:migrationFinished:title"
msgstr "移行完了"

msgid "UnusedBonesByReferencesTool:migrationFinished:description"
msgstr "Trace and Optimizeへの移行が完了しました!"

# endregion

# region TraceAndOptimize
Expand Down Expand Up @@ -318,6 +332,12 @@ msgid "TraceAndOptimize:warn:unknown-type"
msgstr "未知のコンポーネント'{0}'を検出しました! これにより最適化処理の品質が低下し、処理後のアバターが壊れる可能性があります。(元のアバターには影響しません)"
"アバターが壊れた場合、これをAvatarOptimizerに報告してください!"

msgid "TraceAndOptimize:prop:preserveEndBone"
msgstr "endボーンを残す"

msgid "TraceAndOptimize:tooltip:preserveEndBone"
msgstr "親が削除されていないendボーンを削除しないようにします。"

# endregion

#region ApplyObjectMapping
Expand Down
6 changes: 6 additions & 0 deletions Runtime/TraceAndOptimize.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ internal class TraceAndOptimize : AvatarGlobalComponent
[ToggleLeft]
public bool removeUnusedObjects = true;

// Remove Unused Objects Options
[CL4EELocalized("TraceAndOptimize:prop:preserveEndBone",
"TraceAndOptimize:tooltip:preserveEndBone")]
[ToggleLeft]
public bool preserveEndBone;

// common parsing configuration
[CL4EELocalized("TraceAndOptimize:prop:mmdWorldCompatibility",
"TraceAndOptimize:tooltip:mmdWorldCompatibility")]
Expand Down
2 changes: 2 additions & 0 deletions Runtime/UnusedBonesByReferencesTool.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using CustomLocalization4EditorExtension;
using UnityEngine;

Expand All @@ -6,6 +7,7 @@ namespace Anatawa12.AvatarOptimizer
[AddComponentMenu("Avatar Optimizer/AAO UnusedBonesByReferencesTool")]
[DisallowMultipleComponent]
[HelpURL("https://vpm.anatawa12.com/avatar-optimizer/ja/docs/reference/unused-bones-by-references-tool/")]
[Obsolete("Obsoleted by Trace and Optimize")]
internal class UnusedBonesByReferencesTool : AvatarGlobalComponent
{
[CL4EELocalized("UnusedBonesByReferencesTool:prop:preserveEndBone",
Expand Down