use super::init::format_entity_name;
use crate::com::d2d::D2D1DeviceContextExt;
use crate::com::wuc::DrawingSurfaceInteropExt;
use crate::ecs::graphics::{
GraphicsCommandList, GraphicsCore, SurfaceGraphics, SurfaceGraphicsDirty,
};
use crate::ecs::layout::GlobalArrangement;
use bevy_ecs::name::Name;
use bevy_ecs::prelude::*;
use tracing::error;
use windows::Win32::System::WinRT::Composition::ICompositionDrawingSurfaceInterop;
use windows::core::Interface;
pub fn render_surface(
surfaces: Query<
(
Entity,
&SurfaceGraphics,
&GlobalArrangement,
Option<&GraphicsCommandList>,
Option<&Name>,
),
Changed<SurfaceGraphicsDirty>,
>,
_graphics_core: Option<Res<GraphicsCore>>,
_frame_count: Res<crate::ecs::world::FrameCount>,
) {
use windows::Win32::Graphics::Direct2D::Common::D2D1_COLOR_F;
use windows::Win32::Graphics::Direct2D::Common::D2D1_COMPOSITE_MODE_SOURCE_OVER;
use windows::Win32::Graphics::Direct2D::D2D1_INTERPOLATION_MODE_LINEAR;
for (entity, surface, global_arrangement, cmd_list_opt, name) in surfaces.iter() {
let entity_name = format_entity_name(entity, name);
if !surface.is_valid() {
continue;
}
let surface_ref = match surface.surface() {
Some(s) => s,
None => continue,
};
let surface_interop = match surface_ref.cast::<ICompositionDrawingSurfaceInterop>() {
Ok(si) => si,
Err(err) => {
error!(
entity = %entity_name,
error = ?err,
"cast to ICompositionDrawingSurfaceInterop failed"
);
continue;
}
};
let (dc, offset) = match surface_interop.begin_draw(None) {
Ok(result) => {
result
}
Err(err) => {
error!(
entity = %entity_name,
error = ?err,
hresult = format_args!("0x{:08X}", err.code().0),
"BeginDraw failed"
);
continue;
}
};
unsafe {
let scale_x = global_arrangement.scale_x();
let scale_y = global_arrangement.scale_y();
let transform = windows_numerics::Matrix3x2 {
M11: scale_x,
M12: 0.0,
M21: 0.0,
M22: scale_y,
M31: offset.x as f32,
M32: offset.y as f32,
};
dc.SetTransform(&transform);
}
dc.clear(Some(&D2D1_COLOR_F {
r: 0.0,
g: 0.0,
b: 0.0,
a: 0.0,
}));
if let Some(cmd_list) = cmd_list_opt {
if let Some(command_list) = cmd_list.command_list() {
unsafe {
dc.DrawImage(
command_list,
None,
None,
D2D1_INTERPOLATION_MODE_LINEAR,
D2D1_COMPOSITE_MODE_SOURCE_OVER,
);
}
}
}
if let Err(e) = surface_interop.end_draw() {
error!(error = ?e, "EndDraw failed");
}
}
}