Added animation bounds for rendering animations, redid float format stuff

This commit is contained in:
2025-09-15 11:14:58 -04:00
parent 3e22f8eb9d
commit f49eaa6a37
7 changed files with 71 additions and 36 deletions

View File

@@ -114,39 +114,25 @@ static inline std::string string_to_lowercase(std::string string) {
return string; return string;
} }
#define FLOAT_FORMAT_MAX_DECIMALS 5
#define FLOAT_FORMAT_MAX_DECIMALS 9 #define FLOAT_FORMAT_EPSILON 1e-5f
#define FLOAT_FORMAT_EPSILON 1e-9f
static constexpr f32 FLOAT_FORMAT_POW10[] = { static constexpr f32 FLOAT_FORMAT_POW10[] = {
1.f, 1.f,
10.f, 10.f,
100.f, 100.f,
1000.f, 1000.f,
10000.f, 10000.f,
100000.f, 100000.f
1000000.f,
10000000.f,
100000000.f,
1000000000.f
}; };
static inline s32 f32_decimals_needed(f32 value) static inline s32 f32_decimals_needed(f32 value)
{ {
f32 integerPart = 0.f; for (s32 decimalCount = 0; decimalCount <= FLOAT_FORMAT_MAX_DECIMALS; ++decimalCount)
f32 fractionalPart = modff(value, &integerPart);
fractionalPart = fabsf(fractionalPart);
if (fractionalPart < FLOAT_FORMAT_EPSILON)
return 0;
for (s32 decimalCount = 1; decimalCount <= FLOAT_FORMAT_MAX_DECIMALS; ++decimalCount)
{ {
f32 scaledFraction = fractionalPart * FLOAT_FORMAT_POW10[decimalCount]; f32 scale = FLOAT_FORMAT_POW10[decimalCount];
if (fabsf(scaledFraction - roundf(scaledFraction)) < f32 rounded = roundf(value * scale) / scale;
FLOAT_FORMAT_EPSILON * FLOAT_FORMAT_POW10[decimalCount]) if (fabsf(value - rounded) < FLOAT_FORMAT_EPSILON)
{
return decimalCount; return decimalCount;
}
} }
return FLOAT_FORMAT_MAX_DECIMALS; return FLOAT_FORMAT_MAX_DECIMALS;
} }

View File

@@ -1612,8 +1612,10 @@ static void _imgui_taskbar(Imgui* self)
static DialogType& dialogType = self->dialog->type; static DialogType& dialogType = self->dialog->type;
static bool& dialogIsSelected = self->dialog->isSelected; static bool& dialogIsSelected = self->dialog->isSelected;
static s32& type = self->settings->renderType; static s32& type = self->settings->renderType;
static f32& scale = self->settings->renderScale;
static bool& isUseAnimationBounds = self->settings->renderIsUseAnimationBounds;
static std::string& dialogPath = self->dialog->path; static std::string& dialogPath = self->dialog->path;
static std::string& ffmpegPath = self->settings->ffmpegPath; static std::string& ffmpegPath = self->settings->renderFFmpegPath;
static std::string& format = self->settings->renderFormat; static std::string& format = self->settings->renderFormat;
static std::string& path = self->settings->renderPath; static std::string& path = self->settings->renderPath;
@@ -1640,8 +1642,10 @@ static void _imgui_taskbar(Imgui* self)
} }
_imgui_input_text(IMGUI_RENDER_ANIMATION_FFMPEG_PATH, self, ffmpegPath); _imgui_input_text(IMGUI_RENDER_ANIMATION_FFMPEG_PATH, self, ffmpegPath);
_imgui_input_text(IMGUI_RENDER_ANIMATION_FORMAT, self, format);
_imgui_combo(IMGUI_RENDER_ANIMATION_OUTPUT, self, &type); _imgui_combo(IMGUI_RENDER_ANIMATION_OUTPUT, self, &type);
_imgui_input_text(IMGUI_RENDER_ANIMATION_FORMAT.copy({type != RENDER_PNG}), self, format);
_imgui_checkbox(IMGUI_RENDER_ANIMATION_IS_USE_ANIMATION_BOUNDS, self, isUseAnimationBounds);
_imgui_input_float(IMGUI_RENDER_ANIMATION_SCALE.copy({!isUseAnimationBounds}), self, scale);
_imgui_end_child(); // IMGUI_RENDER_ANIMATION_CHILD _imgui_end_child(); // IMGUI_RENDER_ANIMATION_CHILD
@@ -1765,7 +1769,7 @@ static void _imgui_taskbar(Imgui* self)
case RENDER_WEBM: case RENDER_WEBM:
case RENDER_MP4: case RENDER_MP4:
{ {
std::string ffmpegPath = std::string(self->settings->ffmpegPath.c_str()); std::string ffmpegPath = std::string(self->settings->renderFFmpegPath.c_str());
path = path_extension_change(path, RENDER_EXTENSIONS[self->settings->renderType]); path = path_extension_change(path, RENDER_EXTENSIONS[self->settings->renderType]);
if (ffmpeg_render(ffmpegPath, path, frames, self->preview->canvas.size, self->anm2->fps, (RenderType)type)) if (ffmpeg_render(ffmpegPath, path, frames, self->preview->canvas.size, self->anm2->fps, (RenderType)type))
@@ -2463,8 +2467,8 @@ static void _imgui_animation_preview(Imgui* self)
if (_imgui_button(IMGUI_ANIMATION_PREVIEW_CENTER_VIEW.copy({pan == vec2()}), self)) pan = vec2(); if (_imgui_button(IMGUI_ANIMATION_PREVIEW_CENTER_VIEW.copy({pan == vec2()}), self)) pan = vec2();
if (_imgui_button(IMGUI_ANIMATION_PREVIEW_FIT.copy({self->reference->animationID == ID_NONE}), self)) if (_imgui_button(IMGUI_ANIMATION_PREVIEW_FIT.copy({self->reference->animationID == ID_NONE}), self))
{ {
vec4 rect = anm2_animation_rect_get(self->anm2, self->reference, self->settings->previewIsRootTransform); vec4 rect = anm2_animation_rect_get(self->anm2, self->reference, self->settings->previewIsRootTransform);
if (rect != vec4(-1.0f) && (rect.z > 0 && rect.w > 0)) if (rect != vec4(-1.0f) && (rect.z > 0 && rect.w > 0))
{ {
f32 scaleX = self->preview->canvas.size.x / rect.z; f32 scaleX = self->preview->canvas.size.x / rect.z;
@@ -2527,7 +2531,9 @@ static void _imgui_animation_preview(Imgui* self)
_imgui_end_child(); // IMGUI_CANVAS_HELPER_CHILD _imgui_end_child(); // IMGUI_CANVAS_HELPER_CHILD
ImVec2 previewCursorScreenPos = ImGui::GetCursorScreenPos(); ImVec2 previewCursorScreenPos = ImGui::GetCursorScreenPos();
size = ivec2(vec2(ImGui::GetContentRegionAvail()));
if (!self->preview->isRender) size = ivec2(vec2(ImGui::GetContentRegionAvail()));
preview_draw(self->preview); preview_draw(self->preview);
ImGui::Image(self->preview->canvas.framebuffer, vec2(size)); ImGui::Image(self->preview->canvas.framebuffer, vec2(size));

View File

@@ -1132,7 +1132,7 @@ IMGUI_ITEM(IMGUI_RENDER_ANIMATION,
self.label = "&Render Animation", self.label = "&Render Animation",
self.tooltip = "Renders the current animation preview; output options can be customized.", self.tooltip = "Renders the current animation preview; output options can be customized.",
self.popup = "Render Animation", self.popup = "Render Animation",
self.popupSize = {600, 150}, self.popupSize = {500, 170},
self.popupType = IMGUI_POPUP_CENTER_WINDOW self.popupType = IMGUI_POPUP_CENTER_WINDOW
); );
@@ -1157,7 +1157,7 @@ IMGUI_ITEM(IMGUI_RENDER_ANIMATION_LOCATION_BROWSE,
IMGUI_ITEM(IMGUI_RENDER_ANIMATION_LOCATION, IMGUI_ITEM(IMGUI_RENDER_ANIMATION_LOCATION,
self.label = "Location", self.label = "Location",
self.tooltip = "Select the location of the rendered animation.", self.tooltip = "Select the location of the rendered animation.\nFor PNG images, this should be a directory, otherwise, a filepath.",
self.max = 1024 self.max = 1024
); );
@@ -1187,6 +1187,20 @@ IMGUI_ITEM(IMGUI_RENDER_ANIMATION_FORMAT,
self.max = UCHAR_MAX self.max = UCHAR_MAX
); );
IMGUI_ITEM(IMGUI_RENDER_ANIMATION_IS_USE_ANIMATION_BOUNDS,
self.label = "Use Animation Bounds",
self.tooltip = "Instead of using the animation preview's bounds, the rendered animation will use the animation's bounds.\nNOTE: If you're looking to make a transparent animation, set the preview background to be transparent\nand toggle off other drawn things.",
self.value = SETTINGS_RENDER_IS_USE_ANIMATION_BOUNDS_DEFAULT,
self.isSameLine = true
);
IMGUI_ITEM(IMGUI_RENDER_ANIMATION_SCALE,
self.label = "Scale",
self.tooltip = "Change the scale the animation will be rendered at.",
self.value = SETTINGS_RENDER_SCALE_DEFAULT,
self.size = {125, 0}
);
IMGUI_ITEM(IMGUI_RENDER_ANIMATION_CONFIRM, IMGUI_ITEM(IMGUI_RENDER_ANIMATION_CONFIRM,
self.label = "Render", self.label = "Render",
self.tooltip = "Render the animation, with the used settings.", self.tooltip = "Render the animation, with the used settings.",

View File

@@ -242,6 +242,25 @@ void preview_render_start(Preview* self)
self->isPlaying = true; self->isPlaying = true;
self->time = 0.0f; self->time = 0.0f;
_preview_render_textures_free(self); _preview_render_textures_free(self);
self->normalCanvasSize = self->canvas.size;
self->normalCanvasPan = self->settings->previewPan;
self->normalCanvasZoom = self->settings->previewZoom;
if (self->settings->renderIsUseAnimationBounds)
{
vec4 rect = anm2_animation_rect_get(self->anm2, self->reference, self->settings->previewIsRootTransform);
self->canvas.size = ivec2
(
ceilf(rect.z * self->settings->renderScale),
ceilf(rect.w * self->settings->renderScale)
);
vec2 rectCenter = vec2(rect.x + rect.z * 0.5f, rect.y + rect.w * 0.5f);
self->settings->previewPan = -rectCenter * self->settings->renderScale;
self->settings->previewZoom = UNIT_TO_PERCENT(self->settings->renderScale);
}
} }
void preview_render_end(Preview* self) void preview_render_end(Preview* self)
@@ -250,6 +269,10 @@ void preview_render_end(Preview* self)
self->isPlaying = false; self->isPlaying = false;
self->isRenderFinished = false; self->isRenderFinished = false;
_preview_render_textures_free(self); _preview_render_textures_free(self);
self->canvas.size = self->normalCanvasSize;
self->settings->previewPan = self->normalCanvasPan;
self->settings->previewZoom = self->normalCanvasZoom;
} }
void preview_free(Preview* self) void preview_free(Preview* self)

View File

@@ -34,6 +34,9 @@ struct Preview
Settings* settings = nullptr; Settings* settings = nullptr;
s32 animationOverlayID = ID_NONE; s32 animationOverlayID = ID_NONE;
Canvas canvas; Canvas canvas;
vec2 normalCanvasSize{};
vec2 normalCanvasPan{};
f32 normalCanvasZoom{};
bool isPlaying = false; bool isPlaying = false;
bool isRender = false; bool isRender = false;
bool isRenderFinished = false; bool isRenderFinished = false;

View File

@@ -21,9 +21,9 @@
#define SETTINGS_TEMPORARY_EXTENSION ".tmp" #define SETTINGS_TEMPORARY_EXTENSION ".tmp"
#ifdef _WIN32 #ifdef _WIN32
#define SETTINGS_FFMPEG_PATH_VALUE_DEFAULT "C:\\ffmpeg\\bin\\ffmpeg.exe" #define SETTINGS_RENDER_FFMPEG_PATH_VALUE_DEFAULT "C:\\ffmpeg\\bin\\ffmpeg.exe"
#else #else
#define SETTINGS_FFMPEG_PATH_VALUE_DEFAULT "/usr/bin/ffmpeg" #define SETTINGS_RENDER_FFMPEG_PATH_VALUE_DEFAULT "/usr/bin/ffmpeg"
#endif #endif
#define SETTINGS_LIST \ #define SETTINGS_LIST \
@@ -143,10 +143,13 @@
X(tool, TOOL, TYPE_INT, TOOL_PAN) \ X(tool, TOOL, TYPE_INT, TOOL_PAN) \
X(toolColor, TOOL_COLOR, TYPE_VEC4, {1.0,1.0,1.0,1.0}) \ X(toolColor, TOOL_COLOR, TYPE_VEC4, {1.0,1.0,1.0,1.0}) \
\ \
X(renderType, RENDER_TYPE, TYPE_INT, RENDER_PNG) \ X(renderType, RENDER_TYPE, TYPE_INT, RENDER_PNG) \
X(renderPath, RENDER_PATH, TYPE_STRING, ".") \ X(renderPath, RENDER_PATH, TYPE_STRING, ".") \
X(renderFormat, RENDER_FORMAT, TYPE_STRING, "{}.png") \ X(renderFormat, RENDER_FORMAT, TYPE_STRING, "{}.png") \
X(ffmpegPath, FFMPEG_PATH, TYPE_STRING, SETTINGS_FFMPEG_PATH_VALUE_DEFAULT) X(renderIsUseAnimationBounds,RENDER_IS_USE_ANIMATION_BOUNDS,TYPE_BOOL, true) \
X(renderIsTransparent, RENDER_IS_TRANSPARENT, TYPE_BOOL, true) \
X(renderScale, RENDER_SCALE, TYPE_FLOAT, 1.0f) \
X(renderFFmpegPath, RENDER_FFMPEG_PATH, TYPE_STRING, SETTINGS_RENDER_FFMPEG_PATH_VALUE_DEFAULT)
#define X(name, symbol, type, ...) \ #define X(name, symbol, type, ...) \
const inline DATATYPE_TO_CTYPE(type) SETTINGS_##symbol##_DEFAULT = __VA_ARGS__; const inline DATATYPE_TO_CTYPE(type) SETTINGS_##symbol##_DEFAULT = __VA_ARGS__;

View File

@@ -43,6 +43,6 @@ Alternatively, if you have subscribed to the mod, you can find the latest releas
[h3]Happy animating![/h3] [h3]Happy animating![/h3]
[img]https://files.catbox.moe/4auc1c.gif[/img] [img]https://files.catbox.moe/4auc1c.gif[/img]
</description> </description>
<version>1.1</version> <version>1.2</version>
<visibility>Public</visibility> <visibility>Public</visibility>
</metadata> </metadata>