Add brush texture list boundary

This commit is contained in:
2026-06-03 17:21:49 +02:00
parent cee5f141a3
commit 9adfad9609
8 changed files with 727 additions and 64 deletions

View File

@@ -316,6 +316,17 @@ struct PlanBrushOperationArgs {
bool has_brush = true;
};
struct PlanBrushTextureListArgs {
std::string kind = "add";
std::string directory_name = "brushes";
std::string data_path = "data";
std::string source_path = "source.png";
int item_count = 1;
int current_index = 0;
int offset = 1;
bool current_is_user_texture = false;
};
struct PlanGridOperationArgs {
std::string kind = "pick";
std::string path;
@@ -1087,6 +1098,20 @@ const char* brush_ui_operation_name(pp::app::BrushUiOperation operation) noexcep
return "stroke-settings-changed";
}
const char* brush_texture_list_operation_name(pp::app::BrushTextureListOperation operation) noexcept
{
switch (operation) {
case pp::app::BrushTextureListOperation::add_texture:
return "add-texture";
case pp::app::BrushTextureListOperation::remove_texture:
return "remove-texture";
case pp::app::BrushTextureListOperation::move_texture:
return "move-texture";
}
return "add-texture";
}
const char* canvas_tool_operation_name(pp::app::CanvasToolOperation operation) noexcept
{
switch (operation) {
@@ -1613,6 +1638,7 @@ void print_help()
<< " plan-animation-operation --kind add|duplicate|remove|duration|move|select|goto|next|prev|playback|toggle-playback|onion [--frame-count N] [--total-duration N] [--current-frame N] [--selected-frame N] [--layer-index N] [--layer-id N] [--current-duration N] [--delta N] [--offset N] [--onion-size N] [--playing]\n"
<< " plan-animation-panel-action --action goto|next|prev|playback|toggle-playback [--total-duration N] [--current-frame N] [--target-frame N] [--playing]\n"
<< " plan-brush-operation --kind color|tip|pattern|dual|preset|settings [--path FILE] [--thumb FILE] [--r N] [--g N] [--b N] [--a N] [--no-brush]\n"
<< " plan-brush-texture-list --kind add|remove|move [--dir NAME] [--data-path DIR] [--source FILE] [--item-count N] [--current-index N] [--offset N] [--user-texture]\n"
<< " plan-canvas-tool --kind draw|erase|line|camera|grid|copy|cut|fill|mask-free|mask-line|bucket|pick|touch-lock [--current-mode-draw]\n"
<< " plan-canvas-tool-state [--mode draw|erase|line|camera|grid|copy|cut|fill|mask-free|mask-line|bucket] [--picking] [--touch-lock]\n"
<< " plan-grid-operation --kind pick|load|reload|clear|render|commit [--path FILE] [--no-heightmap] [--no-canvas] [--float32] [--float16] [--texture-resolution N] [--samples N]\n"
@@ -4283,6 +4309,116 @@ int plan_brush_operation(int argc, char** argv)
return 0;
}
pp::foundation::Status parse_plan_brush_texture_list_args(
int argc,
char** argv,
PlanBrushTextureListArgs& args)
{
for (int i = 2; i < argc; ++i) {
const std::string_view key(argv[i]);
if (key == "--kind" || key == "--dir" || key == "--data-path" || key == "--source") {
if (i + 1 >= argc) {
return pp::foundation::Status::invalid_argument("missing value for option");
}
if (key == "--kind") {
args.kind = argv[++i];
} else if (key == "--dir") {
args.directory_name = argv[++i];
} else if (key == "--data-path") {
args.data_path = argv[++i];
} else {
args.source_path = argv[++i];
}
} else if (key == "--item-count" || key == "--current-index" || key == "--offset") {
if (i + 1 >= argc) {
return pp::foundation::Status::invalid_argument("missing value for option");
}
const auto value = parse_i32_arg(argv[++i]);
if (!value) {
return value.status();
}
if (key == "--item-count") {
args.item_count = value.value();
} else if (key == "--current-index") {
args.current_index = value.value();
} else {
args.offset = value.value();
}
} else if (key == "--user-texture") {
args.current_is_user_texture = true;
} else {
return pp::foundation::Status::invalid_argument("unknown option");
}
}
return pp::foundation::Status::success();
}
pp::foundation::Result<pp::app::BrushTextureListPlan> make_brush_texture_list_plan(
const PlanBrushTextureListArgs& args)
{
if (args.kind == "add") {
return pp::app::plan_brush_texture_list_add(args.directory_name, args.data_path, args.source_path);
}
if (args.kind == "remove") {
return pp::app::plan_brush_texture_list_remove(
args.item_count,
args.current_index,
args.current_is_user_texture);
}
if (args.kind == "move" || args.kind == "up" || args.kind == "down") {
const int offset = args.kind == "up" ? -1 : (args.kind == "down" ? 1 : args.offset);
return pp::app::plan_brush_texture_list_move(args.item_count, args.current_index, offset);
}
return pp::foundation::Result<pp::app::BrushTextureListPlan>::failure(
pp::foundation::Status::invalid_argument("unknown brush texture list operation kind"));
}
int plan_brush_texture_list(int argc, char** argv)
{
PlanBrushTextureListArgs args;
const auto status = parse_plan_brush_texture_list_args(argc, argv, args);
if (!status.ok()) {
print_error("plan-brush-texture-list", status.message);
return 2;
}
const auto plan = make_brush_texture_list_plan(args);
if (!plan) {
print_error("plan-brush-texture-list", plan.status().message);
return 2;
}
const auto& value = plan.value();
std::cout << "{\"ok\":true,\"command\":\"plan-brush-texture-list\""
<< ",\"state\":{\"kind\":\"" << json_escape(args.kind)
<< "\",\"dir\":\"" << json_escape(args.directory_name)
<< "\",\"dataPath\":\"" << json_escape(args.data_path)
<< "\",\"source\":\"" << json_escape(args.source_path)
<< "\",\"itemCount\":" << args.item_count
<< ",\"currentIndex\":" << args.current_index
<< ",\"offset\":" << args.offset
<< ",\"currentIsUserTexture\":" << json_bool(args.current_is_user_texture)
<< "},\"plan\":{\"operation\":\"" << brush_texture_list_operation_name(value.operation)
<< "\",\"itemCount\":" << value.item_count
<< ",\"currentIndex\":" << value.current_index
<< ",\"targetIndex\":" << value.target_index
<< ",\"moveOffset\":" << value.move_offset
<< ",\"source\":\"" << json_escape(value.source_path)
<< "\",\"path\":\"" << json_escape(value.high_path)
<< "\",\"thumb\":\"" << json_escape(value.thumbnail_path)
<< "\",\"brushName\":\"" << json_escape(value.brush_name)
<< "\",\"userTexture\":" << json_bool(value.user_texture)
<< ",\"deletesTextureFiles\":" << json_bool(value.deletes_texture_files)
<< ",\"savesList\":" << json_bool(value.saves_list)
<< ",\"notifiesSelection\":" << json_bool(value.notifies_selection)
<< ",\"convertsBrushAlpha\":" << json_bool(value.converts_brush_alpha)
<< ",\"noOp\":" << json_bool(value.no_op)
<< "}}\n";
return 0;
}
pp::foundation::Status parse_plan_canvas_tool_args(
int argc,
char** argv,
@@ -7405,6 +7541,10 @@ int main(int argc, char** argv)
return plan_brush_operation(argc, argv);
}
if (command == "plan-brush-texture-list") {
return plan_brush_texture_list(argc, argv);
}
if (command == "plan-canvas-tool") {
return plan_canvas_tool(argc, argv);
}