use bevy::prelude::*;
pub fn warn_without_core<P: Plugin>(app: &App, element: &str) {
if !app.is_plugin_added::<crate::ReactUiPlugin>() {
tracing::warn!(
target: "bevy_react",
"{} is added but ReactUiPlugin is not: the <{element}> element has \
nothing to mount into",
std::any::type_name::<P>()
);
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
pub enum TextRole {
#[default]
None,
Block,
Span,
Input,
}
#[derive(Component, Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct ElementFlags {
pub node_less: bool,
pub owns_image: bool,
pub layer_ineligible: bool,
pub detached: bool,
pub text: TextRole,
pub pick_ignore: bool,
}
impl ElementFlags {
pub const NODE: Self = Self {
node_less: false,
owns_image: false,
layer_ineligible: false,
detached: false,
text: TextRole::None,
pick_ignore: false,
};
pub const OWNS_IMAGE: Self = Self {
owns_image: true,
..Self::NODE
};
pub const NODE_LESS: Self = Self {
node_less: true,
layer_ineligible: true,
..Self::NODE
};
pub const DETACHED_ROOT: Self = Self {
layer_ineligible: true,
detached: true,
..Self::NODE
};
}
#[derive(Component, Debug, Default, Clone, Copy, PartialEq)]
pub struct EventLocalPos(pub Option<Vec2>);
#[derive(Component, Debug, Default, Clone, Copy)]
pub struct LiveTexture;
#[derive(Resource, Debug, Default, Clone)]
pub struct VirtualPointers(Vec<bevy::picking::pointer::PointerId>);
impl VirtualPointers {
pub fn register(&mut self, id: bevy::picking::pointer::PointerId) {
if !self.0.contains(&id) {
self.0.push(id);
}
}
pub fn contains(&self, id: bevy::picking::pointer::PointerId) -> bool {
self.0.contains(&id)
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn iter(&self) -> impl Iterator<Item = bevy::picking::pointer::PointerId> + '_ {
self.0.iter().copied()
}
}
#[derive(Debug, Default)]
pub struct VirtualButtons {
pressed: [bool; 3],
}
impl VirtualButtons {
const FORWARDED: [(MouseButton, bevy::picking::pointer::PointerButton); 3] = [
(
MouseButton::Left,
bevy::picking::pointer::PointerButton::Primary,
),
(
MouseButton::Right,
bevy::picking::pointer::PointerButton::Secondary,
),
(
MouseButton::Middle,
bevy::picking::pointer::PointerButton::Middle,
),
];
pub fn forward(
&mut self,
id: bevy::picking::pointer::PointerId,
location: &bevy::picking::pointer::Location,
buttons: &ButtonInput<MouseButton>,
input: &mut MessageWriter<bevy::picking::pointer::PointerInput>,
) {
use bevy::picking::pointer::{PointerAction, PointerInput};
for (i, (mouse, button)) in Self::FORWARDED.into_iter().enumerate() {
if buttons.just_pressed(mouse) {
input.write(PointerInput::new(
id,
location.clone(),
PointerAction::Press(button),
));
self.pressed[i] = true;
}
if buttons.just_released(mouse) && std::mem::take(&mut self.pressed[i]) {
input.write(PointerInput::new(
id,
location.clone(),
PointerAction::Release(button),
));
}
}
}
pub fn leave(
&mut self,
id: bevy::picking::pointer::PointerId,
location: bevy::picking::pointer::Location,
input: &mut MessageWriter<bevy::picking::pointer::PointerInput>,
) {
use bevy::picking::pointer::{PointerAction, PointerInput};
for (i, (_, button)) in Self::FORWARDED.into_iter().enumerate() {
if std::mem::take(&mut self.pressed[i]) {
input.write(PointerInput::new(
id,
location.clone(),
PointerAction::Release(button),
));
}
}
input.write(PointerInput::new(
id,
location,
PointerAction::Move { delta: Vec2::ZERO },
));
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum DrivenValue {
Scalar(f32),
Color([f32; 4]),
}
#[derive(Debug, Clone, PartialEq)]
pub struct DrivenExt {
pub domain: &'static str,
pub name: String,
pub value: DrivenValue,
}
#[derive(Component, Debug, Default, Clone, PartialEq)]
pub struct DrivenExtValues(pub Vec<DrivenExt>);
impl DrivenExtValues {
pub fn value(&self, domain: &str, name: &str) -> Option<DrivenValue> {
self.0
.iter()
.find(|d| d.domain == domain && d.name == name)
.map(|d| d.value)
}
pub fn get(&self, domain: &str, name: &str) -> Option<f32> {
match self.value(domain, name)? {
DrivenValue::Scalar(v) => Some(v),
DrivenValue::Color(_) => None,
}
}
pub fn get_color(&self, domain: &str, name: &str) -> Option<Srgba> {
match self.value(domain, name)? {
DrivenValue::Color([r, g, b, a]) => Some(Srgba::new(r, g, b, a)),
DrivenValue::Scalar(_) => None,
}
}
}
#[derive(SystemSet, Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct PickRefineSet;
#[derive(SystemSet, Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct InteractionSyncSet;
#[derive(SystemSet, Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ElementRasterSet;
#[derive(SystemSet, Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ElementOverrideSet;
#[derive(SystemSet, Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct MeasureStampSet;
mod registry;
#[cfg(test)]
pub(crate) use registry::install_builtin_registry;
pub(crate) use registry::warn_feature_missing_kind;
pub use registry::{
ExtRegistry, ExtRegistrySlot, FeatureHint, KNOWN_FEATURES, builtin_registry, core_registry,
feature_hint, set_thread_registry, with_thread_registry,
};