tiger_lib/data/
environment.rs

1use crate::block::{BV, Block};
2use crate::db::{Db, DbKind};
3use crate::everything::Everything;
4use crate::game::Game;
5use crate::game::GameFlags;
6use crate::item::{Item, ItemLoader};
7use crate::token::Token;
8use crate::validate::validate_camera_color;
9use crate::validator::Validator;
10
11#[derive(Clone, Debug)]
12pub struct PortraitEnvironment {}
13
14inventory::submit! {
15    ItemLoader::Normal(GameFlags::jomini(), Item::PortraitEnvironment, PortraitEnvironment::add)
16}
17
18impl PortraitEnvironment {
19    pub fn add(db: &mut Db, key: Token, block: Block) {
20        db.add(Item::PortraitEnvironment, key, block, Box::new(Self {}));
21    }
22}
23
24impl DbKind for PortraitEnvironment {
25    fn validate(&self, _key: &Token, block: &Block, data: &Everything) {
26        let mut vd = Validator::new(block, data);
27
28        vd.field_item("cubemap", Item::File);
29        vd.field_precise_numeric("cubemap_intensity");
30        vd.field_precise_numeric("cubemap_y_rotation");
31
32        vd.field_validated("lights", |bv, data| {
33            match bv {
34                BV::Value(token) => data.verify_exists(Item::PortraitEnvironment, token),
35                BV::Block(block) => {
36                    let mut vd = Validator::new(block, data);
37                    for (_, block) in vd.integer_blocks() {
38                        let mut vd = Validator::new(block, data);
39                        vd.field_choice(
40                            "type",
41                            &["spot_light", "point_light", "directional_light"],
42                        );
43                        vd.field_bool("affected_by_shadow");
44                        vd.field_validated_block("color", validate_camera_color);
45
46                        vd.field_list_precise_numeric_exactly("position", 3);
47                        if block.field_value_is("type", "spot_light")
48                            || block.field_value_is("type", "directional_light")
49                        {
50                            vd.field_list_precise_numeric_exactly("look_at", 3);
51                            if Game::is_ck3() {
52                                vd.field_block("look_at_node"); // TODO
53                            } else if Game::is_vic3() {
54                                vd.field_value("look_at_node");
55                            }
56                        } else {
57                            vd.ban_field("look_at", || "spot_light or directional_light");
58                            vd.ban_field("look_at_node", || "spot_light or directional_light");
59                        }
60                        vd.field_block("position_node"); // TODO
61
62                        if block.field_value_is("type", "spot_light")
63                            || block.field_value_is("type", "point_light")
64                        {
65                            vd.field_precise_numeric("radius");
66                            vd.field_precise_numeric("falloff");
67                        } else {
68                            vd.ban_field("radius", || "spot_light or point_light");
69                            vd.ban_field("falloff", || "spot_light or point_light");
70                        }
71                        if block.field_value_is("type", "point_light") {
72                            vd.field_precise_numeric("outer_cone_angle");
73                            vd.field_precise_numeric("inner_cone_angle");
74                        } else {
75                            // These fields are very often present anyway, so instead of lots of warnings,
76                            // just advice about them.
77                            vd.advice_field(
78                                "outer_cone_angle",
79                                "outer_cone_angle is only for point_light",
80                            );
81                            vd.advice_field(
82                                "inner_cone_angle",
83                                "inner_cone_angle is only for point_light",
84                            );
85                        }
86                    }
87                }
88            }
89        });
90
91        vd.field_validated("shadow_camera", |bv, data| {
92            match bv {
93                BV::Value(token) => data.verify_exists(Item::PortraitEnvironment, token),
94                BV::Block(block) => {
95                    let mut vd = Validator::new(block, data);
96
97                    vd.field_list_precise_numeric_exactly("position", 3);
98                    vd.field_list_precise_numeric_exactly("look_at", 3);
99                    if Game::is_ck3() {
100                        vd.field_block("look_at_node"); // TODO
101                    } else if Game::is_vic3() {
102                        vd.field_value("look_at_node"); // TODO
103                    }
104                    vd.field_block("position_node"); // TODO
105                    vd.field_precise_numeric("fov");
106                    vd.field_list_integers_exactly("camera_near_far", 2);
107                }
108            }
109        });
110    }
111}