Add generic Bound<T> type for grouping consts/other bindable things with bind groups

This commit is contained in:
Imbris 2020-12-04 22:56:10 -05:00 committed by Avi Weinstock
parent 455082a7af
commit 49cb1520ca
15 changed files with 125 additions and 99 deletions

View File

@ -3413,7 +3413,7 @@ impl Hud {
span!(_guard, "render", "Hud::render"); span!(_guard, "render", "Hud::render");
// Don't show anything if the UI is toggled off. // Don't show anything if the UI is toggled off.
if self.show.ui { if self.show.ui {
self.ui.render(renderer, Some(globals)); //self.ui.render(renderer, Some(globals));
} }
} }

View File

@ -224,15 +224,25 @@ impl PlayState for CharSelectionState {
fn name(&self) -> &'static str { "Character Selection" } fn name(&self) -> &'static str { "Character Selection" }
fn render(&mut self, renderer: &mut Renderer, _: &Settings) { fn render(&mut self, renderer: &mut Renderer, _: &Settings) {
let mut drawer = match renderer
.start_recording_frame(self.scene.global_bind_group())
.unwrap()
{
Some(d) => d,
// Couldn't get swap chain texture this fime
None => return,
};
let client = self.client.borrow(); let client = self.client.borrow();
let (humanoid_body, loadout) = let (humanoid_body, loadout) =
Self::get_humanoid_body_inventory(&self.char_selection_ui, &client); Self::get_humanoid_body_inventory(&self.char_selection_ui, &client);
// Render the scene. // Render the scene.
self.scene //self.scene
.render(renderer, client.get_tick(), humanoid_body, loadout); // .render(renderer, client.get_tick(), humanoid_body, loadout);
// Draw the UI to the screen. // Draw the UI to the screen.
self.char_selection_ui.render(renderer); self.char_selection_ui
.render(&mut drawer.third_pass().draw_ui());
} }
} }

View File

@ -1,6 +1,6 @@
use crate::{ use crate::{
i18n::{Localization, LocalizationHandle}, i18n::{Localization, LocalizationHandle},
render::Renderer, render::UiDrawer,
ui::{ ui::{
self, self,
fonts::IcedFonts as Fonts, fonts::IcedFonts as Fonts,
@ -1583,9 +1583,7 @@ impl CharSelectionUi {
events events
} }
// TODO: do we need globals? pub fn render<'a>(&'a self, drawer: &mut UiDrawer<'_, 'a>) { self.ui.render(drawer); }
pub fn render(&self, renderer: &mut Renderer) { /* self.ui.render(renderer);*/
}
} }
#[derive(Default)] #[derive(Default)]

View File

@ -346,7 +346,6 @@ impl PlayState for MainMenuState {
fn name(&self) -> &'static str { "Title" } fn name(&self) -> &'static str { "Title" }
fn render(&mut self, renderer: &mut Renderer, _: &Settings) { fn render(&mut self, renderer: &mut Renderer, _: &Settings) {
// TODO: maybe the drawer should be passed in from above?
let mut drawer = match renderer let mut drawer = match renderer
.start_recording_frame(self.scene.global_bind_group()) .start_recording_frame(self.scene.global_bind_group())
.unwrap() .unwrap()

View File

@ -3,8 +3,6 @@ use crate::render::{
}; };
pub struct Scene { pub struct Scene {
// global_data: GlobalModel,
// lod_data: LodData,
bind_group: GlobalsBindGroup, bind_group: GlobalsBindGroup,
} }

View File

@ -0,0 +1,14 @@
pub struct Bound<T> {
pub(super) bind_group: wgpu::BindGroup,
pub(super) with: T,
}
impl<T> std::ops::Deref for Bound<T> {
type Target = T;
fn deref(&self) -> &Self::Target { &self.with }
}
impl<T> std::ops::DerefMut for Bound<T> {
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.with }
}

View File

@ -1,3 +1,4 @@
pub mod bound;
mod buffer; mod buffer;
#[allow(clippy::single_component_path_imports)] // TODO: Pending review in #587 #[allow(clippy::single_component_path_imports)] // TODO: Pending review in #587
pub mod consts; pub mod consts;
@ -11,6 +12,7 @@ pub mod texture;
// Reexports // Reexports
pub use self::{ pub use self::{
bound::Bound,
consts::Consts, consts::Consts,
error::RenderError, error::RenderError,
instances::Instances, instances::Instances,
@ -37,7 +39,7 @@ pub use self::{
ui::{ ui::{
create_quad as create_ui_quad, create_quad as create_ui_quad,
create_quad_vert_gradient as create_ui_quad_vert_gradient, create_tri as create_ui_tri, create_quad_vert_gradient as create_ui_quad_vert_gradient, create_tri as create_ui_tri,
Locals as UiLocals, LocalsBindGroup as UiLocalsBindGroup, Mode as UiMode, BoundLocals as UiBoundLocals, Locals as UiLocals, Mode as UiMode,
TextureBindGroup as UiTextureBindGroup, Vertex as UiVertex, TextureBindGroup as UiTextureBindGroup, Vertex as UiVertex,
}, },
GlobalModel, Globals, GlobalsBindGroup, GlobalsLayouts, Light, Shadow, GlobalModel, Globals, GlobalsBindGroup, GlobalsLayouts, Light, Shadow,

View File

@ -1,4 +1,4 @@
use super::super::{AaMode, Consts, GlobalsLayouts, Quad, Texture, Tri}; use super::super::{AaMode, Bound, Consts, GlobalsLayouts, Quad, Texture, Tri};
use bytemuck::{Pod, Zeroable}; use bytemuck::{Pod, Zeroable};
use vek::*; use vek::*;
@ -80,9 +80,7 @@ impl Mode {
} }
} }
pub struct LocalsBindGroup { pub type BoundLocals = Bound<Consts<Locals>>;
pub(in super::super) bind_group: wgpu::BindGroup,
}
pub struct TextureBindGroup { pub struct TextureBindGroup {
pub(in super::super) bind_group: wgpu::BindGroup, pub(in super::super) bind_group: wgpu::BindGroup,
@ -136,7 +134,7 @@ impl UiLayout {
} }
} }
pub fn bind_locals(&self, device: &wgpu::Device, locals: &Consts<Locals>) -> LocalsBindGroup { pub fn bind_locals(&self, device: &wgpu::Device, locals: Consts<Locals>) -> BoundLocals {
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
label: None, label: None,
layout: &self.locals, layout: &self.locals,
@ -146,7 +144,10 @@ impl UiLayout {
}], }],
}); });
LocalsBindGroup { bind_group } BoundLocals {
bind_group,
with: locals,
}
} }
pub fn bind_texture(&self, device: &wgpu::Device, texture: &Texture) -> TextureBindGroup { pub fn bind_texture(&self, device: &wgpu::Device, texture: &Texture) -> TextureBindGroup {

View File

@ -1,4 +1,4 @@
mod bind_group; mod binding;
mod drawer; mod drawer;
pub use drawer::{Drawer, UiDrawer}; pub use drawer::{Drawer, UiDrawer};

View File

@ -8,6 +8,7 @@ use super::{
}; };
impl Renderer { impl Renderer {
// TODO: rework this to use the Bound type?
pub fn bind_globals( pub fn bind_globals(
&self, &self,
global_model: &GlobalModel, global_model: &GlobalModel,
@ -28,7 +29,8 @@ impl Renderer {
) )
} }
pub fn ui_bind_locals(&self, locals: &Consts<ui::Locals>) -> ui::LocalsBindGroup { pub fn create_ui_bound_locals(&mut self, vals: &[ui::Locals]) -> ui::BoundLocals {
let locals = self.create_consts(vals);
self.layouts.ui.bind_locals(&self.device, locals) self.layouts.ui.bind_locals(&self.device, locals)
} }

View File

@ -104,12 +104,7 @@ impl<'a> Drawer<'a> {
attachment: &self.tex.view, attachment: &self.tex.view,
resolve_target: None, resolve_target: None,
ops: wgpu::Operations { ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color { load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT),
r: 1.0,
g: 0.25,
b: 0.5,
a: 0.5,
}),
store: true, store: true,
}, },
}], }],
@ -310,7 +305,7 @@ impl<'pass_ref, 'pass: 'pass_ref> UiDrawer<'pass_ref, 'pass> {
/// set with every draw call /// set with every draw call
pub fn prepare<'data: 'pass>( pub fn prepare<'data: 'pass>(
&mut self, &mut self,
locals: &'data ui::LocalsBindGroup, locals: &'data ui::BoundLocals,
//texture: &'b ui::TextureBindGroup, //texture: &'b ui::TextureBindGroup,
buf: &'data DynamicModel<ui::Vertex>, buf: &'data DynamicModel<ui::Vertex>,
scissor: Aabr<u16>, scissor: Aabr<u16>,
@ -331,7 +326,7 @@ impl<'pass_ref, 'pass: 'pass_ref> UiDrawer<'pass_ref, 'pass> {
} }
impl<'pass_ref, 'pass: 'pass_ref> PreparedUiDrawer<'pass_ref, 'pass> { impl<'pass_ref, 'pass: 'pass_ref> PreparedUiDrawer<'pass_ref, 'pass> {
pub fn set_locals<'data: 'pass>(&mut self, locals: &'data ui::LocalsBindGroup) { pub fn set_locals<'data: 'pass>(&mut self, locals: &'data ui::BoundLocals) {
self.render_pass.set_bind_group(1, &locals.bind_group, &[]); self.render_pass.set_bind_group(1, &locals.bind_group, &[]);
} }
@ -345,12 +340,12 @@ impl<'pass_ref, 'pass: 'pass_ref> PreparedUiDrawer<'pass_ref, 'pass> {
pub fn set_scissor<'data: 'pass>(&mut self, scissor: Aabr<u16>) { pub fn set_scissor<'data: 'pass>(&mut self, scissor: Aabr<u16>) {
let Aabr { min, max } = scissor; let Aabr { min, max } = scissor;
//self.render_pass.set_scissor_rect( self.render_pass.set_scissor_rect(
// min.x as u32, min.x as u32,
// min.y as u32, min.y as u32,
// (max.x - min.x) as u32, (max.x - min.x) as u32,
// (max.y - min.y) as u32, (max.y - min.y) as u32,
//); );
} }
pub fn draw<'data: 'pass>(&mut self, texture: &'data ui::TextureBindGroup, verts: Range<u32>) { pub fn draw<'data: 'pass>(&mut self, texture: &'data ui::TextureBindGroup, verts: Range<u32>) {

View File

@ -2,9 +2,9 @@ use crate::{
mesh::{greedy::GreedyMesh, segment::generate_mesh_base_vol_terrain}, mesh::{greedy::GreedyMesh, segment::generate_mesh_base_vol_terrain},
render::{ render::{
create_clouds_mesh, create_pp_mesh, create_skybox_mesh, BoneMeshes, CloudsLocals, create_clouds_mesh, create_pp_mesh, create_skybox_mesh, BoneMeshes, CloudsLocals,
CloudsVertex, Consts, FigureModel, GlobalModel, Globals, Light, LodData, Mesh, Model, CloudsVertex, Consts, FigureModel, GlobalModel, Globals, GlobalsBindGroup, Light, LodData,
PostProcessLocals, PostProcessVertex, Renderer, Shadow, ShadowLocals, SkyboxVertex, Mesh, Model, PostProcessLocals, PostProcessVertex, Renderer, Shadow, ShadowLocals,
TerrainVertex, SkyboxVertex, TerrainVertex,
}, },
scene::{ scene::{
camera::{self, Camera, CameraMode}, camera::{self, Camera, CameraMode},
@ -69,6 +69,7 @@ struct Clouds {
pub struct Scene { pub struct Scene {
data: GlobalModel, data: GlobalModel,
globals_bind_group: GlobalsBindGroup,
camera: Camera, camera: Camera,
skybox: Skybox, skybox: Skybox,
@ -117,14 +118,19 @@ impl Scene {
let mut col_lights = FigureColLights::new(renderer); let mut col_lights = FigureColLights::new(renderer);
Self { let data = GlobalModel {
data: GlobalModel { globals: renderer.create_consts(&[Globals::default()]),
globals: renderer.create_consts(&[Globals::default()]), lights: renderer.create_consts(&[Light::default(); 32]),
lights: renderer.create_consts(&[Light::default(); 32]), shadows: renderer.create_consts(&[Shadow::default(); 32]),
shadows: renderer.create_consts(&[Shadow::default(); 32]), shadow_mats: renderer.create_consts(&[ShadowLocals::default(); 6]),
shadow_mats: renderer.create_consts(&[ShadowLocals::default(); 6]), };
}, let lod = LodData::dummy(renderer);
let globals_bind_group = renderer.bind_globals(&data, &lod);
Self {
data,
globals_bind_group,
skybox: Skybox { skybox: Skybox {
model: renderer.create_model(&create_skybox_mesh()).unwrap(), model: renderer.create_model(&create_skybox_mesh()).unwrap(),
}, },
@ -136,7 +142,7 @@ impl Scene {
model: renderer.create_model(&create_pp_mesh()).unwrap(), model: renderer.create_model(&create_pp_mesh()).unwrap(),
locals: renderer.create_consts(&[PostProcessLocals::default()]), locals: renderer.create_consts(&[PostProcessLocals::default()]),
}, },
lod: LodData::dummy(renderer), lod,
map_bounds, map_bounds,
figure_model_cache: FigureModelCache::new(), figure_model_cache: FigureModelCache::new(),
@ -359,6 +365,8 @@ impl Scene {
} }
} }
pub fn global_bind_group(&self) -> &GlobalsBindGroup { &self.globals_bind_group }
pub fn render( pub fn render(
&mut self, &mut self,
renderer: &mut Renderer, renderer: &mut Renderer,

View File

@ -1,6 +1,6 @@
use super::graphic::{Graphic, GraphicCache, Id as GraphicId}; use super::graphic::{Graphic, GraphicCache, Id as GraphicId};
use crate::{ use crate::{
render::{Mesh, Renderer, Texture, UiVertex}, render::{Mesh, Renderer, Texture, UiTextureBindGroup, UiVertex},
Error, Error,
}; };
use conrod_core::{text::GlyphCache, widget::Id}; use conrod_core::{text::GlyphCache, widget::Id};
@ -19,7 +19,7 @@ pub struct Cache {
// Map from text ids to their positioned glyphs. // Map from text ids to their positioned glyphs.
text_cache: TextCache, text_cache: TextCache,
glyph_cache: GlyphCache<'static>, glyph_cache: GlyphCache<'static>,
glyph_cache_tex: Texture, glyph_cache_tex: (Texture, UiTextureBindGroup),
graphic_cache: GraphicCache, graphic_cache: GraphicCache,
} }
@ -33,6 +33,12 @@ impl Cache {
let glyph_cache_dims = let glyph_cache_dims =
Vec2::new(w, h).map(|e| (e * GLYPH_CACHE_SIZE).min(max_texture_size).max(512)); Vec2::new(w, h).map(|e| (e * GLYPH_CACHE_SIZE).min(max_texture_size).max(512));
let glyph_cache_tex = {
let tex = renderer.create_dynamic_texture(glyph_cache_dims);
let bind = renderer.ui_bind_texture(&tex);
(tex, bind)
};
Ok(Self { Ok(Self {
text_cache: Default::default(), text_cache: Default::default(),
glyph_cache: GlyphCache::builder() glyph_cache: GlyphCache::builder()
@ -40,12 +46,12 @@ impl Cache {
.scale_tolerance(SCALE_TOLERANCE) .scale_tolerance(SCALE_TOLERANCE)
.position_tolerance(POSITION_TOLERANCE) .position_tolerance(POSITION_TOLERANCE)
.build(), .build(),
glyph_cache_tex: renderer.create_dynamic_texture(glyph_cache_dims), glyph_cache_tex,
graphic_cache: GraphicCache::new(renderer), graphic_cache: GraphicCache::new(renderer),
}) })
} }
pub fn glyph_cache_tex(&self) -> &Texture { &self.glyph_cache_tex } pub fn glyph_cache_tex(&self) -> &(Texture, UiTextureBindGroup) { &self.glyph_cache_tex }
pub fn cache_mut_and_tex( pub fn cache_mut_and_tex(
&mut self, &mut self,
@ -53,7 +59,7 @@ impl Cache {
&mut GraphicCache, &mut GraphicCache,
&mut TextCache, &mut TextCache,
&mut GlyphCache<'static>, &mut GlyphCache<'static>,
&Texture, &(Texture, UiTextureBindGroup),
) { ) {
( (
&mut self.graphic_cache, &mut self.graphic_cache,
@ -89,7 +95,11 @@ impl Cache {
.scale_tolerance(SCALE_TOLERANCE) .scale_tolerance(SCALE_TOLERANCE)
.position_tolerance(POSITION_TOLERANCE) .position_tolerance(POSITION_TOLERANCE)
.build(); .build();
self.glyph_cache_tex = renderer.create_dynamic_texture(cache_dims); self.glyph_cache_tex = {
let tex = renderer.create_dynamic_texture(cache_dims);
let bind = renderer.ui_bind_texture(&tex);
(tex, bind)
};
Ok(()) Ok(())
} }
} }

View File

@ -16,7 +16,7 @@ use super::{
use crate::{ use crate::{
render::{ render::{
create_ui_quad, create_ui_quad_vert_gradient, Consts, DynamicModel, Mesh, Renderer, create_ui_quad, create_ui_quad_vert_gradient, Consts, DynamicModel, Mesh, Renderer,
UiDrawer, UiLocals, UiLocalsBindGroup, UiMode, UiVertex, UiBoundLocals, UiDrawer, UiLocals, UiMode, UiVertex,
}, },
Error, Error,
}; };
@ -85,10 +85,9 @@ pub struct IcedRenderer {
// Model for drawing the ui // Model for drawing the ui
model: DynamicModel<UiVertex>, model: DynamicModel<UiVertex>,
// Consts to specify positions of ingame elements (e.g. Nametags) // Consts to specify positions of ingame elements (e.g. Nametags)
ingame_locals: Vec<(Consts<UiLocals>, UiLocalsBindGroup)>, ingame_locals: Vec<UiBoundLocals>,
// Consts for default ui drawing position (ie the interface) // Consts for default ui drawing position (ie the interface)
interface_locals: (Consts<UiLocals>, UiLocalsBindGroup), interface_locals: UiBoundLocals,
//default_globals: Consts<Globals>,
// Used to delay cache resizing until after current frame is drawn // Used to delay cache resizing until after current frame is drawn
//need_cache_resize: bool, //need_cache_resize: bool,
@ -125,18 +124,13 @@ impl IcedRenderer {
let (half_res, align, p_scale) = let (half_res, align, p_scale) =
Self::calculate_resolution_dependents(physical_resolution, scaled_resolution); Self::calculate_resolution_dependents(physical_resolution, scaled_resolution);
let interface_locals = { let interface_locals = renderer.create_ui_bound_locals(&[UiLocals::default()]);
let locals = renderer.create_consts(&[UiLocals::default()]);
let bind = renderer.ui_bind_locals(&locals);
(locals, bind)
};
Ok(Self { Ok(Self {
cache: Cache::new(renderer, default_font)?, cache: Cache::new(renderer, default_font)?,
draw_commands: Vec::new(), draw_commands: Vec::new(),
model: renderer.create_dynamic_model(100), model: renderer.create_dynamic_model(100),
interface_locals, interface_locals,
//default_globals: renderer.create_consts(&[Globals::default()]),
ingame_locals: Vec::new(), ingame_locals: Vec::new(),
mesh: Mesh::new(), mesh: Mesh::new(),
glyphs: Vec::new(), glyphs: Vec::new(),
@ -770,15 +764,9 @@ impl IcedRenderer {
} }
} }
pub fn render<'pass_ref, 'pass: 'pass_ref, 'data: 'pass>( pub fn render<'pass, 'data: 'pass>(&'data self, drawer: &mut UiDrawer<'_, 'pass>) {
&'data self,
drawer: &mut UiDrawer<'pass_ref, 'pass>, /* maybe_globals: Option<&Consts<Globals>> */
) {
span!(_guard, "render", "IcedRenderer::render"); span!(_guard, "render", "IcedRenderer::render");
let mut drawer = drawer.prepare(&self.interface_locals.1, &self.model, self.window_scissor); let mut drawer = drawer.prepare(&self.interface_locals, &self.model, self.window_scissor);
//let mut scissor = self.window_scissor;
//let globals = maybe_globals.unwrap_or(&self.default_globals);
//let mut locals = &self.interface_locals.1;
for draw_command in self.draw_commands.iter() { for draw_command in self.draw_commands.iter() {
match draw_command { match draw_command {
DrawCommand::Scissor(new_scissor) => { DrawCommand::Scissor(new_scissor) => {
@ -786,11 +774,11 @@ impl IcedRenderer {
}, },
DrawCommand::WorldPos(index) => { DrawCommand::WorldPos(index) => {
drawer.set_locals( drawer.set_locals(
index.map_or(&self.interface_locals.1, |i| &self.ingame_locals[i].1), index.map_or(&self.interface_locals, |i| &self.ingame_locals[i]),
); );
}, },
DrawCommand::Draw { kind, verts } => { DrawCommand::Draw { kind, verts } => {
// TODO: don't make these assert!(!verts.is_empty()); // TODO: don't make these: assert!(!verts.is_empty());
let tex = match kind { let tex = match kind {
DrawKind::Image(tex_id) => self.cache.graphic_cache().get_tex(*tex_id), DrawKind::Image(tex_id) => self.cache.graphic_cache().get_tex(*tex_id),
DrawKind::Plain => self.cache.glyph_cache_tex(), DrawKind::Plain => self.cache.glyph_cache_tex(),

View File

@ -26,7 +26,7 @@ pub use widgets::{
use crate::{ use crate::{
render::{ render::{
create_ui_quad, create_ui_tri, Consts, DynamicModel, Globals, Mesh, RenderError, Renderer, create_ui_quad, create_ui_tri, Consts, DynamicModel, Globals, Mesh, RenderError, Renderer,
UiLocals, UiMode, UiVertex, UiBoundLocals, UiDrawer, UiLocals, UiMode, UiVertex,
}, },
window::Window, window::Window,
Error, Error,
@ -111,10 +111,9 @@ pub struct Ui {
// Model for drawing the ui // Model for drawing the ui
model: DynamicModel<UiVertex>, model: DynamicModel<UiVertex>,
// Consts for default ui drawing position (ie the interface) // Consts for default ui drawing position (ie the interface)
interface_locals: Consts<UiLocals>, interface_locals: UiBoundLocals,
default_globals: Consts<Globals>,
// Consts to specify positions of ingame elements (e.g. Nametags) // Consts to specify positions of ingame elements (e.g. Nametags)
ingame_locals: Vec<Consts<UiLocals>>, ingame_locals: Vec<UiBoundLocals>,
// Window size for updating scaling // Window size for updating scaling
window_resized: Option<Vec2<f64>>, window_resized: Option<Vec2<f64>>,
// Scale factor changed // Scale factor changed
@ -127,12 +126,15 @@ pub struct Ui {
tooltip_manager: TooltipManager, tooltip_manager: TooltipManager,
// Item tooltips manager // Item tooltips manager
item_tooltip_manager: ItemTooltipManager, item_tooltip_manager: ItemTooltipManager,
// Scissor for the whole window
window_scissor: Aabr<u16>,
} }
impl Ui { impl Ui {
pub fn new(window: &mut Window) -> Result<Self, Error> { pub fn new(window: &mut Window) -> Result<Self, Error> {
let scale = Scale::new(window, ScaleMode::Absolute(1.0), 1.0); let scale = Scale::new(window, ScaleMode::Absolute(1.0), 1.0);
let win_dims = scale.scaled_resolution().into_array(); let win_dims = scale.scaled_resolution().into_array();
let physical_resolution = scale.physical_resolution();
let renderer = window.renderer_mut(); let renderer = window.renderer_mut();
@ -156,6 +158,8 @@ impl Ui {
scale.scale_factor_logical(), scale.scale_factor_logical(),
); );
let interface_locals = renderer.create_ui_bound_locals(&[UiLocals::default()]);
Ok(Self { Ok(Self {
ui, ui,
image_map: Map::new(), image_map: Map::new(),
@ -163,8 +167,7 @@ impl Ui {
draw_commands: Vec::new(), draw_commands: Vec::new(),
mesh: Mesh::new(), mesh: Mesh::new(),
model: renderer.create_dynamic_model(100), model: renderer.create_dynamic_model(100),
interface_locals: renderer.create_consts(&[UiLocals::default()]), interface_locals,
default_globals: renderer.create_consts(&[Globals::default()]),
ingame_locals: Vec::new(), ingame_locals: Vec::new(),
window_resized: None, window_resized: None,
scale_factor_changed: None, scale_factor_changed: None,
@ -172,6 +175,7 @@ impl Ui {
scale, scale,
tooltip_manager, tooltip_manager,
item_tooltip_manager, item_tooltip_manager,
window_scissor: default_scissor(physical_resolution),
}) })
} }
@ -329,6 +333,7 @@ impl Ui {
self.scale.window_resized(new_dims); self.scale.window_resized(new_dims);
let (w, h) = self.scale.scaled_resolution().into_tuple(); let (w, h) = self.scale.scaled_resolution().into_tuple();
self.ui.handle_event(Input::Resize(w, h)); self.ui.handle_event(Input::Resize(w, h));
self.window_scissor = default_scissor(self.scale.physical_resolution());
// Avoid panic in graphic cache when minimizing. // Avoid panic in graphic cache when minimizing.
// Avoid resetting cache if window size didn't change // Avoid resetting cache if window size didn't change
@ -568,7 +573,7 @@ impl Ui {
.map(|x| [255, 255, 255, *x]) .map(|x| [255, 255, 255, *x])
.collect::<Vec<[u8; 4]>>(); .collect::<Vec<[u8; 4]>>();
renderer.update_texture(cache_tex, offset, size, &new_data); renderer.update_texture(&cache_tex.0, offset, size, &new_data);
}) { }) {
// FIXME: If we actually hit this error, it's still possible we could salvage // FIXME: If we actually hit this error, it's still possible we could salvage
// things in various ways (for instance, the current queue might have extra // things in various ways (for instance, the current queue might have extra
@ -604,7 +609,7 @@ impl Ui {
let mut current_state = State::Plain; let mut current_state = State::Plain;
let mut start = 0; let mut start = 0;
let window_scissor = default_scissor(renderer); let window_scissor = self.window_scissor;
let mut current_scissor = window_scissor; let mut current_scissor = window_scissor;
let mut ingame_local_index = 0; let mut ingame_local_index = 0;
@ -954,7 +959,7 @@ impl Ui {
) )
} else { } else {
self.ingame_locals self.ingame_locals
.push(renderer.create_consts(&[world_pos.into()])); .push(renderer.create_ui_bound_locals(&[world_pos.into()]));
} }
self.draw_commands self.draw_commands
.push(DrawCommand::WorldPos(Some(ingame_local_index))); .push(DrawCommand::WorldPos(Some(ingame_local_index)));
@ -1006,42 +1011,38 @@ impl Ui {
renderer.update_model(&self.model, &self.mesh, 0); renderer.update_model(&self.model, &self.mesh, 0);
} }
pub fn render(&self, renderer: &mut Renderer, maybe_globals: Option<&Consts<Globals>>) { pub fn render<'pass, 'data: 'pass>(&'data self, drawer: &mut UiDrawer<'_, 'pass>) {
span!(_guard, "render", "Ui::render"); span!(_guard, "render", "Ui::render");
let mut scissor = default_scissor(renderer); let mut drawer = drawer.prepare(&self.interface_locals, &self.model, self.window_scissor);
let globals = maybe_globals.unwrap_or(&self.default_globals);
let mut locals = &self.interface_locals;
for draw_command in self.draw_commands.iter() { for draw_command in self.draw_commands.iter() {
match draw_command { match draw_command {
DrawCommand::Scissor(new_scissor) => { DrawCommand::Scissor(new_scissor) => {
scissor = *new_scissor; drawer.set_scissor(*new_scissor);
}, },
DrawCommand::WorldPos(index) => { DrawCommand::WorldPos(index) => {
locals = index.map_or(&self.interface_locals, |i| &self.ingame_locals[i]); drawer.set_locals(
index.map_or(&self.interface_locals, |i| &self.ingame_locals[i]),
);
}, },
DrawCommand::Draw { kind, verts } => { DrawCommand::Draw { kind, verts } => {
//let tex = match kind { let tex = match kind {
// DrawKind::Image(tex_id) => DrawKind::Image(tex_id) => self.cache.graphic_cache().get_tex(*tex_id),
// self.cache.graphic_cache().get_tex(*tex_id), DrawKind::Plain => self.cache.glyph_cache_tex(),
// DrawKind::Plain => self.cache.glyph_cache_tex(), };
//}; drawer.draw(&tex.1, verts.clone()); // Note: trivial clone
//let model = self.model.submodel(verts.clone());
// TODO
//renderer.render_ui_element(model, tex, scissor, globals,
// locals);
}, },
} }
} }
} }
} }
fn default_scissor(renderer: &Renderer) -> Aabr<u16> { fn default_scissor(physical_resolution: Vec2<u16>) -> Aabr<u16> {
let (screen_w, screen_h) = renderer.resolution().into_tuple(); let (screen_w, screen_h) = physical_resolution.into_tuple();
Aabr { Aabr {
min: Vec2 { x: 0, y: 0 }, min: Vec2 { x: 0, y: 0 },
max: Vec2 { max: Vec2 {
x: screen_w as u16, x: screen_w,
y: screen_h as u16, y: screen_h,
}, },
} }
} }