add export timelapse
This commit is contained in:
@@ -171,6 +171,9 @@
|
|||||||
<button-custom id="file-submenu-export-anim" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
<button-custom id="file-submenu-export-anim" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||||
<text text="Animation Frames" grow="1" margin="0 0 0 5"/>
|
<text text="Animation Frames" grow="1" margin="0 0 0 5"/>
|
||||||
</button-custom>
|
</button-custom>
|
||||||
|
<button-custom id="file-submenu-export-timelapse" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||||
|
<text text="Timelapse" grow="1" margin="0 0 0 5"/>
|
||||||
|
</button-custom>
|
||||||
</popup-menu>
|
</popup-menu>
|
||||||
</layout>
|
</layout>
|
||||||
|
|
||||||
@@ -201,6 +204,7 @@
|
|||||||
<!-- MENU TOOLS -->
|
<!-- MENU TOOLS -->
|
||||||
<layout id="tools-menu">
|
<layout id="tools-menu">
|
||||||
<popup-menu positioning="absolute" position="100 100" width="150" thickness="1" border-color=".1" color=".4 .4 .4 .8" dir="col">
|
<popup-menu positioning="absolute" position="100 100" width="150" thickness="1" border-color=".1" color=".4 .4 .4 .8" dir="col">
|
||||||
|
<!--
|
||||||
<border dir="row" flood-events="1">
|
<border dir="row" flood-events="1">
|
||||||
<button-custom id="tools-timelapse" height="40" align="center" color=".2" pad="0 0 0 10" dir="row" grow="1">
|
<button-custom id="tools-timelapse" height="40" align="center" color=".2" pad="0 0 0 10" dir="row" grow="1">
|
||||||
<text text="Timelapse" grow="1" margin="0 0 0 5"/>
|
<text text="Timelapse" grow="1" margin="0 0 0 5"/>
|
||||||
@@ -209,6 +213,7 @@
|
|||||||
<icon icon="resultset_next" width="20"/>
|
<icon icon="resultset_next" width="20"/>
|
||||||
</button-custom>
|
</button-custom>
|
||||||
</border>
|
</border>
|
||||||
|
-->
|
||||||
<border dir="row" flood-events="1" >
|
<border dir="row" flood-events="1" >
|
||||||
<button-custom id="tools-panels" height="40" align="center" color=".2" pad="0 0 0 10" dir="row" grow="1">
|
<button-custom id="tools-panels" height="40" align="center" color=".2" pad="0 0 0 10" dir="row" grow="1">
|
||||||
<text text="Panels" grow="1" margin="0 0 0 5"/>
|
<text text="Panels" grow="1" margin="0 0 0 5"/>
|
||||||
@@ -249,10 +254,12 @@
|
|||||||
<icon icon="pencil" width="20"/>
|
<icon icon="pencil" width="20"/>
|
||||||
<text id="menu-label" text="Start SonarPen" margin="0 0 0 5"/>
|
<text id="menu-label" text="Start SonarPen" margin="0 0 0 5"/>
|
||||||
</button-custom>
|
</button-custom>
|
||||||
|
<!--
|
||||||
<button-custom id="mp4test" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
<button-custom id="mp4test" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||||
<icon icon="pencil" width="20"/>
|
<icon icon="pencil" width="20"/>
|
||||||
<text id="menu-label" text="Test MP4 Export" margin="0 0 0 5"/>
|
<text id="menu-label" text="Test MP4 Export" margin="0 0 0 5"/>
|
||||||
</button-custom>
|
</button-custom>
|
||||||
|
-->
|
||||||
</popup-menu>
|
</popup-menu>
|
||||||
</layout>
|
</layout>
|
||||||
|
|
||||||
|
|||||||
@@ -794,7 +794,7 @@ void App::rec_loop()
|
|||||||
{
|
{
|
||||||
std::unique_ptr<Image> frame;
|
std::unique_ptr<Image> frame;
|
||||||
std::unique_lock<std::mutex> lock(rec_mutex);
|
std::unique_lock<std::mutex> lock(rec_mutex);
|
||||||
rec_cv.wait(lock);
|
rec_cv.wait(lock, [this] { return !(rec_frames.empty() && rec_running); });
|
||||||
if (!rec_running)
|
if (!rec_running)
|
||||||
break;
|
break;
|
||||||
if (!rec_frames.empty())
|
if (!rec_frames.empty())
|
||||||
@@ -808,7 +808,10 @@ void App::rec_loop()
|
|||||||
}
|
}
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
if (frame && Canvas::I->m_encoder)
|
if (frame && Canvas::I->m_encoder)
|
||||||
|
{
|
||||||
Canvas::I->m_encoder->encode(*frame);
|
Canvas::I->m_encoder->encode(*frame);
|
||||||
|
LOG("frame encoded");
|
||||||
|
}
|
||||||
update_rec_frames();
|
update_rec_frames();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -257,6 +257,7 @@ public:
|
|||||||
void dialog_preset_download();
|
void dialog_preset_download();
|
||||||
void dialog_ppbr_export();
|
void dialog_ppbr_export();
|
||||||
void dialog_export_mp4();
|
void dialog_export_mp4();
|
||||||
|
void dialog_timelapse_export();
|
||||||
|
|
||||||
void cloud_upload();
|
void cloud_upload();
|
||||||
void cloud_upload_all();
|
void cloud_upload_all();
|
||||||
|
|||||||
@@ -646,6 +646,28 @@ void App::dialog_ppbr_export()
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void App::dialog_timelapse_export()
|
||||||
|
{
|
||||||
|
#if __IOS__ || __WEB__
|
||||||
|
pick_file_save("mp4",
|
||||||
|
[this](std::string path) {
|
||||||
|
rec_export(path);
|
||||||
|
},
|
||||||
|
[this](bool saved) {
|
||||||
|
message_box("Export Timelapse", "Timelapse exported succesfully.");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
#else
|
||||||
|
pick_file_save({ "mp4" }, [this](std::string path) {
|
||||||
|
std::thread([this, path] {
|
||||||
|
BT_SetTerminate();
|
||||||
|
rec_export(path);
|
||||||
|
message_box("Export Timelapse", "Timelapse exported to: " + path);
|
||||||
|
}).detach();
|
||||||
|
});
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void App::dialog_export_mp4()
|
void App::dialog_export_mp4()
|
||||||
{
|
{
|
||||||
std::thread([this] {
|
std::thread([this] {
|
||||||
|
|||||||
@@ -80,11 +80,11 @@ void App::tick(float dt)
|
|||||||
if (auto* main = layout[main_id])
|
if (auto* main = layout[main_id])
|
||||||
main->tick(dt);
|
main->tick(dt);
|
||||||
|
|
||||||
if (rec_running)
|
if (rec_running && Canvas::I->m_encoder)
|
||||||
{
|
{
|
||||||
auto t_now = std::chrono::high_resolution_clock::now();
|
auto t_now = std::chrono::high_resolution_clock::now();
|
||||||
float dt = std::chrono::duration<float>(t_now - canvas->m_canvas->m_disrty_stroke_time).count();
|
float dt = std::chrono::duration<float>(t_now - canvas->m_canvas->m_disrty_stroke_time).count();
|
||||||
if (dt > 1.f && canvas->m_canvas->m_dirty_stroke)
|
if (dt > 0.1f && canvas->m_canvas->m_dirty_stroke)
|
||||||
{
|
{
|
||||||
canvas->m_canvas->m_dirty_stroke = false;
|
canvas->m_canvas->m_dirty_stroke = false;
|
||||||
LOG("rec tick");
|
LOG("rec tick");
|
||||||
@@ -92,7 +92,7 @@ void App::tick(float dt)
|
|||||||
Texture2D equirect;
|
Texture2D equirect;
|
||||||
App::I->render_task([&] {
|
App::I->render_task([&] {
|
||||||
Canvas::I->draw_merge(true);
|
Canvas::I->draw_merge(true);
|
||||||
equirect = Canvas::I->m_layers_merge.gen_equirect({ 1024, 512 });
|
equirect = Canvas::I->m_layers_merge.gen_equirect(Canvas::I->m_encoder->frame_size() / 4);
|
||||||
});
|
});
|
||||||
auto img = std::make_unique<Image>(equirect.get_image());
|
auto img = std::make_unique<Image>(equirect.get_image());
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -611,38 +611,45 @@ void App::init_menu_file()
|
|||||||
layout[main_id]->add_child(subpopup);
|
layout[main_id]->add_child(subpopup);
|
||||||
subpopup->find<NodeButtonCustom>("file-submenu-export-png")->on_click = [this, subpopup, popup](Node*) {
|
subpopup->find<NodeButtonCustom>("file-submenu-export-png")->on_click = [this, subpopup, popup](Node*) {
|
||||||
dialog_export(".png");
|
dialog_export(".png");
|
||||||
subpopup->mouse_release();
|
|
||||||
subpopup->destroy();
|
|
||||||
popup->mouse_release();
|
popup->mouse_release();
|
||||||
popup->destroy();
|
popup->destroy();
|
||||||
|
subpopup->mouse_release();
|
||||||
|
subpopup->destroy();
|
||||||
};
|
};
|
||||||
subpopup->find<NodeButtonCustom>("file-submenu-export-layers")->on_click = [this, subpopup, popup](Node*) {
|
subpopup->find<NodeButtonCustom>("file-submenu-export-layers")->on_click = [this, subpopup, popup](Node*) {
|
||||||
dialog_export_layers();
|
dialog_export_layers();
|
||||||
subpopup->mouse_release();
|
|
||||||
subpopup->destroy();
|
|
||||||
popup->mouse_release();
|
popup->mouse_release();
|
||||||
popup->destroy();
|
popup->destroy();
|
||||||
|
subpopup->mouse_release();
|
||||||
|
subpopup->destroy();
|
||||||
};
|
};
|
||||||
subpopup->find<NodeButtonCustom>("file-submenu-export-cube")->on_click = [this, subpopup, popup](Node*) {
|
subpopup->find<NodeButtonCustom>("file-submenu-export-cube")->on_click = [this, subpopup, popup](Node*) {
|
||||||
dialog_export_cube_faces();
|
dialog_export_cube_faces();
|
||||||
subpopup->mouse_release();
|
|
||||||
subpopup->destroy();
|
|
||||||
popup->mouse_release();
|
popup->mouse_release();
|
||||||
popup->destroy();
|
popup->destroy();
|
||||||
|
subpopup->mouse_release();
|
||||||
|
subpopup->destroy();
|
||||||
};
|
};
|
||||||
subpopup->find<NodeButtonCustom>("file-submenu-export-depth")->on_click = [this, subpopup, popup](Node*) {
|
subpopup->find<NodeButtonCustom>("file-submenu-export-depth")->on_click = [this, subpopup, popup](Node*) {
|
||||||
dialog_export_depth();
|
dialog_export_depth();
|
||||||
subpopup->mouse_release();
|
|
||||||
subpopup->destroy();
|
|
||||||
popup->mouse_release();
|
popup->mouse_release();
|
||||||
popup->destroy();
|
popup->destroy();
|
||||||
|
subpopup->mouse_release();
|
||||||
|
subpopup->destroy();
|
||||||
};
|
};
|
||||||
subpopup->find<NodeButtonCustom>("file-submenu-export-anim")->on_click = [this, subpopup, popup](Node*) {
|
subpopup->find<NodeButtonCustom>("file-submenu-export-anim")->on_click = [this, subpopup, popup](Node*) {
|
||||||
dialog_export_layers();
|
dialog_export_layers();
|
||||||
subpopup->mouse_release();
|
|
||||||
subpopup->destroy();
|
|
||||||
popup->mouse_release();
|
popup->mouse_release();
|
||||||
popup->destroy();
|
popup->destroy();
|
||||||
|
subpopup->mouse_release();
|
||||||
|
subpopup->destroy();
|
||||||
|
};
|
||||||
|
subpopup->find<NodeButtonCustom>("file-submenu-export-timelapse")->on_click = [this, subpopup, popup](Node*) {
|
||||||
|
dialog_timelapse_export();
|
||||||
|
popup->mouse_release();
|
||||||
|
popup->destroy();
|
||||||
|
subpopup->mouse_release();
|
||||||
|
subpopup->destroy();
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
if (auto b = popup->find<NodeButtonCustom>("file-share"))
|
if (auto b = popup->find<NodeButtonCustom>("file-share"))
|
||||||
@@ -1037,11 +1044,13 @@ void App::init_menu_tools()
|
|||||||
popup_exp->destroy();
|
popup_exp->destroy();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
popup_exp->find<NodeButtonCustom>("mp4test")->on_click = [this, popup_exp](Node*) {
|
popup_exp->find<NodeButtonCustom>("mp4test")->on_click = [this, popup_exp](Node*) {
|
||||||
dialog_export_mp4();
|
dialog_export_mp4();
|
||||||
popup_exp->mouse_release();
|
popup_exp->mouse_release();
|
||||||
popup_exp->destroy();
|
popup_exp->destroy();
|
||||||
};
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
#if __IOS__
|
#if __IOS__
|
||||||
popup_exp->find<NodeButtonCustom>("sonarpen")->on_click = [this, popup_exp](Node*) {
|
popup_exp->find<NodeButtonCustom>("sonarpen")->on_click = [this, popup_exp](Node*) {
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ public:
|
|||||||
bool write_mp4(const std::string& filename) const noexcept;
|
bool write_mp4(const std::string& filename) const noexcept;
|
||||||
void destroy() noexcept;
|
void destroy() noexcept;
|
||||||
int frames_count() const noexcept { return m_frames.size(); }
|
int frames_count() const noexcept { return m_frames.size(); }
|
||||||
|
glm::ivec2 frame_size() const noexcept { return { m_width, m_height }; }
|
||||||
virtual bool read(BinaryStreamReader& r) override;
|
virtual bool read(BinaryStreamReader& r) override;
|
||||||
virtual void write(BinaryStreamWriter& w) const override;
|
virtual void write(BinaryStreamWriter& w) const override;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user