189 lines
6.2 KiB
C++
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
|