/// A complete, validated set of delivery defaults for one runtime target.
///
/// The selector keeps atlas, engine, quality, and manifest settings together
/// so a build cannot accidentally mix a mobile atlas with a desktop runtime.
/// The values are chosen from the curated presets exposed by this package.
///|
pub struct DeliveryProfiles {
atlas : AtlasProfile
engine : EngineProfile
quality : QualityProfile
runtime : RuntimePreset
} derive(Debug, Eq, ToJson, FromJson)
/// Select the first compatible delivery configuration for a sheet.
///
/// `mobile` controls the atlas family, while `target` controls both the
/// engine limits and the output manifest. An unknown quality name returns
/// `None` instead of silently falling back to a permissive quality gate.
///|
pub fn select_delivery_profiles(
sheet : SpriteSheet,
target~ : RuntimeTarget,
mobile~ : Bool,
quality~ : String,
) -> DeliveryProfiles? {
let atlas = best_atlas_profile(sheet, mobile)
let engine = best_engine_profile(sheet, target)
let quality_profile = quality_profile_named(quality)
let runtime = runtime_presets_for(target).get(0)
match (atlas, engine, quality_profile, runtime) {
(Some(atlas), Some(engine), Some(quality), Some(runtime)) => {
let selection = { atlas, engine, quality, runtime }
if profile_selection_is_compatible(selection) {
Some(selection)
} else {
None
}
}
_ => None
}
}
/// Check cross-profile invariants that are independent of a concrete sheet.
///|
pub fn profile_selection_is_compatible(selection : DeliveryProfiles) -> Bool {
selection.engine.target == selection.runtime.target &&
selection.atlas.max_width <= selection.engine.max_texture &&
selection.engine.max_frames > 0 &&
selection.atlas.padding >= 0 &&
selection.runtime.extension != ""
}
/// Return a stable, human-readable summary suitable for build logs.
///|
pub fn profile_selection_summary(selection : DeliveryProfiles) -> String {
"atlas=" +
selection.atlas.name +
", engine=" +
selection.engine.name +
", quality=" +
selection.quality.name +
", runtime=" +
target_name(selection.runtime.target)
}
/// Convert the selected atlas and runtime settings into workflow options.
///|
pub fn DeliveryProfiles::workflow_options(
self : DeliveryProfiles,
name : String,
) -> WorkflowOptions {
let mode = if self.quality.name == "development" {
Development
} else {
Release
}
{
name,
mode,
atlas_strategy: self.atlas.strategy,
max_width: self.atlas.max_width,
padding: self.atlas.padding,
runtime: self.runtime.target,
include_diagnostics: self.quality.require_tags ||
self.quality.max_warnings > 0,
}
}
/// Return runtime export options matching the selected manifest preset.
///|
pub fn DeliveryProfiles::runtime_options(
self : DeliveryProfiles,
) -> RuntimeOptions {
self.runtime.options()
}
/// Return the names in a stable order for logs, caches, and snapshot tests.
///|
pub fn DeliveryProfiles::names(self : DeliveryProfiles) -> Array[String] {
[self.atlas.name, self.engine.name, self.quality.name, self.runtime.name]
}
/// Select a target-specific configuration and build its workflow in one step.
///|
pub fn build_delivery_workflow(
sheet : SpriteSheet,
name : String,
target~ : RuntimeTarget,
mobile~ : Bool,
quality~ : String,
) -> WorkflowReport? {
match select_delivery_profiles(sheet, target~, mobile~, quality~) {
Some(selection) =>
Some(build_workflow(sheet, selection.workflow_options(name)))
None => None
}
}
/// List profile sets that can accept a sheet for a target.
///
/// This is useful to UIs that want to show valid deployment choices before
/// asking the user to select a quality gate.
///|
pub fn compatible_delivery_targets(
sheet : SpriteSheet,
mobile~ : Bool,
) -> Array[RuntimeTarget] {
runtime_targets().filter(fn(target) {
engine_profiles_for(target).any(fn(engine) {
engine.usable_for(sheet) &&
atlas_profiles().any(fn(atlas) {
atlas.mobile == mobile &&
atlas.fits(sheet) &&
atlas.max_width <= engine.max_texture
})
})
})
}