Compare commits
12 Commits
custom
...
release-0.
Author | SHA1 | Date | |
---|---|---|---|
![]() |
6acf932cc9 | ||
![]() |
31af9d4ee1 | ||
![]() |
ef5c8e83ad | ||
![]() |
3ae96dd307 | ||
![]() |
523e7af739 | ||
![]() |
98cf6268dc | ||
![]() |
ec88fcacca | ||
![]() |
d11409028a | ||
![]() |
df3d100315 | ||
![]() |
398b15db5c | ||
![]() |
b9337debb9 | ||
![]() |
470f94d19e |
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "bevy"
|
name = "bevy"
|
||||||
version = "0.6.0"
|
version = "0.6.1"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
categories = ["game-engines", "graphics", "gui", "rendering"]
|
categories = ["game-engines", "graphics", "gui", "rendering"]
|
||||||
description = "A refreshingly simple data-driven game engine and app framework"
|
description = "A refreshingly simple data-driven game engine and app framework"
|
||||||
|
@ -469,15 +469,18 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn times_finished_precise() {
|
fn times_finished_precise() {
|
||||||
let mut t = Timer::from_seconds(0.01, true);
|
let mut t = Timer::from_seconds(0.01, true);
|
||||||
let duration = Duration::from_secs_f64(1.0 / 3.0);
|
let duration = Duration::from_secs_f64(0.333);
|
||||||
|
|
||||||
|
// total duration: 0.333 => 33 times finished
|
||||||
t.tick(duration);
|
t.tick(duration);
|
||||||
assert_eq!(t.times_finished(), 33);
|
assert_eq!(t.times_finished(), 33);
|
||||||
|
// total duration: 0.666 => 33 times finished
|
||||||
t.tick(duration);
|
t.tick(duration);
|
||||||
assert_eq!(t.times_finished(), 33);
|
assert_eq!(t.times_finished(), 33);
|
||||||
|
// total duration: 0.999 => 33 times finished
|
||||||
t.tick(duration);
|
t.tick(duration);
|
||||||
assert_eq!(t.times_finished(), 33);
|
assert_eq!(t.times_finished(), 33);
|
||||||
// It has one additional tick this time to compensate for missing 100th tick
|
// total duration: 1.332 => 34 times finished
|
||||||
t.tick(duration);
|
t.tick(duration);
|
||||||
assert_eq!(t.times_finished(), 34);
|
assert_eq!(t.times_finished(), 34);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "bevy_crevice"
|
name = "bevy_crevice"
|
||||||
description = "Create GLSL-compatible versions of structs with explicitly-initialized padding (Bevy version)"
|
description = "Create GLSL-compatible versions of structs with explicitly-initialized padding (Bevy version)"
|
||||||
version = "0.6.0"
|
version = "0.6.1"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
authors = ["Lucien Greathouse <me@lpghatguy.com>"]
|
authors = ["Lucien Greathouse <me@lpghatguy.com>"]
|
||||||
documentation = "https://docs.rs/crevice"
|
documentation = "https://docs.rs/crevice"
|
||||||
|
@ -268,7 +268,7 @@ where
|
|||||||
offset = item.write_std430(writer)?;
|
offset = item.write_std430(writer)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
for item in self.iter() {
|
for item in iter {
|
||||||
item.write_std430(writer)?;
|
item.write_std430(writer)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "bevy_ecs"
|
name = "bevy_ecs"
|
||||||
version = "0.6.0"
|
version = "0.6.1"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "Bevy Engine's entity component system"
|
description = "Bevy Engine's entity component system"
|
||||||
homepage = "https://bevyengine.org"
|
homepage = "https://bevyengine.org"
|
||||||
|
@ -132,7 +132,7 @@ impl ParallelSystemExecutor for ParallelExecutor {
|
|||||||
.finish_receiver
|
.finish_receiver
|
||||||
.recv()
|
.recv()
|
||||||
.await
|
.await
|
||||||
.unwrap_or_else(|error| unreachable!(error));
|
.unwrap_or_else(|error| unreachable!("{}", error));
|
||||||
self.process_finished_system(index);
|
self.process_finished_system(index);
|
||||||
// Gather other systems than may have finished.
|
// Gather other systems than may have finished.
|
||||||
while let Ok(index) = self.finish_receiver.try_recv() {
|
while let Ok(index) = self.finish_receiver.try_recv() {
|
||||||
@ -208,7 +208,7 @@ impl ParallelExecutor {
|
|||||||
start_receiver
|
start_receiver
|
||||||
.recv()
|
.recv()
|
||||||
.await
|
.await
|
||||||
.unwrap_or_else(|error| unreachable!(error));
|
.unwrap_or_else(|error| unreachable!("{}", error));
|
||||||
#[cfg(feature = "trace")]
|
#[cfg(feature = "trace")]
|
||||||
let system_guard = system_span.enter();
|
let system_guard = system_span.enter();
|
||||||
unsafe { system.run_unsafe((), world) };
|
unsafe { system.run_unsafe((), world) };
|
||||||
@ -217,7 +217,7 @@ impl ParallelExecutor {
|
|||||||
finish_sender
|
finish_sender
|
||||||
.send(index)
|
.send(index)
|
||||||
.await
|
.await
|
||||||
.unwrap_or_else(|error| unreachable!(error));
|
.unwrap_or_else(|error| unreachable!("{}", error));
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "trace")]
|
#[cfg(feature = "trace")]
|
||||||
@ -268,7 +268,7 @@ impl ParallelExecutor {
|
|||||||
.start_sender
|
.start_sender
|
||||||
.send(())
|
.send(())
|
||||||
.await
|
.await
|
||||||
.unwrap_or_else(|error| unreachable!(error));
|
.unwrap_or_else(|error| unreachable!("{}", error));
|
||||||
self.running.set(index, true);
|
self.running.set(index, true);
|
||||||
if !system_metadata.is_send {
|
if !system_metadata.is_send {
|
||||||
self.non_send_running = true;
|
self.non_send_running = true;
|
||||||
|
@ -925,24 +925,30 @@ impl World {
|
|||||||
// the ptr value / drop is called when T is dropped
|
// the ptr value / drop is called when T is dropped
|
||||||
unsafe { column.swap_remove_and_forget_unchecked(0) }
|
unsafe { column.swap_remove_and_forget_unchecked(0) }
|
||||||
};
|
};
|
||||||
// SAFE: pointer is of type T
|
// SAFE: pointer is of type T and valid to move out of
|
||||||
let value = Mut {
|
// Read the value onto the stack to avoid potential mut aliasing.
|
||||||
value: unsafe { &mut *ptr.cast::<T>() },
|
let mut value = unsafe { std::ptr::read(ptr.cast::<T>()) };
|
||||||
|
let value_mut = Mut {
|
||||||
|
value: &mut value,
|
||||||
ticks: Ticks {
|
ticks: Ticks {
|
||||||
component_ticks: &mut ticks,
|
component_ticks: &mut ticks,
|
||||||
last_change_tick: self.last_change_tick(),
|
last_change_tick: self.last_change_tick(),
|
||||||
change_tick: self.change_tick(),
|
change_tick: self.change_tick(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let result = f(self, value);
|
let result = f(self, value_mut);
|
||||||
|
assert!(!self.contains_resource::<T>());
|
||||||
let resource_archetype = self.archetypes.resource_mut();
|
let resource_archetype = self.archetypes.resource_mut();
|
||||||
let unique_components = resource_archetype.unique_components_mut();
|
let unique_components = resource_archetype.unique_components_mut();
|
||||||
let column = unique_components
|
let column = unique_components
|
||||||
.get_mut(component_id)
|
.get_mut(component_id)
|
||||||
.unwrap_or_else(|| panic!("resource does not exist: {}", std::any::type_name::<T>()));
|
.unwrap_or_else(|| panic!("resource does not exist: {}", std::any::type_name::<T>()));
|
||||||
|
|
||||||
|
// Wrap the value in MaybeUninit to prepare for passing the value back into the ECS
|
||||||
|
let mut nodrop_wrapped_value = std::mem::MaybeUninit::new(value);
|
||||||
unsafe {
|
unsafe {
|
||||||
// SAFE: pointer is of type T
|
// SAFE: pointer is of type T, and valid to move out of
|
||||||
column.push(ptr, ticks);
|
column.push(nodrop_wrapped_value.as_mut_ptr() as *mut _, ticks);
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "bevy_pbr"
|
name = "bevy_pbr"
|
||||||
version = "0.6.0"
|
version = "0.6.1"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "Adds PBR rendering to Bevy Engine"
|
description = "Adds PBR rendering to Bevy Engine"
|
||||||
homepage = "https://bevyengine.org"
|
homepage = "https://bevyengine.org"
|
||||||
|
@ -641,7 +641,7 @@ pub fn prepare_lights(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut gpu_point_lights = [GpuPointLight::default(); MAX_POINT_LIGHTS];
|
let mut gpu_point_lights = [GpuPointLight::default(); MAX_POINT_LIGHTS];
|
||||||
for (index, &(entity, light)) in point_lights.iter().enumerate() {
|
for (index, &(entity, light)) in point_lights.iter().enumerate().take(MAX_POINT_LIGHTS) {
|
||||||
let mut flags = PointLightFlags::NONE;
|
let mut flags = PointLightFlags::NONE;
|
||||||
// Lights are sorted, shadow enabled lights are first
|
// Lights are sorted, shadow enabled lights are first
|
||||||
if light.shadows_enabled && index < MAX_POINT_LIGHT_SHADOW_MAPS {
|
if light.shadows_enabled && index < MAX_POINT_LIGHT_SHADOW_MAPS {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "bevy_render"
|
name = "bevy_render"
|
||||||
version = "0.6.0"
|
version = "0.6.1"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "Provides rendering functionality for Bevy Engine"
|
description = "Provides rendering functionality for Bevy Engine"
|
||||||
homepage = "https://bevyengine.org"
|
homepage = "https://bevyengine.org"
|
||||||
|
@ -15,8 +15,16 @@ pub struct WgpuOptions {
|
|||||||
pub backends: Option<Backends>,
|
pub backends: Option<Backends>,
|
||||||
pub power_preference: PowerPreference,
|
pub power_preference: PowerPreference,
|
||||||
pub priority: WgpuOptionsPriority,
|
pub priority: WgpuOptionsPriority,
|
||||||
|
/// The enabled features. Setting features will require them to be enabled when initializing
|
||||||
|
/// the renderer.
|
||||||
pub features: WgpuFeatures,
|
pub features: WgpuFeatures,
|
||||||
|
/// The features to ensure are disabled regardless of what the adapter/backend supports
|
||||||
|
pub disabled_features: Option<WgpuFeatures>,
|
||||||
|
/// The imposed limits. Updated based on adapter/backend limits when initializing the renderer
|
||||||
|
/// if using WgpuOptionsPriority::Functionality
|
||||||
pub limits: WgpuLimits,
|
pub limits: WgpuLimits,
|
||||||
|
/// The constraints on limits allowed regardless of what the adapter/backend supports
|
||||||
|
pub constrained_limits: Option<WgpuLimits>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for WgpuOptions {
|
impl Default for WgpuOptions {
|
||||||
@ -50,7 +58,9 @@ impl Default for WgpuOptions {
|
|||||||
power_preference: PowerPreference::HighPerformance,
|
power_preference: PowerPreference::HighPerformance,
|
||||||
priority,
|
priority,
|
||||||
features: wgpu::Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES,
|
features: wgpu::Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES,
|
||||||
|
disabled_features: None,
|
||||||
limits,
|
limits,
|
||||||
|
constrained_limits: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -308,7 +308,7 @@ impl ShaderImportProcessor {
|
|||||||
|
|
||||||
pub fn get_imports_from_str(&self, shader: &str) -> Vec<ShaderImport> {
|
pub fn get_imports_from_str(&self, shader: &str) -> Vec<ShaderImport> {
|
||||||
let mut imports = Vec::new();
|
let mut imports = Vec::new();
|
||||||
for line in shader.split('\n') {
|
for line in shader.lines() {
|
||||||
if let Some(cap) = self.import_asset_path_regex.captures(line) {
|
if let Some(cap) = self.import_asset_path_regex.captures(line) {
|
||||||
let import = cap.get(1).unwrap();
|
let import = cap.get(1).unwrap();
|
||||||
imports.push(ShaderImport::AssetPath(import.as_str().to_string()));
|
imports.push(ShaderImport::AssetPath(import.as_str().to_string()));
|
||||||
@ -366,7 +366,7 @@ impl ShaderProcessor {
|
|||||||
let shader_defs_unique = HashSet::<String>::from_iter(shader_defs.iter().cloned());
|
let shader_defs_unique = HashSet::<String>::from_iter(shader_defs.iter().cloned());
|
||||||
let mut scopes = vec![true];
|
let mut scopes = vec![true];
|
||||||
let mut final_string = String::new();
|
let mut final_string = String::new();
|
||||||
for line in shader_str.split('\n') {
|
for line in shader_str.lines() {
|
||||||
if let Some(cap) = self.ifdef_regex.captures(line) {
|
if let Some(cap) = self.ifdef_regex.captures(line) {
|
||||||
let def = cap.get(1).unwrap();
|
let def = cap.get(1).unwrap();
|
||||||
scopes.push(*scopes.last().unwrap() && shader_defs_unique.contains(def.as_str()));
|
scopes.push(*scopes.last().unwrap() && shader_defs_unique.contains(def.as_str()));
|
||||||
@ -417,7 +417,6 @@ impl ShaderProcessor {
|
|||||||
final_string.push('\n');
|
final_string.push('\n');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final_string.pop();
|
|
||||||
|
|
||||||
if scopes.len() != 1 {
|
if scopes.len() != 1 {
|
||||||
return Err(ProcessShaderError::NotEnoughEndIfs);
|
return Err(ProcessShaderError::NotEnoughEndIfs);
|
||||||
|
@ -73,7 +73,8 @@ pub async fn initialize_renderer(
|
|||||||
.await
|
.await
|
||||||
.expect("Unable to find a GPU! Make sure you have installed required drivers!");
|
.expect("Unable to find a GPU! Make sure you have installed required drivers!");
|
||||||
|
|
||||||
info!("{:?}", adapter.get_info());
|
let adapter_info = adapter.get_info();
|
||||||
|
info!("{:?}", adapter_info);
|
||||||
|
|
||||||
#[cfg(feature = "wgpu_trace")]
|
#[cfg(feature = "wgpu_trace")]
|
||||||
let trace_path = {
|
let trace_path = {
|
||||||
@ -85,10 +86,120 @@ pub async fn initialize_renderer(
|
|||||||
#[cfg(not(feature = "wgpu_trace"))]
|
#[cfg(not(feature = "wgpu_trace"))]
|
||||||
let trace_path = None;
|
let trace_path = None;
|
||||||
|
|
||||||
|
// Maybe get features and limits based on what is supported by the adapter/backend
|
||||||
|
let mut features = wgpu::Features::empty();
|
||||||
|
let mut limits = options.limits.clone();
|
||||||
if matches!(options.priority, WgpuOptionsPriority::Functionality) {
|
if matches!(options.priority, WgpuOptionsPriority::Functionality) {
|
||||||
options.features =
|
features = adapter.features() | wgpu::Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES;
|
||||||
adapter.features() | wgpu::Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES;
|
if adapter_info.device_type == wgpu::DeviceType::DiscreteGpu {
|
||||||
options.limits = adapter.limits();
|
// `MAPPABLE_PRIMARY_BUFFERS` can have a significant, negative performance impact for
|
||||||
|
// discrete GPUs due to having to transfer data across the PCI-E bus and so it
|
||||||
|
// should not be automatically enabled in this case. It is however beneficial for
|
||||||
|
// integrated GPUs.
|
||||||
|
features -= wgpu::Features::MAPPABLE_PRIMARY_BUFFERS;
|
||||||
|
}
|
||||||
|
limits = adapter.limits();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enforce the disabled features
|
||||||
|
if let Some(disabled_features) = options.disabled_features {
|
||||||
|
features -= disabled_features;
|
||||||
|
}
|
||||||
|
// NOTE: |= is used here to ensure that any explicitly-enabled features are respected.
|
||||||
|
options.features |= features;
|
||||||
|
|
||||||
|
// Enforce the limit constraints
|
||||||
|
if let Some(constrained_limits) = options.constrained_limits.as_ref() {
|
||||||
|
// NOTE: Respect the configured limits as an 'upper bound'. This means for 'max' limits, we
|
||||||
|
// take the minimum of the calculated limits according to the adapter/backend and the
|
||||||
|
// specified max_limits. For 'min' limits, take the maximum instead. This is intended to
|
||||||
|
// err on the side of being conservative. We can't claim 'higher' limits that are supported
|
||||||
|
// but we can constrain to 'lower' limits.
|
||||||
|
options.limits = wgpu::Limits {
|
||||||
|
max_texture_dimension_1d: limits
|
||||||
|
.max_texture_dimension_1d
|
||||||
|
.min(constrained_limits.max_texture_dimension_1d),
|
||||||
|
max_texture_dimension_2d: limits
|
||||||
|
.max_texture_dimension_2d
|
||||||
|
.min(constrained_limits.max_texture_dimension_2d),
|
||||||
|
max_texture_dimension_3d: limits
|
||||||
|
.max_texture_dimension_3d
|
||||||
|
.min(constrained_limits.max_texture_dimension_3d),
|
||||||
|
max_texture_array_layers: limits
|
||||||
|
.max_texture_array_layers
|
||||||
|
.min(constrained_limits.max_texture_array_layers),
|
||||||
|
max_bind_groups: limits
|
||||||
|
.max_bind_groups
|
||||||
|
.min(constrained_limits.max_bind_groups),
|
||||||
|
max_dynamic_uniform_buffers_per_pipeline_layout: limits
|
||||||
|
.max_dynamic_uniform_buffers_per_pipeline_layout
|
||||||
|
.min(constrained_limits.max_dynamic_uniform_buffers_per_pipeline_layout),
|
||||||
|
max_dynamic_storage_buffers_per_pipeline_layout: limits
|
||||||
|
.max_dynamic_storage_buffers_per_pipeline_layout
|
||||||
|
.min(constrained_limits.max_dynamic_storage_buffers_per_pipeline_layout),
|
||||||
|
max_sampled_textures_per_shader_stage: limits
|
||||||
|
.max_sampled_textures_per_shader_stage
|
||||||
|
.min(constrained_limits.max_sampled_textures_per_shader_stage),
|
||||||
|
max_samplers_per_shader_stage: limits
|
||||||
|
.max_samplers_per_shader_stage
|
||||||
|
.min(constrained_limits.max_samplers_per_shader_stage),
|
||||||
|
max_storage_buffers_per_shader_stage: limits
|
||||||
|
.max_storage_buffers_per_shader_stage
|
||||||
|
.min(constrained_limits.max_storage_buffers_per_shader_stage),
|
||||||
|
max_storage_textures_per_shader_stage: limits
|
||||||
|
.max_storage_textures_per_shader_stage
|
||||||
|
.min(constrained_limits.max_storage_textures_per_shader_stage),
|
||||||
|
max_uniform_buffers_per_shader_stage: limits
|
||||||
|
.max_uniform_buffers_per_shader_stage
|
||||||
|
.min(constrained_limits.max_uniform_buffers_per_shader_stage),
|
||||||
|
max_uniform_buffer_binding_size: limits
|
||||||
|
.max_uniform_buffer_binding_size
|
||||||
|
.min(constrained_limits.max_uniform_buffer_binding_size),
|
||||||
|
max_storage_buffer_binding_size: limits
|
||||||
|
.max_storage_buffer_binding_size
|
||||||
|
.min(constrained_limits.max_storage_buffer_binding_size),
|
||||||
|
max_vertex_buffers: limits
|
||||||
|
.max_vertex_buffers
|
||||||
|
.min(constrained_limits.max_vertex_buffers),
|
||||||
|
max_vertex_attributes: limits
|
||||||
|
.max_vertex_attributes
|
||||||
|
.min(constrained_limits.max_vertex_attributes),
|
||||||
|
max_vertex_buffer_array_stride: limits
|
||||||
|
.max_vertex_buffer_array_stride
|
||||||
|
.min(constrained_limits.max_vertex_buffer_array_stride),
|
||||||
|
max_push_constant_size: limits
|
||||||
|
.max_push_constant_size
|
||||||
|
.min(constrained_limits.max_push_constant_size),
|
||||||
|
min_uniform_buffer_offset_alignment: limits
|
||||||
|
.min_uniform_buffer_offset_alignment
|
||||||
|
.max(constrained_limits.min_uniform_buffer_offset_alignment),
|
||||||
|
min_storage_buffer_offset_alignment: limits
|
||||||
|
.min_storage_buffer_offset_alignment
|
||||||
|
.max(constrained_limits.min_storage_buffer_offset_alignment),
|
||||||
|
max_inter_stage_shader_components: limits
|
||||||
|
.max_inter_stage_shader_components
|
||||||
|
.min(constrained_limits.max_inter_stage_shader_components),
|
||||||
|
max_compute_workgroup_storage_size: limits
|
||||||
|
.max_compute_workgroup_storage_size
|
||||||
|
.min(constrained_limits.max_compute_workgroup_storage_size),
|
||||||
|
max_compute_invocations_per_workgroup: limits
|
||||||
|
.max_compute_invocations_per_workgroup
|
||||||
|
.min(constrained_limits.max_compute_invocations_per_workgroup),
|
||||||
|
max_compute_workgroup_size_x: limits
|
||||||
|
.max_compute_workgroup_size_x
|
||||||
|
.min(constrained_limits.max_compute_workgroup_size_x),
|
||||||
|
max_compute_workgroup_size_y: limits
|
||||||
|
.max_compute_workgroup_size_y
|
||||||
|
.min(constrained_limits.max_compute_workgroup_size_y),
|
||||||
|
max_compute_workgroup_size_z: limits
|
||||||
|
.max_compute_workgroup_size_z
|
||||||
|
.min(constrained_limits.max_compute_workgroup_size_z),
|
||||||
|
max_compute_workgroups_per_dimension: limits
|
||||||
|
.max_compute_workgroups_per_dimension
|
||||||
|
.min(constrained_limits.max_compute_workgroups_per_dimension),
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
options.limits = limits;
|
||||||
}
|
}
|
||||||
|
|
||||||
let (device, queue) = adapter
|
let (device, queue) = adapter
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "bevy_ui"
|
name = "bevy_ui"
|
||||||
version = "0.6.0"
|
version = "0.6.1"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "A custom ECS-driven UI framework built specifically for Bevy Engine"
|
description = "A custom ECS-driven UI framework built specifically for Bevy Engine"
|
||||||
homepage = "https://bevyengine.org"
|
homepage = "https://bevyengine.org"
|
||||||
|
@ -72,14 +72,9 @@ pub fn ui_focus_system(
|
|||||||
Option<&CalculatedClip>,
|
Option<&CalculatedClip>,
|
||||||
)>,
|
)>,
|
||||||
) {
|
) {
|
||||||
let cursor_position = if let Some(cursor_position) = windows
|
let cursor_position = windows
|
||||||
.get_primary()
|
.get_primary()
|
||||||
.and_then(|window| window.cursor_position())
|
.and_then(|window| window.cursor_position());
|
||||||
{
|
|
||||||
cursor_position
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
// reset entities that were both clicked and released in the last frame
|
// reset entities that were both clicked and released in the last frame
|
||||||
for entity in state.entities_to_reset.drain(..) {
|
for entity in state.entities_to_reset.drain(..) {
|
||||||
@ -120,13 +115,20 @@ pub fn ui_focus_system(
|
|||||||
}
|
}
|
||||||
// if the current cursor position is within the bounds of the node, consider it for
|
// if the current cursor position is within the bounds of the node, consider it for
|
||||||
// clicking
|
// clicking
|
||||||
if (min.x..max.x).contains(&cursor_position.x)
|
let contains_cursor = if let Some(cursor_position) = cursor_position {
|
||||||
&& (min.y..max.y).contains(&cursor_position.y)
|
(min.x..max.x).contains(&cursor_position.x)
|
||||||
{
|
&& (min.y..max.y).contains(&cursor_position.y)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
};
|
||||||
|
|
||||||
|
if contains_cursor {
|
||||||
Some((entity, focus_policy, interaction, FloatOrd(position.z)))
|
Some((entity, focus_policy, interaction, FloatOrd(position.z)))
|
||||||
} else {
|
} else {
|
||||||
if let Some(mut interaction) = interaction {
|
if let Some(mut interaction) = interaction {
|
||||||
if *interaction == Interaction::Hovered {
|
if *interaction == Interaction::Hovered
|
||||||
|
|| (cursor_position.is_none() && *interaction != Interaction::None)
|
||||||
|
{
|
||||||
*interaction = Interaction::None;
|
*interaction = Interaction::None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "bevy_winit"
|
name = "bevy_winit"
|
||||||
version = "0.6.0"
|
version = "0.6.1"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "A winit window and input backend for Bevy Engine"
|
description = "A winit window and input backend for Bevy Engine"
|
||||||
homepage = "https://bevyengine.org"
|
homepage = "https://bevyengine.org"
|
||||||
|
@ -127,10 +127,12 @@ impl WinitWindows {
|
|||||||
|
|
||||||
let winit_window = winit_window_builder.build(event_loop).unwrap();
|
let winit_window = winit_window_builder.build(event_loop).unwrap();
|
||||||
|
|
||||||
match winit_window.set_cursor_grab(window_descriptor.cursor_locked) {
|
if window_descriptor.cursor_locked {
|
||||||
Ok(_) => {}
|
match winit_window.set_cursor_grab(true) {
|
||||||
Err(winit::error::ExternalError::NotSupported(_)) => {}
|
Ok(_) => {}
|
||||||
Err(err) => Err(err).unwrap(),
|
Err(winit::error::ExternalError::NotSupported(_)) => {}
|
||||||
|
Err(err) => Err(err).unwrap(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
winit_window.set_cursor_visible(window_descriptor.cursor_visible);
|
winit_window.set_cursor_visible(window_descriptor.cursor_visible);
|
||||||
|
Loading…
Reference in New Issue
Block a user