Files
panopainter/src/app_core/app_startup.h

189 lines
6.2 KiB
C++

#pragma once
#include "foundation/result.h"
#include <cmath>
#include <limits>
namespace pp::app {
struct AppStartupPlan {
int previous_run_counter = 0;
int next_run_counter = 1;
bool save_preferences = true;
bool start_timelapse = false;
bool vr_controllers_enabled = true;
bool show_license_warning = false;
};
struct AppStartupResourcePlan {
int ui_render_target_width = 0;
int ui_render_target_height = 0;
bool initialize_shaders = true;
bool initialize_assets = true;
bool initialize_layout = true;
bool update_title = true;
bool create_ui_render_target = true;
};
class AppStartupServices {
public:
virtual ~AppStartupServices() = default;
virtual void store_run_counter(int value) = 0;
virtual void save_preferences() = 0;
virtual void start_timelapse_recording() = 0;
virtual void apply_vr_controllers_enabled(bool enabled) = 0;
virtual void show_license_warning() = 0;
};
class AppStartupResourceServices {
public:
virtual ~AppStartupResourceServices() = default;
virtual void initialize_shaders() = 0;
virtual void initialize_assets() = 0;
virtual void initialize_layout() = 0;
virtual void update_title() = 0;
virtual void create_ui_render_target(int width, int height) = 0;
};
[[nodiscard]] inline pp::foundation::Result<AppStartupPlan> plan_app_startup(
int current_run_counter,
bool auto_timelapse_enabled,
bool stored_vr_controllers_enabled,
bool license_valid)
{
if (current_run_counter < 0) {
return pp::foundation::Result<AppStartupPlan>::failure(
pp::foundation::Status::invalid_argument("run counter must not be negative"));
}
if (current_run_counter == std::numeric_limits<int>::max()) {
return pp::foundation::Result<AppStartupPlan>::failure(
pp::foundation::Status::out_of_range("run counter would overflow"));
}
AppStartupPlan plan;
plan.previous_run_counter = current_run_counter;
plan.next_run_counter = current_run_counter + 1;
plan.start_timelapse = auto_timelapse_enabled;
plan.vr_controllers_enabled = stored_vr_controllers_enabled;
plan.show_license_warning = !license_valid;
return pp::foundation::Result<AppStartupPlan>::success(plan);
}
[[nodiscard]] inline pp::foundation::Result<AppStartupResourcePlan> plan_app_startup_resources(
float ui_width,
float ui_height)
{
if (!std::isfinite(ui_width) || !std::isfinite(ui_height)) {
return pp::foundation::Result<AppStartupResourcePlan>::failure(
pp::foundation::Status::invalid_argument("startup resource dimensions must be finite"));
}
if (ui_width < 1.0F || ui_height < 1.0F) {
return pp::foundation::Result<AppStartupResourcePlan>::failure(
pp::foundation::Status::invalid_argument("startup resource dimensions must be positive"));
}
if (ui_width > static_cast<float>(std::numeric_limits<int>::max())
|| ui_height > static_cast<float>(std::numeric_limits<int>::max())) {
return pp::foundation::Result<AppStartupResourcePlan>::failure(
pp::foundation::Status::out_of_range("startup resource dimensions exceed integer range"));
}
AppStartupResourcePlan plan;
plan.ui_render_target_width = static_cast<int>(ui_width);
plan.ui_render_target_height = static_cast<int>(ui_height);
return pp::foundation::Result<AppStartupResourcePlan>::success(plan);
}
[[nodiscard]] inline pp::foundation::Status execute_app_startup_plan(
const AppStartupPlan& plan,
AppStartupServices& services)
{
if (plan.previous_run_counter < 0 || plan.next_run_counter <= plan.previous_run_counter) {
return pp::foundation::Status::invalid_argument("startup plan has invalid run counter state");
}
services.store_run_counter(plan.next_run_counter);
if (plan.save_preferences) {
services.save_preferences();
}
if (plan.start_timelapse) {
services.start_timelapse_recording();
}
services.apply_vr_controllers_enabled(plan.vr_controllers_enabled);
if (plan.show_license_warning) {
services.show_license_warning();
}
return pp::foundation::Status::success();
}
[[nodiscard]] inline pp::foundation::Status execute_app_startup_persistence_plan(
const AppStartupPlan& plan,
AppStartupServices& services)
{
if (plan.previous_run_counter < 0 || plan.next_run_counter <= plan.previous_run_counter) {
return pp::foundation::Status::invalid_argument("startup plan has invalid run counter state");
}
services.store_run_counter(plan.next_run_counter);
if (plan.save_preferences) {
services.save_preferences();
}
return pp::foundation::Status::success();
}
[[nodiscard]] inline pp::foundation::Status execute_app_startup_runtime_plan(
const AppStartupPlan& plan,
AppStartupServices& services)
{
if (plan.previous_run_counter < 0 || plan.next_run_counter <= plan.previous_run_counter) {
return pp::foundation::Status::invalid_argument("startup plan has invalid run counter state");
}
if (plan.start_timelapse) {
services.start_timelapse_recording();
}
services.apply_vr_controllers_enabled(plan.vr_controllers_enabled);
if (plan.show_license_warning) {
services.show_license_warning();
}
return pp::foundation::Status::success();
}
[[nodiscard]] inline pp::foundation::Status execute_app_startup_resources(
const AppStartupResourcePlan& plan,
AppStartupResourceServices& services)
{
if (plan.create_ui_render_target
&& (plan.ui_render_target_width <= 0 || plan.ui_render_target_height <= 0)) {
return pp::foundation::Status::invalid_argument("startup resource plan has invalid UI render target size");
}
if (plan.initialize_shaders) {
services.initialize_shaders();
}
if (plan.initialize_assets) {
services.initialize_assets();
}
if (plan.initialize_layout) {
services.initialize_layout();
}
if (plan.update_title) {
services.update_title();
}
if (plan.create_ui_render_target) {
services.create_ui_render_target(plan.ui_render_target_width, plan.ui_render_target_height);
}
return pp::foundation::Status::success();
}
} // namespace pp::app