mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Hack to allow minimap rotation.
Currently it just always rotates towards the camera, but it wouldn't be hard to create a config option that swaps out the rotation of the indicator and the map.
This commit is contained in:
parent
ed620fd70d
commit
93d7c67cdc
@ -10,8 +10,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Added music system
|
- Added music system
|
||||||
|
- Added zoomable and rotatable minimap
|
||||||
|
- Added rotating orientation marker to main-map
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
- Brighter / higher contrast main-map
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
|
BIN
assets/voxygen/element/buttons/button_mmap_closed_hover.vox
(Stored with Git LFS)
BIN
assets/voxygen/element/buttons/button_mmap_closed_hover.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/element/buttons/button_mmap_closed_press.vox
(Stored with Git LFS)
BIN
assets/voxygen/element/buttons/button_mmap_closed_press.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/element/buttons/button_mmap_open.vox
(Stored with Git LFS)
BIN
assets/voxygen/element/buttons/button_mmap_open.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/element/buttons/button_mmap_open_hover.vox
(Stored with Git LFS)
BIN
assets/voxygen/element/buttons/button_mmap_open_hover.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/element/buttons/button_mmap_open_press.vox
(Stored with Git LFS)
BIN
assets/voxygen/element/buttons/button_mmap_open_press.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/element/buttons/indicator_mmap_small.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/buttons/indicator_mmap_small.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/element/buttons/map_indicator.vox
(Stored with Git LFS)
BIN
assets/voxygen/element/buttons/map_indicator.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/element/buttons/min_plus/mmap_button-min.vox
(Stored with Git LFS)
BIN
assets/voxygen/element/buttons/min_plus/mmap_button-min.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/element/buttons/min_plus/mmap_button-min_hover.vox
(Stored with Git LFS)
BIN
assets/voxygen/element/buttons/min_plus/mmap_button-min_hover.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/element/buttons/min_plus/mmap_button-min_press.vox
(Stored with Git LFS)
BIN
assets/voxygen/element/buttons/min_plus/mmap_button-min_press.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/element/buttons/min_plus/mmap_button-plus.vox
(Stored with Git LFS)
BIN
assets/voxygen/element/buttons/min_plus/mmap_button-plus.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/element/buttons/min_plus/mmap_button-plus_hover.vox
(Stored with Git LFS)
BIN
assets/voxygen/element/buttons/min_plus/mmap_button-plus_hover.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/element/buttons/min_plus/mmap_button-plus_press.vox
(Stored with Git LFS)
BIN
assets/voxygen/element/buttons/min_plus/mmap_button-plus_press.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/element/frames/mmap.vox
(Stored with Git LFS)
BIN
assets/voxygen/element/frames/mmap.vox
(Stored with Git LFS)
Binary file not shown.
@ -20,7 +20,8 @@ void main() {
|
|||||||
if (f_mode == uint(0)) {
|
if (f_mode == uint(0)) {
|
||||||
tgt_color = f_color * vec4(1.0, 1.0, 1.0, texture(u_tex, f_uv).a);
|
tgt_color = f_color * vec4(1.0, 1.0, 1.0, texture(u_tex, f_uv).a);
|
||||||
// Image
|
// Image
|
||||||
} else if (f_mode == uint(1)) {
|
// HACK: bit 0 is set for both ordinary and north-facing images.
|
||||||
|
} else if ((f_mode & uint(1)) == uint(1)) {
|
||||||
tgt_color = f_color * texture(u_tex, f_uv);
|
tgt_color = f_color * texture(u_tex, f_uv);
|
||||||
// 2D Geometry
|
// 2D Geometry
|
||||||
} else if (f_mode == uint(2)) {
|
} else if (f_mode == uint(2)) {
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
in vec2 v_pos;
|
in vec2 v_pos;
|
||||||
in vec2 v_uv;
|
in vec2 v_uv;
|
||||||
|
in vec2 v_center;
|
||||||
in vec4 v_color;
|
in vec4 v_color;
|
||||||
in uint v_mode;
|
in uint v_mode;
|
||||||
|
|
||||||
@ -19,15 +20,31 @@ flat out uint f_mode;
|
|||||||
out vec4 f_color;
|
out vec4 f_color;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
f_uv = v_uv;
|
|
||||||
f_color = v_color;
|
f_color = v_color;
|
||||||
|
|
||||||
if (w_pos.w == 1.0) {
|
if (w_pos.w == 1.0) {
|
||||||
|
f_uv = v_uv;
|
||||||
// Fixed scale In-game element
|
// Fixed scale In-game element
|
||||||
vec4 projected_pos = proj_mat * view_mat * vec4(w_pos.xyz, 1.0);
|
vec4 projected_pos = proj_mat * view_mat * vec4(w_pos.xyz, 1.0);
|
||||||
gl_Position = vec4(projected_pos.xy / projected_pos.w + v_pos, 0.0, 1.0);
|
gl_Position = vec4(projected_pos.xy / projected_pos.w + v_pos, 0.0, 1.0);
|
||||||
|
} else if (v_mode == uint(3)) {
|
||||||
|
// HACK: North facing source rectangle.
|
||||||
|
vec2 look_at_dir = normalize(vec2(-view_mat[0][2], -view_mat[1][2]));
|
||||||
|
mat2 look_at = mat2(look_at_dir.y, look_at_dir.x, -look_at_dir.x, look_at_dir.y);
|
||||||
|
f_uv = v_center + look_at * (v_uv - v_center);
|
||||||
|
gl_Position = vec4(v_pos, 0.0, 1.0);
|
||||||
|
} else if (v_mode == uint(5)) {
|
||||||
|
// HACK: North facing target rectangle.
|
||||||
|
f_uv = v_uv;
|
||||||
|
float aspect_ratio = screen_res.x / screen_res.y;
|
||||||
|
vec2 look_at_dir = normalize(vec2(-view_mat[0][2], -view_mat[1][2]));
|
||||||
|
mat2 look_at = mat2(look_at_dir.y, -look_at_dir.x, look_at_dir.x, look_at_dir.y);
|
||||||
|
vec2 v_len = v_pos - v_center;
|
||||||
|
vec2 v_proj = look_at * vec2(v_len.x, v_len.y / aspect_ratio);
|
||||||
|
gl_Position = vec4(v_center + vec2(v_proj.x, v_proj.y * aspect_ratio), 0.0, 1.0);
|
||||||
} else {
|
} else {
|
||||||
// Interface element
|
// Interface element
|
||||||
|
f_uv = v_uv;
|
||||||
gl_Position = vec4(v_pos, 0.0, 1.0);
|
gl_Position = vec4(v_pos, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
f_mode = v_mode;
|
f_mode = v_mode;
|
||||||
|
@ -8,6 +8,13 @@ rotation_image_ids! {
|
|||||||
// Tooltip Test
|
// Tooltip Test
|
||||||
tt_side: "voxygen/element/frames/tt_test_edge",
|
tt_side: "voxygen/element/frames/tt_test_edge",
|
||||||
tt_corner: "voxygen/element/frames/tt_test_corner_tr",
|
tt_corner: "voxygen/element/frames/tt_test_corner_tr",
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
<VoxelPixArtGraphic>
|
||||||
|
|
||||||
|
// Minimap
|
||||||
|
indicator_mmap_small: "voxygen.element.buttons.indicator_mmap_small",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,7 +138,6 @@ image_ids! {
|
|||||||
skull_2: "voxygen.element.icons.skull_2",
|
skull_2: "voxygen.element.icons.skull_2",
|
||||||
|
|
||||||
// Map
|
// Map
|
||||||
map_indicator: "voxygen.element.buttons.map_indicator",
|
|
||||||
indicator_mmap: "voxygen.element.buttons.indicator_mmap",
|
indicator_mmap: "voxygen.element.buttons.indicator_mmap",
|
||||||
indicator_mmap_2: "voxygen.element.buttons.indicator_mmap_2",
|
indicator_mmap_2: "voxygen.element.buttons.indicator_mmap_2",
|
||||||
indicator_mmap_3: "voxygen.element.buttons.indicator_mmap_3",
|
indicator_mmap_3: "voxygen.element.buttons.indicator_mmap_3",
|
||||||
@ -169,7 +175,7 @@ image_ids! {
|
|||||||
mmap_open_press: "voxygen.element.buttons.button_mmap_open_press",
|
mmap_open_press: "voxygen.element.buttons.button_mmap_open_press",
|
||||||
mmap_plus: "voxygen.element.buttons.min_plus.mmap_button-plus",
|
mmap_plus: "voxygen.element.buttons.min_plus.mmap_button-plus",
|
||||||
mmap_plus_hover: "voxygen.element.buttons.min_plus.mmap_button-plus_hover",
|
mmap_plus_hover: "voxygen.element.buttons.min_plus.mmap_button-plus_hover",
|
||||||
mmap_plus_press: "voxygen.element.buttons.min_plus.mmap_button-plus_hover",
|
mmap_plus_press: "voxygen.element.buttons.min_plus.mmap_button-plus_press",
|
||||||
mmap_minus: "voxygen.element.buttons.min_plus.mmap_button-min",
|
mmap_minus: "voxygen.element.buttons.min_plus.mmap_button-min",
|
||||||
mmap_minus_hover: "voxygen.element.buttons.min_plus.mmap_button-min_hover",
|
mmap_minus_hover: "voxygen.element.buttons.min_plus.mmap_button-min_hover",
|
||||||
mmap_minus_press: "voxygen.element.buttons.min_plus.mmap_button-min_press",
|
mmap_minus_press: "voxygen.element.buttons.min_plus.mmap_button-min_press",
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
use super::{img_ids::Imgs, Fonts, Show, TEXT_COLOR};
|
use super::{
|
||||||
|
img_ids::{Imgs, ImgsRot},
|
||||||
|
Fonts, Show, TEXT_COLOR,
|
||||||
|
};
|
||||||
|
use crate::ui::img_ids;
|
||||||
use client::{self, Client};
|
use client::{self, Client};
|
||||||
use common::{comp, terrain::TerrainChunkSize, vol::RectVolSize};
|
use common::{comp, terrain::TerrainChunkSize, vol::RectVolSize};
|
||||||
use conrod_core::{
|
use conrod_core::{
|
||||||
color,
|
color,
|
||||||
image::Id,
|
|
||||||
widget::{self, Button, Image, Rectangle, Text},
|
widget::{self, Button, Image, Rectangle, Text},
|
||||||
widget_ids, Color, Colorable, Positionable, Sizeable, Widget, WidgetCommon,
|
widget_ids, Color, Colorable, Positionable, Sizeable, Widget, WidgetCommon,
|
||||||
};
|
};
|
||||||
@ -30,12 +33,13 @@ widget_ids! {
|
|||||||
pub struct Map<'a> {
|
pub struct Map<'a> {
|
||||||
_show: &'a Show,
|
_show: &'a Show,
|
||||||
client: &'a Client,
|
client: &'a Client,
|
||||||
world_map: (Id, Vec2<u32>),
|
world_map: &'a (img_ids::Rotations, Vec2<u32>),
|
||||||
imgs: &'a Imgs,
|
imgs: &'a Imgs,
|
||||||
|
rot_imgs: &'a ImgsRot,
|
||||||
fonts: &'a Fonts,
|
fonts: &'a Fonts,
|
||||||
#[conrod(common_builder)]
|
#[conrod(common_builder)]
|
||||||
common: widget::CommonBuilder,
|
common: widget::CommonBuilder,
|
||||||
pulse: f32,
|
_pulse: f32,
|
||||||
velocity: f32,
|
velocity: f32,
|
||||||
}
|
}
|
||||||
impl<'a> Map<'a> {
|
impl<'a> Map<'a> {
|
||||||
@ -43,7 +47,8 @@ impl<'a> Map<'a> {
|
|||||||
show: &'a Show,
|
show: &'a Show,
|
||||||
client: &'a Client,
|
client: &'a Client,
|
||||||
imgs: &'a Imgs,
|
imgs: &'a Imgs,
|
||||||
world_map: (Id, Vec2<u32>),
|
rot_imgs: &'a ImgsRot,
|
||||||
|
world_map: &'a (img_ids::Rotations, Vec2<u32>),
|
||||||
fonts: &'a Fonts,
|
fonts: &'a Fonts,
|
||||||
pulse: f32,
|
pulse: f32,
|
||||||
velocity: f32,
|
velocity: f32,
|
||||||
@ -51,11 +56,12 @@ impl<'a> Map<'a> {
|
|||||||
Self {
|
Self {
|
||||||
_show: show,
|
_show: show,
|
||||||
imgs,
|
imgs,
|
||||||
|
rot_imgs,
|
||||||
world_map,
|
world_map,
|
||||||
client,
|
client,
|
||||||
fonts,
|
fonts,
|
||||||
common: widget::CommonBuilder::default(),
|
common: widget::CommonBuilder::default(),
|
||||||
pulse,
|
_pulse: pulse,
|
||||||
velocity,
|
velocity,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -160,9 +166,9 @@ impl<'a> Widget for Map<'a> {
|
|||||||
let (world_map, worldsize) = self.world_map;
|
let (world_map, worldsize) = self.world_map;
|
||||||
let worldsize = worldsize.map2(TerrainChunkSize::RECT_SIZE, |e, f| e as f64 * f as f64);
|
let worldsize = worldsize.map2(TerrainChunkSize::RECT_SIZE, |e, f| e as f64 * f as f64);
|
||||||
|
|
||||||
Image::new(world_map)
|
Image::new(world_map.none)
|
||||||
.middle_of(state.ids.map_bg)
|
.middle_of(state.ids.map_bg)
|
||||||
.color(Some(Color::Rgba(1.0, 1.0, 1.0, fade - 0.1)))
|
.color(Some(Color::Rgba(1.0, 1.0, 1.0, fade + 0.5)))
|
||||||
.w_h(700.0, 700.0)
|
.w_h(700.0, 700.0)
|
||||||
.parent(state.ids.map_bg)
|
.parent(state.ids.map_bg)
|
||||||
.set(state.ids.grid, ui);
|
.set(state.ids.grid, ui);
|
||||||
@ -177,31 +183,18 @@ impl<'a> Widget for Map<'a> {
|
|||||||
|
|
||||||
let x = player_pos.x as f64 / worldsize.x * 700.0;
|
let x = player_pos.x as f64 / worldsize.x * 700.0;
|
||||||
let y = player_pos.y as f64 / worldsize.y * 700.0;
|
let y = player_pos.y as f64 / worldsize.y * 700.0;
|
||||||
let indic_ani = (self.pulse * 6.0/*animation speed*/).cos()/*starts at 1.0*/ * 0.5 + 0.50; // changes the animation frame
|
let indic_scale = 0.6;
|
||||||
let indic_scale = 1.2;
|
Image::new(self.rot_imgs.indicator_mmap_small.target_north)
|
||||||
// Indicator
|
.bottom_left_with_margins_on(
|
||||||
Image::new(if indic_ani <= 0.3 {
|
state.ids.grid,
|
||||||
self.imgs.indicator_mmap
|
y - 37.0 * indic_scale / 2.0,
|
||||||
} else if indic_ani <= 0.6 {
|
x - 32.0 * indic_scale / 2.0,
|
||||||
self.imgs.indicator_mmap_2
|
)
|
||||||
} else {
|
.w_h(32.0 * indic_scale, 37.0 * indic_scale)
|
||||||
self.imgs.indicator_mmap_3
|
.color(Some(Color::Rgba(1.0, 1.0, 1.0, 1.0)))
|
||||||
})
|
.floating(true)
|
||||||
.bottom_left_with_margins_on(state.ids.grid, y, x - (20.0 * 1.2) / 2.0)
|
.parent(ui.window)
|
||||||
.w_h(
|
.set(state.ids.indicator, ui);
|
||||||
22.0 * 1.2,
|
|
||||||
if indic_ani <= 0.3 {
|
|
||||||
16.0 * indic_scale
|
|
||||||
} else if indic_ani <= 0.6 {
|
|
||||||
23.0 * indic_scale
|
|
||||||
} else {
|
|
||||||
34.0 * indic_scale
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.color(Some(Color::Rgba(1.0, 1.0, 1.0, fade + 0.2)))
|
|
||||||
.floating(true)
|
|
||||||
.parent(ui.window)
|
|
||||||
.set(state.ids.indicator, ui);
|
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
use super::{img_ids::Imgs, Fonts, Show, HP_COLOR, TEXT_COLOR};
|
use super::{
|
||||||
|
img_ids::{Imgs, ImgsRot},
|
||||||
|
Fonts, Show, HP_COLOR, TEXT_COLOR,
|
||||||
|
};
|
||||||
|
use crate::ui::img_ids;
|
||||||
use client::{self, Client};
|
use client::{self, Client};
|
||||||
use common::{comp, terrain::TerrainChunkSize, vol::RectVolSize};
|
use common::{comp, terrain::TerrainChunkSize, vol::RectVolSize};
|
||||||
use conrod_core::{
|
use conrod_core::{
|
||||||
color,
|
color, position,
|
||||||
image::Id,
|
|
||||||
widget::{self, Button, Image, Rectangle, Text},
|
widget::{self, Button, Image, Rectangle, Text},
|
||||||
widget_ids, Color, Colorable, Positionable, Sizeable, Widget, WidgetCommon,
|
widget_ids, Color, Colorable, Positionable, Sizeable, Widget, WidgetCommon,
|
||||||
};
|
};
|
||||||
@ -33,12 +36,11 @@ pub struct MiniMap<'a> {
|
|||||||
client: &'a Client,
|
client: &'a Client,
|
||||||
|
|
||||||
imgs: &'a Imgs,
|
imgs: &'a Imgs,
|
||||||
world_map: (Id, Vec2<u32>),
|
rot_imgs: &'a ImgsRot,
|
||||||
|
world_map: &'a (img_ids::Rotations, Vec2<u32>),
|
||||||
fonts: &'a Fonts,
|
fonts: &'a Fonts,
|
||||||
#[conrod(common_builder)]
|
#[conrod(common_builder)]
|
||||||
common: widget::CommonBuilder,
|
common: widget::CommonBuilder,
|
||||||
pulse: f32,
|
|
||||||
zoom: f32,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> MiniMap<'a> {
|
impl<'a> MiniMap<'a> {
|
||||||
@ -46,20 +48,18 @@ impl<'a> MiniMap<'a> {
|
|||||||
show: &'a Show,
|
show: &'a Show,
|
||||||
client: &'a Client,
|
client: &'a Client,
|
||||||
imgs: &'a Imgs,
|
imgs: &'a Imgs,
|
||||||
world_map: (Id, Vec2<u32>),
|
rot_imgs: &'a ImgsRot,
|
||||||
|
world_map: &'a (img_ids::Rotations, Vec2<u32>),
|
||||||
fonts: &'a Fonts,
|
fonts: &'a Fonts,
|
||||||
pulse: f32,
|
|
||||||
zoom: f32,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
show,
|
show,
|
||||||
client,
|
client,
|
||||||
imgs,
|
imgs,
|
||||||
|
rot_imgs,
|
||||||
world_map,
|
world_map,
|
||||||
fonts,
|
fonts,
|
||||||
common: widget::CommonBuilder::default(),
|
common: widget::CommonBuilder::default(),
|
||||||
pulse,
|
|
||||||
zoom,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -69,6 +69,7 @@ pub struct State {
|
|||||||
|
|
||||||
last_region_name: Option<String>,
|
last_region_name: Option<String>,
|
||||||
last_update: Instant,
|
last_update: Instant,
|
||||||
|
zoom: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
@ -86,6 +87,14 @@ impl<'a> Widget for MiniMap<'a> {
|
|||||||
|
|
||||||
last_region_name: None,
|
last_region_name: None,
|
||||||
last_update: Instant::now(),
|
last_update: Instant::now(),
|
||||||
|
zoom: {
|
||||||
|
let min_world_dim = self.world_map.1.reduce_partial_min() as f64;
|
||||||
|
min_world_dim.min(
|
||||||
|
min_world_dim
|
||||||
|
* (TerrainChunkSize::RECT_SIZE.reduce_partial_max() as f64 / 32.0)
|
||||||
|
* (16.0 / 1024.0),
|
||||||
|
)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,53 +102,74 @@ impl<'a> Widget for MiniMap<'a> {
|
|||||||
|
|
||||||
fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
|
fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
|
||||||
let widget::UpdateArgs { state, ui, .. } = args;
|
let widget::UpdateArgs { state, ui, .. } = args;
|
||||||
let zoom = self.zoom as f64;
|
let zoom = state.zoom;
|
||||||
if self.show.mini_map {
|
if self.show.mini_map {
|
||||||
Image::new(self.imgs.mmap_frame)
|
Image::new(self.imgs.mmap_frame)
|
||||||
.w_h(100.0 * 4.0 * zoom, 100.0 * 4.0 * zoom)
|
.w_h(100.0 * 3.0, 100.0 * 3.0)
|
||||||
.top_right_with_margins_on(ui.window, 5.0, 5.0)
|
.top_right_with_margins_on(ui.window, 5.0, 5.0)
|
||||||
.set(state.ids.mmap_frame, ui);
|
.set(state.ids.mmap_frame, ui);
|
||||||
|
|
||||||
Rectangle::fill_with([92.0 * 4.0, 82.0 * 4.0], color::TRANSPARENT)
|
Rectangle::fill_with([92.0 * 3.0, 82.0 * 3.0], color::TRANSPARENT)
|
||||||
.mid_top_with_margin_on(state.ids.mmap_frame, 13.0 * 4.0 + 4.0 * zoom)
|
.mid_top_with_margin_on(state.ids.mmap_frame, 13.0 * 3.0 + 3.0)
|
||||||
.set(state.ids.mmap_frame_bg, ui);
|
.set(state.ids.mmap_frame_bg, ui);
|
||||||
// Zoom Buttons
|
|
||||||
// TODO: Add zoomable minimap
|
|
||||||
|
|
||||||
/*if Button::image(self.imgs.mmap_plus)
|
// Map size
|
||||||
.w_h(100.0 * 0.2 * zoom, 100.0 * 0.2 * zoom)
|
|
||||||
.hover_image(self.imgs.mmap_plus_hover)
|
|
||||||
.press_image(self.imgs.mmap_plus_press)
|
|
||||||
.top_left_with_margins_on(state.ids.mmap_frame, 0.0, 0.0)
|
|
||||||
.set(state.ids.mmap_plus, ui)
|
|
||||||
.was_clicked()
|
|
||||||
{
|
|
||||||
if zoom > 0.0 {
|
|
||||||
zoom = zoom + 1.0
|
|
||||||
} else if zoom == 5.0 {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if Button::image(self.imgs.mmap_minus)
|
|
||||||
.w_h(100.0 * 0.2 * zoom, 100.0 * 0.2 * zoom)
|
|
||||||
.hover_image(self.imgs.mmap_minus_hover)
|
|
||||||
.press_image(self.imgs.mmap_minus_press)
|
|
||||||
.down_from(state.ids.mmap_plus, 0.0)
|
|
||||||
.set(state.ids.mmap_minus, ui)
|
|
||||||
.was_clicked()
|
|
||||||
{
|
|
||||||
if zoom < 6.0 {
|
|
||||||
zoom = zoom - 1.0
|
|
||||||
} else if zoom == 0.0 {
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
// Map Image
|
|
||||||
let (world_map, worldsize) = self.world_map;
|
let (world_map, worldsize) = self.world_map;
|
||||||
let worldsize = worldsize.map2(TerrainChunkSize::RECT_SIZE, |e, f| e as f64 * f as f64);
|
let worldsize = worldsize.map2(TerrainChunkSize::RECT_SIZE, |e, f| e as f64 * f as f64);
|
||||||
Image::new(world_map)
|
|
||||||
.middle_of(state.ids.mmap_frame_bg)
|
// Zoom Buttons
|
||||||
.w_h(92.0 * 4.0 * zoom, 82.0 * 4.0 * zoom)
|
|
||||||
.parent(state.ids.mmap_frame_bg)
|
// Pressing + multiplies, and - divides, zoom by ZOOM_FACTOR.
|
||||||
.set(state.ids.grid, ui);
|
const ZOOM_FACTOR: f64 = 2.0;
|
||||||
|
|
||||||
|
// TODO: Either prevent zooming all the way in, *or* see if we can interpolate
|
||||||
|
// somehow if you zoom in too far. Or both.
|
||||||
|
let min_zoom = 1.0;
|
||||||
|
let max_zoom = (worldsize / TerrainChunkSize::RECT_SIZE.map(|e| e as f64))
|
||||||
|
.reduce_partial_min()/*.min(f64::MAX)*/;
|
||||||
|
|
||||||
|
// NOTE: Not sure if a button can be clicked while disabled, but we still double
|
||||||
|
// check for both kinds of zoom to make sure that not only was the
|
||||||
|
// button clicked, it is also okay to perform the zoom action.
|
||||||
|
// Note that since `Button::image` has side effects, we must perform
|
||||||
|
// the `can_zoom_in` and `can_zoom_out` checks after the `&&` to avoid
|
||||||
|
// undesired early termination.
|
||||||
|
let can_zoom_in = zoom < max_zoom;
|
||||||
|
let can_zoom_out = zoom > min_zoom;
|
||||||
|
|
||||||
|
if Button::image(self.imgs.mmap_minus)
|
||||||
|
.w_h(100.0 * 0.30, 100.0 * 0.30)
|
||||||
|
.hover_image(self.imgs.mmap_minus_hover)
|
||||||
|
.press_image(self.imgs.mmap_minus_press)
|
||||||
|
.top_left_with_margins_on(state.ids.mmap_frame, 0.0, 0.0)
|
||||||
|
.enabled(can_zoom_out)
|
||||||
|
.set(state.ids.mmap_minus, ui)
|
||||||
|
.was_clicked()
|
||||||
|
&& can_zoom_out
|
||||||
|
{
|
||||||
|
// Set the image dimensions here, rather than recomputing each time.
|
||||||
|
let zoom = min_zoom.max(zoom / ZOOM_FACTOR);
|
||||||
|
state.update(|s| s.zoom = zoom);
|
||||||
|
// set_image_dims(zoom);
|
||||||
|
}
|
||||||
|
if Button::image(self.imgs.mmap_plus)
|
||||||
|
.w_h(100.0 * 0.30, 100.0 * 0.30)
|
||||||
|
.hover_image(self.imgs.mmap_plus_hover)
|
||||||
|
.press_image(self.imgs.mmap_plus_press)
|
||||||
|
.right_from(state.ids.mmap_minus, 6.0)
|
||||||
|
.enabled(can_zoom_in)
|
||||||
|
.set(state.ids.mmap_plus, ui)
|
||||||
|
.was_clicked()
|
||||||
|
&& can_zoom_in
|
||||||
|
{
|
||||||
|
let zoom = max_zoom.min(zoom * ZOOM_FACTOR);
|
||||||
|
state.update(|s| s.zoom = zoom);
|
||||||
|
// set_image_dims(zoom);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reload zoom in case it changed.
|
||||||
|
let zoom = state.zoom;
|
||||||
|
|
||||||
// Coordinates
|
// Coordinates
|
||||||
let player_pos = self
|
let player_pos = self
|
||||||
.client
|
.client
|
||||||
@ -149,30 +179,36 @@ impl<'a> Widget for MiniMap<'a> {
|
|||||||
.get(self.client.entity())
|
.get(self.client.entity())
|
||||||
.map_or(Vec3::zero(), |pos| pos.0);
|
.map_or(Vec3::zero(), |pos| pos.0);
|
||||||
|
|
||||||
let x = player_pos.x as f64 / worldsize.x * 92.0 * 4.0;
|
// Get map image source rectangle dimensons.
|
||||||
let y = player_pos.y as f64 / worldsize.y * 82.0 * 4.0;
|
let w_src = worldsize.x / TerrainChunkSize::RECT_SIZE.x as f64 / zoom;
|
||||||
let indic_ani = (self.pulse * 6.0).cos() * 0.5 + 0.5; //Animation timer
|
let h_src = worldsize.y / TerrainChunkSize::RECT_SIZE.y as f64 / zoom;
|
||||||
let indic_scale = 0.8;
|
|
||||||
|
// Set map image to be centered around player coordinates.
|
||||||
|
let rect_src = position::Rect::from_xy_dim(
|
||||||
|
[
|
||||||
|
player_pos.x as f64 / TerrainChunkSize::RECT_SIZE.x as f64,
|
||||||
|
(worldsize.y - player_pos.y as f64) / TerrainChunkSize::RECT_SIZE.y as f64,
|
||||||
|
],
|
||||||
|
[w_src, h_src],
|
||||||
|
);
|
||||||
|
|
||||||
|
// Map Image
|
||||||
|
Image::new(world_map.source_north)
|
||||||
|
.middle_of(state.ids.mmap_frame_bg)
|
||||||
|
.w_h(92.0 * 3.0, 82.0 * 3.0)
|
||||||
|
.parent(state.ids.mmap_frame_bg)
|
||||||
|
.source_rectangle(rect_src)
|
||||||
|
.set(state.ids.grid, ui);
|
||||||
|
|
||||||
// Indicator
|
// Indicator
|
||||||
Image::new(if indic_ani <= 0.5 {
|
let ind_scale = 0.4;
|
||||||
self.imgs.indicator_mmap
|
Image::new(self.rot_imgs.indicator_mmap_small.none)
|
||||||
} else {
|
.middle_of(state.ids.grid)
|
||||||
self.imgs.indicator_mmap_2
|
.w_h(32.0 * ind_scale, 37.0 * ind_scale)
|
||||||
})
|
.color(Some(Color::Rgba(1.0, 1.0, 1.0, 1.0)))
|
||||||
.bottom_left_with_margins_on(state.ids.grid, y, x - 5.0)
|
.floating(true)
|
||||||
.w_h(
|
.parent(ui.window)
|
||||||
// Animation frames depening on timer value from 0.0 to 1.0
|
.set(state.ids.indicator, ui);
|
||||||
22.0 * 0.8,
|
|
||||||
if indic_ani <= 0.5 {
|
|
||||||
18.0 * indic_scale
|
|
||||||
} else {
|
|
||||||
23.0 * indic_scale
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.color(Some(Color::Rgba(1.0, 1.0, 1.0, 1.0)))
|
|
||||||
.floating(true)
|
|
||||||
.parent(ui.window)
|
|
||||||
.set(state.ids.indicator, ui);
|
|
||||||
} else {
|
} else {
|
||||||
Image::new(self.imgs.mmap_frame_closed)
|
Image::new(self.imgs.mmap_frame_closed)
|
||||||
.w_h(100.0 * 2.0, 11.0 * 2.0)
|
.w_h(100.0 * 2.0, 11.0 * 2.0)
|
||||||
@ -186,9 +222,9 @@ impl<'a> Widget for MiniMap<'a> {
|
|||||||
self.imgs.mmap_closed
|
self.imgs.mmap_closed
|
||||||
})
|
})
|
||||||
.wh(if self.show.mini_map {
|
.wh(if self.show.mini_map {
|
||||||
[100.0 * 0.4; 2]
|
[100.0 * 0.3; 2]
|
||||||
} else {
|
} else {
|
||||||
[100.0 * 0.2 * zoom; 2]
|
[100.0 * 0.2; 2]
|
||||||
})
|
})
|
||||||
.hover_image(if self.show.mini_map {
|
.hover_image(if self.show.mini_map {
|
||||||
self.imgs.mmap_open_hover
|
self.imgs.mmap_open_hover
|
||||||
@ -267,7 +303,7 @@ impl<'a> Widget for MiniMap<'a> {
|
|||||||
state.ids.mmap_frame,
|
state.ids.mmap_frame,
|
||||||
if self.show.mini_map { 6.0 } else { 0.0 },
|
if self.show.mini_map { 6.0 } else { 0.0 },
|
||||||
)
|
)
|
||||||
.font_size(if self.show.mini_map { 30 } else { 18 })
|
.font_size(if self.show.mini_map { 20 } else { 18 })
|
||||||
.font_id(self.fonts.cyri)
|
.font_id(self.fonts.cyri)
|
||||||
.color(TEXT_COLOR)
|
.color(TEXT_COLOR)
|
||||||
.set(state.ids.mmap_location, ui),
|
.set(state.ids.mmap_location, ui),
|
||||||
|
@ -13,7 +13,7 @@ mod skillbar;
|
|||||||
mod social;
|
mod social;
|
||||||
mod spell;
|
mod spell;
|
||||||
|
|
||||||
use crate::{ecs::comp::HpFloaterList, hud::img_ids::ImgsRot};
|
use crate::{ecs::comp::HpFloaterList, hud::img_ids::ImgsRot, ui::img_ids::Rotations};
|
||||||
pub use settings_window::ScaleChange;
|
pub use settings_window::ScaleChange;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
@ -46,7 +46,6 @@ use crate::{
|
|||||||
use client::{Client, Event as ClientEvent};
|
use client::{Client, Event as ClientEvent};
|
||||||
use common::{assets::load_expect, comp, terrain::TerrainChunk, vol::RectRasterableVol};
|
use common::{assets::load_expect, comp, terrain::TerrainChunk, vol::RectRasterableVol};
|
||||||
use conrod_core::{
|
use conrod_core::{
|
||||||
image::Id,
|
|
||||||
text::cursor::Index,
|
text::cursor::Index,
|
||||||
widget::{self, Button, Image, Rectangle, Text},
|
widget::{self, Button, Image, Rectangle, Text},
|
||||||
widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, Widget,
|
widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, Widget,
|
||||||
@ -307,7 +306,7 @@ impl Show {
|
|||||||
fn map(&mut self, open: bool) {
|
fn map(&mut self, open: bool) {
|
||||||
self.map = open;
|
self.map = open;
|
||||||
self.bag = false;
|
self.bag = false;
|
||||||
self.want_grab = !open;
|
self.want_grab = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn character_window(&mut self, open: bool) {
|
fn character_window(&mut self, open: bool) {
|
||||||
@ -431,7 +430,7 @@ impl Show {
|
|||||||
pub struct Hud {
|
pub struct Hud {
|
||||||
ui: Ui,
|
ui: Ui,
|
||||||
ids: Ids,
|
ids: Ids,
|
||||||
world_map: (Id, Vec2<u32>),
|
world_map: (/* Id */ Rotations, Vec2<u32>),
|
||||||
imgs: Imgs,
|
imgs: Imgs,
|
||||||
item_imgs: ItemImgs,
|
item_imgs: ItemImgs,
|
||||||
fonts: Fonts,
|
fonts: Fonts,
|
||||||
@ -446,7 +445,6 @@ pub struct Hud {
|
|||||||
force_chat_input: Option<String>,
|
force_chat_input: Option<String>,
|
||||||
force_chat_cursor: Option<Index>,
|
force_chat_cursor: Option<Index>,
|
||||||
pulse: f32,
|
pulse: f32,
|
||||||
zoom: f32,
|
|
||||||
velocity: f32,
|
velocity: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -461,7 +459,7 @@ impl Hud {
|
|||||||
let ids = Ids::new(ui.id_generator());
|
let ids = Ids::new(ui.id_generator());
|
||||||
// Load world map
|
// Load world map
|
||||||
let world_map = (
|
let world_map = (
|
||||||
ui.add_graphic(Graphic::Image(client.world_map.0.clone())),
|
ui.add_graphic_with_rotations(Graphic::Image(client.world_map.0.clone())),
|
||||||
client.world_map.1,
|
client.world_map.1,
|
||||||
);
|
);
|
||||||
// Load images.
|
// Load images.
|
||||||
@ -497,7 +495,7 @@ impl Hud {
|
|||||||
quest: false,
|
quest: false,
|
||||||
spell: false,
|
spell: false,
|
||||||
character_window: false,
|
character_window: false,
|
||||||
mini_map: false,
|
mini_map: true,
|
||||||
settings_tab: SettingsTab::Interface,
|
settings_tab: SettingsTab::Interface,
|
||||||
social_tab: SocialTab::Online,
|
social_tab: SocialTab::Online,
|
||||||
want_grab: true,
|
want_grab: true,
|
||||||
@ -509,7 +507,6 @@ impl Hud {
|
|||||||
force_chat_input: None,
|
force_chat_input: None,
|
||||||
force_chat_cursor: None,
|
force_chat_cursor: None,
|
||||||
pulse: 0.0,
|
pulse: 0.0,
|
||||||
zoom: 1.0,
|
|
||||||
velocity: 0.0,
|
velocity: 0.0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1590,10 +1587,9 @@ impl Hud {
|
|||||||
&self.show,
|
&self.show,
|
||||||
client,
|
client,
|
||||||
&self.imgs,
|
&self.imgs,
|
||||||
self.world_map,
|
&self.rot_imgs,
|
||||||
|
&self.world_map,
|
||||||
&self.fonts,
|
&self.fonts,
|
||||||
self.pulse,
|
|
||||||
self.zoom,
|
|
||||||
)
|
)
|
||||||
.set(self.ids.minimap, ui_widgets)
|
.set(self.ids.minimap, ui_widgets)
|
||||||
{
|
{
|
||||||
@ -1864,7 +1860,8 @@ impl Hud {
|
|||||||
&self.show,
|
&self.show,
|
||||||
client,
|
client,
|
||||||
&self.imgs,
|
&self.imgs,
|
||||||
self.world_map,
|
&self.rot_imgs,
|
||||||
|
&self.world_map,
|
||||||
&self.fonts,
|
&self.fonts,
|
||||||
self.pulse,
|
self.pulse,
|
||||||
self.velocity,
|
self.velocity,
|
||||||
|
@ -10,6 +10,7 @@ gfx_defines! {
|
|||||||
pos: [f32; 2] = "v_pos",
|
pos: [f32; 2] = "v_pos",
|
||||||
uv: [f32; 2] = "v_uv",
|
uv: [f32; 2] = "v_uv",
|
||||||
color: [f32; 4] = "v_color",
|
color: [f32; 4] = "v_color",
|
||||||
|
center: [f32; 2] = "v_center",
|
||||||
mode: u32 = "v_mode",
|
mode: u32 = "v_mode",
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,11 +56,23 @@ pub const MODE_TEXT: u32 = 0;
|
|||||||
pub const MODE_IMAGE: u32 = 1;
|
pub const MODE_IMAGE: u32 = 1;
|
||||||
/// Ignore `tex` and draw simple, colored 2D geometry.
|
/// Ignore `tex` and draw simple, colored 2D geometry.
|
||||||
pub const MODE_GEOMETRY: u32 = 2;
|
pub const MODE_GEOMETRY: u32 = 2;
|
||||||
|
/// Draw an image from the texture at `tex` in the fragment shader, with the
|
||||||
|
/// source rectangle rotated to face north.
|
||||||
|
///
|
||||||
|
/// FIXME: Make more principled.
|
||||||
|
pub const MODE_IMAGE_SOURCE_NORTH: u32 = 3;
|
||||||
|
/// Draw an image from the texture at `tex` in the fragment shader, with the
|
||||||
|
/// target rectangle rotated to face north.
|
||||||
|
///
|
||||||
|
/// FIXME: Make more principled.
|
||||||
|
pub const MODE_IMAGE_TARGET_NORTH: u32 = 5;
|
||||||
|
|
||||||
pub enum Mode {
|
pub enum Mode {
|
||||||
Text,
|
Text,
|
||||||
Image,
|
Image,
|
||||||
Geometry,
|
Geometry,
|
||||||
|
ImageSourceNorth,
|
||||||
|
ImageTargetNorth,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mode {
|
impl Mode {
|
||||||
@ -68,6 +81,8 @@ impl Mode {
|
|||||||
Mode::Text => MODE_TEXT,
|
Mode::Text => MODE_TEXT,
|
||||||
Mode::Image => MODE_IMAGE,
|
Mode::Image => MODE_IMAGE,
|
||||||
Mode::Geometry => MODE_GEOMETRY,
|
Mode::Geometry => MODE_GEOMETRY,
|
||||||
|
Mode::ImageSourceNorth => MODE_IMAGE_SOURCE_NORTH,
|
||||||
|
Mode::ImageTargetNorth => MODE_IMAGE_TARGET_NORTH,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -78,10 +93,16 @@ pub fn create_quad(
|
|||||||
color: Rgba<f32>,
|
color: Rgba<f32>,
|
||||||
mode: Mode,
|
mode: Mode,
|
||||||
) -> Quad<UiPipeline> {
|
) -> Quad<UiPipeline> {
|
||||||
|
let center = if let Mode::ImageSourceNorth = mode {
|
||||||
|
uv_rect.center().into_array()
|
||||||
|
} else {
|
||||||
|
rect.center().into_array()
|
||||||
|
};
|
||||||
let mode_val = mode.value();
|
let mode_val = mode.value();
|
||||||
let v = |pos, uv| Vertex {
|
let v = |pos, uv| Vertex {
|
||||||
pos,
|
pos,
|
||||||
uv,
|
uv,
|
||||||
|
center,
|
||||||
color: color.into_array(),
|
color: color.into_array(),
|
||||||
mode: mode_val,
|
mode: mode_val,
|
||||||
};
|
};
|
||||||
@ -118,10 +139,12 @@ pub fn create_tri(
|
|||||||
color: Rgba<f32>,
|
color: Rgba<f32>,
|
||||||
mode: Mode,
|
mode: Mode,
|
||||||
) -> Tri<UiPipeline> {
|
) -> Tri<UiPipeline> {
|
||||||
|
let center = [0.0, 0.0];
|
||||||
let mode_val = mode.value();
|
let mode_val = mode.value();
|
||||||
let v = |pos, uv| Vertex {
|
let v = |pos, uv| Vertex {
|
||||||
pos,
|
pos,
|
||||||
uv,
|
uv,
|
||||||
|
center,
|
||||||
color: color.into_array(),
|
color: color.into_array(),
|
||||||
mode: mode_val,
|
mode: mode_val,
|
||||||
};
|
};
|
||||||
|
@ -190,7 +190,7 @@ impl Camera {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the focus position of the camera.
|
/// Get the focus position of the camera.
|
||||||
pub fn get_focus_pos(&self) -> Vec3<f32> { self.tgt_focus }
|
pub fn get_focus_pos(&self) -> Vec3<f32> { self.focus }
|
||||||
|
|
||||||
/// Set the focus position of the camera.
|
/// Set the focus position of the camera.
|
||||||
pub fn set_focus_pos(&mut self, focus: Vec3<f32>) { self.tgt_focus = focus; }
|
pub fn set_focus_pos(&mut self, focus: Vec3<f32>) { self.tgt_focus = focus; }
|
||||||
|
@ -6,7 +6,7 @@ pub use renderer::{SampleStrat, Transform};
|
|||||||
use crate::render::{Renderer, Texture};
|
use crate::render::{Renderer, Texture};
|
||||||
use dot_vox::DotVoxData;
|
use dot_vox::DotVoxData;
|
||||||
use guillotiere::{size2, SimpleAtlasAllocator};
|
use guillotiere::{size2, SimpleAtlasAllocator};
|
||||||
use hashbrown::HashMap;
|
use hashbrown::{hash_map::Entry, HashMap};
|
||||||
use image::{DynamicImage, RgbaImage};
|
use image::{DynamicImage, RgbaImage};
|
||||||
use log::warn;
|
use log::warn;
|
||||||
use pixel_art::resize_pixel_art;
|
use pixel_art::resize_pixel_art;
|
||||||
@ -26,6 +26,14 @@ pub enum Rotation {
|
|||||||
Cw90,
|
Cw90,
|
||||||
Cw180,
|
Cw180,
|
||||||
Cw270,
|
Cw270,
|
||||||
|
/// Orientation of source rectangle that always faces true north.
|
||||||
|
/// Simple hack to get around Conrod not having space for proper
|
||||||
|
/// rotation data (though it should be possible to add in other ways).
|
||||||
|
SourceNorth,
|
||||||
|
/// Orientation of target rectangle that always faces true north.
|
||||||
|
/// Simple hack to get around Conrod not having space for proper
|
||||||
|
/// rotation data (though it should be possible to add in other ways).
|
||||||
|
TargetNorth,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Images larger than this are stored in individual textures
|
/// Images larger than this are stored in individual textures
|
||||||
@ -41,7 +49,7 @@ pub struct Id(u32);
|
|||||||
#[derive(PartialEq, Eq, Hash, Copy, Clone)]
|
#[derive(PartialEq, Eq, Hash, Copy, Clone)]
|
||||||
pub struct TexId(usize);
|
pub struct TexId(usize);
|
||||||
|
|
||||||
type Parameters = (Id, Vec2<u16>, Aabr<u64>);
|
type Parameters = (Id, Vec2<u16>);
|
||||||
type GraphicMap = HashMap<Id, Graphic>;
|
type GraphicMap = HashMap<Id, Graphic>;
|
||||||
|
|
||||||
enum CacheLoc {
|
enum CacheLoc {
|
||||||
@ -130,6 +138,8 @@ impl GraphicCache {
|
|||||||
self.textures = vec![texture];
|
self.textures = vec![texture];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Source rectangle should be from 0 to 1, and represents a bounding box
|
||||||
|
/// for the source image of the graphic.
|
||||||
pub fn cache_res(
|
pub fn cache_res(
|
||||||
&mut self,
|
&mut self,
|
||||||
renderer: &mut Renderer,
|
renderer: &mut Renderer,
|
||||||
@ -137,15 +147,18 @@ impl GraphicCache {
|
|||||||
dims: Vec2<u16>,
|
dims: Vec2<u16>,
|
||||||
source: Aabr<f64>,
|
source: Aabr<f64>,
|
||||||
rotation: Rotation,
|
rotation: Rotation,
|
||||||
) -> Option<(Aabr<u16>, TexId)> {
|
) -> Option<(Aabr<f64>, TexId)> {
|
||||||
let dims = match rotation {
|
let dims = match rotation {
|
||||||
Rotation::Cw90 | Rotation::Cw270 => Vec2::new(dims.y, dims.x),
|
Rotation::Cw90 | Rotation::Cw270 => Vec2::new(dims.y, dims.x),
|
||||||
Rotation::None | Rotation::Cw180 => dims,
|
Rotation::None | Rotation::Cw180 => dims,
|
||||||
|
Rotation::SourceNorth => dims,
|
||||||
|
Rotation::TargetNorth => dims,
|
||||||
};
|
};
|
||||||
let key = (graphic_id, dims, source.map(|e| e.to_bits())); // TODO: Replace this with rounded representation of source
|
let key = (graphic_id, dims);
|
||||||
|
|
||||||
|
// Rotate aabr according to requested rotation.
|
||||||
let rotated_aabr = |Aabr { min, max }| match rotation {
|
let rotated_aabr = |Aabr { min, max }| match rotation {
|
||||||
Rotation::None => Aabr { min, max },
|
Rotation::None | Rotation::SourceNorth | Rotation::TargetNorth => Aabr { min, max },
|
||||||
Rotation::Cw90 => Aabr {
|
Rotation::Cw90 => Aabr {
|
||||||
min: Vec2::new(min.x, max.y),
|
min: Vec2::new(min.x, max.y),
|
||||||
max: Vec2::new(max.x, min.y),
|
max: Vec2::new(max.x, min.y),
|
||||||
@ -156,101 +169,115 @@ impl GraphicCache {
|
|||||||
max: Vec2::new(min.x, max.y),
|
max: Vec2::new(min.x, max.y),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
// Scale aabr according to provided source rectangle.
|
||||||
|
let scaled_aabr = |aabr: Aabr<_>| {
|
||||||
|
let size: Vec2<_> = aabr.size().into();
|
||||||
|
Aabr {
|
||||||
|
min: size.mul_add(source.min, aabr.min),
|
||||||
|
max: size.mul_add(source.max, aabr.min),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// Apply all transformations.
|
||||||
|
// TODO: Verify rotation is being applied correctly.
|
||||||
|
let transformed_aabr = |aabr| rotated_aabr(scaled_aabr(aabr));
|
||||||
|
|
||||||
if let Some(details) = self.cache_map.get(&key) {
|
let details = match self.cache_map.entry(key) {
|
||||||
let (idx, aabr) = match details.location {
|
Entry::Occupied(details) => {
|
||||||
CacheLoc::Atlas {
|
let details = details.get();
|
||||||
atlas_idx, aabr, ..
|
let (idx, aabr) = match details.location {
|
||||||
} => (self.atlases[atlas_idx].1, aabr),
|
CacheLoc::Atlas {
|
||||||
CacheLoc::Texture { index } => {
|
atlas_idx, aabr, ..
|
||||||
(index, Aabr {
|
} => (self.atlases[atlas_idx].1, aabr),
|
||||||
min: Vec2::new(0, 0),
|
CacheLoc::Texture { index } => {
|
||||||
// Note texture should always match the cached dimensions
|
(index, Aabr {
|
||||||
max: dims,
|
min: Vec2::new(0, 0),
|
||||||
})
|
// Note texture should always match the cached dimensions
|
||||||
},
|
max: dims,
|
||||||
};
|
})
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
// Check if the cached version has been invalidated by replacing the underlying
|
// Check if the cached version has been invalidated by replacing the underlying
|
||||||
// graphic
|
// graphic
|
||||||
if !details.valid {
|
if !details.valid {
|
||||||
// Create image
|
// Create image
|
||||||
let image = draw_graphic(&self.graphic_map, graphic_id, dims)?;
|
let image = draw_graphic(&self.graphic_map, graphic_id, dims)?;
|
||||||
// Transfer to the gpu
|
// Transfer to the gpu
|
||||||
upload_image(renderer, aabr, &self.textures[idx], &image);
|
upload_image(renderer, aabr, &self.textures[idx], &image);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Some((transformed_aabr(aabr.map(|e| e as f64)), TexId(idx)));
|
||||||
|
},
|
||||||
|
Entry::Vacant(details) => details,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create image
|
||||||
|
let image = draw_graphic(&self.graphic_map, graphic_id, dims)?;
|
||||||
|
|
||||||
|
// Allocate space on the gpu
|
||||||
|
// Check size of graphic
|
||||||
|
// Graphics over a particular size are sent to their own textures
|
||||||
|
let location = if Vec2::<i32>::from(self.atlases[0].0.size().to_tuple())
|
||||||
|
.map(|e| e as u16)
|
||||||
|
.map2(dims, |a, d| a as f32 * ATLAS_CUTTOFF_FRAC >= d as f32)
|
||||||
|
.reduce_and()
|
||||||
|
{
|
||||||
|
// Fit into an atlas
|
||||||
|
let mut loc = None;
|
||||||
|
for (atlas_idx, (ref mut atlas, _)) in self.atlases.iter_mut().enumerate() {
|
||||||
|
if let Some(rectangle) = atlas.allocate(size2(i32::from(dims.x), i32::from(dims.y)))
|
||||||
|
{
|
||||||
|
let aabr = aabr_from_alloc_rect(rectangle);
|
||||||
|
loc = Some(CacheLoc::Atlas { atlas_idx, aabr });
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Some((rotated_aabr(aabr), TexId(idx)))
|
match loc {
|
||||||
} else {
|
Some(loc) => loc,
|
||||||
// Create image
|
// Create a new atlas
|
||||||
let image = draw_graphic(&self.graphic_map, graphic_id, dims)?;
|
None => {
|
||||||
|
let (mut atlas, texture) = create_atlas_texture(renderer);
|
||||||
// Allocate space on the gpu
|
let aabr = atlas
|
||||||
// Check size of graphic
|
.allocate(size2(i32::from(dims.x), i32::from(dims.y)))
|
||||||
// Graphics over a particular size are sent to their own textures
|
.map(aabr_from_alloc_rect)
|
||||||
let location = if Vec2::<i32>::from(self.atlases[0].0.size().to_tuple())
|
.unwrap();
|
||||||
.map(|e| e as u16)
|
let tex_idx = self.textures.len();
|
||||||
.map2(dims, |a, d| a as f32 * ATLAS_CUTTOFF_FRAC >= d as f32)
|
let atlas_idx = self.atlases.len();
|
||||||
.reduce_and()
|
self.textures.push(texture);
|
||||||
{
|
self.atlases.push((atlas, tex_idx));
|
||||||
// Fit into an atlas
|
CacheLoc::Atlas { atlas_idx, aabr }
|
||||||
let mut loc = None;
|
|
||||||
for (atlas_idx, (ref mut atlas, _)) in self.atlases.iter_mut().enumerate() {
|
|
||||||
if let Some(rectangle) =
|
|
||||||
atlas.allocate(size2(i32::from(dims.x), i32::from(dims.y)))
|
|
||||||
{
|
|
||||||
let aabr = aabr_from_alloc_rect(rectangle);
|
|
||||||
loc = Some(CacheLoc::Atlas { atlas_idx, aabr });
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match loc {
|
|
||||||
Some(loc) => loc,
|
|
||||||
// Create a new atlas
|
|
||||||
None => {
|
|
||||||
let (mut atlas, texture) = create_atlas_texture(renderer);
|
|
||||||
let aabr = atlas
|
|
||||||
.allocate(size2(i32::from(dims.x), i32::from(dims.y)))
|
|
||||||
.map(aabr_from_alloc_rect)
|
|
||||||
.unwrap();
|
|
||||||
let tex_idx = self.textures.len();
|
|
||||||
let atlas_idx = self.atlases.len();
|
|
||||||
self.textures.push(texture);
|
|
||||||
self.atlases.push((atlas, tex_idx));
|
|
||||||
CacheLoc::Atlas { atlas_idx, aabr }
|
|
||||||
},
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Create a texture just for this
|
|
||||||
let texture = renderer.create_dynamic_texture(dims).unwrap();
|
|
||||||
let index = self.textures.len();
|
|
||||||
self.textures.push(texture);
|
|
||||||
CacheLoc::Texture { index }
|
|
||||||
};
|
|
||||||
|
|
||||||
let (idx, aabr) = match location {
|
|
||||||
CacheLoc::Atlas {
|
|
||||||
atlas_idx, aabr, ..
|
|
||||||
} => (self.atlases[atlas_idx].1, aabr),
|
|
||||||
CacheLoc::Texture { index } => {
|
|
||||||
(index, Aabr {
|
|
||||||
min: Vec2::new(0, 0),
|
|
||||||
// Note texture should always match the cached dimensions
|
|
||||||
max: dims,
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
// Upload
|
} else {
|
||||||
upload_image(renderer, aabr, &self.textures[idx], &image);
|
// Create a texture just for this
|
||||||
// Insert into cached map
|
let texture = renderer.create_dynamic_texture(dims).unwrap();
|
||||||
self.cache_map.insert(key, CachedDetails {
|
let index = self.textures.len();
|
||||||
location,
|
self.textures.push(texture);
|
||||||
valid: true,
|
CacheLoc::Texture { index }
|
||||||
});
|
};
|
||||||
|
|
||||||
Some((rotated_aabr(aabr), TexId(idx)))
|
let (idx, aabr) = match location {
|
||||||
}
|
CacheLoc::Atlas {
|
||||||
|
atlas_idx, aabr, ..
|
||||||
|
} => (self.atlases[atlas_idx].1, aabr),
|
||||||
|
CacheLoc::Texture { index } => {
|
||||||
|
(index, Aabr {
|
||||||
|
min: Vec2::new(0, 0),
|
||||||
|
// Note texture should always match the cached dimensions
|
||||||
|
max: dims,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
};
|
||||||
|
// Upload
|
||||||
|
upload_image(renderer, aabr, &self.textures[idx], &image);
|
||||||
|
// Insert into cached map
|
||||||
|
details.insert(CachedDetails {
|
||||||
|
location,
|
||||||
|
valid: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
Some((transformed_aabr(aabr.map(|e| e as f64)), TexId(idx)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,6 +106,8 @@ pub struct Rotations {
|
|||||||
pub cw90: conrod_core::image::Id,
|
pub cw90: conrod_core::image::Id,
|
||||||
pub cw180: conrod_core::image::Id,
|
pub cw180: conrod_core::image::Id,
|
||||||
pub cw270: conrod_core::image::Id,
|
pub cw270: conrod_core::image::Id,
|
||||||
|
pub source_north: conrod_core::image::Id,
|
||||||
|
pub target_north: conrod_core::image::Id,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This macro will automatically load all specified assets, get the
|
/// This macro will automatically load all specified assets, get the
|
||||||
|
@ -28,6 +28,7 @@ use crate::{
|
|||||||
window::Window,
|
window::Window,
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
|
use ::image::GenericImageView;
|
||||||
use cache::Cache;
|
use cache::Cache;
|
||||||
use common::{assets, util::srgba_to_linear};
|
use common::{assets, util::srgba_to_linear};
|
||||||
use conrod_core::{
|
use conrod_core::{
|
||||||
@ -43,6 +44,7 @@ use conrod_core::{
|
|||||||
use graphic::{Rotation, TexId};
|
use graphic::{Rotation, TexId};
|
||||||
use log::{error, warn};
|
use log::{error, warn};
|
||||||
use std::{
|
use std::{
|
||||||
|
f32, f64,
|
||||||
fs::File,
|
fs::File,
|
||||||
io::{BufReader, Read},
|
io::{BufReader, Read},
|
||||||
ops::Range,
|
ops::Range,
|
||||||
@ -172,6 +174,16 @@ impl Ui {
|
|||||||
cw90: self.image_map.insert((graphic_id, Rotation::Cw90)),
|
cw90: self.image_map.insert((graphic_id, Rotation::Cw90)),
|
||||||
cw180: self.image_map.insert((graphic_id, Rotation::Cw180)),
|
cw180: self.image_map.insert((graphic_id, Rotation::Cw180)),
|
||||||
cw270: self.image_map.insert((graphic_id, Rotation::Cw270)),
|
cw270: self.image_map.insert((graphic_id, Rotation::Cw270)),
|
||||||
|
// Hacky way to make sure a source rectangle always faces north regardless of player
|
||||||
|
// orientation.
|
||||||
|
// This is an easy way to get around Conrod's lack of rotation data for images (for this
|
||||||
|
// specific use case).
|
||||||
|
source_north: self.image_map.insert((graphic_id, Rotation::SourceNorth)),
|
||||||
|
// Hacky way to make sure a target rectangle always faces north regardless of player
|
||||||
|
// orientation.
|
||||||
|
// This is an easy way to get around Conrod's lack of rotation data for images (for this
|
||||||
|
// specific use case).
|
||||||
|
target_north: self.image_map.insert((graphic_id, Rotation::TargetNorth)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -420,46 +432,88 @@ impl Ui {
|
|||||||
PrimitiveKind::Image {
|
PrimitiveKind::Image {
|
||||||
image_id,
|
image_id,
|
||||||
color,
|
color,
|
||||||
source_rect: _, // TODO: <-- use this
|
source_rect,
|
||||||
} => {
|
} => {
|
||||||
let (graphic_id, rotation) = self
|
let (graphic_id, rotation) = self
|
||||||
.image_map
|
.image_map
|
||||||
.get(&image_id)
|
.get(&image_id)
|
||||||
.expect("Image does not exist in image map");
|
.expect("Image does not exist in image map");
|
||||||
let graphic_cache = self.cache.graphic_cache_mut();
|
let graphic_cache = self.cache.graphic_cache_mut();
|
||||||
|
let gl_aabr = gl_aabr(rect);
|
||||||
match graphic_cache.get_graphic(*graphic_id) {
|
let (source_aabr, gl_size) = {
|
||||||
Some(Graphic::Blank) | None => continue,
|
// Transform the source rectangle into uv coordinate.
|
||||||
_ => {},
|
// TODO: Make sure this is right. Especially the conversions.
|
||||||
}
|
let ((uv_l, uv_r, uv_b, uv_t), gl_size) =
|
||||||
|
match graphic_cache.get_graphic(*graphic_id) {
|
||||||
|
Some(Graphic::Blank) | None => continue,
|
||||||
|
Some(Graphic::Image(image)) => {
|
||||||
|
source_rect.and_then(|src_rect| {
|
||||||
|
let (image_w, image_h) = image.dimensions();
|
||||||
|
let (source_w, source_h) = src_rect.w_h();
|
||||||
|
let gl_size = gl_aabr.size();
|
||||||
|
if image_w == 0
|
||||||
|
|| image_h == 0
|
||||||
|
|| source_w < 1.0
|
||||||
|
|| source_h < 1.0
|
||||||
|
|| gl_size.reduce_partial_max() < f32::EPSILON
|
||||||
|
{
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
// Multiply drawn image size by ratio of original image
|
||||||
|
// size to
|
||||||
|
// source rectangle size (since as the proportion of the
|
||||||
|
// image gets
|
||||||
|
// smaller, the drawn size should get bigger), up to the
|
||||||
|
// actual
|
||||||
|
// size of the original image.
|
||||||
|
let ratio_x = (image_w as f64 / source_w).min(
|
||||||
|
(image_w as f64 / (gl_size.w * half_res.x) as f64)
|
||||||
|
.max(1.0),
|
||||||
|
);
|
||||||
|
let ratio_y = (image_h as f64 / source_h).min(
|
||||||
|
(image_h as f64 / (gl_size.h * half_res.y) as f64)
|
||||||
|
.max(1.0),
|
||||||
|
);
|
||||||
|
let (l, r, b, t) = src_rect.l_r_b_t();
|
||||||
|
Some((
|
||||||
|
(
|
||||||
|
l / image_w as f64, /* * ratio_x*/
|
||||||
|
r / image_w as f64, /* * ratio_x*/
|
||||||
|
b / image_h as f64, /* * ratio_y*/
|
||||||
|
t / image_h as f64, /* * ratio_y*/
|
||||||
|
),
|
||||||
|
Extent2::new(
|
||||||
|
(gl_size.w as f64 * ratio_x) as f32,
|
||||||
|
(gl_size.h as f64 * ratio_y) as f32,
|
||||||
|
),
|
||||||
|
))
|
||||||
|
/* ((l / image_w as f64),
|
||||||
|
(r / image_w as f64),
|
||||||
|
(b / image_h as f64),
|
||||||
|
(t / image_h as f64)) */
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// No easy way to interpret source_rect for voxels...
|
||||||
|
Some(Graphic::Voxel(..)) => None,
|
||||||
|
}
|
||||||
|
.unwrap_or_else(|| ((0.0, 1.0, 0.0, 1.0), gl_aabr.size()));
|
||||||
|
(
|
||||||
|
Aabr {
|
||||||
|
min: Vec2::new(uv_l, uv_b),
|
||||||
|
max: Vec2::new(uv_r, uv_t),
|
||||||
|
},
|
||||||
|
gl_size,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
let color =
|
let color =
|
||||||
srgba_to_linear(color.unwrap_or(conrod_core::color::WHITE).to_fsa().into());
|
srgba_to_linear(color.unwrap_or(conrod_core::color::WHITE).to_fsa().into());
|
||||||
|
|
||||||
let gl_aabr = gl_aabr(rect);
|
|
||||||
let resolution = Vec2::new(
|
let resolution = Vec2::new(
|
||||||
(gl_aabr.size().w * half_res.x).round() as u16,
|
(gl_size.w * half_res.x).round() as u16,
|
||||||
(gl_aabr.size().h * half_res.y).round() as u16,
|
(gl_size.h * half_res.y).round() as u16,
|
||||||
);
|
);
|
||||||
// Transform the source rectangle into uv coordinate.
|
|
||||||
// TODO: Make sure this is right.
|
|
||||||
let source_aabr = {
|
|
||||||
let (uv_l, uv_r, uv_b, uv_t) = (0.0, 1.0, 0.0, 1.0);
|
|
||||||
/*match source_rect {
|
|
||||||
Some(src_rect) => {
|
|
||||||
let (l, r, b, t) = src_rect.l_r_b_t();
|
|
||||||
((l / image_w) as f32,
|
|
||||||
(r / image_w) as f32,
|
|
||||||
(b / image_h) as f32,
|
|
||||||
(t / image_h) as f32)
|
|
||||||
}
|
|
||||||
None => (0.0, 1.0, 0.0, 1.0),
|
|
||||||
};*/
|
|
||||||
Aabr {
|
|
||||||
min: Vec2::new(uv_l, uv_b),
|
|
||||||
max: Vec2::new(uv_r, uv_t),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Cache graphic at particular resolution.
|
// Cache graphic at particular resolution.
|
||||||
let (uv_aabr, tex_id) = match graphic_cache.cache_res(
|
let (uv_aabr, tex_id) = match graphic_cache.cache_res(
|
||||||
@ -500,7 +554,13 @@ impl Ui {
|
|||||||
State::Image(_) => {},
|
State::Image(_) => {},
|
||||||
}
|
}
|
||||||
|
|
||||||
mesh.push_quad(create_ui_quad(gl_aabr, uv_aabr, color, UiMode::Image));
|
mesh.push_quad(create_ui_quad(gl_aabr, uv_aabr, color, match *rotation {
|
||||||
|
Rotation::None | Rotation::Cw90 | Rotation::Cw180 | Rotation::Cw270 => {
|
||||||
|
UiMode::Image
|
||||||
|
},
|
||||||
|
Rotation::SourceNorth => UiMode::ImageSourceNorth,
|
||||||
|
Rotation::TargetNorth => UiMode::ImageTargetNorth,
|
||||||
|
}));
|
||||||
},
|
},
|
||||||
PrimitiveKind::Text {
|
PrimitiveKind::Text {
|
||||||
color,
|
color,
|
||||||
|
@ -239,6 +239,9 @@ impl MapConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let water_color_factor = 2.0;
|
||||||
|
let g_water = 32.0 * water_color_factor;
|
||||||
|
let b_water = 64.0 * water_color_factor;
|
||||||
let rgba = match (river_kind, (is_water, true_alt >= true_sea_level)) {
|
let rgba = match (river_kind, (is_water, true_alt >= true_sea_level)) {
|
||||||
(_, (false, _)) | (None, (_, true)) => {
|
(_, (false, _)) | (None, (_, true)) => {
|
||||||
let (r, g, b) = (
|
let (r, g, b) = (
|
||||||
@ -251,7 +254,7 @@ impl MapConfig {
|
|||||||
0.0
|
0.0
|
||||||
})
|
})
|
||||||
.sqrt(),
|
.sqrt(),
|
||||||
if is_shaded { 0.2 + (alt * 0.8) } else { alt },
|
if is_shaded { 0.4 + (alt * 0.6) } else { alt },
|
||||||
(if is_shaded { alt } else { alt }
|
(if is_shaded { alt } else { alt }
|
||||||
* if is_humidity {
|
* if is_humidity {
|
||||||
humidity as f64
|
humidity as f64
|
||||||
@ -272,17 +275,22 @@ impl MapConfig {
|
|||||||
},
|
},
|
||||||
(Some(RiverKind::Ocean), _) => (
|
(Some(RiverKind::Ocean), _) => (
|
||||||
0,
|
0,
|
||||||
((32.0 - water_depth * 32.0) * 1.0) as u8,
|
((g_water - water_depth * g_water) * 1.0) as u8,
|
||||||
((64.0 - water_depth * 64.0) * 1.0) as u8,
|
((b_water - water_depth * b_water) * 1.0) as u8,
|
||||||
|
255,
|
||||||
|
),
|
||||||
|
(Some(RiverKind::River { .. }), _) => (
|
||||||
|
0,
|
||||||
|
g_water as u8 + (alt * (127.0 - g_water)) as u8,
|
||||||
|
b_water as u8 + (alt * (255.0 - b_water)) as u8,
|
||||||
255,
|
255,
|
||||||
),
|
),
|
||||||
(Some(RiverKind::River { .. }), _) => {
|
|
||||||
(0, 32 + (alt * 95.0) as u8, 64 + (alt * 191.0) as u8, 255)
|
|
||||||
},
|
|
||||||
(None, _) | (Some(RiverKind::Lake { .. }), _) => (
|
(None, _) | (Some(RiverKind::Lake { .. }), _) => (
|
||||||
0,
|
0,
|
||||||
(((32.0 + water_alt * 95.0) + (-water_depth * 32.0)) * 1.0) as u8,
|
(((g_water + water_alt * (127.0 - 32.0)) + (-water_depth * g_water)) * 1.0)
|
||||||
(((64.0 + water_alt * 191.0) + (-water_depth * 64.0)) * 1.0) as u8,
|
as u8,
|
||||||
|
(((b_water + water_alt * (255.0 - b_water)) + (-water_depth * b_water))
|
||||||
|
* 1.0) as u8,
|
||||||
255,
|
255,
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
@ -292,6 +292,9 @@ impl WorldFile {
|
|||||||
|
|
||||||
pub struct WorldSim {
|
pub struct WorldSim {
|
||||||
pub seed: u32,
|
pub seed: u32,
|
||||||
|
/// Maximum height above sea level of any chunk in the map (not including
|
||||||
|
/// post-erosion warping, cliffs, and other things like that).
|
||||||
|
pub max_height: f32,
|
||||||
pub(crate) chunks: Vec<SimChunk>,
|
pub(crate) chunks: Vec<SimChunk>,
|
||||||
pub(crate) locations: Vec<Location>,
|
pub(crate) locations: Vec<Location>,
|
||||||
|
|
||||||
@ -1288,6 +1291,7 @@ impl WorldSim {
|
|||||||
|
|
||||||
let mut this = Self {
|
let mut this = Self {
|
||||||
seed,
|
seed,
|
||||||
|
max_height: maxh as f32,
|
||||||
chunks,
|
chunks,
|
||||||
locations: Vec::new(),
|
locations: Vec::new(),
|
||||||
gen_ctx,
|
gen_ctx,
|
||||||
@ -1306,7 +1310,11 @@ impl WorldSim {
|
|||||||
pub fn get_map(&self) -> Vec<u32> {
|
pub fn get_map(&self) -> Vec<u32> {
|
||||||
let mut v = vec![0u32; WORLD_SIZE.x * WORLD_SIZE.y];
|
let mut v = vec![0u32; WORLD_SIZE.x * WORLD_SIZE.y];
|
||||||
// TODO: Parallelize again.
|
// TODO: Parallelize again.
|
||||||
MapConfig::default().generate(&self, |pos, (r, g, b, a)| {
|
MapConfig {
|
||||||
|
gain: self.max_height,
|
||||||
|
..MapConfig::default()
|
||||||
|
}
|
||||||
|
.generate(&self, |pos, (r, g, b, a)| {
|
||||||
v[pos.y * WORLD_SIZE.x + pos.x] = u32::from_le_bytes([r, g, b, a]);
|
v[pos.y * WORLD_SIZE.x + pos.x] = u32::from_le_bytes([r, g, b, a]);
|
||||||
});
|
});
|
||||||
v
|
v
|
||||||
|
Loading…
Reference in New Issue
Block a user