#include "pch.h" #include "app.h" #include "app_core/app_dialog.h" #include "app_core/document_export.h" #include "legacy_brush_package_export_services.h" #include "legacy_document_export_services.h" #include "legacy_ui_overlay_services.h" #include "node_dialog_export_ppbr.h" #include #define MP4V2_NO_STDINT_DEFS #include #include namespace pp::panopainter { namespace { [[nodiscard]] bool can_start_document_export(App& app, bool requires_license) { const auto decision = pp::app::plan_document_export_start( requires_license, !requires_license || app.check_license(), app.canvas != nullptr); switch (decision) { case pp::app::DocumentExportStartDecision::start_now: return true; case pp::app::DocumentExportStartDecision::show_license_disabled: { const auto plan = pp::app::plan_document_export_license_disabled_dialog(); app.message_box(plan.title, plan.message, plan.show_cancel); return false; } case pp::app::DocumentExportStartDecision::unavailable_no_canvas: return false; } return false; } void start_document_export_collection( App& app, pp::app::DocumentExportCollectionKind kind) { const auto plan = pp::app::plan_document_export_collection_target( kind, app.uses_work_directory_document_export_collections()); const auto success_kind = pp::app::document_export_collection_success_kind(kind); if (plan.destination == pp::app::DocumentExportCollectionDestination::work_directory_collection) { const auto target = pp::app::make_document_export_collection_target( app.work_path, app.doc_name, plan.suffix); if (!target) { const auto dialog = pp::app::plan_document_export_failure_dialog(success_kind, target.status().message); app.message_box(dialog.title, dialog.message, dialog.show_cancel); return; } const auto status = pp::panopainter::execute_legacy_document_export_collection( app, plan.kind, target.value()); if (!status.ok()) LOG( "%s: %s", pp::app::document_export_execution_log_message( kind == pp::app::DocumentExportCollectionKind::layers ? pp::app::DocumentExportExecutionKind::layers_collection : pp::app::DocumentExportExecutionKind::animation_frames_collection), status.message); return; } app.pick_dir([ &app, kind = plan.kind, success_kind ](std::string path) { const auto target = pp::app::make_document_export_stem_target(path, app.doc_name); if (!target) { const auto dialog = pp::app::plan_document_export_failure_dialog(success_kind, target.status().message); app.message_box(dialog.title, dialog.message, dialog.show_cancel); return; } const auto status = pp::panopainter::execute_legacy_document_export_stem( app, kind, target.value()); if (!status.ok()) LOG( "%s: %s", pp::app::document_export_execution_log_message( kind == pp::app::DocumentExportCollectionKind::layers ? pp::app::DocumentExportExecutionKind::layers_stem : pp::app::DocumentExportExecutionKind::animation_frames_stem), status.message); }); } void start_document_video_export( App& app, pp::app::DocumentVideoExportKind kind, pp::app::DocumentExportSuccessKind success_kind, const char* suffix, pp::app::DocumentExportExecutionKind execution_kind) { if (!can_start_document_export(app, false)) return; if (app.uses_prepared_file_writes()) { const auto target = pp::app::make_document_export_suggested_name(app.doc_name, suffix); if (!target) { const auto dialog = pp::app::plan_document_export_failure_dialog( success_kind, target.status().message); app.message_box(dialog.title, dialog.message, dialog.show_cancel); return; } app.pick_file_save("mp4", target.value().name, [&app, kind, execution_kind](std::string path) { const auto status = pp::panopainter::execute_legacy_document_video_export( app, kind, path, false); if (!status.ok()) LOG( "%s: %s", pp::app::document_export_execution_log_message(execution_kind), status.message); }, [](const std::string& path, bool saved) { (void)path; (void)saved; } ); return; } app.pick_file_save({ "mp4" }, [&app, kind, execution_kind](std::string path) { const auto status = pp::panopainter::execute_legacy_document_video_export( app, kind, path, true); if (!status.ok()) LOG( "%s: %s", pp::app::document_export_execution_log_message(execution_kind), status.message); }); } } // namespace void open_document_export_dialog(App& app, std::string ext) { if (!can_start_document_export(app, true)) return; // TODO: use picker const auto target = pp::app::make_document_export_file_target(app.work_path, app.doc_name, ext); if (!target) { const auto dialog = pp::app::plan_document_export_failure_dialog( pp::app::DocumentExportSuccessKind::equirectangular, target.status().message); app.message_box(dialog.title, dialog.message, dialog.show_cancel); return; } const auto status = pp::panopainter::execute_legacy_document_export_file(app, target.value()); if (!status.ok()) LOG( "%s: %s", pp::app::document_export_execution_log_message( pp::app::DocumentExportExecutionKind::equirectangular_file), status.message); } void open_document_export_layers_dialog(App& app) { if (!can_start_document_export(app, true)) return; start_document_export_collection( app, pp::app::DocumentExportCollectionKind::layers); } void open_document_export_anim_frames_dialog(App& app) { if (!can_start_document_export(app, true)) return; start_document_export_collection( app, pp::app::DocumentExportCollectionKind::animation_frames); } void open_document_export_depth_dialog(App& app) { if (!can_start_document_export(app, true)) return; const auto status = pp::panopainter::execute_legacy_document_export_depth(app, app.doc_name); if (!status.ok()) LOG( "%s: %s", pp::app::document_export_execution_log_message(pp::app::DocumentExportExecutionKind::depth), status.message); } void open_document_export_cube_faces_dialog(App& app) { if (!can_start_document_export(app, false)) return; const auto status = pp::panopainter::execute_legacy_document_export_cube_faces(app, app.doc_name); if (!status.ok()) LOG( "%s: %s", pp::app::document_export_execution_log_message(pp::app::DocumentExportExecutionKind::cube_faces), status.message); } void open_document_timelapse_export_dialog(App& app) { start_document_video_export( app, pp::app::DocumentVideoExportKind::timelapse, pp::app::DocumentExportSuccessKind::timelapse, "-timelapse", pp::app::DocumentExportExecutionKind::timelapse); } void open_document_export_mp4_dialog(App& app) { start_document_video_export( app, pp::app::DocumentVideoExportKind::animation_mp4, pp::app::DocumentExportSuccessKind::animation_mp4, "-animation", pp::app::DocumentExportExecutionKind::animation_mp4); } void open_ppbr_export_dialog(App& app) { auto* overlay_anchor = app.layout[app.main_id]; if (!overlay_anchor) { LOG("PPBR export dialog open failed: main layout anchor is missing"); return; } auto dialog = pp::panopainter::make_legacy_overlay_node(app); const auto overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*overlay_anchor, dialog); if (!overlay) { LOG("PPBR export dialog open failed: %s", overlay.status().message); return; } const auto overlay_handle = overlay.value(); const auto close_dialog = [overlay_anchor, overlay_handle]() { const auto close_status = pp::panopainter::close_legacy_overlay_node(*overlay_anchor, overlay_handle); (void)close_status; }; dialog->btn_ok->on_click = [&app, dialog] (Node*) { const auto request = pp::panopainter::make_legacy_brush_package_export_request(*dialog); if (app.uses_prepared_file_writes()) { app.pick_file_save("ppbr", "exported-brushes", [&app, dialog, request] (std::string path) { const auto status = pp::panopainter::execute_legacy_brush_package_export( app, *dialog, request, path, pp::panopainter::LegacyBrushPackageExportMode::inline_export_only); if (!status.ok()) LOG("PPBR export failed: %s", status.message); }, [dialog] (const std::string& path, bool saved) { (void)path; pp::panopainter::complete_legacy_brush_package_export(*dialog, saved); } ); return; } app.pick_file_save({ "ppbr" }, [&app, dialog, request] (std::string path) { const auto status = pp::panopainter::execute_legacy_brush_package_export( app, *dialog, request, path, pp::panopainter::LegacyBrushPackageExportMode::desktop_async_close_and_message); if (!status.ok()) LOG("PPBR export failed: %s", status.message); }); }; dialog->btn_cancel->on_click = [close_dialog](Node*) { close_dialog(); }; } } // namespace pp::panopainter