Plan app export targets in app core
This commit is contained in:
1
src/app_core/document_export.cpp
Normal file
1
src/app_core/document_export.cpp
Normal file
@@ -0,0 +1 @@
|
||||
#include "app_core/document_export.h"
|
||||
111
src/app_core/document_export.h
Normal file
111
src/app_core/document_export.h
Normal file
@@ -0,0 +1,111 @@
|
||||
#pragma once
|
||||
|
||||
#include "foundation/result.h"
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
namespace pp::app {
|
||||
|
||||
struct DocumentExportFileTarget {
|
||||
std::string path;
|
||||
std::string suggested_name;
|
||||
};
|
||||
|
||||
struct DocumentExportCollectionTarget {
|
||||
std::string directory;
|
||||
std::string stem_path;
|
||||
};
|
||||
|
||||
struct DocumentExportStemTarget {
|
||||
std::string stem_path;
|
||||
};
|
||||
|
||||
struct DocumentExportSuggestedName {
|
||||
std::string name;
|
||||
};
|
||||
|
||||
[[nodiscard]] inline pp::foundation::Result<DocumentExportFileTarget> make_document_export_file_target(
|
||||
std::string_view work_directory,
|
||||
std::string_view document_name,
|
||||
std::string_view extension)
|
||||
{
|
||||
if (document_name.empty()) {
|
||||
return pp::foundation::Result<DocumentExportFileTarget>::failure(
|
||||
pp::foundation::Status::invalid_argument("document name must not be empty"));
|
||||
}
|
||||
|
||||
if (extension.empty()) {
|
||||
return pp::foundation::Result<DocumentExportFileTarget>::failure(
|
||||
pp::foundation::Status::invalid_argument("extension must not be empty"));
|
||||
}
|
||||
|
||||
DocumentExportFileTarget target;
|
||||
target.suggested_name.reserve(document_name.size() + extension.size());
|
||||
target.suggested_name += document_name;
|
||||
target.suggested_name += extension;
|
||||
target.path.reserve(work_directory.size() + target.suggested_name.size() + 1);
|
||||
target.path += work_directory;
|
||||
target.path += "/";
|
||||
target.path += target.suggested_name;
|
||||
return pp::foundation::Result<DocumentExportFileTarget>::success(std::move(target));
|
||||
}
|
||||
|
||||
[[nodiscard]] inline pp::foundation::Result<DocumentExportCollectionTarget> make_document_export_collection_target(
|
||||
std::string_view work_directory,
|
||||
std::string_view document_name,
|
||||
std::string_view suffix)
|
||||
{
|
||||
if (document_name.empty()) {
|
||||
return pp::foundation::Result<DocumentExportCollectionTarget>::failure(
|
||||
pp::foundation::Status::invalid_argument("document name must not be empty"));
|
||||
}
|
||||
|
||||
DocumentExportCollectionTarget target;
|
||||
target.directory.reserve(work_directory.size() + document_name.size() + suffix.size() + 1);
|
||||
target.directory += work_directory;
|
||||
target.directory += "/";
|
||||
target.directory += document_name;
|
||||
target.directory += suffix;
|
||||
target.stem_path.reserve(target.directory.size() + document_name.size() + 1);
|
||||
target.stem_path += target.directory;
|
||||
target.stem_path += "/";
|
||||
target.stem_path += document_name;
|
||||
return pp::foundation::Result<DocumentExportCollectionTarget>::success(std::move(target));
|
||||
}
|
||||
|
||||
[[nodiscard]] inline pp::foundation::Result<DocumentExportStemTarget> make_document_export_stem_target(
|
||||
std::string_view directory,
|
||||
std::string_view document_name)
|
||||
{
|
||||
if (document_name.empty()) {
|
||||
return pp::foundation::Result<DocumentExportStemTarget>::failure(
|
||||
pp::foundation::Status::invalid_argument("document name must not be empty"));
|
||||
}
|
||||
|
||||
DocumentExportStemTarget target;
|
||||
target.stem_path.reserve(directory.size() + document_name.size() + 1);
|
||||
target.stem_path += directory;
|
||||
target.stem_path += "/";
|
||||
target.stem_path += document_name;
|
||||
return pp::foundation::Result<DocumentExportStemTarget>::success(std::move(target));
|
||||
}
|
||||
|
||||
[[nodiscard]] inline pp::foundation::Result<DocumentExportSuggestedName> make_document_export_suggested_name(
|
||||
std::string_view document_name,
|
||||
std::string_view suffix)
|
||||
{
|
||||
if (document_name.empty()) {
|
||||
return pp::foundation::Result<DocumentExportSuggestedName>::failure(
|
||||
pp::foundation::Status::invalid_argument("document name must not be empty"));
|
||||
}
|
||||
|
||||
DocumentExportSuggestedName target;
|
||||
target.name.reserve(document_name.size() + suffix.size());
|
||||
target.name += document_name;
|
||||
target.name += suffix;
|
||||
return pp::foundation::Result<DocumentExportSuggestedName>::success(std::move(target));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "pch.h"
|
||||
#include "app.h"
|
||||
#include "action.h"
|
||||
#include "app_core/document_export.h"
|
||||
#include "settings.h"
|
||||
#include "node_dialog_open.h"
|
||||
#include "node_dialog_browse.h"
|
||||
@@ -421,9 +422,13 @@ void App::dialog_export(std::string ext)
|
||||
if (canvas)
|
||||
{
|
||||
// TODO: use picker
|
||||
auto path = work_path + "/" + doc_name + ext;
|
||||
auto name = doc_name + ext;
|
||||
canvas->m_canvas->export_equirectangular(path, [this, path, name]{
|
||||
const auto target = pp::app::make_document_export_file_target(work_path, doc_name, ext);
|
||||
if (!target) {
|
||||
message_box("Export Equirectangular", target.status().message);
|
||||
return;
|
||||
}
|
||||
|
||||
canvas->m_canvas->export_equirectangular(target.value().path, [this, target = target.value()]{
|
||||
#if defined(__IOS__)
|
||||
message_box("Export Equirectangular", "Image exported to Photos");
|
||||
#elif defined(__OSX__)
|
||||
@@ -434,7 +439,7 @@ void App::dialog_export(std::string ext)
|
||||
//auto result = ovr_Media_ShareToFacebook("Sharing from PanoPainter on Oculus Quest", path.c_str(), ovrMediaContentType_Photo);
|
||||
#elif __WEB__
|
||||
ui_task([=]{
|
||||
webgl_pick_file_save(path, name, [](bool success){ });
|
||||
webgl_pick_file_save(target.path, target.suggested_name, [](bool success){ });
|
||||
});
|
||||
#endif
|
||||
});
|
||||
@@ -452,19 +457,28 @@ void App::dialog_export_layers()
|
||||
if (canvas)
|
||||
{
|
||||
#if defined(__IOS__)
|
||||
auto dir = work_path + "/" + doc_name + "_layers";
|
||||
if (Asset::create_dir(dir))
|
||||
const auto target = pp::app::make_document_export_collection_target(work_path, doc_name, "_layers");
|
||||
if (!target) {
|
||||
message_box("Export Layers", target.status().message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Asset::create_dir(target.value().directory))
|
||||
{
|
||||
auto p = dir + "/" + doc_name;
|
||||
canvas->m_canvas->export_layers(p, [this, p] {
|
||||
canvas->m_canvas->export_layers(target.value().stem_path, [this] {
|
||||
message_box("Export Layers", "Image layers exported to Files/PanoPainter");
|
||||
});
|
||||
}
|
||||
#else
|
||||
pick_dir([this](std::string path) {
|
||||
auto p = path + "/" + doc_name;
|
||||
canvas->m_canvas->export_layers(p, [this, p] {
|
||||
message_box("Export Layers", "Layers exported to: " + p);
|
||||
const auto target = pp::app::make_document_export_stem_target(path, doc_name);
|
||||
if (!target) {
|
||||
message_box("Export Layers", target.status().message);
|
||||
return;
|
||||
}
|
||||
|
||||
canvas->m_canvas->export_layers(target.value().stem_path, [this, target = target.value()] {
|
||||
message_box("Export Layers", "Layers exported to: " + target.stem_path);
|
||||
});
|
||||
});
|
||||
#endif
|
||||
@@ -482,19 +496,28 @@ void App::dialog_export_anim_frames()
|
||||
if (canvas)
|
||||
{
|
||||
#if defined(__IOS__)
|
||||
auto dir = work_path + "/" + doc_name + "_frames";
|
||||
if (Asset::create_dir(dir))
|
||||
const auto target = pp::app::make_document_export_collection_target(work_path, doc_name, "_frames");
|
||||
if (!target) {
|
||||
message_box("Export Layers", target.status().message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Asset::create_dir(target.value().directory))
|
||||
{
|
||||
auto p = dir + "/" + doc_name;
|
||||
canvas->m_canvas->export_anim_frames(p, [this, p] {
|
||||
canvas->m_canvas->export_anim_frames(target.value().stem_path, [this] {
|
||||
message_box("Export Layers", "Image layers exported to Files/PanoPainter");
|
||||
});
|
||||
}
|
||||
#else
|
||||
pick_dir([this](std::string path) {
|
||||
auto p = path + "/" + doc_name;
|
||||
canvas->m_canvas->export_anim_frames(p, [this, p] {
|
||||
message_box("Export Layers", "Layers exported to: " + p);
|
||||
const auto target = pp::app::make_document_export_stem_target(path, doc_name);
|
||||
if (!target) {
|
||||
message_box("Export Layers", target.status().message);
|
||||
return;
|
||||
}
|
||||
|
||||
canvas->m_canvas->export_anim_frames(target.value().stem_path, [this, target = target.value()] {
|
||||
message_box("Export Layers", "Layers exported to: " + target.stem_path);
|
||||
});
|
||||
});
|
||||
#endif
|
||||
@@ -657,7 +680,13 @@ void App::dialog_ppbr_export()
|
||||
void App::dialog_timelapse_export()
|
||||
{
|
||||
#if __IOS__ || __WEB__
|
||||
pick_file_save("mp4", doc_name + "-timelapse",
|
||||
const auto target = pp::app::make_document_export_suggested_name(doc_name, "-timelapse");
|
||||
if (!target) {
|
||||
message_box("Export Timelapse", target.status().message);
|
||||
return;
|
||||
}
|
||||
|
||||
pick_file_save("mp4", target.value().name,
|
||||
[this](std::string path) {
|
||||
rec_export(path);
|
||||
},
|
||||
@@ -679,7 +708,13 @@ void App::dialog_timelapse_export()
|
||||
void App::dialog_export_mp4()
|
||||
{
|
||||
#if __IOS__ || __WEB__
|
||||
pick_file_save("mp4", doc_name + "-animation",
|
||||
const auto target = pp::app::make_document_export_suggested_name(doc_name, "-animation");
|
||||
if (!target) {
|
||||
message_box("Export Animation", target.status().message);
|
||||
return;
|
||||
}
|
||||
|
||||
pick_file_save("mp4", target.value().name,
|
||||
[this](std::string path) {
|
||||
export_anim_mp4(path);
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user