Simulate strokes from pano cli
This commit is contained in:
@@ -98,6 +98,8 @@ Known local toolchain state:
|
||||
`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`.
|
||||
- `pano_cli simulate-stroke` exposes the pure stroke sampler for scripted
|
||||
automation and is covered by `pano_cli_simulate_stroke_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.
|
||||
|
||||
@@ -328,9 +328,10 @@ 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 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.
|
||||
frame count/duration, and `pano_cli simulate-stroke` exercises the pure stroke
|
||||
sampler for scripted-stroke automation. `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:
|
||||
|
||||
@@ -582,6 +583,8 @@ Results:
|
||||
- `pano_cli_inspect_png_metadata_smoke` passed and reports PNG metadata JSON
|
||||
for the tiny IHDR fixture.
|
||||
- `pano_cli_parse_layout_smoke` passed.
|
||||
- `pano_cli_simulate_stroke_smoke` passed and reports deterministic stroke
|
||||
sample counts/distances.
|
||||
- `panopainter_validate_shaders` passed, validating 25 shader programs and 7
|
||||
shader includes for stage markers and include graph integrity.
|
||||
- PowerShell analyze automation returns JSON summaries and includes the shader
|
||||
|
||||
@@ -224,4 +224,10 @@ if(TARGET pano_cli)
|
||||
COMMAND pano_cli parse-layout --path "${CMAKE_CURRENT_SOURCE_DIR}/data/layouts/simple-layout.xml")
|
||||
set_tests_properties(pano_cli_parse_layout_smoke PROPERTIES
|
||||
LABELS "ui;integration;desktop-fast")
|
||||
|
||||
add_test(NAME pano_cli_simulate_stroke_smoke
|
||||
COMMAND pano_cli simulate-stroke --x1 0 --y1 0 --x2 10 --y2 0 --spacing 2)
|
||||
set_tests_properties(pano_cli_simulate_stroke_smoke PROPERTIES
|
||||
LABELS "paint;integration;desktop-fast"
|
||||
PASS_REGULAR_EXPRESSION "\"samples\":6.*\"distance\":10")
|
||||
endif()
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "document/document.h"
|
||||
#include "foundation/parse.h"
|
||||
#include "foundation/result.h"
|
||||
#include "paint/stroke.h"
|
||||
#include "ui_core/layout_xml.h"
|
||||
|
||||
#include <cstdint>
|
||||
@@ -37,6 +38,14 @@ struct InspectProjectArgs {
|
||||
std::string path;
|
||||
};
|
||||
|
||||
struct SimulateStrokeArgs {
|
||||
std::uint32_t x1 = 0;
|
||||
std::uint32_t y1 = 0;
|
||||
std::uint32_t x2 = 0;
|
||||
std::uint32_t y2 = 0;
|
||||
std::uint32_t spacing = 1;
|
||||
};
|
||||
|
||||
void print_error(std::string_view command, std::string_view message)
|
||||
{
|
||||
std::cout << "{\"ok\":false,\"command\":\"" << command
|
||||
@@ -51,6 +60,7 @@ void print_help()
|
||||
<< " inspect-image --path FILE\n"
|
||||
<< " inspect-project --path FILE\n"
|
||||
<< " parse-layout --path FILE\n"
|
||||
<< " simulate-stroke --x1 N --y1 N --x2 N --y2 N [--spacing N]\n"
|
||||
<< " --help\n";
|
||||
}
|
||||
|
||||
@@ -291,6 +301,84 @@ int inspect_project(int argc, char** argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
pp::foundation::Status parse_simulate_stroke_args(int argc, char** argv, SimulateStrokeArgs& args)
|
||||
{
|
||||
for (int i = 2; i < argc; ++i) {
|
||||
const std::string_view key(argv[i]);
|
||||
if (key == "--x1" || key == "--y1" || key == "--x2" || key == "--y2" || key == "--spacing") {
|
||||
if (i + 1 >= argc) {
|
||||
return pp::foundation::Status::invalid_argument("missing value for option");
|
||||
}
|
||||
|
||||
const auto value = pp::foundation::parse_u32(argv[++i]);
|
||||
if (!value) {
|
||||
return value.status();
|
||||
}
|
||||
|
||||
if (key == "--x1") {
|
||||
args.x1 = value.value();
|
||||
} else if (key == "--y1") {
|
||||
args.y1 = value.value();
|
||||
} else if (key == "--x2") {
|
||||
args.x2 = value.value();
|
||||
} else if (key == "--y2") {
|
||||
args.y2 = value.value();
|
||||
} else {
|
||||
args.spacing = value.value();
|
||||
}
|
||||
} else {
|
||||
return pp::foundation::Status::invalid_argument("unknown option");
|
||||
}
|
||||
}
|
||||
|
||||
if (args.spacing == 0) {
|
||||
return pp::foundation::Status::invalid_argument("stroke spacing must be greater than zero");
|
||||
}
|
||||
|
||||
return pp::foundation::Status::success();
|
||||
}
|
||||
|
||||
int simulate_stroke(int argc, char** argv)
|
||||
{
|
||||
SimulateStrokeArgs args;
|
||||
const auto status = parse_simulate_stroke_args(argc, argv, args);
|
||||
if (!status.ok()) {
|
||||
print_error("simulate-stroke", status.message);
|
||||
return 2;
|
||||
}
|
||||
|
||||
const pp::paint::StrokePoint points[] {
|
||||
pp::paint::StrokePoint {
|
||||
.x = static_cast<float>(args.x1),
|
||||
.y = static_cast<float>(args.y1),
|
||||
.pressure = 1.0F,
|
||||
},
|
||||
pp::paint::StrokePoint {
|
||||
.x = static_cast<float>(args.x2),
|
||||
.y = static_cast<float>(args.y2),
|
||||
.pressure = 1.0F,
|
||||
},
|
||||
};
|
||||
const auto samples = pp::paint::sample_stroke(
|
||||
points,
|
||||
pp::paint::StrokeSamplingConfig {
|
||||
.spacing = static_cast<float>(args.spacing),
|
||||
});
|
||||
if (!samples) {
|
||||
print_error("simulate-stroke", samples.status().message);
|
||||
return 2;
|
||||
}
|
||||
|
||||
const auto& first = samples.value().front();
|
||||
const auto& last = samples.value().back();
|
||||
std::cout << "{\"ok\":true,\"command\":\"simulate-stroke\""
|
||||
<< ",\"samples\":" << samples.value().size()
|
||||
<< ",\"first\":{\"x\":" << first.x << ",\"y\":" << first.y << "}"
|
||||
<< ",\"last\":{\"x\":" << last.x << ",\"y\":" << last.y
|
||||
<< ",\"distance\":" << last.distance << "}}\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
pp::foundation::Status parse_layout_args(int argc, char** argv, ParseLayoutArgs& args)
|
||||
{
|
||||
for (int i = 2; i < argc; ++i) {
|
||||
@@ -372,6 +460,10 @@ int main(int argc, char** argv)
|
||||
return inspect_project(argc, argv);
|
||||
}
|
||||
|
||||
if (command == "simulate-stroke") {
|
||||
return simulate_stroke(argc, argv);
|
||||
}
|
||||
|
||||
if (command == "parse-layout") {
|
||||
return parse_layout(argc, argv);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user