Merge pull request #349 from Helooprototo/main
Allow controlling of the Watch and Kbd via wayvrctl
This commit is contained in:
@@ -19,8 +19,8 @@ use wlx_common::{audio, dash_interface::BoxDashInterface, timestep::Timestep};
|
||||
use crate::{
|
||||
assets,
|
||||
tab::{
|
||||
apps::TabApps, games::TabGames, home::TabHome, monado::TabMonado, processes::TabProcesses, settings::TabSettings,
|
||||
Tab, TabType,
|
||||
Tab, TabType, apps::TabApps, games::TabGames, home::TabHome, monado::TabMonado, processes::TabProcesses,
|
||||
settings::TabSettings,
|
||||
},
|
||||
util::{
|
||||
popup_manager::{MountPopupParams, PopupManager, PopupManagerParams},
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
use anyhow::Context;
|
||||
use button::setup_custom_button;
|
||||
use glam::{Affine2, Vec2, vec2};
|
||||
use label::setup_custom_label;
|
||||
@@ -8,15 +9,23 @@ use wgui::{
|
||||
components::button::ComponentButton,
|
||||
drawing,
|
||||
event::{
|
||||
Event as WguiEvent, EventCallback, EventListenerID, EventListenerKind,
|
||||
InternalStateChangeEvent, MouseButtonIndex, MouseDownEvent, MouseLeaveEvent,
|
||||
MouseMotionEvent, MouseUpEvent, MouseWheelEvent,
|
||||
CallbackDataCommon, Event as WguiEvent, EventAlterables, EventCallback, EventListenerID,
|
||||
EventListenerKind, InternalStateChangeEvent, MouseButtonIndex, MouseDownEvent,
|
||||
MouseLeaveEvent, MouseMotionEvent, MouseUpEvent, MouseWheelEvent,
|
||||
},
|
||||
gfx::cmd::WGfxClearMode,
|
||||
i18n::Translation,
|
||||
layout::{Layout, LayoutParams, LayoutUpdateParams, WidgetID},
|
||||
parser::{self, CustomAttribsInfoOwned, Fetchable, ParseDocumentExtra, ParserState},
|
||||
parser::{
|
||||
self, CustomAttribsInfoOwned, Fetchable, ParseDocumentExtra, ParserState, parse_color_hex,
|
||||
},
|
||||
renderer_vk::context::Context as WguiContext,
|
||||
widget::{EventResult, label::WidgetLabel},
|
||||
renderer_vk::text::custom_glyph::CustomGlyphData,
|
||||
taffy,
|
||||
widget::{
|
||||
EventResult, image::WidgetImage, label::WidgetLabel, rectangle::WidgetRectangle,
|
||||
sprite::WidgetSprite,
|
||||
},
|
||||
windowing::context_menu::{self, ContextMenu},
|
||||
};
|
||||
use wlx_common::overlays::{BackendAttrib, BackendAttribValue};
|
||||
@@ -25,6 +34,7 @@ use wlx_common::timestep::Timestep;
|
||||
use crate::{
|
||||
app_misc,
|
||||
backend::input::{Haptics, HoverResult, PointerHit, PointerMode},
|
||||
backend::task::ModifyPanelCommand,
|
||||
state::AppState,
|
||||
subsystem::hid::WheelDelta,
|
||||
windowing::backend::{
|
||||
@@ -474,3 +484,103 @@ fn log_cmd_invalid_arg(
|
||||
parser_state.path.get_path_buf()
|
||||
)
|
||||
}
|
||||
|
||||
pub fn apply_custom_command<T>(
|
||||
panel: &mut GuiPanel<T>,
|
||||
app: &mut AppState,
|
||||
element: &str,
|
||||
command: &ModifyPanelCommand,
|
||||
) -> anyhow::Result<()> {
|
||||
let mut alterables = EventAlterables::default();
|
||||
let mut com = CallbackDataCommon {
|
||||
alterables: &mut alterables,
|
||||
state: &panel.layout.state,
|
||||
};
|
||||
|
||||
match command {
|
||||
ModifyPanelCommand::SetText(text) => {
|
||||
if let Ok(mut label) = panel
|
||||
.parser_state
|
||||
.fetch_widget_as::<WidgetLabel>(&panel.layout.state, element)
|
||||
{
|
||||
label.set_text(&mut com, Translation::from_raw_text(text));
|
||||
} else if let Ok(button) = panel
|
||||
.parser_state
|
||||
.fetch_component_as::<ComponentButton>(element)
|
||||
{
|
||||
button.set_text(&mut com, Translation::from_raw_text(text));
|
||||
} else {
|
||||
anyhow::bail!("No <label> or <Button> with such id.");
|
||||
}
|
||||
}
|
||||
ModifyPanelCommand::SetImage(path) => {
|
||||
if let Ok(pair) = panel
|
||||
.parser_state
|
||||
.fetch_widget(&panel.layout.state, element)
|
||||
{
|
||||
let data = CustomGlyphData::from_assets(
|
||||
&app.wgui_globals,
|
||||
wgui::assets::AssetPath::File(path),
|
||||
)
|
||||
.context("Could not load content from supplied path.")?;
|
||||
|
||||
if let Some(mut sprite) = pair.widget.get_as::<WidgetSprite>() {
|
||||
sprite.set_content(&mut com, Some(data));
|
||||
} else if let Some(mut image) = pair.widget.get_as::<WidgetImage>() {
|
||||
image.set_content(&mut com, Some(data));
|
||||
} else {
|
||||
anyhow::bail!("No <sprite> or <image> with such id.");
|
||||
}
|
||||
} else {
|
||||
anyhow::bail!("No <sprite> or <image> with such id.");
|
||||
}
|
||||
}
|
||||
ModifyPanelCommand::SetColor(color) => {
|
||||
let color = parse_color_hex(color)
|
||||
.context("Invalid color format, must be a html hex color!")?;
|
||||
|
||||
if let Ok(pair) = panel
|
||||
.parser_state
|
||||
.fetch_widget(&panel.layout.state, element)
|
||||
{
|
||||
if let Some(mut rect) = pair.widget.get_as::<WidgetRectangle>() {
|
||||
rect.set_color(&mut com, color);
|
||||
} else if let Some(mut label) = pair.widget.get_as::<WidgetLabel>() {
|
||||
label.set_color(&mut com, color, true);
|
||||
} else if let Some(mut sprite) = pair.widget.get_as::<WidgetSprite>() {
|
||||
sprite.set_color(&mut com, color);
|
||||
} else {
|
||||
anyhow::bail!("No <rectangle> or <label> or <sprite> with such id.");
|
||||
}
|
||||
} else {
|
||||
anyhow::bail!("No <rectangle> or <label> or <sprite> with such id.");
|
||||
}
|
||||
}
|
||||
ModifyPanelCommand::SetVisible(visible) => {
|
||||
let wid = panel
|
||||
.parser_state
|
||||
.get_widget_id(element)
|
||||
.context("No widget with such id.")?;
|
||||
|
||||
let display = if *visible {
|
||||
taffy::Display::Flex
|
||||
} else {
|
||||
taffy::Display::None
|
||||
};
|
||||
|
||||
com.alterables
|
||||
.set_style(wid, wgui::event::StyleSetRequest::Display(display));
|
||||
com.alterables.mark_redraw();
|
||||
}
|
||||
ModifyPanelCommand::SetStickyState(sticky_down) => {
|
||||
let button = panel
|
||||
.parser_state
|
||||
.fetch_component_as::<ComponentButton>(element)
|
||||
.context("No <Button> with such id.")?;
|
||||
button.set_sticky_state(&mut com, *sticky_down);
|
||||
}
|
||||
}
|
||||
|
||||
panel.layout.process_alterables(alterables)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,24 +1,11 @@
|
||||
use std::{sync::Arc, time::Duration};
|
||||
|
||||
use anyhow::Context;
|
||||
use glam::{Affine3A, Quat, Vec3, vec3};
|
||||
use wgui::{
|
||||
components::button::ComponentButton,
|
||||
event::{CallbackDataCommon, EventAlterables},
|
||||
i18n::Translation,
|
||||
parser::{Fetchable, parse_color_hex},
|
||||
renderer_vk::text::custom_glyph::CustomGlyphData,
|
||||
taffy,
|
||||
widget::{
|
||||
image::WidgetImage, label::WidgetLabel, rectangle::WidgetRectangle, sprite::WidgetSprite,
|
||||
},
|
||||
};
|
||||
use wlx_common::windowing::OverlayWindowState;
|
||||
|
||||
use crate::{
|
||||
backend::task::ModifyPanelCommand,
|
||||
gui::{
|
||||
panel::{GuiPanel, NewGuiPanelParams},
|
||||
panel::{GuiPanel, NewGuiPanelParams, apply_custom_command},
|
||||
timer::GuiTimer,
|
||||
},
|
||||
state::AppState,
|
||||
@@ -83,102 +70,3 @@ pub fn create_custom(app: &mut AppState, name: Arc<str>) -> Option<OverlayWindow
|
||||
..OverlayWindowConfig::from_backend(Box::new(panel))
|
||||
})
|
||||
}
|
||||
|
||||
fn apply_custom_command(
|
||||
panel: &mut GuiPanel<CustomPanelState>,
|
||||
app: &mut AppState,
|
||||
element: &str,
|
||||
command: &ModifyPanelCommand,
|
||||
) -> anyhow::Result<()> {
|
||||
let mut alterables = EventAlterables::default();
|
||||
let mut com = CallbackDataCommon {
|
||||
alterables: &mut alterables,
|
||||
state: &panel.layout.state,
|
||||
};
|
||||
|
||||
match command {
|
||||
ModifyPanelCommand::SetText(text) => {
|
||||
if let Ok(mut label) = panel
|
||||
.parser_state
|
||||
.fetch_widget_as::<WidgetLabel>(&panel.layout.state, element)
|
||||
{
|
||||
label.set_text(&mut com, Translation::from_raw_text(text));
|
||||
} else if let Ok(button) = panel
|
||||
.parser_state
|
||||
.fetch_component_as::<ComponentButton>(element)
|
||||
{
|
||||
button.set_text(&mut com, Translation::from_raw_text(text));
|
||||
} else {
|
||||
anyhow::bail!("No <label> or <Button> with such id.");
|
||||
}
|
||||
}
|
||||
ModifyPanelCommand::SetImage(path) => {
|
||||
if let Ok(pair) = panel
|
||||
.parser_state
|
||||
.fetch_widget(&panel.layout.state, element)
|
||||
{
|
||||
let data = CustomGlyphData::from_assets(
|
||||
&app.wgui_globals,
|
||||
wgui::assets::AssetPath::File(path),
|
||||
)
|
||||
.context("Could not load content from supplied path.")?;
|
||||
|
||||
if let Some(mut sprite) = pair.widget.get_as::<WidgetSprite>() {
|
||||
sprite.set_content(&mut com, Some(data));
|
||||
} else if let Some(mut image) = pair.widget.get_as::<WidgetImage>() {
|
||||
image.set_content(&mut com, Some(data));
|
||||
} else {
|
||||
anyhow::bail!("No <sprite> or <image> with such id.");
|
||||
}
|
||||
} else {
|
||||
anyhow::bail!("No <sprite> or <image> with such id.");
|
||||
}
|
||||
}
|
||||
ModifyPanelCommand::SetColor(color) => {
|
||||
let color = parse_color_hex(color)
|
||||
.context("Invalid color format, must be a html hex color!")?;
|
||||
|
||||
if let Ok(pair) = panel
|
||||
.parser_state
|
||||
.fetch_widget(&panel.layout.state, element)
|
||||
{
|
||||
if let Some(mut rect) = pair.widget.get_as::<WidgetRectangle>() {
|
||||
rect.set_color(&mut com, color);
|
||||
} else if let Some(mut label) = pair.widget.get_as::<WidgetLabel>() {
|
||||
label.set_color(&mut com, color, true);
|
||||
} else if let Some(mut sprite) = pair.widget.get_as::<WidgetSprite>() {
|
||||
sprite.set_color(&mut com, color);
|
||||
} else {
|
||||
anyhow::bail!("No <rectangle> or <label> or <sprite> with such id.");
|
||||
}
|
||||
} else {
|
||||
anyhow::bail!("No <rectangle> or <label> or <sprite> with such id.");
|
||||
}
|
||||
}
|
||||
ModifyPanelCommand::SetVisible(visible) => {
|
||||
let wid = panel
|
||||
.parser_state
|
||||
.get_widget_id(element)
|
||||
.context("No widget with such id.")?;
|
||||
|
||||
let display = if *visible {
|
||||
taffy::Display::Flex
|
||||
} else {
|
||||
taffy::Display::None
|
||||
};
|
||||
|
||||
com.alterables
|
||||
.set_style(wid, wgui::event::StyleSetRequest::Display(display));
|
||||
}
|
||||
ModifyPanelCommand::SetStickyState(sticky_down) => {
|
||||
let button = panel
|
||||
.parser_state
|
||||
.fetch_component_as::<ComponentButton>(element)
|
||||
.context("No <Button> with such id.")?;
|
||||
button.set_sticky_state(&mut com, *sticky_down);
|
||||
}
|
||||
}
|
||||
|
||||
panel.layout.process_alterables(alterables)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ use std::{collections::HashMap, rc::Rc, time::Duration};
|
||||
use crate::{
|
||||
app_misc,
|
||||
gui::{
|
||||
panel::{GuiPanel, NewGuiPanelParams},
|
||||
panel::{GuiPanel, NewGuiPanelParams, apply_custom_command},
|
||||
timer::GuiTimer,
|
||||
},
|
||||
overlays::keyboard::alt_modifier_to_key,
|
||||
@@ -260,36 +260,49 @@ pub(super) fn create_keyboard_panel(
|
||||
}
|
||||
}
|
||||
|
||||
panel.on_notify = Some(Box::new(move |panel, app, event_data| {
|
||||
let mut alterables = EventAlterables::default();
|
||||
panel.on_notify = Some(Box::new({
|
||||
let name = "kbd";
|
||||
move |panel, app, event_data| {
|
||||
let mut alterables = EventAlterables::default();
|
||||
|
||||
let mut elems_changed = panel.state.overlay_list.on_notify(
|
||||
&mut panel.layout,
|
||||
&mut panel.parser_state,
|
||||
&event_data,
|
||||
&mut alterables,
|
||||
&doc_params,
|
||||
)?;
|
||||
let mut elems_changed = panel.state.overlay_list.on_notify(
|
||||
&mut panel.layout,
|
||||
&mut panel.parser_state,
|
||||
&event_data,
|
||||
&mut alterables,
|
||||
&doc_params,
|
||||
)?;
|
||||
|
||||
elems_changed |= panel.state.set_list.on_notify(
|
||||
&mut panel.layout,
|
||||
&mut panel.parser_state,
|
||||
&event_data,
|
||||
&mut alterables,
|
||||
&doc_params,
|
||||
)?;
|
||||
elems_changed |= panel.state.set_list.on_notify(
|
||||
&mut panel.layout,
|
||||
&mut panel.parser_state,
|
||||
&event_data,
|
||||
&mut alterables,
|
||||
&doc_params,
|
||||
)?;
|
||||
|
||||
if elems_changed {
|
||||
panel.process_custom_elems(app);
|
||||
if elems_changed {
|
||||
panel.process_custom_elems(app);
|
||||
}
|
||||
|
||||
match event_data {
|
||||
OverlayEventData::SettingsChanged => {
|
||||
panel.state.alt_modifier =
|
||||
alt_modifier_to_key(app.session.config.keyboard_middle_click_mode);
|
||||
}
|
||||
|
||||
OverlayEventData::CustomCommand { element, command } => {
|
||||
if let Err(e) = apply_custom_command(panel, app, &element, &command) {
|
||||
log::warn!("Could not apply {command:?} on {name}/{element}: {e:?}");
|
||||
}
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
|
||||
panel.layout.process_alterables(alterables)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
if matches!(event_data, OverlayEventData::SettingsChanged) {
|
||||
panel.state.alt_modifier =
|
||||
alt_modifier_to_key(app.session.config.keyboard_middle_click_mode);
|
||||
}
|
||||
|
||||
panel.layout.process_alterables(alterables)?;
|
||||
Ok(())
|
||||
}));
|
||||
|
||||
panel
|
||||
|
||||
@@ -17,8 +17,8 @@ use wlx_common::{
|
||||
use crate::{
|
||||
gui::{
|
||||
panel::{
|
||||
GuiPanel, NewGuiPanelParams, device_list::DeviceList, overlay_list::OverlayList,
|
||||
set_list::SetList,
|
||||
GuiPanel, NewGuiPanelParams, apply_custom_command, device_list::DeviceList,
|
||||
overlay_list::OverlayList, set_list::SetList,
|
||||
},
|
||||
timer::GuiTimer,
|
||||
},
|
||||
@@ -74,76 +74,86 @@ pub fn create_watch(app: &mut AppState) -> anyhow::Result<OverlayWindowConfig> {
|
||||
extra: panel.doc_extra.take().unwrap_or_default(),
|
||||
};
|
||||
|
||||
panel.on_notify = Some(Box::new(move |panel, app, event_data| {
|
||||
let mut alterables = EventAlterables::default();
|
||||
panel.on_notify = Some(Box::new({
|
||||
let name = WATCH_NAME;
|
||||
move |panel, app, event_data| {
|
||||
let mut alterables = EventAlterables::default();
|
||||
|
||||
let mut elems_changed = panel.state.overlay_list.on_notify(
|
||||
&mut panel.layout,
|
||||
&mut panel.parser_state,
|
||||
&event_data,
|
||||
&mut alterables,
|
||||
&doc_params,
|
||||
)?;
|
||||
let mut elems_changed = panel.state.overlay_list.on_notify(
|
||||
&mut panel.layout,
|
||||
&mut panel.parser_state,
|
||||
&event_data,
|
||||
&mut alterables,
|
||||
&doc_params,
|
||||
)?;
|
||||
|
||||
elems_changed |= panel.state.set_list.on_notify(
|
||||
&mut panel.layout,
|
||||
&mut panel.parser_state,
|
||||
&event_data,
|
||||
&mut alterables,
|
||||
&doc_params,
|
||||
)?;
|
||||
elems_changed |= panel.state.set_list.on_notify(
|
||||
&mut panel.layout,
|
||||
&mut panel.parser_state,
|
||||
&event_data,
|
||||
&mut alterables,
|
||||
&doc_params,
|
||||
)?;
|
||||
|
||||
elems_changed |= panel.state.device_list.on_notify(
|
||||
app,
|
||||
&mut panel.layout,
|
||||
&mut panel.parser_state,
|
||||
&event_data,
|
||||
&doc_params,
|
||||
)?;
|
||||
elems_changed |= panel.state.device_list.on_notify(
|
||||
app,
|
||||
&mut panel.layout,
|
||||
&mut panel.parser_state,
|
||||
&event_data,
|
||||
&doc_params,
|
||||
)?;
|
||||
|
||||
match event_data {
|
||||
OverlayEventData::EditModeChanged(edit_mode) => {
|
||||
if let Ok(btn_edit_mode) = panel
|
||||
.parser_state
|
||||
.fetch_component_as::<ComponentButton>("btn_edit_mode")
|
||||
{
|
||||
let mut com = CallbackDataCommon {
|
||||
alterables: &mut alterables,
|
||||
state: &panel.layout.state,
|
||||
};
|
||||
btn_edit_mode.set_sticky_state(&mut com, edit_mode);
|
||||
match event_data {
|
||||
OverlayEventData::EditModeChanged(edit_mode) => {
|
||||
if let Ok(btn_edit_mode) = panel
|
||||
.parser_state
|
||||
.fetch_component_as::<ComponentButton>("btn_edit_mode")
|
||||
{
|
||||
let mut com = CallbackDataCommon {
|
||||
alterables: &mut alterables,
|
||||
state: &panel.layout.state,
|
||||
};
|
||||
btn_edit_mode.set_sticky_state(&mut com, edit_mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
OverlayEventData::SettingsChanged => {
|
||||
panel.layout.mark_redraw();
|
||||
sets_or_overlays(panel, app, &mut alterables);
|
||||
OverlayEventData::SettingsChanged => {
|
||||
panel.layout.mark_redraw();
|
||||
sets_or_overlays(panel, app, &mut alterables);
|
||||
|
||||
if app.session.config.clock_12h != panel.state.clock_12h {
|
||||
panel.state.clock_12h = app.session.config.clock_12h;
|
||||
if app.session.config.clock_12h != panel.state.clock_12h {
|
||||
panel.state.clock_12h = app.session.config.clock_12h;
|
||||
|
||||
let clock_root = panel.parser_state.get_widget_id("clock_root")?;
|
||||
panel.layout.remove_children(clock_root);
|
||||
let clock_root = panel.parser_state.get_widget_id("clock_root")?;
|
||||
panel.layout.remove_children(clock_root);
|
||||
|
||||
panel.parser_state.instantiate_template(
|
||||
&doc_params,
|
||||
"Clock",
|
||||
&mut panel.layout,
|
||||
clock_root,
|
||||
Default::default(),
|
||||
)?;
|
||||
panel.parser_state.instantiate_template(
|
||||
&doc_params,
|
||||
"Clock",
|
||||
&mut panel.layout,
|
||||
clock_root,
|
||||
Default::default(),
|
||||
)?;
|
||||
|
||||
elems_changed = true;
|
||||
elems_changed = true;
|
||||
}
|
||||
}
|
||||
OverlayEventData::CustomCommand { element, command } => {
|
||||
if let Err(e) = apply_custom_command(panel, app, &element, &command) {
|
||||
log::warn!("Could not apply {command:?} on {name}/{element}: {e:?}");
|
||||
} else {
|
||||
elems_changed = true;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
if elems_changed {
|
||||
panel.process_custom_elems(app);
|
||||
}
|
||||
if elems_changed {
|
||||
panel.process_custom_elems(app);
|
||||
}
|
||||
|
||||
panel.layout.process_alterables(alterables)?;
|
||||
Ok(())
|
||||
panel.layout.process_alterables(alterables)?;
|
||||
Ok(())
|
||||
}
|
||||
}));
|
||||
|
||||
panel
|
||||
|
||||
@@ -355,7 +355,12 @@ where
|
||||
if let Some(oid) = self.lookup(&task.overlay)
|
||||
&& let Some(o) = self.mut_by_id(oid)
|
||||
{
|
||||
if !matches!(o.config.category, OverlayCategory::Panel) {
|
||||
if !matches!(
|
||||
o.config.category,
|
||||
OverlayCategory::Panel
|
||||
| OverlayCategory::Keyboard
|
||||
| OverlayCategory::Internal
|
||||
) {
|
||||
log::warn!(
|
||||
"Received command for '{}', but this overlay does not support commands",
|
||||
&task.overlay
|
||||
|
||||
@@ -7,26 +7,26 @@ use std::{marker::PhantomData, slice::Iter, sync::Arc};
|
||||
use cmd::{GfxCommandBuffer, XferCommandBuffer};
|
||||
use pipeline::WGfxPipeline;
|
||||
use vulkano::{
|
||||
DeviceSize,
|
||||
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage, IndexBuffer, Subbuffer},
|
||||
command_buffer::{
|
||||
allocator::{StandardCommandBufferAllocator, StandardCommandBufferAllocatorCreateInfo},
|
||||
AutoCommandBufferBuilder, CommandBufferUsage,
|
||||
allocator::{StandardCommandBufferAllocator, StandardCommandBufferAllocatorCreateInfo},
|
||||
},
|
||||
descriptor_set::allocator::{StandardDescriptorSetAllocator, StandardDescriptorSetAllocatorCreateInfo},
|
||||
device::{Device, Queue},
|
||||
format::Format,
|
||||
image::{sampler::Filter, Image, ImageCreateInfo, ImageType, ImageUsage},
|
||||
image::{Image, ImageCreateInfo, ImageType, ImageUsage, sampler::Filter},
|
||||
instance::Instance,
|
||||
memory::{
|
||||
allocator::{AllocationCreateInfo, GenericMemoryAllocatorCreateInfo, MemoryTypeFilter, StandardMemoryAllocator},
|
||||
ExternalMemoryHandleTypes, MemoryPropertyFlags,
|
||||
allocator::{AllocationCreateInfo, GenericMemoryAllocatorCreateInfo, MemoryTypeFilter, StandardMemoryAllocator},
|
||||
},
|
||||
pipeline::graphics::{
|
||||
color_blend::{AttachmentBlend, BlendFactor, BlendOp},
|
||||
vertex_input::Vertex,
|
||||
},
|
||||
shader::ShaderModule,
|
||||
DeviceSize,
|
||||
};
|
||||
|
||||
use crate::gfx::pipeline::WPipelineCreateInfo;
|
||||
|
||||
Reference in New Issue
Block a user