#pragma once #include "foundation/result.h" #include #include #include namespace pp::app { enum class GridUiOperation { request_heightmap_pick, load_heightmap, clear_heightmap, reload_heightmap, render_lightmap, commit_heightmap, }; struct GridUiPlan { GridUiOperation operation = GridUiOperation::request_heightmap_pick; std::string path; int texture_resolution = 0; int sample_count = 0; bool opens_picker = false; bool loads_heightmap = false; bool clears_heightmap = false; bool renders_lightmap = false; bool commits_heightmap = false; bool updates_preview = false; bool updates_ground_opacity = false; bool updates_shading_mode = false; bool shows_unsupported_message = false; bool shows_progress = false; bool mutates_grid_state = false; }; [[nodiscard]] inline pp::foundation::Status validate_grid_texture_resolution(int texture_resolution) noexcept { if (texture_resolution <= 0 || texture_resolution > 16384) { return pp::foundation::Status::out_of_range("grid texture resolution must be within 1..16384"); } return pp::foundation::Status::success(); } [[nodiscard]] inline pp::foundation::Status validate_grid_lightmap_samples(int sample_count) noexcept { if (sample_count <= 0 || sample_count > 4096) { return pp::foundation::Status::out_of_range("grid lightmap samples must be within 1..4096"); } return pp::foundation::Status::success(); } [[nodiscard]] inline constexpr GridUiPlan plan_grid_heightmap_pick() noexcept { GridUiPlan plan; plan.operation = GridUiOperation::request_heightmap_pick; plan.opens_picker = true; return plan; } [[nodiscard]] inline pp::foundation::Result plan_grid_heightmap_load(std::string_view path) { if (path.empty()) { return pp::foundation::Result::failure( pp::foundation::Status::invalid_argument("heightmap path must not be empty")); } GridUiPlan plan; plan.operation = GridUiOperation::load_heightmap; plan.path = std::string(path); plan.loads_heightmap = true; plan.updates_preview = true; plan.updates_ground_opacity = true; plan.mutates_grid_state = true; return pp::foundation::Result::success(std::move(plan)); } [[nodiscard]] inline constexpr GridUiPlan plan_grid_heightmap_clear(bool has_heightmap) noexcept { GridUiPlan plan; plan.operation = GridUiOperation::clear_heightmap; plan.clears_heightmap = true; plan.updates_preview = has_heightmap; plan.mutates_grid_state = has_heightmap; return plan; } [[nodiscard]] inline pp::foundation::Result plan_grid_heightmap_reload(std::string_view path) { auto plan = plan_grid_heightmap_load(path); if (!plan) { return pp::foundation::Result::failure(plan.status()); } plan.value().operation = GridUiOperation::reload_heightmap; plan.value().updates_ground_opacity = false; return plan; } [[nodiscard]] inline pp::foundation::Result plan_grid_lightmap_render( bool has_heightmap, bool supports_float32, bool supports_float16, int texture_resolution, int sample_count) { const auto texture_status = validate_grid_texture_resolution(texture_resolution); if (!texture_status.ok()) { return pp::foundation::Result::failure(texture_status); } const auto sample_status = validate_grid_lightmap_samples(sample_count); if (!sample_status.ok()) { return pp::foundation::Result::failure(sample_status); } GridUiPlan plan; plan.operation = GridUiOperation::render_lightmap; plan.texture_resolution = texture_resolution; plan.sample_count = sample_count; if (!supports_float32 && !supports_float16) { plan.shows_unsupported_message = true; return pp::foundation::Result::success(plan); } plan.renders_lightmap = has_heightmap; plan.shows_progress = has_heightmap; plan.updates_shading_mode = has_heightmap; plan.mutates_grid_state = has_heightmap; return pp::foundation::Result::success(plan); } [[nodiscard]] inline constexpr GridUiPlan plan_grid_heightmap_commit(bool has_canvas) noexcept { GridUiPlan plan; plan.operation = GridUiOperation::commit_heightmap; plan.commits_heightmap = has_canvas; plan.updates_ground_opacity = has_canvas; plan.mutates_grid_state = has_canvas; return plan; } } // namespace pp::app