ck3-regions 0.1.2

Generates title-based region textures for use with the custom dynamic terrain shader system implemented in some CK3 mods.
Documentation
use std::path::PathBuf;

use crate::{
    cli::{Cli, ModeArg},
    model::game::TitleTier,
};

//
// pub enum ModeSettings
//

#[derive(Debug, Clone)]
pub enum ModeSettings {
    TitleBasedRegions{
        region_title_tier: TitleTier,
    },
    PredefinedRegions{
        input_regions_map_path: PathBuf,
    }
}

impl ModeSettings {
    pub fn from_cli_mode_arg(mode_arg: ModeArg) -> Self {
        assert!(mode_arg.regions_map.is_none() || mode_arg.title_tier.is_none(), "mode_arg must be unambiguous");

        if let Some(region_title_tier) = mode_arg.title_tier {
            Self::TitleBasedRegions { region_title_tier }
        } else {
            Self::PredefinedRegions { input_regions_map_path: mode_arg.regions_map.unwrap() }
        }
    }
}

//
// pub struct ModPaths
//

#[derive(Debug, Clone)]
pub struct ModPaths {
    pub mod_root:        PathBuf,
    pub raw_regions_map: PathBuf,
    pub regions_map:     PathBuf,
    pub adjacency_map_0: PathBuf,
    //pub adjacency_map_1: PathBuf,
    pub proximity_map:   PathBuf,
}

impl ModPaths {
    pub fn new(mod_root_path: PathBuf, mod_prefix: &str) -> Self {
        Self {
            raw_regions_map: mod_root_path.join(format!("map_data/{}_dynamic_terrain_regions_raw.png", mod_prefix)),
            regions_map:     mod_root_path.join(format!("map_data/{}_dynamic_terrain_regions.png",     mod_prefix)),
            adjacency_map_0: mod_root_path.join(format!("map_data/{}_dynamic_terrain_adjacency.png", mod_prefix)),
            //adjacency_map_1: mod_root_path.join(format!("map_data/{}_dynamic_terrain_adjacency_1.png", mod_prefix)),
            proximity_map:   mod_root_path.join(format!("map_data/{}_dynamic_terrain_proximity.png",   mod_prefix)),
            mod_root:        mod_root_path,
        }
    }
}

//
// pub struct Config
//

#[derive(Debug, Clone)]
pub struct Config {
    pub mode_settings:             ModeSettings,
    pub proximity_distance_limit:  f32,
    pub mod_paths:                 ModPaths,
    pub mod_prefix:                String,
    //pub must_expand_regions        bool, // TODO?
    pub output_metadata_yaml_path: Option<PathBuf>,
    pub must_expand_regions:       bool,
    pub must_attempt_early_exit:   bool,
    pub is_dry_run:                bool,
    pub is_color_disabled:         bool,
}

impl Config {
    pub fn from_cli(cli: Cli) -> Self {
        Self {
            mode_settings:             ModeSettings::from_cli_mode_arg(cli.mode_arg),
            proximity_distance_limit:  cli.proximity_limit,
            mod_paths:                 ModPaths::new(cli.mod_root_path, &cli.mod_prefix),
            mod_prefix:                cli.mod_prefix,
            output_metadata_yaml_path: cli.output_metadata_yaml_path,
            must_expand_regions:       cli.must_expand_regions,
            must_attempt_early_exit:   cli.must_attempt_early_exit,
            is_dry_run:                cli.is_dry_run,
            is_color_disabled:         cli.is_color_disabled,
        }
    }
}

//
// Interface
//

pub fn is_valid_mod_prefix(prefix_str: &str) -> bool {
    !prefix_str.is_empty() && prefix_str.chars().all(|c| c.is_ascii_alphanumeric() || c == '_')
}