Skip to content

Instantly share code, notes, and snippets.

@alankent
Created February 16, 2023 18:31
Show Gist options
  • Save alankent/383cbda8adf8ba4aad1235a77c2e2d83 to your computer and use it in GitHub Desktop.
Save alankent/383cbda8adf8ba4aad1235a77c2e2d83 to your computer and use it in GitHub Desktop.
using System.Linq;
using UnityEditor;
using UnityEditor.Timeline;
using UnityEditor.Timeline.Actions;
using UnityEngine;
using UnityEngine.Timeline;
// Adding a new menu item to the move/rotate etc commands would be cooler!
// https://github.com/Unity-Technologies/UnityCsReference/blob/master/Editor/Mono/GUI/Tools/BuiltinTools.cs
// Also https://github.com/HiddenMonk/Unity3DRuntimeTransformGizmo looked interesting (a move gizmo)
// See https://docs.unity3d.com/ScriptReference/MenuItem.html
#if UNITY_EDITOR
namespace OrdinaryCartoonMaker
{
[MenuEntry("Mark Object Position", MenuPriority.CustomTimelineActionSection.start)]
public class MarkAnimatedCharacterMenuItem : TimelineAction
{
public static bool markedPositionSet = false;
public static Vector3 markedPosition;
public static AnimationTrack markedPositionTrack;
public override bool Execute(ActionContext context)
{
var track = context.tracks.First() as AnimationTrack;
var binding = context.director.GetGenericBinding(track) as Animator;
markedPosition = binding.transform.localPosition;
Debug.Log("MARKING POSITION");
Debug.Log(markedPosition);
markedPositionSet = true;
markedPositionTrack = track;
return true;
}
public override ActionValidity Validate(ActionContext context)
{
if (!context.tracks.Any())
{
return ActionValidity.NotApplicable;
}
var track = context.tracks.First() as AnimationTrack;
if (track != null && context.director != null)
{
// TODO: Really should be cleared when selection changes to a different track.
if (track != markedPositionTrack)
{
markedPositionSet = false;
markedPositionTrack = null;
}
var binding = context.director.GetGenericBinding(track);
if (binding != null)
{
return ActionValidity.Valid;
}
}
return ActionValidity.Invalid;
}
}
[MenuEntry("Move Object Position", MenuPriority.CustomTimelineActionSection.start)]
public class MoveAnimatedCharacterMenuItem : TimelineAction
{
public override bool Execute(ActionContext context)
{
var track = context.tracks.First() as AnimationTrack;
var binding = context.director.GetGenericBinding(track) as Animator;
var deltaMovement = binding.transform.localPosition - MarkAnimatedCharacterMenuItem.markedPosition;
Debug.Log(deltaMovement);
Undo.RegisterCompleteObjectUndo(binding.gameObject, "Move animated object position");
var originalTrackMute = track.muted;
track.muted = true;
TimelineEditor.Refresh(RefreshReason.ContentsAddedOrRemoved);
binding.transform.localPosition += deltaMovement;
track.muted = originalTrackMute;
TimelineEditor.Refresh(RefreshReason.ContentsAddedOrRemoved);
return true;
}
public override ActionValidity Validate(ActionContext context)
{
if (!context.tracks.Any() || !MarkAnimatedCharacterMenuItem.markedPositionSet)
{
return ActionValidity.NotApplicable;
}
var track = context.tracks.First() as AnimationTrack;
if (track != null && context.director != null)
{
var binding = context.director.GetGenericBinding(track);
if (binding != null)
{
return ActionValidity.Valid;
}
}
return ActionValidity.Invalid;
}
}
}
#endif
@alankent
Copy link
Author

Line 102, should probably should also add "binding.localPosition != markedPosition" so menu item only appears if character is moved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment