Skip to content
Snippets Groups Projects
Verified Commit 7235c116 authored by Louis's avatar Louis :fire:
Browse files

Import from cresthollow

parents
No related branches found
No related tags found
No related merge requests found
/target
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Environment-dependent path to Maven home directory
/mavenHomeManager.xml
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/weirdboi_opacity_tree.iml" filepath="$PROJECT_DIR$/.idea/weirdboi_opacity_tree.iml" />
</modules>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
\ No newline at end of file
This diff is collapsed.
[package]
name = "weirdboi_opacity_tree"
version = "0.1.0"
edition = "2024"
[features]
default = ["reflect", "ui", "sprite"]
reflect = ["dep:bevy_reflect"]
ui = ["dep:bevy_ui", "dep:bevy_text", "dep:bevy_color"]
sprite = ["dep:bevy_sprite", "dep:bevy_color"]
[dependencies]
bevy_ecs = "0.16"
bevy_app = "0.16"
bevy_math = "0.16"
bevy_reflect = { version = "0.16", optional = true }
bevy_ui = { version = "0.16", optional = true }
bevy_text = { version = "0.16", optional = true }
bevy_sprite = { version = "0.16", optional = true }
bevy_color = { version = "0.16", optional = true }
\ No newline at end of file
hard_tabs = true
use_field_init_shorthand = true
use_try_shorthand = true
\ No newline at end of file
use bevy_color::Alpha;
use bevy_sprite::Sprite;
use crate::HandlesTreeOpacity;
impl HandlesTreeOpacity for Sprite {
fn on_change_opacity(&mut self, opacity: f32) {
self.color.set_alpha(opacity);
}
}
\ No newline at end of file
use crate::HandlesTreeOpacity;
use bevy_color::Alpha;
use bevy_text::TextColor;
use bevy_ui::widget::ImageNode;
use bevy_ui::{BackgroundColor, BorderColor, TextShadow};
impl HandlesTreeOpacity for ImageNode {
fn on_change_opacity(&mut self, opacity: f32) {
self.color.set_alpha(opacity);
}
}
impl HandlesTreeOpacity for TextColor {
fn on_change_opacity(&mut self, opacity: f32) {
self.0.set_alpha(opacity);
}
}
impl HandlesTreeOpacity for BackgroundColor {
fn on_change_opacity(&mut self, opacity: f32) {
self.0.set_alpha(opacity);
}
}
impl HandlesTreeOpacity for BorderColor {
fn on_change_opacity(&mut self, opacity: f32) {
self.0.set_alpha(opacity);
}
}
impl HandlesTreeOpacity for TextShadow {
fn on_change_opacity(&mut self, opacity: f32) {
self.color.set_alpha(opacity);
}
}
use bevy_app::{App, Plugin, PostUpdate};
use bevy_ecs::schedule::{IntoScheduleConfigs, SystemSet};
mod opacity_tree;
pub mod presets;
#[cfg(feature = "ui")]
mod bevy_ui_ext;
#[cfg(feature = "sprite")]
mod bevy_sprite_ext;
pub use opacity_tree::{
HandlesTreeOpacity, IgnoreOpacity, ObserveOpacityTreeExt, OpacityChanged, TreeOpacity,
};
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, SystemSet)]
#[non_exhaustive]
pub enum TreeOpacitySet {
ProcessChanges,
}
pub struct TreeOpacityPlugin;
impl Plugin for TreeOpacityPlugin {
fn build(&self, app: &mut App) {
app.add_systems(
PostUpdate,
opacity_tree::track_opacity_change.in_set(TreeOpacitySet::ProcessChanges),
)
.add_observer(opacity_tree::traverse_opacity_tree);
#[cfg(feature = "ui")]
{
app.register_opacity_type::<bevy_ui::widget::ImageNode>();
app.register_opacity_type::<bevy_text::TextColor>();
app.register_opacity_type::<bevy_ui::BackgroundColor>();
app.register_opacity_type::<bevy_ui::BorderColor>();
app.register_opacity_type::<bevy_ui::TextShadow>();
}
#[cfg(feature = "sprite")]
{
app.register_opacity_type::<bevy_sprite::Sprite>();
}
#[cfg(feature = "reflect")]
{
app.register_type::<TreeOpacity>();
}
}
}
use bevy_app::App;
use bevy_ecs::component::{Component, Mutable};
use bevy_ecs::entity::Entity;
use bevy_ecs::event::Event;
use bevy_ecs::hierarchy::Children;
use bevy_ecs::observer::Trigger;
use bevy_ecs::query::{Changed, Without};
use bevy_ecs::system::{Commands, Query};
use bevy_math::curve::{Curve, CurveExt, Ease};
use std::marker::PhantomData;
#[derive(Debug, Clone, PartialEq, Copy, Component)]
#[cfg_attr(feature = "reflect", derive(bevy_reflect::Reflect))]
pub struct TreeOpacity(pub f32);
impl Default for TreeOpacity {
fn default() -> Self {
Self(1.0)
}
}
pub trait HandlesTreeOpacity: Component<Mutability = Mutable> {
fn on_change_opacity(&mut self, opacity: f32);
}
impl Ease for TreeOpacity {
fn interpolating_curve_unbounded(start: Self, end: Self) -> impl Curve<Self> {
f32::interpolating_curve_unbounded(start.0, end.0).map(TreeOpacity)
}
}
#[derive(Debug, Copy, Clone, Component)]
#[cfg_attr(feature = "reflect", derive(bevy_reflect::Reflect))]
pub struct IgnoreOpacity<C: Component> {
_c: PhantomData<C>,
}
impl<C: Component> IgnoreOpacity<C> {
pub fn new() -> Self {
IgnoreOpacity {
_c: Default::default(),
}
}
}
#[derive(Debug, Copy, Clone, Event)]
pub struct OpacityChanged {
pub opacity: f32,
pub target: Entity,
}
pub fn track_opacity_change(
mut commands: Commands,
root_nodes: Query<(Entity, &TreeOpacity), Changed<TreeOpacity>>,
) {
for (entity, opacity) in &root_nodes {
commands.trigger(OpacityChanged {
opacity: opacity.0,
target: entity,
});
}
}
fn trigger_opacity_changed<B: HandlesTreeOpacity>(
trigger: Trigger<OpacityChanged>,
mut data: Query<&mut B, Without<IgnoreOpacity<B>>>,
) {
if let Ok(mut data) = data.get_mut(trigger.event().target) {
data.on_change_opacity(trigger.event().opacity);
};
}
pub fn traverse_opacity_tree(
trigger: Trigger<OpacityChanged>,
mut commands: Commands,
children: Query<&Children>,
) {
if let Ok(children) = children.get(trigger.event().target) {
for child in children.iter() {
commands.trigger(OpacityChanged {
opacity: trigger.event().opacity,
target: *child,
});
}
}
}
pub trait ObserveOpacityTreeExt {
fn register_opacity_type<B: HandlesTreeOpacity>(&mut self) -> &mut Self;
}
impl ObserveOpacityTreeExt for App {
fn register_opacity_type<B: HandlesTreeOpacity>(&mut self) -> &mut Self {
self.add_observer(trigger_opacity_changed::<B>)
}
}
use bevy_ecs::bundle::Bundle;
use crate::IgnoreOpacity;
/// Create a set of `IgnoreOpacity` components for a text node. This preset will avoid a
/// usage of TreeOpacity from creating a black box around text due to required components
/// on [bevy_ui::widget::Text]
#[cfg(feature = "ui")]
pub fn text_node_opacity_preset() -> impl Bundle {
(
IgnoreOpacity::<bevy_ui::BorderColor>::new(),
IgnoreOpacity::<bevy_ui::BackgroundColor>::new(),
)
}
/// Create a set of `IgnoreOpacity` components for a text node. This preset will avoid a
/// usage of TreeOpacity from creating a black background for the image node due to
/// required components on [bevy_ui::widget::ImageNode]
#[cfg(feature = "ui")]
pub fn image_node_opacity_preset() -> impl Bundle {
(
IgnoreOpacity::<bevy_ui::BorderColor>::new(),
IgnoreOpacity::<bevy_ui::BackgroundColor>::new(),
)
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment