Skip to content

Commit

Permalink
Merge branch 'main' into avatar_root_utils
Browse files Browse the repository at this point in the history
  • Loading branch information
kaikoga committed Oct 4, 2023
2 parents ae8937b + b7c88bf commit 1cbfc0b
Show file tree
Hide file tree
Showing 23 changed files with 192 additions and 22 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [unreleased]

### Added
- Added toplevel menu for manual bake avatar, even when MA is also installed (#35)
- Added support for multiple ExportsPlugin declarations (#40)
- Added additional convenience overloads for BeforePlugin and AfterPlugin

### Fixed
- Create ApplyOnPlayGlobalActivator correctly when creating and opening scenes (#31)
- Time resolution on the plugin sequence display is milliseconds, not 0.01 ms (#43)
- BeforePlugin/AfterPlugin declarations don't work (#44)

### Changed
- Position of the Plugin sequence display window is now preserved after restarting the Unity Editor (#42)

### Removed

Expand Down
2 changes: 1 addition & 1 deletion Editor/API/Attributes/ExportsPlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace nadena.dev.ndmf
/// }
/// </code>
/// </summary>
[AttributeUsage(AttributeTargets.Assembly)]
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
public sealed class ExportsPlugin : Attribute
{
public Type PluginType { get; }
Expand Down
6 changes: 3 additions & 3 deletions Editor/API/BuildContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ internal void RunPass(ConcretePass pass)
Stopwatch sw2 = new Stopwatch();
sw2.Start();
DeactivateExtensionContext(ty);
deactivationTimes = deactivationTimes.Add(ty, sw2.ElapsedMilliseconds);
deactivationTimes = deactivationTimes.Add(ty, sw2.Elapsed.TotalMilliseconds);
}

ImmutableDictionary<Type, double> activationTimes = ImmutableDictionary<Type, double>.Empty;
Expand All @@ -261,7 +261,7 @@ internal void RunPass(ConcretePass pass)
Stopwatch sw2 = new Stopwatch();
sw2.Start();
ActivateExtensionContext(ty);
activationTimes = activationTimes.Add(ty, sw2.ElapsedMilliseconds);
activationTimes = activationTimes.Add(ty, sw2.Elapsed.TotalMilliseconds);
}

Stopwatch passTimer = new Stopwatch();
Expand All @@ -283,7 +283,7 @@ internal void RunPass(ConcretePass pass)

BuildEvent.Dispatch(new BuildEvent.PassExecuted(
pass.InstantiatedPass.QualifiedName,
passTimer.ElapsedMilliseconds,
passTimer.Elapsed.TotalMilliseconds,
activationTimes,
deactivationTimes
));
Expand Down
2 changes: 2 additions & 0 deletions Editor/API/Fluent/PluginInfo.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#region

using System.Collections.Generic;
using nadena.dev.ndmf.fluent;
using nadena.dev.ndmf.model;

Expand All @@ -12,6 +13,7 @@ internal class PluginInfo
private readonly SolverContext _solverContext;
private readonly IPlugin _plugin;
private int sequenceIndex = 0;
private HashSet<BuildPhase> _createdInnatePhases = new HashSet<BuildPhase>();

public PluginInfo(SolverContext solverContext, IPlugin plugin)
{
Expand Down
12 changes: 12 additions & 0 deletions Editor/API/Fluent/Sequence/Constraints.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ public Sequence BeforePlugin<T>(T plugin, [CallerFilePath] string sourceFile = "
{
return BeforePlugin(plugin.QualifiedName, sourceFile, sourceLine);
}

public Sequence BeforePlugin<T>([CallerFilePath] string sourceFile = "",
[CallerLineNumber] int sourceLine = 0) where T : Plugin<T>, new()
{
return BeforePlugin(Plugin<T>.Instance.QualifiedName, sourceFile, sourceLine);
}

public Sequence AfterPlugin(string qualifiedName, [CallerFilePath] string sourceFile = "",
[CallerLineNumber] int sourceLine = 0)
Expand All @@ -64,6 +70,12 @@ public Sequence AfterPlugin<T>(T plugin, [CallerFilePath] string sourceFile = ""
{
return AfterPlugin(plugin.QualifiedName, sourceFile, sourceLine);
}

public Sequence AfterPlugin<T>([CallerFilePath] string sourceFile = "",
[CallerLineNumber] int sourceLine = 0) where T : Plugin<T>, new()
{
return AfterPlugin(Plugin<T>.Instance.QualifiedName, sourceFile, sourceLine);
}

public Sequence WaitFor<T>(T pass, [CallerFilePath] string sourceFile = "",
[CallerLineNumber] int sourceLine = 0) where T : Pass<T>, new()
Expand Down
2 changes: 1 addition & 1 deletion Editor/API/Fluent/Sequence/Sequence.cs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ internal Sequence(BuildPhase phase, SolverContext solverContext, IPlugin plugin,
private SolverPass CreateSequencingPass(string displayName, InlinePass callback, string sourceFile,
int sourceLine)
{
var anonPass = new AnonymousPass(_sequenceBaseName + "/anonymous#" + inlinePassIndex++, displayName,
var anonPass = new AnonymousPass(_sequenceBaseName + "/" + displayName + "#" + inlinePassIndex++, displayName,
callback);
var pass = new SolverPass(_plugin, anonPass, _phase, _compatibleExtensions, _requiredExtensions);
anonPass.IsPhantom = true;
Expand Down
5 changes: 5 additions & 0 deletions Editor/API/Model/Constraint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,10 @@ internal struct Constraint
public int DeclaredLine;
public PassKey First, Second;
public ConstraintType Type;

public override string ToString()
{
return $"{First} {Type} {Second}";
}
}
}
2 changes: 2 additions & 0 deletions Editor/API/Model/SolverContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ public InnatePhases GetPluginPhases(BuildPhase phase, string pluginQualifiedName
{
phases = new InnatePhases(phase, pluginQualifiedName);
_innatePhases[(pluginQualifiedName, phase)] = phases;
Passes.Add(phases.PluginStart);
Passes.Add(phases.PluginEnd);
}

return phases;
Expand Down
5 changes: 5 additions & 0 deletions Editor/API/Model/SolverPass.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,10 @@ internal SolverPass(IPlugin plugin, IPass pass, BuildPhase phase, IImmutableSet<
RequiredExtensions = requiredExtensions;
CompatibleExtensions = compatibleExtensions;
}

public override string ToString()
{
return Pass.DisplayName;
}
}
}
11 changes: 10 additions & 1 deletion Editor/API/Solver/PluginResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections.Immutable;
using System.Linq;
using nadena.dev.ndmf.model;
using UnityEngine;

#endregion

Expand Down Expand Up @@ -142,7 +143,15 @@ public PluginResolver(IEnumerable<IPlugin> pluginTemplates)
constraintsByPhase.TryGetValue(phase, out var constraintList)
? constraintList
: new List<(SolverPass, SolverPass, ConstraintType)>();

#if NDMF_INTERNAL_DEBUG
var dumpString = "";
foreach (var constraint in constraints)
{
dumpString += $"\"{constraint.Item1.PassKey.QualifiedName}\" -> \"{constraint.Item2.PassKey.QualifiedName}\" [label=\"{constraint.Item3}\"];\n";
}
Debug.Log(dumpString);
#endif

var sorted = TopoSort.DoSort(passes, constraints);

var concrete = ToConcretePasses(phase, sorted);
Expand Down
18 changes: 16 additions & 2 deletions Editor/UI/Menus.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ namespace nadena.dev.ndmf.ui
internal static class Menus
{
private const string APPLY_ON_PLAY_MENU_NAME = "Tools/NDM Framework/Apply on Play";
private const string TOPLEVEL_MANUAL_BAKE_MENU_NAME = "Tools/NDM Framework/Manual bake avatar";
private const int APPLY_ON_PLAY_PRIO = 1;
private const int TOPLEVEL_MANUAL_BAKE_PRIO = 2;

[InitializeOnLoadMethod]
static void Init()
Expand All @@ -24,18 +26,30 @@ static void Init()
// so we'll keep that entry.
#if !MODULAR_AVATAR
[MenuItem("GameObject/[NDMF] Manual bake avatar", true, 49)]
internal static bool ValidateApplyToCurrentAvatarGameobject()
private static bool ValidateManualBakeGameObject()
{
return AvatarProcessor.CanProcessObject(Selection.activeGameObject);
}

[MenuItem("GameObject/[NDMF] Manual bake avatar", false, 49)]
public static void ApplyToCurrentAvatarGameobject()
private static void ManualBakeGameObject()
{
AvatarProcessor.ProcessAvatarUI(Selection.activeGameObject);
}
#endif

[MenuItem(TOPLEVEL_MANUAL_BAKE_MENU_NAME, true, TOPLEVEL_MANUAL_BAKE_PRIO)]
private static bool ValidateManualBakeToplevel()
{
return AvatarProcessor.CanProcessObject(Selection.activeGameObject);
}

[MenuItem(TOPLEVEL_MANUAL_BAKE_MENU_NAME, false, TOPLEVEL_MANUAL_BAKE_PRIO)]
private static void ManualBakeToplevel()
{
AvatarProcessor.ProcessAvatarUI(Selection.activeGameObject);
}

[MenuItem(APPLY_ON_PLAY_MENU_NAME, false, APPLY_ON_PLAY_PRIO)]
private static void ApplyOnPlay()
{
Expand Down
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Future plans include:

## Project status

This project is currently in a pre-alpha state. Expect large-scale refactoring, including renaming of the project itself, in the coming weeks. The framework is however functional, and you can take a look at the draft PRs for [Modular Avatar](https://github.com/bdunderscore/modular-avatar/pull/406) and [AAO](https://github.com/anatawa12/AvatarOptimizer/pull/375) to see examples of usage.
This project is currently considered API-stable, but is still very new. Please report any bugs you run into!

## Getting started

Expand Down
10 changes: 3 additions & 7 deletions Runtime/ApplyOnPlayGlobalActivator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,9 @@ class ApplyOnPlayGlobalActivator : MonoBehaviour

static ApplyOnPlayGlobalActivator()
{
SceneManager.sceneLoaded += (scene, mode) =>
{
if (scene.IsValid())
{
EditorApplication.delayCall += () => CreateIfNotPresent(scene);
}
};
void DelayCreateIfNotPresent(Scene scene) => EditorApplication.delayCall += () => CreateIfNotPresent(scene);
EditorSceneManager.newSceneCreated += (scene, setup, mode) => DelayCreateIfNotPresent(scene);
EditorSceneManager.sceneOpened += (scene, mode) => DelayCreateIfNotPresent(scene);

EditorApplication.delayCall += () => CreateIfNotPresent(SceneManager.GetActiveScene());
}
Expand Down
8 changes: 8 additions & 0 deletions UnitTests~/PluginResolverTests.meta

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

56 changes: 56 additions & 0 deletions UnitTests~/PluginResolverTests/BeforeAfterPlugin.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using System.Collections.Immutable;
using System.Linq;
using nadena.dev.ndmf;
using NUnit.Framework;
using PlasticPipe.PlasticProtocol.Messages;

namespace UnitTests.PluginResolverTests
{
class PluginA : Plugin<PluginA>
{
protected override void Configure()
{
InPhase(BuildPhase.Generating)
.AfterPlugin<PluginB>()
.Run("PluginA", _ctx => { });
}
}

class PluginB : Plugin<PluginB>
{
protected override void Configure()
{
InPhase(BuildPhase.Generating)
.Run("PluginB", _ctx => { });
}
}

class PluginC : Plugin<PluginC>
{
protected override void Configure()
{
InPhase(BuildPhase.Generating)
.BeforePlugin<PluginB>()
.Run("PluginC", _ctx => { });
}
}

public class BeforeAfterPlugin
{
[Test]
public void TestBeforeAfterPluginConstraints()
{
var resolver = new PluginResolver(new IPlugin[]
{
PluginA.Instance, PluginB.Instance, PluginC.Instance
});
var passNames = resolver.Passes.SelectMany(kv => kv.Item2)
.Select(pass => pass.Description)
.ToImmutableList();

var wantedPassNames = ImmutableList.Create("PluginC", "PluginB", "PluginA");

Assert.That(passNames, Is.EqualTo(wantedPassNames));
}
}
}
11 changes: 11 additions & 0 deletions UnitTests~/PluginResolverTests/BeforeAfterPlugin.cs.meta

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

43 changes: 43 additions & 0 deletions UnitTests~/PluginResolverTests/SupportsMultipleDeclarations.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using System.Collections.Immutable;
using System.Linq;
using nadena.dev.ndmf;
using NUnit.Framework;
using UnitTests.ExportsPluginTest;

[assembly: ExportsPlugin(typeof(PluginA))]
[assembly: ExportsPlugin(typeof(PluginB))]

namespace UnitTests.ExportsPluginTest
{
internal class PluginA : Plugin<PluginA>
{
protected override void Configure()
{
InPhase(BuildPhase.Transforming).Run("test", _ctx => { });
}
}

internal class PluginB : Plugin<PluginB>
{
protected override void Configure()
{
InPhase(BuildPhase.Transforming).Run("test", _ctx => { });
}
}

public class SupportsMultipleDeclarations
{
[Test]
public void TestSupportsMultipleDeclarations()
{
var resolver = new PluginResolver();
var plugins =
resolver.Passes.SelectMany(kv => kv.Item2) // passes per phase
.Select(pass => pass.Plugin.GetType())
.ToImmutableHashSet();

Assert.IsTrue(plugins.Contains(typeof(PluginA)));
Assert.IsTrue(plugins.Contains(typeof(PluginB)));
}
}
}

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

4 changes: 2 additions & 2 deletions docfx~/index.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# NDM Framework

NFM Framework ("Nademof" for short) is a framework for running non-destructive build plugins when building avatars for
NDM Framework ("Nademof" for short) is a framework for running non-destructive build plugins when building avatars for
VRChat (and, eventually, for other VRSNS platforms).

## Why is this needed?
Expand Down Expand Up @@ -41,4 +41,4 @@ For more information, see the [API documentation](api/index.html) or the other a

## Support model

NDMF is currently in an alpha state. The API is not fully stable yet - hopefully soon, though!
See the [Versioning policy](versioning-policy.html) for more information.
3 changes: 0 additions & 3 deletions docfx~/versioning-policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,3 @@ are declared, the order of execution of the two passes is not fully determined.
to determine the order of execution. NDMF will strive not to change this heuristic between patch releases, but it may
change on minor releases. If you run into problems with changes in a heuristic, please constrain the order of execution
of your passes explicitly.

**Versions before 1.0.0**: Versions starting with 0.x.y are considered to be unstable and do not guarantee API stability.
We will make a best-effort attempt to increment the "x" version when making incompatible changes.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "nadena.dev.ndmf",
"displayName": "Non-Destructive Modular Framework",
"version": "1.0.2",
"version": "1.1.0",
"unity": "2019.4",
"description": "A framework for building non-destructive plugins for VRChat Avatar 3.0",
"vrchatVersion": "2022.1.1",
Expand Down

0 comments on commit 1cbfc0b

Please sign in to comment.