From d0ef88be892592d7b492d7f881ca39edce274bb5 Mon Sep 17 00:00:00 2001 From: omigamedev Date: Mon, 1 Jun 2026 09:10:59 +0200 Subject: [PATCH] Create animation documents from pano cli --- docs/modernization/build-inventory.md | 2 + docs/modernization/roadmap.md | 9 +++-- tests/CMakeLists.txt | 6 +++ tools/pano_cli/main.cpp | 55 +++++++++++++++++++++------ 4 files changed, 57 insertions(+), 15 deletions(-) diff --git a/docs/modernization/build-inventory.md b/docs/modernization/build-inventory.md index 0778414..0422419 100644 --- a/docs/modernization/build-inventory.md +++ b/docs/modernization/build-inventory.md @@ -96,6 +96,8 @@ Known local toolchain state: parsing, and layout XML parse coverage. - `pano_cli inspect-image` reports PNG IHDR metadata as JSON and is covered by `pano_cli_inspect_png_metadata_smoke` with a tiny IHDR fixture. +- `pano_cli create-document` supports `--frames` and `--frame-duration-ms` and + is covered by `pano_cli_create_animation_document_smoke`. - `panopainter_validate_shaders` validates the current combined GLSL shader files for one vertex stage marker, one fragment stage marker, valid marker order, and existing relative includes. diff --git a/docs/modernization/roadmap.md b/docs/modernization/roadmap.md index fcd3ee0..3acc921 100644 --- a/docs/modernization/roadmap.md +++ b/docs/modernization/roadmap.md @@ -327,9 +327,10 @@ the paint blend reference. `pp_ui_core` has started with XML-layout-facing length parsing, color parsing, tinyxml-backed layout XML parsing, and invalid input tests. `pano_cli inspect-image` exposes PNG IHDR metadata as JSON, and -`pano_cli parse-layout` exercises the XML layout path. Continue expanding -document behavior toward legacy Canvas parity and then port OpenGL classes -behind the renderer boundary. +`pano_cli create-document` can create simple animation documents with explicit +frame count/duration. `pano_cli parse-layout` exercises the XML layout path. +Continue expanding document behavior toward legacy Canvas parity and then port +OpenGL classes behind the renderer boundary. Implementation tasks: @@ -574,6 +575,8 @@ Results: - `pp_ui_core_layout_value_tests` passed. - `pp_ui_core_layout_xml_tests` passed. - `pano_cli_create_document_smoke` passed. +- `pano_cli_create_animation_document_smoke` passed and reports animation + duration JSON. - `pano_cli_inspect_image_rejects_unsupported` passed as an expected failure test. - `pano_cli_inspect_png_metadata_smoke` passed and reports PNG metadata JSON diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 50b41df..8a107af 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -202,6 +202,12 @@ if(TARGET pano_cli) set_tests_properties(pano_cli_create_document_smoke PROPERTIES LABELS "integration;desktop-fast") + add_test(NAME pano_cli_create_animation_document_smoke + COMMAND pano_cli create-document --width 64 --height 32 --layers 2 --frames 3 --frame-duration-ms 250) + set_tests_properties(pano_cli_create_animation_document_smoke PROPERTIES + LABELS "document;integration;desktop-fast" + PASS_REGULAR_EXPRESSION "\"frames\":3.*\"activeFrame\":2.*\"animationDurationMs\":750") + add_test(NAME pano_cli_inspect_image_rejects_unsupported COMMAND pano_cli inspect-image --path "${CMAKE_CURRENT_SOURCE_DIR}/data/images/unsupported-image.txt") set_tests_properties(pano_cli_inspect_image_rejects_unsupported PROPERTIES diff --git a/tools/pano_cli/main.cpp b/tools/pano_cli/main.cpp index 6d21882..4c94ae9 100644 --- a/tools/pano_cli/main.cpp +++ b/tools/pano_cli/main.cpp @@ -21,6 +21,8 @@ struct DocumentArgs { std::uint32_t width = 0; std::uint32_t height = 0; std::uint32_t layers = 1; + std::uint32_t frames = 1; + std::uint32_t frame_duration_ms = 100; }; struct InspectImageArgs { @@ -45,7 +47,7 @@ void print_help() { std::cout << "pano_cli commands:\n" - << " create-document --width N --height N [--layers N]\n" + << " create-document --width N --height N [--layers N] [--frames N] [--frame-duration-ms N]\n" << " inspect-image --path FILE\n" << " inspect-project --path FILE\n" << " parse-layout --path FILE\n" @@ -56,7 +58,8 @@ pp::foundation::Status parse_document_args(int argc, char** argv, DocumentArgs& { for (int i = 2; i < argc; ++i) { const std::string_view key(argv[i]); - if (key == "--width" || key == "--height" || key == "--layers") { + if (key == "--width" || key == "--height" || key == "--layers" || key == "--frames" + || key == "--frame-duration-ms") { if (i + 1 >= argc) { return pp::foundation::Status::invalid_argument("missing value for option"); } @@ -70,8 +73,12 @@ pp::foundation::Status parse_document_args(int argc, char** argv, DocumentArgs& args.width = value.value(); } else if (key == "--height") { args.height = value.value(); - } else { + } else if (key == "--layers") { args.layers = value.value(); + } else if (key == "--frames") { + args.frames = value.value(); + } else { + args.frame_duration_ms = value.value(); } } else { return pp::foundation::Status::invalid_argument("unknown option"); @@ -86,6 +93,14 @@ pp::foundation::Status parse_document_args(int argc, char** argv, DocumentArgs& return pp::foundation::Status::invalid_argument("layer count must be greater than zero"); } + if (args.frames == 0) { + return pp::foundation::Status::invalid_argument("frame count must be greater than zero"); + } + + if (args.frame_duration_ms == 0) { + return pp::foundation::Status::invalid_argument("frame duration must be greater than zero"); + } + return pp::foundation::Status::success(); } @@ -98,24 +113,40 @@ int create_document(int argc, char** argv) return 2; } - const auto document = pp::document::CanvasDocument::create( + const auto document_result = pp::document::CanvasDocument::create( pp::document::DocumentConfig { .width = args.width, .height = args.height, .layer_count = args.layers, }); - if (!document) { - print_error("create-document", document.status().message); + if (!document_result) { + print_error("create-document", document_result.status().message); return 2; } + auto document = document_result.value(); + const auto duration_status = document.set_frame_duration(0, args.frame_duration_ms); + if (!duration_status.ok()) { + print_error("create-document", duration_status.message); + return 2; + } + + for (std::uint32_t i = 1; i < args.frames; ++i) { + const auto added_frame = document.add_frame(args.frame_duration_ms); + if (!added_frame) { + print_error("create-document", added_frame.status().message); + return 2; + } + } + std::cout << "{\"ok\":true,\"command\":\"create-document\",\"document\":{" - << "\"width\":" << document.value().width() - << ",\"height\":" << document.value().height() - << ",\"layers\":" << document.value().layers().size() - << ",\"activeLayer\":" << document.value().active_layer_index() - << ",\"frames\":" << document.value().frames().size() - << ",\"activeFrame\":" << document.value().active_frame_index() + << "\"width\":" << document.width() + << ",\"height\":" << document.height() + << ",\"layers\":" << document.layers().size() + << ",\"activeLayer\":" << document.active_layer_index() + << ",\"frames\":" << document.frames().size() + << ",\"activeFrame\":" << document.active_frame_index() + << ",\"animationDurationMs\":" << document.animation_duration_ms() << "}}\n"; return 0; }