Report render progress if stdout is a TTY
This commit is contained in:
1 parent
d8a37c6e9a
commit
040ca57cb3
2 files changed
+86
-1
No files matched your search
+84
-1
@@ -1,8 +1,81 @@
|
||||
#include <fart/Engine.h>
|
||||
#include <fart/Parser.h>
|
||||
#include <chrono>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
/**
|
||||
* Reports render progress to stdout when stdout is a TTY.
|
||||
*
|
||||
* An update is written only when progress has increased by at least 1%,
|
||||
* or when progress has increased at all and at least 1 second has elapsed
|
||||
* since the last update.
|
||||
*/
|
||||
class ProgressReporter
|
||||
{
|
||||
public:
|
||||
using clock = std::chrono::steady_clock;
|
||||
|
||||
explicit ProgressReporter(size_t total)
|
||||
: total(total)
|
||||
, enabled(total > 0u && isatty(STDOUT_FILENO))
|
||||
{
|
||||
if (enabled)
|
||||
{
|
||||
last_time = clock::now();
|
||||
print(0u);
|
||||
}
|
||||
}
|
||||
|
||||
void update(size_t done)
|
||||
{
|
||||
if (!enabled || done <= last_done)
|
||||
{
|
||||
return;
|
||||
}
|
||||
/* (done - last_done) / total >= 1 / 100 */
|
||||
bool percent_step = (done - last_done) * 100u >= total;
|
||||
clock::time_point now = clock::now();
|
||||
if (percent_step || (now - last_time) >= std::chrono::seconds(1))
|
||||
{
|
||||
last_time = now;
|
||||
print(done);
|
||||
}
|
||||
}
|
||||
|
||||
void finish()
|
||||
{
|
||||
if (enabled)
|
||||
{
|
||||
if (last_done < total)
|
||||
{
|
||||
print(total);
|
||||
}
|
||||
fputc('\n', stdout);
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
size_t total;
|
||||
bool enabled;
|
||||
size_t last_done = 0u;
|
||||
clock::time_point last_time;
|
||||
|
||||
void print(size_t done)
|
||||
{
|
||||
last_done = done;
|
||||
printf("\rRendering: %6.2f%%", (double)done * 100.0 / (double)total);
|
||||
fflush(stdout);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Engine::Engine(const Options & options)
|
||||
: options(options)
|
||||
@@ -67,13 +140,18 @@ int Engine::run(string_view input_file, opt<string_view> output_file)
|
||||
options.apply_defaults();
|
||||
|
||||
Image image(*options.width, *options.height);
|
||||
ProgressReporter progress(*options.width * *options.height);
|
||||
size_t pixels_done = 0u;
|
||||
for (size_t y = 0u; y < *options.height; y++)
|
||||
{
|
||||
for (size_t x = 0u; x < *options.width; x++)
|
||||
{
|
||||
image[x, y] = *options.background;
|
||||
image[x, y] = render_pixel(x, y);
|
||||
pixels_done++;
|
||||
progress.update(pixels_done);
|
||||
}
|
||||
}
|
||||
progress.finish();
|
||||
|
||||
if (!image_writer->write(image))
|
||||
{
|
||||
@@ -82,3 +160,8 @@ int Engine::run(string_view input_file, opt<string_view> output_file)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Color Engine::render_pixel(size_t x, size_t y)
|
||||
{
|
||||
return *this->options.background;
|
||||
}
|
||||
@@ -16,4 +16,6 @@ protected:
|
||||
Options options;
|
||||
std::unique_ptr<ImageWriter> image_writer;
|
||||
Scene * scene = nullptr;
|
||||
|
||||
Color render_pixel(size_t x, size_t y);
|
||||
};
|
||||
Reference in new issue
Block a user