This commit is contained in:
2026-05-07 00:19:53 -04:00
parent a1bdbeba1c
commit 5c746d99c2
12 changed files with 51 additions and 69 deletions
+2 -2
View File
@@ -2,10 +2,10 @@
namespace anm2ed::imgui
{
void Dockspace::tick(Manager& manager, Settings& settings)
void Dockspace::tick(Manager& manager, Settings& settings, float deltaSeconds)
{
if (auto document = manager.get(); document)
if (settings.windowIsAnimationPreview) animationPreview.tick(manager, settings);
if (settings.windowIsAnimationPreview) animationPreview.tick(manager, settings, deltaSeconds);
}
void Dockspace::update(Taskbar& taskbar, Documents& documents, Manager& manager, Settings& settings,
+1 -1
View File
@@ -37,7 +37,7 @@ namespace anm2ed::imgui
Welcome welcome;
public:
void tick(Manager&, Settings&);
void tick(Manager&, Settings&, float);
void update(Taskbar&, Documents&, Manager&, Settings&, Resources&, Dialog&, Clipboard&);
};
}
+13 -28
View File
@@ -34,8 +34,6 @@ namespace anm2ed::imgui
constexpr auto POINT_SIZE = vec2(4, 4);
constexpr auto TRIGGER_TEXT_COLOR_DARK = ImVec4(1.0f, 1.0f, 1.0f, 0.5f);
constexpr auto TRIGGER_TEXT_COLOR_LIGHT = ImVec4(0.0f, 0.0f, 0.0f, 0.5f);
constexpr auto PLAYBACK_TICK_RATE = 30.0f;
namespace
{
std::filesystem::path render_destination_directory(const std::filesystem::path& path, int type)
@@ -153,7 +151,7 @@ namespace anm2ed::imgui
AnimationPreview::AnimationPreview() : Canvas(vec2()) {}
void AnimationPreview::tick(Manager& manager, Settings& settings)
void AnimationPreview::tick(Manager& manager, Settings& settings, float deltaSeconds)
{
auto& document = *manager.get();
auto& anm2 = document.anm2;
@@ -176,8 +174,9 @@ namespace anm2ed::imgui
auto& path = settings.renderPath;
auto pathString = path::to_utf8(path);
auto& type = settings.renderType;
auto renderFrameRate = std::max(settings.playbackTickRate, 1);
if (playback.time > end || playback.isFinished)
if (playback.time >= (float)end + 1.0f || playback.isFinished)
{
if (settings.timelineIsSound) audioStream.capture_end(mixer);
@@ -262,7 +261,7 @@ namespace anm2ed::imgui
{
if (settings.timelineIsSound && type != render::GIF)
{
if (!render_audio_stream_generate(audioStream, anm2.content.sounds, renderFrameSoundIDs, anm2.info.fps))
if (!render_audio_stream_generate(audioStream, anm2.content.sounds, renderFrameSoundIDs, renderFrameRate))
{
toasts.push(localize.get(TOAST_EXPORT_RENDERED_ANIMATION_FAILED));
logger.error("Failed to generate deterministic render audio stream; exporting without audio.");
@@ -273,7 +272,7 @@ namespace anm2ed::imgui
audioStream.stream.clear();
if (animation_render(ffmpegPath, path, renderTempFrames, renderTempFrameDurations, audioStream,
(render::Type)type, anm2.info.fps))
(render::Type)type, renderFrameRate))
{
toasts.push(std::vformat(localize.get(TOAST_EXPORT_RENDERED_ANIMATION), std::make_format_args(pathString)));
logger.info(std::vformat(localize.get(TOAST_EXPORT_RENDERED_ANIMATION, anm2ed::ENGLISH),
@@ -325,8 +324,10 @@ namespace anm2ed::imgui
auto frameSoundID = -1;
if (settings.timelineIsSound && !anm2.content.sounds.empty())
{
if (auto animation = document.animation_get();
animation && animation->triggers.isVisible && (!settings.timelineIsOnlyShowLayers || manager.isRecording))
auto soundTime = (int)std::floor(playback.time);
if (auto animation = document.animation_get(); soundTime != renderFrameSoundTimePrev && animation &&
animation->triggers.isVisible &&
(!settings.timelineIsOnlyShowLayers || manager.isRecording))
{
if (auto trigger = animation->triggers.frame_generate(playback.time, anm2::TRIGGER); trigger.isVisible)
{
@@ -341,6 +342,7 @@ namespace anm2ed::imgui
}
}
}
renderFrameSoundTimePrev = soundTime;
}
renderFrameSoundIDs.push_back(frameSoundID);
@@ -352,24 +354,8 @@ namespace anm2ed::imgui
if (Texture::write_pixels_png(framePath, size, pixels.data()))
{
renderTempFrames.push_back(framePath);
auto nowCounter = SDL_GetPerformanceCounter();
auto counterFrequency = SDL_GetPerformanceFrequency();
auto fallbackDuration = 1.0 / (double)std::max(anm2.info.fps, 1);
if (renderTempFrames.size() == 1)
{
renderCaptureCounterPrev = nowCounter;
renderTempFrameDurations.push_back(fallbackDuration);
}
else
{
auto elapsedCounter = nowCounter - renderCaptureCounterPrev;
auto frameDuration = counterFrequency > 0 ? (double)elapsedCounter / (double)counterFrequency : 0.0;
frameDuration = std::max(frameDuration, 1.0 / 1000.0);
renderTempFrameDurations.back() = frameDuration;
renderTempFrameDurations.push_back(frameDuration);
renderCaptureCounterPrev = nowCounter;
}
auto fallbackDuration = 1.0 / (double)renderFrameRate;
renderTempFrameDurations.push_back(fallbackDuration);
}
else
{
@@ -416,7 +402,6 @@ namespace anm2ed::imgui
}
auto fps = std::max(anm2.info.fps, 1);
auto deltaSeconds = manager.isRecording ? (1.0f / (float)fps) : (1.0f / PLAYBACK_TICK_RATE);
playback.tick(fps, animation->frameNum, (animation->isLoop || settings.playbackIsLoop) && !manager.isRecording,
deltaSeconds);
@@ -657,7 +642,7 @@ namespace anm2ed::imgui
renderTempFrames.clear();
renderTempFrameDurations.clear();
renderFrameSoundIDs.clear();
renderCaptureCounterPrev = 0;
renderFrameSoundTimePrev = -1;
if (settings.renderType == render::PNGS)
{
renderTempDirectory = settings.renderPath;
+2 -2
View File
@@ -33,11 +33,11 @@ namespace anm2ed::imgui
std::vector<std::filesystem::path> renderTempFrames{};
std::vector<double> renderTempFrameDurations{};
std::vector<int> renderFrameSoundIDs{};
Uint64 renderCaptureCounterPrev{};
int renderFrameSoundTimePrev{-1};
public:
AnimationPreview();
void tick(Manager&, Settings&);
void tick(Manager&, Settings&, float);
void update(Manager&, Settings&, Resources&);
};
}
+1 -1
View File
@@ -1312,7 +1312,7 @@ namespace anm2ed::imgui
document.frameTime = playback.time;
}
playback.clamp(settings.playbackIsClamp ? length : anm2::FRAME_NUM_MAX);
if (!playback.isPlaying) playback.clamp(settings.playbackIsClamp ? length : anm2::FRAME_NUM_MAX);
if (ImGui::IsMouseReleased(ImGuiMouseButton_Left)) isDragging = false;
+7
View File
@@ -32,6 +32,13 @@ namespace anm2ed::imgui::wizard
ImGui::Checkbox(localize.get(LABEL_VSYNC), &temporary.isVsync);
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_VSYNC));
ImGui::SeparatorText(localize.get(LABEL_PLAYBACK_MENU));
ImGui::RadioButton("30 Hz", &temporary.playbackTickRate, 30);
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_PLAYBACK_TICK_RATE));
ImGui::SameLine();
ImGui::RadioButton("60 Hz", &temporary.playbackTickRate, 60);
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_PLAYBACK_TICK_RATE));
ImGui::SeparatorText(localize.get(LABEL_LOCALIZATION));
ImGui::Combo(localize.get(LABEL_LANGUAGE), &temporary.language, LANGUAGE_STRINGS, LANGUAGE_COUNT);
ImGui::SetItemTooltip("%s", localize.get(TOOLTIP_LANGUAGE));