Skip to content

Commit

Permalink
Custom targets grouping
Browse files Browse the repository at this point in the history
  • Loading branch information
acidbubbles committed Sep 13, 2022
1 parent 13077ee commit a4b6a54
Show file tree
Hide file tree
Showing 14 changed files with 104 additions and 6 deletions.
1 change: 1 addition & 0 deletions VamTimeline.AtomAnimation.cslist
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ src\UI\Screens\BulkScreen.cs
src\UI\Screens\ControllerTargetSettingsScreen.cs
src\UI\Screens\DiagnosticsScreen.cs
src\UI\Screens\EditAnimationScreen.cs
src\UI\Screens\GroupingScreen.cs
src\UI\Screens\HelpScreen.cs
src\UI\Screens\ImportAssignScreen.cs
src\UI\Screens\ImportExportScreen.cs
Expand Down
1 change: 1 addition & 0 deletions VamTimeline.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@
<Compile Include="src\UI\Screens\ControllerTargetSettingsScreen.cs" />
<Compile Include="src\UI\Screens\DiagnosticsScreen.cs" />
<Compile Include="src\UI\Screens\EditAnimationScreen.cs" />
<Compile Include="src\UI\Screens\GroupingScreen.cs" />
<Compile Include="src\UI\Screens\HelpScreen.cs" />
<Compile Include="src\UI\Screens\ImportAssignScreen.cs" />
<Compile Include="src\UI\Screens\ImportExportScreen.cs" />
Expand Down
1 change: 1 addition & 0 deletions meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@
"Custom\\Scripts\\AcidBubbles\\Timeline\\src\\UI\\Screens\\ControllerTargetSettingsScreen.cs",
"Custom\\Scripts\\AcidBubbles\\Timeline\\src\\UI\\Screens\\DiagnosticsScreen.cs",
"Custom\\Scripts\\AcidBubbles\\Timeline\\src\\UI\\Screens\\EditAnimationScreen.cs",
"Custom\\Scripts\\AcidBubbles\\Timeline\\src\\UI\\Screens\\GroupingScreen.cs",
"Custom\\Scripts\\AcidBubbles\\Timeline\\src\\UI\\Screens\\HelpScreen.cs",
"Custom\\Scripts\\AcidBubbles\\Timeline\\src\\UI\\Screens\\ImportAssignScreen.cs",
"Custom\\Scripts\\AcidBubbles\\Timeline\\src\\UI\\Screens\\ImportExportScreen.cs",
Expand Down
2 changes: 2 additions & 0 deletions src/AtomAnimations/Animatables/Base/AnimationTargetBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ public bool collapsed
}
}

public string group { get; set; }

public string name => animatableRef.name;
public string GetShortName() => animatableRef.GetShortName();
public string GetFullName() => animatableRef.GetFullName();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public interface IAtomAnimationTarget : IDisposable
string name { get; }
bool selected { get; set; }
bool collapsed { get; set; }
string group { get; set; }
IAtomAnimationClip clip { get; set; }

void Validate(float animationLength);
Expand Down
2 changes: 1 addition & 1 deletion src/AtomAnimations/Animations/AtomAnimation.Playback.cs
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,7 @@ public void SampleParentedControllers(AtomAnimationClip source)
if (simulationFrozen) return;
if (_globalScaledWeight <= 0) return;
// TODO: Index keep track if there is any parenting
if (source == null) return;
var layers = GetMainAndBestSiblingPerLayer(playingAnimationSegmentId, source.animationNameId, source.animationSetId);
for (var layerIndex = 0; layerIndex < layers.Count; layerIndex++)
{
Expand All @@ -637,7 +638,6 @@ public void SampleParentedControllers(AtomAnimationClip source)
if (controller.currentPositionState != FreeControllerV3.PositionState.Off)
controller.control.position = Vector3.Lerp(controller.control.position, targetPosition, _globalWeight);
}

var rotationParentRB = ctrl.GetRotationParentRB();
if (!ReferenceEquals(rotationParentRB, null))
{
Expand Down
10 changes: 6 additions & 4 deletions src/AtomAnimations/Animations/AtomAnimationClip.cs
Original file line number Diff line number Diff line change
Expand Up @@ -615,17 +615,19 @@ public void DirtyAll()
public IEnumerable<IAtomAnimationTargetsList> GetTargetGroups()
{
yield return targetTriggers;
foreach (var group in targetControllers.GroupBy(t => t.animatableRef.groupKey))
foreach (var group in targetControllers.GroupBy(t => t.group ?? t.animatableRef.groupKey))
{
yield return new AtomAnimationTargetsList<FreeControllerV3AnimationTarget>(group) { label = group.First().animatableRef.groupLabel };
var first = group.First();
yield return new AtomAnimationTargetsList<FreeControllerV3AnimationTarget>(group) { label = first.group ?? first.animatableRef.groupLabel };
}
foreach (var target in targetFloatParams)
{
target.animatableRef.EnsureAvailable();
}
foreach (var group in targetFloatParams.GroupBy(t => t.animatableRef.groupKey))
foreach (var group in targetFloatParams.GroupBy(t => t.group ?? t.animatableRef.groupKey))
{
yield return new AtomAnimationTargetsList<JSONStorableFloatAnimationTarget>(group) { label = group.First().animatableRef.groupLabel };
var first = group.First();
yield return new AtomAnimationTargetsList<JSONStorableFloatAnimationTarget>(group) { label = first.group ?? first.animatableRef.groupLabel };
}
}

Expand Down
6 changes: 5 additions & 1 deletion src/AtomAnimations/Operations/AddAnimationOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,19 +69,20 @@ public CreatedAnimation AddAnimation(AtomAnimationClip source, string animationN
{
if (!origTarget.animatableRef.EnsureAvailable(false)) continue;
var newTarget = clip.Add(new JSONStorableFloatAnimationTarget(origTarget));
newTarget.group = origTarget.group;
newTarget.value.keys = new List<BezierKeyframe>(origTarget.value.keys);
newTarget.dirty = true;
}

foreach (var origTarget in source.targetTriggers)
{
var newTarget = clip.Add(new TriggersTrackAnimationTarget(origTarget.animatableRef, _animation.logger));
newTarget.group = origTarget.group;
foreach (var origTrigger in origTarget.triggersMap)
{
var trigger = newTarget.CreateKeyframe(origTrigger.Key);
trigger.RestoreFromJSON(origTrigger.Value.GetJSON());
}

newTarget.dirty = true;
}

Expand All @@ -101,13 +102,15 @@ public CreatedAnimation AddAnimation(AtomAnimationClip source, string animationN
{
if (!origTarget.animatableRef.EnsureAvailable(false)) continue;
var newTarget = clip.Add(origTarget.animatableRef);
newTarget.group = origTarget.group;
newTarget.SetKeyframeToCurrent(0f);
newTarget.SetKeyframeToCurrent(clip.animationLength);
}

foreach (var origTarget in source.targetTriggers)
{
var newTarget = new TriggersTrackAnimationTarget(origTarget.animatableRef, _animation.logger);
newTarget.group = origTarget.group;
newTarget.AddEdgeFramesIfMissing(clip.animationLength);
clip.Add(newTarget);
}
Expand Down Expand Up @@ -183,6 +186,7 @@ private static FreeControllerV3AnimationTarget CopyTarget(AtomAnimationClip clip
newTarget.weight = origTarget.weight;
newTarget.controlPosition = origTarget.controlPosition;
newTarget.controlRotation = origTarget.controlRotation;
newTarget.group = origTarget.group;
return newTarget;
}

Expand Down
16 changes: 16 additions & 0 deletions src/AtomAnimations/Serialization/AtomAnimationSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ private void DeserializeClip(AtomAnimationClip clip, JSONClass clipJSON, Animata
target.controlPosition = DeserializeBool(controllerJSON["ControlPosition"], true);
target.controlRotation = DeserializeBool(controllerJSON["ControlRotation"], true);
target.weight = DeserializeFloat(controllerJSON["Weight"], 1f);
target.group = DeserializeString(controllerJSON["Group"], null);
if (controllerJSON.HasKey("Parent"))
{
var parentJSON = controllerJSON["Parent"].AsObject;
Expand Down Expand Up @@ -232,6 +233,7 @@ private void DeserializeClip(AtomAnimationClip clip, JSONClass clipJSON, Animata
SuperController.LogError($"Timeline: Float param {atom.name} / {storableId} / {floatParamName} was added more than once in clip {clip.animationNameQualified}. Dropping second instance.");
continue;
}
target.group = DeserializeString(paramJSON["Group"], null);
var dirty = false;
DeserializeCurve(target.value, paramJSON["Value"], ref dirty);
target.AddEdgeFramesIfMissing(clip.animationLength);
Expand Down Expand Up @@ -263,6 +265,7 @@ private void DeserializeClip(AtomAnimationClip clip, JSONClass clipJSON, Animata
SuperController.LogError($"The triggers track {triggerTrackName} exists more than once in clip {clip.animationNameQualified}. Trigger keyframes may be overwritten.");
}
}
target.group = DeserializeString(triggerJSON["Group"], null);
foreach (JSONClass entryJSON in triggerJSON["Triggers"].AsArray)
{
var trigger = target.CreateCustomTrigger();
Expand Down Expand Up @@ -547,6 +550,10 @@ private static void SerializeClipTargets(AtomAnimationClip clip, JSONClass clipJ
{
controllerJSON["Weight"] = target.weight.ToString(CultureInfo.InvariantCulture);
}
if (target.group != null)
{
controllerJSON["Group"] = target.group;
}
controllersJSON.Add(controllerJSON);
}
if(controllersJSON.Count > 0)
Expand All @@ -570,10 +577,15 @@ private static void SerializeClipTargets(AtomAnimationClip clip, JSONClass clipJ
}
paramJSON["Atom"] = target.animatableRef.storable.containingAtom.uid;
}
if (target.group != null)
{
paramJSON["Group"] = target.group;
}
var min = target.animatableRef.floatParam?.min ?? target.animatableRef.assignMinValueOnBound;
if (min != null) paramJSON["Min"] = min.Value.ToString(CultureInfo.InvariantCulture);
var max = target.animatableRef.floatParam?.max ?? target.animatableRef.assignMaxValueOnBound;
if (max != null) paramJSON["Max"] = max.Value.ToString(CultureInfo.InvariantCulture);

floatParamsJSON.Add(paramJSON);
}
if(floatParamsJSON.Count > 0)
Expand All @@ -587,6 +599,10 @@ private static void SerializeClipTargets(AtomAnimationClip clip, JSONClass clipJ
{"Name", target.name},
{"Live", target.animatableRef.live ? "1" : "0"},
};
if (target.group != null)
{
triggerJSON["Group"] = target.group;
}
var entriesJSON = new JSONArray();
foreach (var x in target.triggersMap.OrderBy(kvp => kvp.Key))
{
Expand Down
1 change: 1 addition & 0 deletions src/AtomPlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1103,6 +1103,7 @@ public void OnBindingsListRequested(List<object> bindings)
bindings.Add(new JSONStorableAction("OpenUI_MoreTab_Diagnostics", () => { ChangeScreen(DiagnosticsScreen.ScreenName, null); SelectAndOpenUI(); }));
bindings.Add(new JSONStorableAction("OpenUI_MoreTab_Options", () => { ChangeScreen(OptionsScreen.ScreenName, null); SelectAndOpenUI(); }));
bindings.Add(new JSONStorableAction("OpenUI_MoreTab_Logging", () => { ChangeScreen(LoggingScreen.ScreenName, null); SelectAndOpenUI(); }));
bindings.Add(new JSONStorableAction("OpenUI_MoreTab_Grouping", () => { ChangeScreen(GroupingScreen.ScreenName, null); SelectAndOpenUI(); }));
bindings.Add(new JSONStorableAction("Toggle_DopeSheetMode", () => _ui.ToggleDopeSheetMode()));
bindings.Add(new JSONStorableAction("Toggle_ExpandCollapseRightPanel", () => _ui.ToggleExpandCollapse()));
bindings.Add(new JSONStorableAction("Toggle_SelectAllTargets", () => animationEditContext.SelectAll(!animationEditContext.current.GetAllTargets().Any(t => t.selected))));
Expand Down
63 changes: 63 additions & 0 deletions src/UI/Screens/GroupingScreen.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using System.Linq;
using System.Text.RegularExpressions;

namespace VamTimeline
{
public class GroupingScreen : ScreenBase
{
public const string ScreenName = "Grouping";

private JSONStorableString _assignGroupJSON;

public override string screenId => ScreenName;

public override void Init(IAtomPlugin plugin, object arg)
{
base.Init(plugin, arg);

CreateChangeScreenButton("<b><</b> <i>Back</i>", MoreScreen.ScreenName);

InitAssignToGroupUI();

prefabFactory.CreateButton("Assign to selected targets").button.onClick.AddListener(Assign);

animation.animatables.onTargetsSelectionChanged.AddListener(OnTargetsSelectionChanged);
OnTargetsSelectionChanged();
}

private void InitAssignToGroupUI()
{
_assignGroupJSON = new JSONStorableString("Group name (empty for auto)", "");
prefabFactory.CreateTextInput(_assignGroupJSON);
}

private void OnTargetsSelectionChanged()
{
var groups = animationEditContext.GetSelectedTargets().Select(t => t.group).Distinct().ToList();
if (groups.Count == 1) _assignGroupJSON.val = groups[0];
}

private void Assign()
{
var group = _assignGroupJSON.val;
if (string.IsNullOrEmpty(group)) group = null;
foreach (var target in animationEditContext.GetSelectedTargets())
{
foreach (var c in animationEditContext.currentLayer)
{
var t = c.GetAllTargets().FirstOrDefault(x => x.TargetsSameAs(target));
if (t == null) continue;
t.group = group;
}
}
current.onTargetsListChanged.Invoke();
}

public override void OnDestroy()
{
animation.animatables.onTargetsSelectionChanged.RemoveListener(OnTargetsSelectionChanged);
base.OnDestroy();
}
}
}

1 change: 1 addition & 0 deletions src/UI/Screens/MoreScreen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public override void Init(IAtomPlugin plugin, object arg)

CreateChangeScreenButton("<b>Bulk</b> changes...", BulkScreen.ScreenName);
CreateChangeScreenButton("<b>Advanced</b> keyframe tools...", AdvancedKeyframeToolsScreen.ScreenName);
CreateChangeScreenButton("<b>Grouping</b>...", GroupingScreen.ScreenName);

prefabFactory.CreateSpacer();

Expand Down
4 changes: 4 additions & 0 deletions src/UI/Screens/ScreensManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,10 @@ private IEnumerator RefreshCurrentUIDeferred(string screen)
case LoggingScreen.ScreenName:
_current = screenContainer.AddComponent<LoggingScreen>();
break;
case GroupingScreen.ScreenName:
_current = screenContainer.AddComponent<GroupingScreen>();
break;

default:
throw new InvalidOperationException($"Unknown screen {screen}");
}
Expand Down
1 change: 1 addition & 0 deletions tests/VamTimeline.Tests.cslist
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@
..\src\UI\Screens\ControllerTargetSettingsScreen.cs
..\src\UI\Screens\DiagnosticsScreen.cs
..\src\UI\Screens\EditAnimationScreen.cs
..\src\UI\Screens\GroupingScreen.cs
..\src\UI\Screens\HelpScreen.cs
..\src\UI\Screens\ImportAssignScreen.cs
..\src\UI\Screens\ImportExportScreen.cs
Expand Down

0 comments on commit a4b6a54

Please sign in to comment.