Add multi-layer PPI save automation
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <bit>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
@@ -89,6 +90,18 @@ void append_ascii(std::vector<std::byte>& bytes, std::string_view value)
|
||||
return pp::foundation::Status::success();
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string generated_layer_name(std::string_view base_name, std::uint32_t layer_index, std::uint32_t layer_count)
|
||||
{
|
||||
if (layer_count == 1U) {
|
||||
return std::string(base_name);
|
||||
}
|
||||
|
||||
std::string name(base_name);
|
||||
name.push_back(' ');
|
||||
name += std::to_string(layer_index + 1U);
|
||||
return name;
|
||||
}
|
||||
|
||||
[[nodiscard]] pp::foundation::Status add_payload_bytes(PpiBodySummary& summary, std::uint32_t bytes) noexcept
|
||||
{
|
||||
const auto next = summary.compressed_face_bytes + static_cast<std::uint64_t>(bytes);
|
||||
@@ -654,6 +667,11 @@ pp::foundation::Result<std::vector<std::byte>> create_minimal_ppi_project(PpiMin
|
||||
pp::foundation::Status::out_of_range("PPI layer name exceeds the configured limit"));
|
||||
}
|
||||
|
||||
if (config.layer_count == 0 || config.layer_count > max_ppi_layer_count) {
|
||||
return pp::foundation::Result<std::vector<std::byte>>::failure(
|
||||
pp::foundation::Status::out_of_range("PPI layer count is outside the configured range"));
|
||||
}
|
||||
|
||||
if (config.frame_duration_ms == 0) {
|
||||
return pp::foundation::Result<std::vector<std::byte>>::failure(
|
||||
pp::foundation::Status::invalid_argument("PPI frame duration must be greater than zero"));
|
||||
@@ -664,6 +682,19 @@ pp::foundation::Result<std::vector<std::byte>> create_minimal_ppi_project(PpiMin
|
||||
pp::foundation::Status::out_of_range("PPI frame count is outside the configured range"));
|
||||
}
|
||||
|
||||
if (config.layer_count > max_ppi_frame_count / config.frame_count) {
|
||||
return pp::foundation::Result<std::vector<std::byte>>::failure(
|
||||
pp::foundation::Status::out_of_range("PPI total layer frame count exceeds the configured range"));
|
||||
}
|
||||
|
||||
for (std::uint32_t layer = 0; layer < config.layer_count; ++layer) {
|
||||
const auto name = generated_layer_name(config.layer_name, layer, config.layer_count);
|
||||
if (name.size() > max_ppi_layer_name_length) {
|
||||
return pp::foundation::Result<std::vector<std::byte>>::failure(
|
||||
pp::foundation::Status::out_of_range("PPI generated layer name exceeds the configured limit"));
|
||||
}
|
||||
}
|
||||
|
||||
bool seen_faces[6] {};
|
||||
std::uint64_t total_payload_bytes = 0;
|
||||
for (const auto& face : config.dirty_faces) {
|
||||
@@ -733,41 +764,44 @@ pp::foundation::Result<std::vector<std::byte>> create_minimal_ppi_project(PpiMin
|
||||
|
||||
append_u32(bytes, config.width);
|
||||
append_u32(bytes, config.height);
|
||||
append_u32(bytes, 1);
|
||||
append_u32(bytes, config.frame_count);
|
||||
append_u32(bytes, 0);
|
||||
append_f32(bytes, 1.0F);
|
||||
append_u32(bytes, static_cast<std::uint32_t>(config.layer_name.size()));
|
||||
append_ascii(bytes, config.layer_name);
|
||||
append_u32(bytes, 0);
|
||||
bytes.push_back(std::byte { 0 });
|
||||
bytes.push_back(std::byte { 1 });
|
||||
append_u32(bytes, config.frame_count);
|
||||
for (std::uint32_t frame = 0; frame < config.frame_count; ++frame) {
|
||||
append_u32(bytes, config.frame_duration_ms);
|
||||
for (std::uint32_t face = 0; face < 6U; ++face) {
|
||||
const PpiDirtyFacePayloadConfig* dirty_face = nullptr;
|
||||
if (frame == 0U) {
|
||||
for (const auto& candidate : config.dirty_faces) {
|
||||
if (candidate.face_index == face) {
|
||||
dirty_face = &candidate;
|
||||
break;
|
||||
append_u32(bytes, config.layer_count);
|
||||
append_u32(bytes, config.layer_count * config.frame_count);
|
||||
for (std::uint32_t layer = 0; layer < config.layer_count; ++layer) {
|
||||
const auto name = generated_layer_name(config.layer_name, layer, config.layer_count);
|
||||
append_u32(bytes, layer);
|
||||
append_f32(bytes, 1.0F);
|
||||
append_u32(bytes, static_cast<std::uint32_t>(name.size()));
|
||||
append_ascii(bytes, name);
|
||||
append_u32(bytes, 0);
|
||||
bytes.push_back(std::byte { 0 });
|
||||
bytes.push_back(std::byte { 1 });
|
||||
append_u32(bytes, config.frame_count);
|
||||
for (std::uint32_t frame = 0; frame < config.frame_count; ++frame) {
|
||||
append_u32(bytes, config.frame_duration_ms);
|
||||
for (std::uint32_t face = 0; face < 6U; ++face) {
|
||||
const PpiDirtyFacePayloadConfig* dirty_face = nullptr;
|
||||
if (layer == 0U && frame == 0U) {
|
||||
for (const auto& candidate : config.dirty_faces) {
|
||||
if (candidate.face_index == face) {
|
||||
dirty_face = &candidate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dirty_face == nullptr) {
|
||||
append_u32(bytes, 0);
|
||||
continue;
|
||||
}
|
||||
if (dirty_face == nullptr) {
|
||||
append_u32(bytes, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
append_u32(bytes, 1);
|
||||
append_u32(bytes, dirty_face->x);
|
||||
append_u32(bytes, dirty_face->y);
|
||||
append_u32(bytes, dirty_face->x + dirty_face->width);
|
||||
append_u32(bytes, dirty_face->y + dirty_face->height);
|
||||
append_u32(bytes, static_cast<std::uint32_t>(dirty_face->png_rgba8.size()));
|
||||
bytes.insert(bytes.end(), dirty_face->png_rgba8.begin(), dirty_face->png_rgba8.end());
|
||||
append_u32(bytes, 1);
|
||||
append_u32(bytes, dirty_face->x);
|
||||
append_u32(bytes, dirty_face->y);
|
||||
append_u32(bytes, dirty_face->x + dirty_face->width);
|
||||
append_u32(bytes, dirty_face->y + dirty_face->height);
|
||||
append_u32(bytes, static_cast<std::uint32_t>(dirty_face->png_rgba8.size()));
|
||||
bytes.insert(bytes.end(), dirty_face->png_rgba8.begin(), dirty_face->png_rgba8.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
append_u32(bytes, 0);
|
||||
|
||||
@@ -131,6 +131,7 @@ struct PpiMinimalProjectConfig {
|
||||
std::uint32_t width = 0;
|
||||
std::uint32_t height = 0;
|
||||
std::string layer_name;
|
||||
std::uint32_t layer_count = 1;
|
||||
std::uint32_t frame_count = 1;
|
||||
std::uint32_t frame_duration_ms = 100;
|
||||
std::span<const PpiDirtyFacePayloadConfig> dirty_faces;
|
||||
|
||||
Reference in New Issue
Block a user