Files
Project-M/Packages/com.rukhanka.animation/Rukhanka.Editor/WaybackMachine/TimelinePortalData.cs
T
2026-05-31 14:27:52 -07:00

133 lines
4.2 KiB
C#

using System;
using Rukhanka.WaybackMachine;
using Unity.Collections;
using Unity.Mathematics;
using UnityEngine;
///////////////////////////////////////////////////////////////////////////////////////////
namespace Rukhanka.Editor
{
public struct TimelinePortalData: IDisposable
{
public float frameSizeInSec;
public float2 frameRange, visibleRange;
public float contentWidth;
public int knobFrame;
public bool knobDragging;
public struct VLineDef
{
public bool majorTick;
public float2 lineFrom, lineTo;
public int frameIndex;
}
public NativeList<VLineDef> tickLines;
///////////////////////////////////////////////////////////////////////////////////////////
public void Construct()
{
tickLines = new (0xff, Allocator.Persistent);
}
///////////////////////////////////////////////////////////////////////////////////////////
public void SetKnobFromPos(float xPos)
{
var zeroFramePos = GetPosXForFrame(0);
var zeroRelativePos = xPos - zeroFramePos;
var fIndex = math.round(zeroRelativePos / OneFrameWidth());
knobFrame = (int)math.clamp(fIndex, frameRange.x, frameRange.y);
}
///////////////////////////////////////////////////////////////////////////////////////////
public float GetFrameForTime(float t) => t / frameSizeInSec;
///////////////////////////////////////////////////////////////////////////////////////////
public float GetTimeForFrame(float frame) => frame * frameSizeInSec;
///////////////////////////////////////////////////////////////////////////////////////////
public float GetFrameForPosX(float x) => GetFrameForTime(GetTimeForPosX(x));
///////////////////////////////////////////////////////////////////////////////////////////
public float GetPosXForFrame(int frameIndex)
{
var oneFrameWidth = OneFrameWidth();
var startOffset = visibleRange.x * oneFrameWidth;
var rv = frameIndex * oneFrameWidth - startOffset;
return rv;
}
///////////////////////////////////////////////////////////////////////////////////////////
public float GetKnobPosX() => GetPosXForFrame(knobFrame);
///////////////////////////////////////////////////////////////////////////////////////////
public float GetTimeForPosX(float xPos)
{
var oneFrameWidth = OneFrameWidth();
var startOffset = visibleRange.x * oneFrameWidth;
var rv = (xPos + startOffset) / oneFrameWidth * frameSizeInSec;
return rv;
}
///////////////////////////////////////////////////////////////////////////////////////////
public float OneFrameWidth()
{
var visibleFramesCount = visibleRange.y - visibleRange.x;
var oneFrameWidth = contentWidth / visibleFramesCount;
return oneFrameWidth;
}
///////////////////////////////////////////////////////////////////////////////////////////
public void ComputeTicks()
{
tickLines.Clear();
var oneFrameWidth = OneFrameWidth();
var d = WaybackMachineWindow.TIMELINE_TICKS_MIN_SKIP_SPACE / oneFrameWidth;
var skipStep = math.ceilpow2(math.max(1, (int)math.ceil(d)));
var prevStep = skipStep >> 1;
var lerpFactor = (d - prevStep) / (skipStep - prevStep) ;
var startIndex = (int)(math.floor(visibleRange.x / skipStep) * skipStep);
var endIndex = (int)math.ceil(visibleRange.y);
for (int i = startIndex; i < endIndex; i += skipStep)
{
var marked = math.select(1, 0, (i / skipStep & 1) == 0 || skipStep == 1);
var x0 = GetPosXForFrame(i);
var y0 = lerpFactor * marked;
// 0.5 offset for 1 point width lines
var lineP0 = new Vector2((int)x0 + 0.5f, y0);
var lineP1 = new Vector2(lineP0.x, 1);
var ld = new VLineDef
{
lineFrom = lineP0,
lineTo = lineP1,
majorTick = marked == 0,
frameIndex = i
};
tickLines.Add(ld);
}
}
///////////////////////////////////////////////////////////////////////////////////////////
public void Dispose()
{
tickLines.Dispose();
}
}
}