use bevy_ecs::lifecycle::HookContext;
use bevy_ecs::prelude::*;
use bevy_ecs::world::DeferredWorld;
use windows::UI::Composition::Desktop::DesktopWindowTarget;
use windows::UI::Composition::{CompositionDrawingSurface, CompositionSurfaceBrush, Visual};
use windows::Win32::Graphics::Direct2D::*;
#[derive(Component, Default, Debug, Clone, Copy, PartialEq, Eq)]
pub struct HasGraphicsResources;
#[derive(Debug)]
struct WindowGraphicsInner {
pub target: DesktopWindowTarget,
pub device_context: ID2D1DeviceContext,
}
#[derive(Component, Debug)]
#[component(storage = "SparseSet")]
pub struct WindowGraphics {
inner: Option<WindowGraphicsInner>,
generation: u32,
}
unsafe impl Send for WindowGraphics {}
unsafe impl Sync for WindowGraphics {}
impl WindowGraphics {
pub fn new(target: DesktopWindowTarget, device_context: ID2D1DeviceContext) -> Self {
Self {
inner: Some(WindowGraphicsInner {
target,
device_context,
}),
generation: 0,
}
}
pub fn invalidate(&mut self) {
self.inner = None;
}
pub fn is_valid(&self) -> bool {
self.inner.is_some()
}
pub fn generation(&self) -> u32 {
self.generation
}
pub fn increment_generation(&mut self) {
self.generation = self.generation.wrapping_add(1);
}
pub fn get_target(&self) -> Option<&DesktopWindowTarget> {
self.inner.as_ref().map(|i| &i.target)
}
pub fn get_dc(&self) -> Option<&ID2D1DeviceContext> {
self.inner.as_ref().map(|i| &i.device_context)
}
}
#[derive(Component)]
#[component(on_remove = on_visual_graphics_remove)]
pub struct VisualGraphics {
inner: Option<Visual>,
parent_visual: Option<Visual>,
}
fn on_visual_graphics_remove(world: DeferredWorld, hook: HookContext) {
if let Some(vg) = world.get::<VisualGraphics>(hook.entity) {
if let (Some(parent), Some(visual)) = (&vg.parent_visual, &vg.inner) {
use windows::core::Interface;
let _ = parent
.cast::<windows::UI::Composition::ContainerVisual>()
.and_then(|cv| cv.Children())
.and_then(|c| c.Remove(visual)); }
}
}
unsafe impl Send for VisualGraphics {}
unsafe impl Sync for VisualGraphics {}
impl std::fmt::Debug for VisualGraphics {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("VisualGraphics")
.field("inner", &self.inner.is_some())
.field("parent_visual", &self.parent_visual.is_some())
.finish()
}
}
impl Default for VisualGraphics {
fn default() -> Self {
Self {
inner: None,
parent_visual: None,
}
}
}
impl VisualGraphics {
pub fn new(visual: Visual) -> Self {
Self {
inner: Some(visual),
parent_visual: None,
}
}
pub fn new_with_parent(visual: Visual, parent_visual: Option<Visual>) -> Self {
Self {
inner: Some(visual),
parent_visual,
}
}
pub fn invalidate(&mut self) {
self.inner = None;
self.parent_visual = None;
}
pub fn is_valid(&self) -> bool {
self.inner.is_some()
}
pub fn visual(&self) -> Option<&Visual> {
self.inner.as_ref()
}
pub fn parent_visual(&self) -> Option<&Visual> {
self.parent_visual.as_ref()
}
pub fn set_parent_visual(&mut self, parent: Option<Visual>) {
self.parent_visual = parent;
}
}
#[derive(Component, Debug, Default)]
pub struct SurfaceGraphics {
inner: Option<CompositionDrawingSurface>,
brush: Option<CompositionSurfaceBrush>,
pub size: (u32, u32),
}
unsafe impl Send for SurfaceGraphics {}
unsafe impl Sync for SurfaceGraphics {}
impl SurfaceGraphics {
pub fn new(
surface: CompositionDrawingSurface,
brush: CompositionSurfaceBrush,
size: (u32, u32),
) -> Self {
Self {
inner: Some(surface),
brush: Some(brush),
size,
}
}
pub fn invalidate(&mut self) {
self.inner = None;
self.brush = None;
self.size = (0, 0);
}
pub fn is_valid(&self) -> bool {
self.inner.is_some()
}
pub fn surface(&self) -> Option<&CompositionDrawingSurface> {
self.inner.as_ref()
}
pub fn brush(&self) -> Option<&CompositionSurfaceBrush> {
self.brush.as_ref()
}
pub fn set_surface(
&mut self,
surface: CompositionDrawingSurface,
brush: CompositionSurfaceBrush,
size: (u32, u32),
) {
self.inner = Some(surface);
self.brush = Some(brush);
self.size = size;
}
pub fn clear(&mut self) {
self.inner = None;
self.brush = None;
self.size = (0, 0);
}
}
#[derive(Component, Default, Debug, Clone, PartialEq)]
pub struct SurfaceGraphicsDirty {
pub requested_frame: u64,
}
#[derive(Resource, Default, Debug, Clone, PartialEq)]
pub struct SurfaceCreationStats {
pub created_count: u64,
pub skipped_count: u64,
pub deleted_count: u64,
pub resize_count: u64,
}
impl SurfaceCreationStats {
pub fn record_created(&mut self) {
self.created_count += 1;
}
pub fn record_skipped(&mut self) {
self.skipped_count += 1;
}
pub fn record_deleted(&mut self) {
self.deleted_count += 1;
}
pub fn record_resized(&mut self) {
self.resize_count += 1;
}
}