Timeline playback controls — transport icons, loop/bounce/rewind
- Replace all text buttons with SVG icon buttons (skip-back, step-back, play-back, play, pause, step-forward, skip-end) - Add rewind: separate play-backward button that flips direction - Add loop mode button with submenu (Loop / Bounce / Off) - Loop wraps at boundaries; Bounce reflects direction (ping-pong) - Start/end frames moved to flank the scrub slider as plain numbers - New icons: play-back.svg, loop.svg (FA repeat), bounce.svg (FA exchange-alt) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2021 Fonticons, Inc. --><path d="M0 168v-16c0-13.255 10.745-24 24-24h360V80c0-21.367 25.9-32 40.971-16.971l80 80c8.994 8.994 9.055 23.508 0 32.781l-80 80C409.956 271.748 384 261.641 384 240v-48H24c-13.255 0-24-10.745-24-24zm488 152H128v-48c0-21.591-25.993-31.806-40.971-16.971l-80 80c-9.055 9.273-8.994 23.787 0 32.781l80 80C102.1 463.93 128 453.686 128 432v-48h360c13.255 0 24-10.745 24-24v-16c0-13.255-10.745-24-24-24z"/></svg>
|
||||||
|
After Width: | Height: | Size: 680 B |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc. --><path d="M0 224c0 17.7 14.3 32 32 32s32-14.3 32-32c0-53 43-96 96-96H320v32c0 12.9 7.8 24.6 19.8 29.6s25.7 2.2 34.9-6.9l64-64c12.5-12.5 12.5-32.8 0-45.3l-64-64c-9.2-9.2-22.9-11.9-34.9-6.9S320 19.1 320 32V64H160C71.6 64 0 135.6 0 224zm512 64c0-17.7-14.3-32-32-32s-32 14.3-32 32c0 53-43 96-96 96H192v-32c0-12.9-7.8-24.6-19.8-29.6s-25.7-2.2-34.9 6.9l-64 64c-12.5 12.5-12.5 32.8 0 45.3l64 64c9.2 9.2 22.9 11.9 34.9 6.9s19.8-16.6 19.8-29.6V448h160c88.4 0 160-71.6 160-160z"/></svg>
|
||||||
|
After Width: | Height: | Size: 749 B |
@@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||||
|
<path d="M 472 60 L 472 452 L 40 256 Z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 112 B |
@@ -50,10 +50,13 @@ static const char* IconFilename(Icon icon) {
|
|||||||
case Icon::LayoutQuad: return "layout-quad.svg";
|
case Icon::LayoutQuad: return "layout-quad.svg";
|
||||||
case Icon::SkipBack: return "skip-back.svg";
|
case Icon::SkipBack: return "skip-back.svg";
|
||||||
case Icon::StepBack: return "step-back.svg";
|
case Icon::StepBack: return "step-back.svg";
|
||||||
|
case Icon::PlayBack: return "play-back.svg";
|
||||||
case Icon::Play: return "play.svg";
|
case Icon::Play: return "play.svg";
|
||||||
case Icon::Pause: return "pause.svg";
|
case Icon::Pause: return "pause.svg";
|
||||||
case Icon::StepForward: return "step-forward.svg";
|
case Icon::StepForward: return "step-forward.svg";
|
||||||
case Icon::SkipEnd: return "skip-end.svg";
|
case Icon::SkipEnd: return "skip-end.svg";
|
||||||
|
case Icon::Loop: return "loop.svg";
|
||||||
|
case Icon::Bounce: return "bounce.svg";
|
||||||
default: return nullptr;
|
default: return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -67,7 +70,8 @@ static constexpr Icon kAllIcons[] = {
|
|||||||
Icon::ToolSelect, Icon::ToolMove, Icon::ToolRotate, Icon::ToolScale,
|
Icon::ToolSelect, Icon::ToolMove, Icon::ToolRotate, Icon::ToolScale,
|
||||||
Icon::WorldSpace, Icon::LocalSpace, Icon::Grid, Icon::Antialias,
|
Icon::WorldSpace, Icon::LocalSpace, Icon::Grid, Icon::Antialias,
|
||||||
Icon::LayoutSingle, Icon::LayoutHSplit, Icon::LayoutVSplit, Icon::LayoutQuad,
|
Icon::LayoutSingle, Icon::LayoutHSplit, Icon::LayoutVSplit, Icon::LayoutQuad,
|
||||||
Icon::SkipBack, Icon::StepBack, Icon::Play, Icon::Pause, Icon::StepForward, Icon::SkipEnd,
|
Icon::SkipBack, Icon::StepBack, Icon::PlayBack, Icon::Play, Icon::Pause,
|
||||||
|
Icon::StepForward, Icon::SkipEnd, Icon::Loop, Icon::Bounce,
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -43,10 +43,13 @@ enum class Icon {
|
|||||||
// Timeline transport
|
// Timeline transport
|
||||||
SkipBack, // go to first frame (|◀)
|
SkipBack, // go to first frame (|◀)
|
||||||
StepBack, // previous frame (◀◀)
|
StepBack, // previous frame (◀◀)
|
||||||
|
PlayBack, // play in reverse (◀)
|
||||||
Play, // play (▶)
|
Play, // play (▶)
|
||||||
Pause, // pause (⏸)
|
Pause, // pause (⏸)
|
||||||
StepForward, // next frame (▶▶)
|
StepForward, // next frame (▶▶)
|
||||||
SkipEnd, // go to last frame (▶|)
|
SkipEnd, // go to last frame (▶|)
|
||||||
|
Loop, // loop toggle (↻)
|
||||||
|
Bounce, // bounce/ping-pong (↔)
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Loads SVG files from disk, rasterizes them with NanoSVG, uploads them as
|
/// Loads SVG files from disk, rasterizes them with NanoSVG, uploads them as
|
||||||
|
|||||||
+178
-39
@@ -13,6 +13,7 @@ void TimelinePanel::SetStage(pxr::UsdStageRefPtr stage)
|
|||||||
{
|
{
|
||||||
m_stage = stage;
|
m_stage = stage;
|
||||||
m_playing = false;
|
m_playing = false;
|
||||||
|
m_reversed = false;
|
||||||
|
|
||||||
m_startFrame = 1.0;
|
m_startFrame = 1.0;
|
||||||
m_endFrame = 100.0;
|
m_endFrame = 100.0;
|
||||||
@@ -27,8 +28,6 @@ void TimelinePanel::SetStage(pxr::UsdStageRefPtr stage)
|
|||||||
}
|
}
|
||||||
if (m_endFrame < m_startFrame) m_endFrame = m_startFrame;
|
if (m_endFrame < m_startFrame) m_endFrame = m_startFrame;
|
||||||
|
|
||||||
// Always notify on stage change so consumers pick up the new range,
|
|
||||||
// even when the numeric frame happens to be unchanged.
|
|
||||||
m_currentFrame = m_startFrame;
|
m_currentFrame = m_startFrame;
|
||||||
NotifyTimeChanged();
|
NotifyTimeChanged();
|
||||||
}
|
}
|
||||||
@@ -37,20 +36,61 @@ void TimelinePanel::SetStage(pxr::UsdStageRefPtr stage)
|
|||||||
void TimelinePanel::Update(float deltaTime)
|
void TimelinePanel::Update(float deltaTime)
|
||||||
{
|
{
|
||||||
if (!m_playing) return;
|
if (!m_playing) return;
|
||||||
double next = m_currentFrame + double(deltaTime) * m_fps;
|
|
||||||
if (next > m_endFrame) {
|
double playStart = m_startFrame;
|
||||||
double span = m_endFrame - m_startFrame;
|
double playEnd = m_endFrame;
|
||||||
|
double sign = m_reversed ? -1.0 : 1.0;
|
||||||
|
double next = m_currentFrame + sign * double(deltaTime) * m_fps;
|
||||||
|
|
||||||
|
if (m_reversed && next < playStart) {
|
||||||
|
switch (m_loopMode) {
|
||||||
|
case LoopMode::Loop: {
|
||||||
|
double span = playEnd - playStart;
|
||||||
next = (span > 0.0)
|
next = (span > 0.0)
|
||||||
? m_startFrame + std::fmod(next - m_startFrame, span)
|
? playEnd - std::fmod(playStart - next, span)
|
||||||
: m_startFrame;
|
: playEnd;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
case LoopMode::Bounce:
|
||||||
|
next = playStart + (playStart - next); // reflect
|
||||||
|
m_reversed = false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
next = playStart;
|
||||||
|
m_playing = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (!m_reversed && next > playEnd) {
|
||||||
|
switch (m_loopMode) {
|
||||||
|
case LoopMode::Loop: {
|
||||||
|
double span = playEnd - playStart;
|
||||||
|
next = (span > 0.0)
|
||||||
|
? playStart + std::fmod(next - playStart, span)
|
||||||
|
: playStart;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LoopMode::Bounce:
|
||||||
|
next = playEnd - (next - playEnd); // reflect
|
||||||
|
m_reversed = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
next = playEnd;
|
||||||
|
m_playing = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SetCurrentFrame(next);
|
SetCurrentFrame(next);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
void TimelinePanel::Render()
|
void TimelinePanel::Render()
|
||||||
{
|
{
|
||||||
// ---- Transport row: icon buttons | start/end range | fps | auto-key ----
|
// Shared colours for active (pressed-in) toggle buttons.
|
||||||
|
const ImVec4 kActive (0.26f, 0.59f, 0.98f, 1.00f);
|
||||||
|
const ImVec4 kActiveHv(0.36f, 0.69f, 1.00f, 1.00f);
|
||||||
|
|
||||||
|
// Plain icon button (no active-state colouring).
|
||||||
auto iconBtn = [&](const char* id, Icon icon, const char* fallback) -> bool {
|
auto iconBtn = [&](const char* id, Icon icon, const char* fallback) -> bool {
|
||||||
if (m_iconManager) {
|
if (m_iconManager) {
|
||||||
ImTextureID tex = m_iconManager->Get(icon);
|
ImTextureID tex = m_iconManager->Get(icon);
|
||||||
@@ -59,51 +99,150 @@ void TimelinePanel::Render()
|
|||||||
return ImGui::Button(fallback);
|
return ImGui::Button(fallback);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (iconBtn("##skipback", Icon::SkipBack, "|<")) { m_playing = false; SetCurrentFrame(m_startFrame); }
|
// Icon button that highlights blue when `active` is true.
|
||||||
ImGui::SameLine();
|
auto iconToggle = [&](const char* id, Icon icon, const char* fallback,
|
||||||
if (iconBtn("##stepback", Icon::StepBack, "<")) { m_playing = false; SetCurrentFrame(std::floor(m_currentFrame) - 1.0); }
|
bool active) -> bool {
|
||||||
ImGui::SameLine();
|
if (active) {
|
||||||
if (iconBtn("##playpause", m_playing ? Icon::Pause : Icon::Play, m_playing ? "Pause" : "Play")) m_playing = !m_playing;
|
ImGui::PushStyleColor(ImGuiCol_Button, kActive);
|
||||||
ImGui::SameLine();
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, kActiveHv);
|
||||||
if (iconBtn("##stepfwd", Icon::StepForward, ">")) { m_playing = false; SetCurrentFrame(std::floor(m_currentFrame) + 1.0); }
|
}
|
||||||
ImGui::SameLine();
|
bool clicked = iconBtn(id, icon, fallback);
|
||||||
if (iconBtn("##skipend", Icon::SkipEnd, ">|")) { m_playing = false; SetCurrentFrame(m_endFrame); }
|
if (active) ImGui::PopStyleColor(2);
|
||||||
|
return clicked;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ---- Transport buttons ----
|
||||||
|
if (iconBtn("##skipback", Icon::SkipBack, "|<")) {
|
||||||
|
m_playing = false;
|
||||||
|
m_reversed = false;
|
||||||
|
SetCurrentFrame(m_startFrame);
|
||||||
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
if (iconBtn("##stepback", Icon::StepBack, "<")) {
|
||||||
|
m_playing = false;
|
||||||
|
SetCurrentFrame(std::floor(m_currentFrame) - 1.0);
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
// Play backward (rewind): clicking starts reverse play; clicking again pauses.
|
||||||
|
{
|
||||||
|
bool isPlayingBack = m_playing && m_reversed;
|
||||||
|
if (iconToggle("##playback",
|
||||||
|
isPlayingBack ? Icon::Pause : Icon::PlayBack,
|
||||||
|
isPlayingBack ? "||" : "<|",
|
||||||
|
isPlayingBack)) {
|
||||||
|
if (isPlayingBack) {
|
||||||
|
m_playing = false;
|
||||||
|
} else {
|
||||||
|
m_reversed = true;
|
||||||
|
m_playing = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
// Play forward: clicking starts forward play; clicking again pauses.
|
||||||
|
{
|
||||||
|
bool isPlayingFwd = m_playing && !m_reversed;
|
||||||
|
if (iconToggle("##playfwd",
|
||||||
|
isPlayingFwd ? Icon::Pause : Icon::Play,
|
||||||
|
isPlayingFwd ? "||" : "|>",
|
||||||
|
isPlayingFwd)) {
|
||||||
|
if (isPlayingFwd) {
|
||||||
|
m_playing = false;
|
||||||
|
} else {
|
||||||
|
m_reversed = false;
|
||||||
|
m_playing = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
if (iconBtn("##stepfwd", Icon::StepForward, ">")) {
|
||||||
|
m_playing = false;
|
||||||
|
SetCurrentFrame(std::floor(m_currentFrame) + 1.0);
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
if (iconBtn("##skipend", Icon::SkipEnd, ">|")) {
|
||||||
|
m_playing = false;
|
||||||
|
m_reversed = false;
|
||||||
|
SetCurrentFrame(m_endFrame);
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
// ---- Loop mode button — click to open Loop / Bounce / Off submenu ----
|
||||||
|
ImGui::TextDisabled("|");
|
||||||
|
ImGui::SameLine();
|
||||||
|
{
|
||||||
|
bool isActive = (m_loopMode != LoopMode::None);
|
||||||
|
Icon modeIcon = (m_loopMode == LoopMode::Bounce) ? Icon::Bounce : Icon::Loop;
|
||||||
|
const char* tip = (m_loopMode == LoopMode::Bounce) ? "Bounce (click to change)"
|
||||||
|
: (m_loopMode == LoopMode::Loop) ? "Loop (click to change)"
|
||||||
|
: "No loop (click to change)";
|
||||||
|
if (iconToggle("##loopModeBtn", modeIcon, "Loop", isActive))
|
||||||
|
ImGui::OpenPopup("##loopModePopup");
|
||||||
|
if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", tip);
|
||||||
|
|
||||||
|
if (ImGui::BeginPopup("##loopModePopup")) {
|
||||||
|
if (ImGui::Selectable("Loop", m_loopMode == LoopMode::Loop))
|
||||||
|
m_loopMode = LoopMode::Loop;
|
||||||
|
if (ImGui::Selectable("Bounce", m_loopMode == LoopMode::Bounce))
|
||||||
|
m_loopMode = LoopMode::Bounce;
|
||||||
|
ImGui::Separator();
|
||||||
|
if (ImGui::Selectable("Off", m_loopMode == LoopMode::None))
|
||||||
|
m_loopMode = LoopMode::None;
|
||||||
|
ImGui::EndPopup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
// ---- FPS + Auto-Key ----
|
||||||
|
ImGui::TextDisabled("|");
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::Text("%.6g fps", m_fps);
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Checkbox("Auto-Key", &m_autoKey)) NotifyTimeChanged();
|
||||||
|
|
||||||
|
// ---- Slider row: [start] [----slider----] [end] ----
|
||||||
|
{
|
||||||
|
const float kNumWidth = 50.f;
|
||||||
|
const float kGap = 4.f;
|
||||||
|
|
||||||
int start = int(std::lround(m_startFrame));
|
int start = int(std::lround(m_startFrame));
|
||||||
int end = int(std::lround(m_endFrame));
|
int end = int(std::lround(m_endFrame));
|
||||||
ImGui::SetNextItemWidth(90.f);
|
|
||||||
bool rangeEdited = ImGui::DragInt("##start", &start, 1.0f, 0, 0, "Start %d");
|
ImGui::SetNextItemWidth(kNumWidth);
|
||||||
ImGui::SameLine();
|
bool rangeEdited = ImGui::DragInt("##start", &start, 1.0f, 0, 0, "%d");
|
||||||
ImGui::SetNextItemWidth(90.f);
|
if (ImGui::IsItemHovered()) ImGui::SetTooltip("Start frame");
|
||||||
rangeEdited |= ImGui::DragInt("##end", &end, 1.0f, 0, 0, "End %d");
|
ImGui::SameLine(0.f, kGap);
|
||||||
|
|
||||||
|
float sliderWidth = ImGui::GetContentRegionAvail().x - kNumWidth - kGap;
|
||||||
|
float frame = float(m_currentFrame);
|
||||||
|
ImGui::SetNextItemWidth(sliderWidth);
|
||||||
|
if (ImGui::SliderFloat("##frame", &frame,
|
||||||
|
float(m_startFrame), float(m_endFrame), "%.0f")) {
|
||||||
|
m_playing = false;
|
||||||
|
SetCurrentFrame(std::round(double(frame)));
|
||||||
|
}
|
||||||
|
ImGui::SameLine(0.f, kGap);
|
||||||
|
|
||||||
|
ImGui::SetNextItemWidth(kNumWidth);
|
||||||
|
rangeEdited |= ImGui::DragInt("##end", &end, 1.0f, 0, 0, "%d");
|
||||||
|
if (ImGui::IsItemHovered()) ImGui::SetTooltip("End frame");
|
||||||
|
|
||||||
if (rangeEdited) {
|
if (rangeEdited) {
|
||||||
if (end < start) end = start;
|
if (end < start) end = start;
|
||||||
m_startFrame = double(start);
|
m_startFrame = double(start);
|
||||||
m_endFrame = double(end);
|
m_endFrame = double(end);
|
||||||
if (m_stage) {
|
if (m_stage) {
|
||||||
// Stage time metadata must live on the root (or session) layer;
|
|
||||||
// the active edit target may be a sublayer.
|
|
||||||
pxr::UsdEditContext ec(m_stage, m_stage->GetRootLayer());
|
pxr::UsdEditContext ec(m_stage, m_stage->GetRootLayer());
|
||||||
m_stage->SetStartTimeCode(m_startFrame);
|
m_stage->SetStartTimeCode(m_startFrame);
|
||||||
m_stage->SetEndTimeCode(m_endFrame);
|
m_stage->SetEndTimeCode(m_endFrame);
|
||||||
}
|
}
|
||||||
SetCurrentFrame(m_currentFrame); // re-clamp into the new range
|
SetCurrentFrame(m_currentFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::Text("%.6g fps", m_fps);
|
|
||||||
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::Checkbox("Auto-Key", &m_autoKey)) NotifyTimeChanged();
|
|
||||||
|
|
||||||
// ---- Frame slider: full width, snaps to whole frames ----
|
|
||||||
float frame = float(m_currentFrame);
|
|
||||||
ImGui::SetNextItemWidth(-FLT_MIN);
|
|
||||||
if (ImGui::SliderFloat("##frame", &frame,
|
|
||||||
float(m_startFrame), float(m_endFrame), "%.0f")) {
|
|
||||||
m_playing = false;
|
|
||||||
SetCurrentFrame(std::round(double(frame)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+16
-3
@@ -10,10 +10,14 @@ namespace UsdLayerManager {
|
|||||||
/// Bottom-docked playback timeline.
|
/// Bottom-docked playback timeline.
|
||||||
///
|
///
|
||||||
/// Owns the current frame, playback state, and the Auto-Key toggle, and fires
|
/// Owns the current frame, playback state, and the Auto-Key toggle, and fires
|
||||||
/// OnTimeChanged whenever either changes:
|
/// OnTimeChanged whenever the time changes:
|
||||||
/// displayTime — the current frame; used for all reads/evaluation
|
/// displayTime — the current frame; used for all reads/evaluation
|
||||||
/// editTime — the current frame when Auto-Key is ON, otherwise Default()
|
/// editTime — the current frame when Auto-Key is ON, otherwise Default()
|
||||||
/// (writes at editTime author time samples = keyframes)
|
///
|
||||||
|
/// Supports:
|
||||||
|
/// Loop — playback wraps from end back to start (or vice-versa).
|
||||||
|
/// Bounce — playback reverses direction at each boundary (ping-pong).
|
||||||
|
/// Rewind — reverse-direction playback (m_reversed).
|
||||||
class TimelinePanel {
|
class TimelinePanel {
|
||||||
public:
|
public:
|
||||||
void SetStage(pxr::UsdStageRefPtr stage);
|
void SetStage(pxr::UsdStageRefPtr stage);
|
||||||
@@ -27,7 +31,7 @@ public:
|
|||||||
pxr::UsdTimeCode editTime)> OnTimeChanged;
|
pxr::UsdTimeCode editTime)> OnTimeChanged;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Clamp to [start, end]; fires OnTimeChanged when the frame changes.
|
/// Clamp to [startFrame, endFrame]; fires OnTimeChanged when the frame changes.
|
||||||
void SetCurrentFrame(double frame);
|
void SetCurrentFrame(double frame);
|
||||||
void NotifyTimeChanged();
|
void NotifyTimeChanged();
|
||||||
pxr::UsdTimeCode EditTime() const;
|
pxr::UsdTimeCode EditTime() const;
|
||||||
@@ -35,11 +39,20 @@ private:
|
|||||||
IconManager* m_iconManager = nullptr;
|
IconManager* m_iconManager = nullptr;
|
||||||
pxr::UsdStageRefPtr m_stage;
|
pxr::UsdStageRefPtr m_stage;
|
||||||
|
|
||||||
|
// Stage range (written back to stage metadata on edit).
|
||||||
double m_startFrame = 1.0;
|
double m_startFrame = 1.0;
|
||||||
double m_endFrame = 100.0;
|
double m_endFrame = 100.0;
|
||||||
double m_fps = 24.0;
|
double m_fps = 24.0;
|
||||||
|
|
||||||
|
// Playback state.
|
||||||
double m_currentFrame = 1.0;
|
double m_currentFrame = 1.0;
|
||||||
bool m_playing = false;
|
bool m_playing = false;
|
||||||
|
enum class LoopMode { None, Loop, Bounce };
|
||||||
|
|
||||||
|
bool m_reversed = false; // play backward when true
|
||||||
|
LoopMode m_loopMode = LoopMode::Loop; // boundary behaviour
|
||||||
|
|
||||||
|
// Auto-Key.
|
||||||
bool m_autoKey = false;
|
bool m_autoKey = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user