1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
use std::borrow::Cow;

use bevy_reflect::{TypeData, TypeInfo, TypeRegistry};

use crate::{
    inspector_options::{std_options::NumberOptions, Target},
    prelude::ReflectInspectorOptions,
    InspectorOptions,
};

fn insert_options_struct<T: 'static>(
    type_registry: &mut TypeRegistry,
    fields: &[(&'static str, &dyn TypeData)],
) {
    let registration = type_registry.get_mut(std::any::TypeId::of::<T>()).unwrap();
    if registration.data::<ReflectInspectorOptions>().is_none() {
        let mut options = InspectorOptions::new();
        for (field, data) in fields {
            let info = match registration.type_info() {
                TypeInfo::Struct(info) => info,
                _ => unreachable!(),
            };
            let field_index = info.index_of(field).unwrap();
            options.insert_boxed(Target::Field(field_index), TypeData::clone_type_data(*data));
        }
        registration.insert(ReflectInspectorOptions(options));
    }
}

fn insert_options_enum<T: 'static>(
    type_registry: &mut TypeRegistry,
    fields: &[(&'static str, &'static str, &dyn TypeData)],
) {
    let registration = type_registry.get_mut(std::any::TypeId::of::<T>()).unwrap();
    if registration.data::<ReflectInspectorOptions>().is_none() {
        let mut options = InspectorOptions::new();
        for (variant, field, data) in fields {
            let info = match registration.type_info() {
                TypeInfo::Enum(info) => info,
                _ => unreachable!(),
            };
            let field_index = match info.variant(variant).unwrap() {
                bevy_reflect::VariantInfo::Struct(strukt) => strukt.index_of(field).unwrap(),
                bevy_reflect::VariantInfo::Tuple(_) => field.parse().unwrap(),
                bevy_reflect::VariantInfo::Unit(_) => todo!(),
            };
            options.insert_boxed(
                Target::VariantField(Cow::Borrowed(variant), field_index),
                TypeData::clone_type_data(*data),
            );
        }
        registration.insert(ReflectInspectorOptions(options));
    }
}

pub fn register_default_options(type_registry: &mut TypeRegistry) {
    insert_options_enum::<bevy_render::color::Color>(
        type_registry,
        &[
            ("Rgba", "red", &NumberOptions::<f32>::normalized()),
            ("Rgba", "green", &NumberOptions::<f32>::normalized()),
            ("Rgba", "blue", &NumberOptions::<f32>::normalized()),
            ("Rgba", "alpha", &NumberOptions::<f32>::normalized()),
            ("RgbaLinear", "red", &NumberOptions::<f32>::normalized()),
            ("RgbaLinear", "green", &NumberOptions::<f32>::normalized()),
            ("RgbaLinear", "blue", &NumberOptions::<f32>::normalized()),
            ("RgbaLinear", "alpha", &NumberOptions::<f32>::normalized()),
            ("Hsla", "hue", &NumberOptions::<f32>::between(0.0, 360.0)),
            ("Hsla", "saturation", &NumberOptions::<f32>::normalized()),
            ("Hsla", "lightness", &NumberOptions::<f32>::normalized()),
            ("Hsla", "alpha", &NumberOptions::<f32>::normalized()),
        ],
    );

    insert_options_struct::<bevy_pbr::AmbientLight>(
        type_registry,
        &[("brightness", &NumberOptions::<f32>::normalized())],
    );
    insert_options_struct::<bevy_pbr::StandardMaterial>(
        type_registry,
        &[
            (
                "perceptual_roughness",
                &NumberOptions::<f32>::between(0.089, 1.0),
            ),
            ("metallic", &NumberOptions::<f32>::normalized()),
            ("reflectance", &NumberOptions::<f32>::normalized()),
            ("depth_bias", &NumberOptions::<f32>::positive()),
        ],
    );

    // TODO: register in bevy
    /*insert_options_enum::<bevy_pbr::ClusterConfig>(
        type_registry,
        &[
            ("FixedZ", "z_slices", &NumberOptions::<u32>::at_least(1)),
            (
                "XYZ",
                "dimensions",
                &NumberOptions::<UVec3>::at_least(UVec3::ONE),
            ),
        ],
    );*/

    insert_options_enum::<bevy_core_pipeline::core_3d::Camera3dDepthLoadOp>(
        type_registry,
        &[("Clear", "0", &NumberOptions::<f32>::normalized())],
    );
}