Skip to content

Instantly share code, notes, and snippets.

@kokeiro001
Last active March 1, 2026 01:58
Show Gist options
  • Select an option

  • Save kokeiro001/38530ebdf7aa4a813aeb08a9dba2c842 to your computer and use it in GitHub Desktop.

Select an option

Save kokeiro001/38530ebdf7aa4a813aeb08a9dba2c842 to your computer and use it in GitHub Desktop.
Unity TimelineClipの背景色変更
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);
}
}
@kokeiro001
Copy link
Author

DrawSolid

image

DrawGradient

image

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