Moved UI positioning to shaders
parent
9cd4ead368
commit
45bc3d3b41
|
@ -0,0 +1,41 @@
|
|||
// Given an anchored position and sprite dimensions,
|
||||
// return the translation that should be applied on
|
||||
// vertex coordinates
|
||||
fn anchor(
|
||||
anchor: u32, // Anchor index
|
||||
position: vec2<f32>, // Anchored position
|
||||
dim: vec2<f32>, // Sprite dimensions (width, height)
|
||||
) -> vec2<f32> {
|
||||
|
||||
var trans: vec2<f32> = vec2(0.0, 0.0);
|
||||
let window_dim = global_data.window_size / global_data.window_scale.x;
|
||||
|
||||
if anchor == 0u { // NW C (screen anchor, sprite anchor)
|
||||
trans += vec2(-window_dim.x, window_dim.y) / 2.0; // origin
|
||||
trans += vec2(0.0, 0.0) / 2.0; // offset
|
||||
} else if anchor == 1u { // NW NW
|
||||
trans += vec2(-window_dim.x, window_dim.y) / 2.0;
|
||||
trans += vec2(dim.x, -dim.y) / 2.0;
|
||||
} else if anchor == 2u { // NW NE
|
||||
trans += vec2(-window_dim.x, window_dim.y) / 2.0;
|
||||
trans += vec2(-dim.x, -dim.y) / 2.0;
|
||||
} else if anchor == 3u { // NW SW
|
||||
trans += vec2(-window_dim.x, window_dim.y) / 2.0;
|
||||
trans += vec2(dim.x, dim.y) / 2.0;
|
||||
} else if anchor == 4u { // NW SE
|
||||
trans += vec2(-window_dim.x, window_dim.y) / 2.0;
|
||||
trans += vec2(-dim.x, dim.y) / 2.0;
|
||||
} else if anchor == 5u { // NE NE
|
||||
trans += vec2(window_dim.x, window_dim.y) / 2.0;
|
||||
trans += vec2(dim.x, -dim.y) / 2.0;
|
||||
} else { // center / center as default, since it's the most visible variant.
|
||||
trans += vec2(0.0, 0.0);
|
||||
trans += vec2(0.0, 0.0) / 2.0;
|
||||
}
|
||||
|
||||
trans += position;
|
||||
|
||||
// This renders correctly, but the offsets here are off by a factor of two.
|
||||
// I'm not sure why... might be because WGPU screen coordinates are -1 to 1.
|
||||
return (trans / window_dim) * 2.0;
|
||||
}
|
|
@ -1,10 +1,10 @@
|
|||
// INCLUDE: global uniform header
|
||||
|
||||
struct InstanceInput {
|
||||
@location(2) transform_matrix_0: vec4<f32>,
|
||||
@location(3) transform_matrix_1: vec4<f32>,
|
||||
@location(4) transform_matrix_2: vec4<f32>,
|
||||
@location(5) transform_matrix_3: vec4<f32>,
|
||||
@location(2) anchor: u32,
|
||||
@location(3) position: vec2<f32>,
|
||||
@location(4) angle: f32,
|
||||
@location(5) size: f32,
|
||||
@location(6) color_transform: vec4<f32>,
|
||||
@location(7) sprite_index: u32,
|
||||
};
|
||||
|
@ -28,7 +28,7 @@ var sampler_array: binding_array<sampler>;
|
|||
|
||||
|
||||
// INCLUDE: animate.wgsl
|
||||
|
||||
// INCLUDE: anchor.wgsl
|
||||
|
||||
@vertex
|
||||
fn vertex_main(
|
||||
|
@ -36,17 +36,43 @@ fn vertex_main(
|
|||
instance: InstanceInput,
|
||||
) -> VertexOutput {
|
||||
|
||||
let transform = mat4x4<f32>(
|
||||
instance.transform_matrix_0,
|
||||
instance.transform_matrix_1,
|
||||
instance.transform_matrix_2,
|
||||
instance.transform_matrix_3,
|
||||
|
||||
let window_dim = global_data.window_size / global_data.window_scale.x;
|
||||
let scale = instance.size / window_dim.y;
|
||||
let sprite_aspect = global_sprites[instance.sprite_index].aspect;
|
||||
|
||||
// Apply scale and sprite aspect
|
||||
// Note that our mesh starts centered at (0, 0). This is important!
|
||||
var pos: vec2<f32> = vec2(
|
||||
vertex.position.x * scale * sprite_aspect,
|
||||
vertex.position.y * scale
|
||||
);
|
||||
|
||||
// Apply rotation
|
||||
pos = mat2x2(
|
||||
vec2(cos(instance.angle), sin(instance.angle)),
|
||||
vec2(-sin(instance.angle), cos(instance.angle))
|
||||
) * pos;
|
||||
|
||||
// Correct for screen aspect, preserving height
|
||||
pos = vec2(
|
||||
pos.x / global_data.window_aspect.x,
|
||||
pos.y
|
||||
);
|
||||
|
||||
pos = pos + anchor(
|
||||
instance.anchor,
|
||||
instance.position,
|
||||
vec2(instance.size * sprite_aspect, instance.size)
|
||||
);
|
||||
|
||||
var out: VertexOutput;
|
||||
out.position = transform * vec4<f32>(vertex.position, 1.0);
|
||||
out.position = vec4<f32>(pos, 1.0, 1.0);
|
||||
out.color_transform = instance.color_transform;
|
||||
|
||||
|
||||
|
||||
// TODO: animate
|
||||
// Pick texture frame
|
||||
let t = global_atlas[u32(animate(instance.sprite_index, global_data.current_time.x, 0.0))];
|
||||
out.texture_index = u32(t.atlas_texture);
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
/// The location of a UI element, in one of a few
|
||||
/// possible coordinate systems.
|
||||
///
|
||||
/// Positive Y always points up,
|
||||
/// positive X always points right.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum PositionAnchor {
|
||||
/// Position of this sprite's center,
|
||||
/// relative to the nw corner of the window.
|
||||
NwC,
|
||||
|
||||
/// Position of this sprite's nw corner,
|
||||
/// relative to the nw corner of the window.
|
||||
NwNw,
|
||||
|
||||
/// Position of this sprite's ne corner,
|
||||
/// relative to the nw corner of the window.
|
||||
NwNe,
|
||||
|
||||
/// Position of this sprite's sw corner,
|
||||
/// relative to the nw corner of the window.
|
||||
NwSw,
|
||||
|
||||
/// Position of this sprite's se corner,
|
||||
/// relative to the nw corner of the window.
|
||||
NwSe,
|
||||
|
||||
/// Position of this sprite's ne corner,
|
||||
/// relative to the ne corner of the window.
|
||||
NeNe,
|
||||
}
|
||||
|
||||
// These offsets are implemented in wgsl shaders.
|
||||
|
||||
impl PositionAnchor {
|
||||
/// Get the uint that represents this anchor mode in shaders
|
||||
pub fn to_int(&self) -> u32 {
|
||||
match self {
|
||||
Self::NwC => 0,
|
||||
Self::NwNw => 1,
|
||||
Self::NwNe => 2,
|
||||
Self::NwSw => 3,
|
||||
Self::NwSe => 4,
|
||||
Self::NeNe => 5,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +1,9 @@
|
|||
//! GPUState routines for drawing HUD elements
|
||||
|
||||
use cgmath::{Deg, InnerSpace, Point2, Vector2};
|
||||
use cgmath::{Deg, InnerSpace, Point2, Rad, Vector2};
|
||||
use galactica_world::util;
|
||||
|
||||
use crate::{
|
||||
sprite::UiSprite, vertexbuffer::types::UiInstance, AnchoredUiPosition, GPUState, RenderState,
|
||||
};
|
||||
use crate::{vertexbuffer::types::UiInstance, GPUState, PositionAnchor, RenderState};
|
||||
|
||||
impl GPUState {
|
||||
pub(super) fn hud_add_radar(&mut self, state: &RenderState, instances: &mut Vec<UiInstance>) {
|
||||
|
@ -14,7 +12,7 @@ impl GPUState {
|
|||
let hide_range = 0.85;
|
||||
let shrink_distance = 20.0;
|
||||
//let system_object_scale = 1.0 / 600.0;
|
||||
let ship_scale = 1.0 / 15.0;
|
||||
let ship_scale = 1.0 / 10.0;
|
||||
|
||||
let (_, player_body) = state.world.get_ship_body(*state.player).unwrap();
|
||||
let player_position = util::rigidbody_position(player_body);
|
||||
|
@ -22,33 +20,23 @@ impl GPUState {
|
|||
let ship_sprite = state.content.get_sprite_handle("ui::shipblip");
|
||||
let arrow_sprite = state.content.get_sprite_handle("ui::centerarrow");
|
||||
|
||||
self.push_ui_sprite(
|
||||
instances,
|
||||
&UiSprite {
|
||||
sprite: state.content.get_sprite_handle("ui::status"),
|
||||
pos: AnchoredUiPosition::NeNe(Point2 { x: -10.0, y: -10.0 }),
|
||||
dimensions: Point2 {
|
||||
x: radar_size,
|
||||
y: radar_size,
|
||||
},
|
||||
angle: Deg(0.0),
|
||||
color: None,
|
||||
},
|
||||
);
|
||||
instances.push(UiInstance {
|
||||
anchor: PositionAnchor::NeNe.to_int(),
|
||||
position: [0.0, 0.0],
|
||||
angle: 0.0,
|
||||
size: radar_size,
|
||||
color: [1.0, 1.0, 1.0, 1.0],
|
||||
sprite_index: state.content.get_sprite_handle("ui::status").get_index(),
|
||||
});
|
||||
|
||||
self.push_ui_sprite(
|
||||
instances,
|
||||
&UiSprite {
|
||||
sprite: state.content.get_sprite_handle("ui::radar"),
|
||||
pos: AnchoredUiPosition::NwNw(Point2 { x: 10.0, y: -10.0 }),
|
||||
dimensions: Point2 {
|
||||
x: radar_size,
|
||||
y: radar_size,
|
||||
},
|
||||
angle: Deg(0.0),
|
||||
color: None,
|
||||
},
|
||||
);
|
||||
instances.push(UiInstance {
|
||||
anchor: PositionAnchor::NwNw.to_int(),
|
||||
position: [10.0, -10.0],
|
||||
angle: 0.0,
|
||||
size: radar_size,
|
||||
color: [1.0, 1.0, 1.0, 1.0],
|
||||
sprite_index: state.content.get_sprite_handle("ui::radar").get_index(),
|
||||
});
|
||||
|
||||
/*
|
||||
// Draw system objects
|
||||
|
@ -104,24 +92,20 @@ impl GPUState {
|
|||
.into();
|
||||
let f = state.content.get_faction(s.ship.faction).color;
|
||||
let f = [f[0], f[1], f[2], 1.0];
|
||||
self.push_ui_sprite(
|
||||
instances,
|
||||
&UiSprite {
|
||||
sprite: ship_sprite,
|
||||
pos: AnchoredUiPosition::NwC(
|
||||
Point2 {
|
||||
x: radar_size / 2.0 + 10.0,
|
||||
y: radar_size / -2.0 - 10.0,
|
||||
} + (d * (radar_size / 2.0)),
|
||||
),
|
||||
dimensions: Point2 {
|
||||
x: ship_sprite.aspect,
|
||||
y: 1.0,
|
||||
} * size,
|
||||
angle: -angle,
|
||||
color: Some(f),
|
||||
},
|
||||
);
|
||||
|
||||
let position = Point2 {
|
||||
x: radar_size / 2.0 + 10.0,
|
||||
y: radar_size / -2.0 - 10.0,
|
||||
} + (d * (radar_size / 2.0));
|
||||
|
||||
instances.push(UiInstance {
|
||||
anchor: PositionAnchor::NwC.to_int(),
|
||||
position: position.into(),
|
||||
angle: -Rad::from(angle).0, // TODO: consistent angles
|
||||
size,
|
||||
color: f.into(),
|
||||
sprite_index: ship_sprite.get_index(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -132,93 +116,83 @@ impl GPUState {
|
|||
} / radar_range;
|
||||
let m = d.magnitude();
|
||||
let d = d * (radar_size / 2.0);
|
||||
let color = Some([0.3, 0.3, 0.3, 1.0]);
|
||||
let color = [0.3, 0.3, 0.3, 1.0];
|
||||
if m < 0.8 {
|
||||
let sprite = state.content.get_sprite_handle("ui::radarframe");
|
||||
let dimensions = Point2 {
|
||||
x: sprite.aspect,
|
||||
y: 1.0,
|
||||
} * 7.0f32.min((0.8 - m) * 70.0);
|
||||
self.push_ui_sprite(
|
||||
instances,
|
||||
&UiSprite {
|
||||
sprite,
|
||||
pos: AnchoredUiPosition::NwNw(Point2 {
|
||||
x: (radar_size / 2.0 + 10.0) - d.x,
|
||||
y: (radar_size / -2.0 - 10.0) + d.y,
|
||||
}),
|
||||
dimensions,
|
||||
angle: Deg(0.0),
|
||||
color,
|
||||
},
|
||||
);
|
||||
let size = 7.0f32.min((0.8 - m) * 70.0);
|
||||
|
||||
self.push_ui_sprite(
|
||||
instances,
|
||||
&UiSprite {
|
||||
sprite,
|
||||
pos: AnchoredUiPosition::NwSw(Point2 {
|
||||
x: (radar_size / 2.0 + 10.0) - d.x,
|
||||
y: (radar_size / -2.0 - 10.0) - d.y,
|
||||
}),
|
||||
dimensions,
|
||||
angle: Deg(90.0),
|
||||
color,
|
||||
},
|
||||
);
|
||||
instances.push(UiInstance {
|
||||
anchor: PositionAnchor::NwNw.to_int(),
|
||||
position: Point2 {
|
||||
x: (radar_size / 2.0 + 10.0) - d.x,
|
||||
y: (radar_size / -2.0 - 10.0) + d.y,
|
||||
}
|
||||
.into(),
|
||||
angle: 0.0,
|
||||
size,
|
||||
color,
|
||||
sprite_index: sprite.get_index(),
|
||||
});
|
||||
|
||||
self.push_ui_sprite(
|
||||
instances,
|
||||
&UiSprite {
|
||||
sprite,
|
||||
pos: AnchoredUiPosition::NwSe(Point2 {
|
||||
x: (radar_size / 2.0 + 10.0) + d.x,
|
||||
y: (radar_size / -2.0 - 10.0) - d.y,
|
||||
}),
|
||||
dimensions,
|
||||
angle: Deg(180.0),
|
||||
color,
|
||||
},
|
||||
);
|
||||
instances.push(UiInstance {
|
||||
anchor: PositionAnchor::NwSw.to_int(),
|
||||
position: Point2 {
|
||||
x: (radar_size / 2.0 + 10.0) - d.x,
|
||||
y: (radar_size / -2.0 - 10.0) - d.y,
|
||||
}
|
||||
.into(),
|
||||
angle: Rad::from(Deg(90.0)).0,
|
||||
size,
|
||||
color,
|
||||
sprite_index: sprite.get_index(),
|
||||
});
|
||||
|
||||
self.push_ui_sprite(
|
||||
instances,
|
||||
&UiSprite {
|
||||
sprite,
|
||||
pos: AnchoredUiPosition::NwNe(Point2 {
|
||||
x: (radar_size / 2.0 + 10.0) + d.x,
|
||||
y: (radar_size / -2.0 - 10.0) + d.y,
|
||||
}),
|
||||
dimensions,
|
||||
angle: Deg(270.0),
|
||||
color,
|
||||
},
|
||||
);
|
||||
instances.push(UiInstance {
|
||||
anchor: PositionAnchor::NwSe.to_int(),
|
||||
position: Point2 {
|
||||
x: (radar_size / 2.0 + 10.0) + d.x,
|
||||
y: (radar_size / -2.0 - 10.0) - d.y,
|
||||
}
|
||||
.into(),
|
||||
angle: Rad::from(Deg(180.0)).0,
|
||||
size,
|
||||
color,
|
||||
sprite_index: sprite.get_index(),
|
||||
});
|
||||
|
||||
instances.push(UiInstance {
|
||||
anchor: PositionAnchor::NwNe.to_int(),
|
||||
position: Point2 {
|
||||
x: (radar_size / 2.0 + 10.0) + d.x,
|
||||
y: (radar_size / -2.0 - 10.0) + d.y,
|
||||
}
|
||||
.into(),
|
||||
angle: Rad::from(Deg(270.0)).0,
|
||||
size,
|
||||
color,
|
||||
sprite_index: sprite.get_index(),
|
||||
});
|
||||
}
|
||||
|
||||
// Arrow to center of system
|
||||
let q = Point2 { x: 0.0, y: 0.0 } - player_position;
|
||||
let m = q.magnitude();
|
||||
if m > 200.0 {
|
||||
let player_angle: Deg<f32> = q.angle(Vector2 { x: 0.0, y: 1.0 }).into();
|
||||
self.push_ui_sprite(
|
||||
instances,
|
||||
&UiSprite {
|
||||
sprite: arrow_sprite,
|
||||
pos: AnchoredUiPosition::NwC(
|
||||
Point2 {
|
||||
x: radar_size / 2.0 + 10.0,
|
||||
y: radar_size / -2.0 - 10.0,
|
||||
} + ((q.normalize() * 0.865) * (radar_size / 2.0)),
|
||||
),
|
||||
dimensions: Point2 {
|
||||
x: arrow_sprite.aspect,
|
||||
y: 1.0,
|
||||
} * 10.0,
|
||||
angle: -player_angle,
|
||||
color: Some([1.0, 1.0, 1.0, 1f32.min((m - 200.0) / 400.0)]),
|
||||
},
|
||||
);
|
||||
let player_angle = q.angle(Vector2 { x: 0.0, y: 1.0 });
|
||||
|
||||
let position: Point2<f32> = Point2 {
|
||||
x: radar_size / 2.0 + 10.0,
|
||||
y: radar_size / -2.0 - 10.0,
|
||||
} + ((q.normalize() * 0.865) * (radar_size / 2.0));
|
||||
|
||||
instances.push(UiInstance {
|
||||
anchor: PositionAnchor::NwC.to_int(),
|
||||
position: position.into(),
|
||||
angle: -player_angle.0,
|
||||
size: 10.0,
|
||||
color: [1.0, 1.0, 1.0, 1f32.min((m - 200.0) / 400.0)],
|
||||
sprite_index: arrow_sprite.get_index(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,17 @@
|
|||
use anyhow::Result;
|
||||
use bytemuck;
|
||||
use cgmath::{Matrix4, Point2, Vector3};
|
||||
use cgmath::Point2;
|
||||
use galactica_constants;
|
||||
|
||||
use rand::seq::SliceRandom;
|
||||
use std::{iter, rc::Rc};
|
||||
use wgpu;
|
||||
use winit::{self, dpi::LogicalSize, window::Window};
|
||||
use winit::{self, window::Window};
|
||||
|
||||
use crate::{
|
||||
content,
|
||||
globaluniform::{GlobalDataContent, GlobalUniform},
|
||||
pipeline::PipelineBuilder,
|
||||
sprite::UiSprite,
|
||||
starfield::Starfield,
|
||||
texturearray::TextureArray,
|
||||
vertexbuffer::{
|
||||
|
@ -23,7 +22,7 @@ use crate::{
|
|||
},
|
||||
BufferObject, VertexBuffer,
|
||||
},
|
||||
RenderState, OPENGL_TO_WGPU_MATRIX,
|
||||
RenderState,
|
||||
};
|
||||
|
||||
// Additional implementaitons for GPUState
|
||||
|
@ -94,6 +93,15 @@ fn preprocess_shader(
|
|||
)),
|
||||
);
|
||||
|
||||
let shader = shader.replace(
|
||||
"// INCLUDE: anchor.wgsl",
|
||||
&include_str!(concat!(
|
||||
env!("CARGO_MANIFEST_DIR"),
|
||||
"/shaders/include/",
|
||||
"anchor.wgsl"
|
||||
)),
|
||||
);
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
|
@ -337,65 +345,6 @@ impl GPUState {
|
|||
self.update_starfield_buffer()
|
||||
}
|
||||
|
||||
// TODO:remove
|
||||
/// Create a UiInstance for a ui sprite and add it to `instances`
|
||||
fn push_ui_sprite(&self, instances: &mut Vec<UiInstance>, s: &UiSprite) {
|
||||
let logical_size: LogicalSize<f32> =
|
||||
self.window_size.to_logical(self.window.scale_factor());
|
||||
|
||||
let width = s.dimensions.x;
|
||||
let height = s.dimensions.y;
|
||||
|
||||
// Compute square scale, since we must apply screen aspect ratio
|
||||
// AFTER rotation.
|
||||
let scale = Matrix4::from_nonuniform_scale(
|
||||
width / logical_size.height,
|
||||
height / logical_size.height,
|
||||
1.0,
|
||||
);
|
||||
let rotate = Matrix4::from_angle_z(s.angle);
|
||||
let translate = Matrix4::from_translation(match s.pos {
|
||||
super::AnchoredUiPosition::NwC(p) => Vector3 {
|
||||
// Note the signs. Positive y points north!
|
||||
x: -1.0 + p.x / (logical_size.width / 2.0),
|
||||
y: 1.0 + p.y / (logical_size.height / 2.0),
|
||||
z: 0.0,
|
||||
},
|
||||
super::AnchoredUiPosition::NwNw(p) => Vector3 {
|
||||
x: -1.0 + (width / 2.0 + p.x) / (logical_size.width / 2.0),
|
||||
y: 1.0 - (height / 2.0 - p.y) / (logical_size.height / 2.0),
|
||||
z: 0.0,
|
||||
},
|
||||
super::AnchoredUiPosition::NwNe(p) => Vector3 {
|
||||
x: -1.0 - (width / 2.0 - p.x) / (logical_size.width / 2.0),
|
||||
y: 1.0 - (height / 2.0 - p.y) / (logical_size.height / 2.0),
|
||||
z: 0.0,
|
||||
},
|
||||
super::AnchoredUiPosition::NwSw(p) => Vector3 {
|
||||
x: -1.0 + (width / 2.0 + p.x) / (logical_size.width / 2.0),
|
||||
y: 1.0 + (height / 2.0 + p.y) / (logical_size.height / 2.0),
|
||||
z: 0.0,
|
||||
},
|
||||
super::AnchoredUiPosition::NwSe(p) => Vector3 {
|
||||
x: -1.0 - (width / 2.0 - p.x) / (logical_size.width / 2.0),
|
||||
y: 1.0 + (height / 2.0 + p.y) / (logical_size.height / 2.0),
|
||||
z: 0.0,
|
||||
},
|
||||
super::AnchoredUiPosition::NeNe(p) => Vector3 {
|
||||
x: 1.0 - (width / 2.0 - p.x) / (logical_size.width / 2.0),
|
||||
y: 1.0 - (height / 2.0 - p.y) / (logical_size.height / 2.0),
|
||||
z: 0.0,
|
||||
},
|
||||
});
|
||||
let screen_aspect = Matrix4::from_nonuniform_scale(1.0 / self.window_aspect, 1.0, 1.0);
|
||||
|
||||
instances.push(UiInstance {
|
||||
transform: (OPENGL_TO_WGPU_MATRIX * translate * screen_aspect * rotate * scale).into(),
|
||||
sprite_index: s.sprite.get_index(),
|
||||
color: s.color.unwrap_or([1.0, 1.0, 1.0, 1.0]),
|
||||
});
|
||||
}
|
||||
|
||||
/// Make an instance for all the game's sprites
|
||||
/// (Objects and UI)
|
||||
/// This will Will panic if any X_SPRITE_INSTANCE_LIMIT is exceeded.
|
||||
|
@ -637,7 +586,7 @@ impl GPUState {
|
|||
]),
|
||||
);*/
|
||||
|
||||
// Ui pipeline
|
||||
// Radial progress bar
|
||||
// TODO: do we need to do this every time?
|
||||
self.vertex_buffers.radialbar.set_in_pass(&mut render_pass);
|
||||
render_pass.set_pipeline(&self.radialbar_pipeline);
|
||||
|
|
|
@ -7,19 +7,19 @@
|
|||
//! and the only one external code should interact with.
|
||||
//! (Excluding data structs, like [`ObjectSprite`])
|
||||
|
||||
mod anchoredposition;
|
||||
mod globaluniform;
|
||||
mod gpustate;
|
||||
mod pipeline;
|
||||
mod renderstate;
|
||||
mod sprite;
|
||||
mod starfield;
|
||||
mod texturearray;
|
||||
mod vertexbuffer;
|
||||
|
||||
pub use anchoredposition::PositionAnchor;
|
||||
use galactica_content as content;
|
||||
pub use gpustate::GPUState;
|
||||
pub use renderstate::RenderState;
|
||||
pub use sprite::AnchoredUiPosition;
|
||||
|
||||
use cgmath::Matrix4;
|
||||
|
||||
|
|
|
@ -1,79 +0,0 @@
|
|||
use crate::content;
|
||||
use cgmath::{Deg, Point2};
|
||||
|
||||
/// The location of a UI element, in one of a few
|
||||
/// possible coordinate systems.
|
||||
///
|
||||
/// Positive Y always points up,
|
||||
/// positive X always points right.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum AnchoredUiPosition {
|
||||
/// Position of this sprite's center,
|
||||
/// relative to the nw corner of the window.
|
||||
NwC(Point2<f32>),
|
||||
|
||||
/// Position of this sprite's nw corner,
|
||||
/// relative to the nw corner of the window.
|
||||
NwNw(Point2<f32>),
|
||||
|
||||
/// Position of this sprite's ne corner,
|
||||
/// relative to the nw corner of the window.
|
||||
NwNe(Point2<f32>),
|
||||
|
||||
/// Position of this sprite's sw corner,
|
||||
/// relative to the nw corner of the window.
|
||||
NwSw(Point2<f32>),
|
||||
|
||||
/// Position of this sprite's se corner,
|
||||
/// relative to the nw corner of the window.
|
||||
NwSe(Point2<f32>),
|
||||
|
||||
/// Position of this sprite's ne corner,
|
||||
/// relative to the ne corner of the window.
|
||||
NeNe(Point2<f32>),
|
||||
}
|
||||
|
||||
impl AnchoredUiPosition {
|
||||
pub fn to_anchor_int(&self) -> u32 {
|
||||
match self {
|
||||
Self::NwC(_) => 0,
|
||||
Self::NwNw(_) => 1,
|
||||
Self::NwNe(_) => 2,
|
||||
Self::NwSw(_) => 3,
|
||||
Self::NwSe(_) => 4,
|
||||
Self::NeNe(_) => 5,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn position(&self) -> &Point2<f32> {
|
||||
match self {
|
||||
Self::NwC(x)
|
||||
| Self::NwNw(x)
|
||||
| Self::NwNe(x)
|
||||
| Self::NwSw(x)
|
||||
| Self::NwSe(x)
|
||||
| Self::NeNe(x) => x,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: remove
|
||||
/// A sprite that represents a ui element
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct UiSprite {
|
||||
/// The sprite to draw
|
||||
pub sprite: content::SpriteHandle,
|
||||
|
||||
/// This object's position, in logical (dpi-adjusted) pixels
|
||||
pub pos: AnchoredUiPosition,
|
||||
|
||||
/// This sprite's color will be multiplied by this value.
|
||||
/// If this is None, color will not be changed.
|
||||
pub color: Option<[f32; 4]>,
|
||||
|
||||
/// The size of this sprite, in logical (dpi-adjusted) pixels
|
||||
pub dimensions: Point2<f32>,
|
||||
|
||||
/// This sprite's rotation, measured ccw
|
||||
pub angle: Deg<f32>,
|
||||
}
|
|
@ -120,10 +120,18 @@ impl BufferObject for ObjectInstance {
|
|||
#[repr(C)]
|
||||
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
||||
pub struct UiInstance {
|
||||
/// Extra transformations this sprite
|
||||
/// (rotation, etc)
|
||||
/// TODO: remove
|
||||
pub transform: [[f32; 4]; 4],
|
||||
/// How to interpret this object's coordinates.
|
||||
/// this should be generated from an AnchoredUiPosition
|
||||
pub anchor: u32,
|
||||
|
||||
/// Position of this object in logical pixels
|
||||
pub position: [f32; 2],
|
||||
|
||||
/// The angle of this sprite, in radians
|
||||
pub angle: f32,
|
||||
|
||||
/// The height of this sprite, in logical pixels
|
||||
pub size: f32,
|
||||
|
||||
/// This lets us color ui sprites dynamically.
|
||||
/// Each fragment's color is multiplied by this value.
|
||||
|
@ -143,36 +151,39 @@ impl BufferObject for UiInstance {
|
|||
// instance when the shader starts processing a new instance
|
||||
step_mode: wgpu::VertexStepMode::Instance,
|
||||
attributes: &[
|
||||
// 4 arrays = 1 4x4 matrix
|
||||
// Anchor
|
||||
wgpu::VertexAttribute {
|
||||
offset: 0,
|
||||
shader_location: 2,
|
||||
format: wgpu::VertexFormat::Float32x4,
|
||||
format: wgpu::VertexFormat::Uint32,
|
||||
},
|
||||
// Position
|
||||
wgpu::VertexAttribute {
|
||||
offset: mem::size_of::<[f32; 1]>() as wgpu::BufferAddress,
|
||||
shader_location: 3,
|
||||
format: wgpu::VertexFormat::Float32x2,
|
||||
},
|
||||
// Angle
|
||||
wgpu::VertexAttribute {
|
||||
offset: mem::size_of::<[f32; 3]>() as wgpu::BufferAddress,
|
||||
shader_location: 4,
|
||||
format: wgpu::VertexFormat::Float32,
|
||||
},
|
||||
// Size
|
||||
wgpu::VertexAttribute {
|
||||
offset: mem::size_of::<[f32; 4]>() as wgpu::BufferAddress,
|
||||
shader_location: 3,
|
||||
format: wgpu::VertexFormat::Float32x4,
|
||||
},
|
||||
wgpu::VertexAttribute {
|
||||
offset: mem::size_of::<[f32; 8]>() as wgpu::BufferAddress,
|
||||
shader_location: 4,
|
||||
format: wgpu::VertexFormat::Float32x4,
|
||||
},
|
||||
wgpu::VertexAttribute {
|
||||
offset: mem::size_of::<[f32; 12]>() as wgpu::BufferAddress,
|
||||
shader_location: 5,
|
||||
format: wgpu::VertexFormat::Float32x4,
|
||||
format: wgpu::VertexFormat::Float32,
|
||||
},
|
||||
// Color
|
||||
wgpu::VertexAttribute {
|
||||
offset: mem::size_of::<[f32; 16]>() as wgpu::BufferAddress,
|
||||
offset: mem::size_of::<[f32; 5]>() as wgpu::BufferAddress,
|
||||
shader_location: 6,
|
||||
format: wgpu::VertexFormat::Float32x4,
|
||||
},
|
||||
// Sprite
|
||||
wgpu::VertexAttribute {
|
||||
offset: mem::size_of::<[f32; 20]>() as wgpu::BufferAddress,
|
||||
offset: mem::size_of::<[f32; 9]>() as wgpu::BufferAddress,
|
||||
shader_location: 7,
|
||||
format: wgpu::VertexFormat::Uint32,
|
||||
},
|
||||
|
@ -286,7 +297,7 @@ pub struct RadialBarInstance {
|
|||
/// this should be generated from an AnchoredUiPosition
|
||||
pub anchor: u32,
|
||||
|
||||
/// Position of this particle in logical pixels
|
||||
/// Position of this object in logical pixels
|
||||
pub position: [f32; 2],
|
||||
|
||||
/// The diameter of this bar, in logical pixels
|
||||
|
|
Loading…
Reference in New Issue