Last active
March 1, 2026 01:58
-
-
Save kokeiro001/38530ebdf7aa4a813aeb08a9dba2c842 to your computer and use it in GitHub Desktop.
Unity TimelineClipの背景色変更
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using UnityEditor; | |
| using UnityEngine; | |
| using UnityEngine.Timeline; | |
| /// <summary> | |
| /// Timeline の <see cref="ClipEditor.DrawBackground"/> で使える、 | |
| /// 汎用クリップ背景描画ユーティリティ | |
| /// </summary> | |
| public static class TimelineClipGUI | |
| { | |
| /// <summary>グラデーションテクスチャの幅</summary> | |
| private const int GradTextureWidth = 32; | |
| /// <summary> | |
| /// hasBlendIn 時の bottomLeft.x 補正値。<br/> | |
| /// ClipBackgroundRegion の rect はクリップ枠線の内側領域を指すため、 | |
| /// mixInWidth の位置と実際の輪郭線が枠線幅 + AA にじみ分ずれる。その経験的補正値。 | |
| /// </summary> | |
| private const float DefaultBlendInBorderOffset = 3f; | |
| /// <summary>グラデーションテクスチャ(左=透明、右=不透明 の ease-in)。ドメインリロード後に null になるため、アクセス時に再生成する。</summary> | |
| private static Texture2D _gradientTex; | |
| /// <summary>通常向き UV(左=透明、右=不透明)。MixIn で使用。</summary> | |
| private static readonly Rect UVNormal = new Rect(0f, 0f, 1f, 1f); | |
| /// <summary>水平反転 UV(左=不透明、右=透明)。MixOut で使用。</summary> | |
| private static readonly Rect UVFlipped = new Rect(1f, 0f, -1f, 1f); | |
| /// <summary> | |
| /// MixIn/MixOut 区間を ease カーブのアルファグラデーションで塗りつぶす | |
| /// </para> | |
| public static void DrawGradient(Rect rect, TimelineClip clip, Color baseColor) | |
| { | |
| float clipDuration = (float)clip.duration; | |
| if (clipDuration <= 0f) | |
| { | |
| return; | |
| } | |
| if (Event.current.type != EventType.Repaint) | |
| { | |
| return; | |
| } | |
| float mixInWidth = ToPixels(rect.width, clip.mixInDuration, clipDuration); | |
| float mixOutWidth = ToPixels(rect.width, clip.mixOutDuration, clipDuration); | |
| // 中央(MixIn終端〜MixOut開始) | |
| float centerX = rect.x + mixInWidth; | |
| float centerWidth = rect.width - mixInWidth - mixOutWidth; | |
| if (centerWidth > 0f) | |
| { | |
| EditorGUI.DrawRect(new Rect(centerX, rect.y, centerWidth, rect.height), baseColor); | |
| } | |
| // GUI.color でテクスチャをベースカラーにティント | |
| Color previousGUIColor = GUI.color; | |
| GUI.color = baseColor; | |
| // MixIn グラデーション: テクスチャを通常向きで引き伸ばす(左=透明、右=不透明) | |
| if (mixInWidth > 0f) | |
| { | |
| DrawGradientRegion(new Rect(rect.x, rect.y, mixInWidth, rect.height), UVNormal); | |
| } | |
| // MixOut グラデーション: UV を水平反転して引き伸ばす(左=不透明、右=透明) | |
| if (mixOutWidth > 0f) | |
| { | |
| DrawGradientRegion(new Rect(rect.xMax - mixOutWidth, rect.y, mixOutWidth, rect.height), UVFlipped); | |
| } | |
| GUI.color = previousGUIColor; | |
| } | |
| /// <summary>グラデーションを指定領域に描画する</summary> | |
| private static void DrawGradientRegion(Rect rect, Rect uv) | |
| { | |
| if (_gradientTex == null) | |
| { | |
| _gradientTex = new Texture2D(GradTextureWidth, 1, TextureFormat.RGBA32, mipChain: false) | |
| { | |
| wrapMode = TextureWrapMode.Clamp, | |
| filterMode = FilterMode.Bilinear, | |
| hideFlags = HideFlags.HideAndDontSave, | |
| }; | |
| var pixels = new Color[GradTextureWidth]; | |
| for (int i = 0; i < GradTextureWidth; i++) | |
| { | |
| float t = (i + 0.5f) / GradTextureWidth; | |
| pixels[i] = new Color(1f, 1f, 1f, t * t); | |
| } | |
| _gradientTex.SetPixels(pixels); | |
| _gradientTex.Apply(updateMipmaps: false); | |
| } | |
| GUI.DrawTextureWithTexCoords(rect, _gradientTex, uv); | |
| } | |
| /// <summary> | |
| /// クリップ輪郭に合わせた凸四角形で塗りつぶす。 | |
| /// | |
| /// <para> | |
| /// クリップ形状は常に4頂点の凸多角形で表現できる。<br/> | |
| /// MixIn 斜辺の向きは <see cref="TimelineClip.hasBlendIn"/> で決まる。<br/> | |
| /// - <c>hasBlendIn == true</c>(直前クリップとブレンド中): <c>\</c> 形<br/> | |
| /// - <c>hasBlendIn == false</c>(EaseIn のみ) : <c>/</c> 形<br/> | |
| /// MixOut 斜辺は常に <c>\</c> 形。 | |
| /// </para> | |
| /// | |
| /// <code> | |
| /// hasBlendIn=true の例(\ + \): | |
| /// topLeft _________ topRight | |
| /// | \ | |
| /// |____________\ bottomRight | |
| /// bottomLeft | |
| /// </code> | |
| /// </summary> | |
| public static void DrawSolid(Rect rect, TimelineClip clip, Color baseColor) | |
| { | |
| float clipDuration = (float)clip.duration; | |
| if (clipDuration <= 0f) | |
| { | |
| return; | |
| } | |
| if (Event.current.type != EventType.Repaint) | |
| { | |
| return; | |
| } | |
| float mixInWidth = ToPixels(rect.width, clip.mixInDuration, clipDuration); | |
| float mixOutWidth = ToPixels(rect.width, clip.mixOutDuration, clipDuration); | |
| float top = rect.y; | |
| float bottom = rect.yMax; | |
| float left = rect.x; | |
| float right = rect.xMax; | |
| // MixIn: hasBlendIn=true → \ 形、false → / 形 | |
| Vector3 topLeft, bottomLeft; | |
| if (clip.hasBlendIn) | |
| { | |
| // \ 形: 左上 → MixIn終端下へ斜辺 | |
| topLeft = new Vector3(left, top); | |
| bottomLeft = new Vector3(left + mixInWidth - DefaultBlendInBorderOffset, bottom); | |
| } | |
| else | |
| { | |
| // / 形: 左下 → MixIn終端上へ斜辺 | |
| topLeft = new Vector3(left + mixInWidth, top); | |
| bottomLeft = new Vector3(left, bottom); | |
| } | |
| // MixOut: 常に \ 形(MixOut開始上 → 右下へ斜辺) | |
| var topRight = new Vector3(right - mixOutWidth, top); | |
| var bottomRight = new Vector3(right, bottom); | |
| Handles.BeginGUI(); | |
| Color previousHandlesColor = Handles.color; | |
| Handles.color = baseColor; | |
| Handles.DrawAAConvexPolygon(topLeft, topRight, bottomRight, bottomLeft); | |
| Handles.color = previousHandlesColor; | |
| Handles.EndGUI(); | |
| } | |
| /// <summary>duration をピクセル幅に変換する。</summary> | |
| private static float ToPixels(float totalWidth, double duration, float clipDuration) | |
| { | |
| return totalWidth * Mathf.Clamp01((float)duration / clipDuration); | |
| } | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
DrawSolid
DrawGradient