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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
extern crate oxygengine_core as core;
extern crate oxygengine_input as input;

pub mod component;
pub mod resource;
pub mod system;
pub mod ui_theme_asset_protocol;

// reexport macros.
pub use raui_core::{
    post_hooks, pre_hooks,
    prelude::{MessageData, Prefab, PropsData},
    unpack_named_slots, widget,
};

pub mod prelude {
    pub use crate::{component::*, resource::*, system::*, ui_theme_asset_protocol::*};
}
pub mod raui {
    pub mod core {
        pub use raui_core::*;
    }
    pub mod material {
        pub use raui_material::*;
    }
}

use crate::{
    component::UserInterfaceView,
    raui::core::application::ProcessContext,
    resource::UserInterface,
    system::{user_interface_system, UserInterfaceSystemCache, UserInterfaceSystemResources},
};
use core::{
    app::AppBuilder,
    assets::database::AssetsDatabase,
    ecs::{
        pipeline::{PipelineBuilder, PipelineBuilderError},
        AccessType, ResQuery, ResQueryItem, ResRead, ResWrite,
    },
    prefab::PrefabManager,
};

pub fn bundle_installer<PB, Q>(
    builder: &mut AppBuilder<PB>,
    user_interface: UserInterface,
) -> Result<(), PipelineBuilderError>
where
    PB: PipelineBuilder,
    Q: AccessType + ResQuery + 'static,
    ResQueryItem<Q>: FeedProcessContext,
{
    builder.install_resource(user_interface);
    builder.install_resource(UserInterfaceSystemCache::default());
    builder.install_system::<UserInterfaceSystemResources<Q>>(
        "user-interface",
        user_interface_system::<Q>,
        &[],
    )?;
    Ok(())
}

pub fn prefabs_installer(prefabs: &mut PrefabManager) {
    prefabs.register_component_factory::<UserInterfaceView>("UserInterfaceView");
}

pub fn protocols_installer(database: &mut AssetsDatabase) {
    database.register(ui_theme_asset_protocol::UiThemeAssetProtocol);
}

pub trait FeedProcessContext
where
    Self: Sized,
{
    fn feed_process_context(self, _context: &mut ProcessContext) {}
}

impl FeedProcessContext for () {}

impl<T> FeedProcessContext for ResRead<T>
where
    T: 'static,
{
    fn feed_process_context(self, context: &mut ProcessContext) {
        context.insert_owned(self);
    }
}

impl<T> FeedProcessContext for ResWrite<T>
where
    T: 'static,
{
    fn feed_process_context(self, context: &mut ProcessContext) {
        context.insert_owned(self);
    }
}

impl<T> FeedProcessContext for Option<ResRead<T>>
where
    T: 'static,
{
    fn feed_process_context(self, context: &mut ProcessContext) {
        if let Some(resource) = self {
            context.insert_owned(resource);
        }
    }
}

impl<T> FeedProcessContext for Option<ResWrite<T>>
where
    T: 'static,
{
    fn feed_process_context(self, context: &mut ProcessContext) {
        if let Some(resource) = self {
            context.insert_owned(resource);
        }
    }
}

macro_rules! impl_feed_process_context {
    ( $( $ty:ident ),+ ) => {
        impl<$( $ty ),+> FeedProcessContext for ( $( $ty, )+ ) where $( $ty: FeedProcessContext ),+ {
            fn feed_process_context(self, context: &mut ProcessContext) {
                #[allow(non_snake_case)]
                let ( $( $ty, )+ ) = self;
                $( $ty.feed_process_context(context) );+
            }
        }
    }
}

impl_feed_process_context!(A);
impl_feed_process_context!(A, B);
impl_feed_process_context!(A, B, C);
impl_feed_process_context!(A, B, C, D);
impl_feed_process_context!(A, B, C, D, E);
impl_feed_process_context!(A, B, C, D, E, F);
impl_feed_process_context!(A, B, C, D, E, F, G);
impl_feed_process_context!(A, B, C, D, E, F, G, H);
impl_feed_process_context!(A, B, C, D, E, F, G, H, I);
impl_feed_process_context!(A, B, C, D, E, F, G, H, I, J);
impl_feed_process_context!(A, B, C, D, E, F, G, H, I, J, K);
impl_feed_process_context!(A, B, C, D, E, F, G, H, I, J, K, L);
impl_feed_process_context!(A, B, C, D, E, F, G, H, I, J, K, L, M);
impl_feed_process_context!(A, B, C, D, E, F, G, H, I, J, K, L, M, N);
impl_feed_process_context!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);