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 music system
|
||||
- Added zoomable and rotatable minimap
|
||||
- Added rotating orientation marker to main-map
|
||||
|
||||
### Changed
|
||||
- Brighter / higher contrast main-map
|
||||
|
||||
### 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)) {
|
||||
tgt_color = f_color * vec4(1.0, 1.0, 1.0, texture(u_tex, f_uv).a);
|
||||
// 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);
|
||||
// 2D Geometry
|
||||
} else if (f_mode == uint(2)) {
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
in vec2 v_pos;
|
||||
in vec2 v_uv;
|
||||
in vec2 v_center;
|
||||
in vec4 v_color;
|
||||
in uint v_mode;
|
||||
|
||||
@ -19,15 +20,31 @@ flat out uint f_mode;
|
||||
out vec4 f_color;
|
||||
|
||||
void main() {
|
||||
f_uv = v_uv;
|
||||
f_color = v_color;
|
||||
|
||||
if (w_pos.w == 1.0) {
|
||||
f_uv = v_uv;
|
||||
// Fixed scale In-game element
|
||||
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);
|
||||
} 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 {
|
||||
// Interface element
|
||||
f_uv = v_uv;
|
||||
gl_Position = vec4(v_pos, 0.0, 1.0);
|
||||
}
|
||||
f_mode = v_mode;
|
||||
|
@ -8,6 +8,13 @@ rotation_image_ids! {
|
||||
// Tooltip Test
|
||||
tt_side: "voxygen/element/frames/tt_test_edge",
|
||||
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",
|
||||
|
||||
// Map
|
||||
map_indicator: "voxygen.element.buttons.map_indicator",
|
||||
indicator_mmap: "voxygen.element.buttons.indicator_mmap",
|
||||
indicator_mmap_2: "voxygen.element.buttons.indicator_mmap_2",
|
||||
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_plus: "voxygen.element.buttons.min_plus.mmap_button-plus",
|
||||
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_hover: "voxygen.element.buttons.min_plus.mmap_button-min_hover",
|
||||
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 common::{comp, terrain::TerrainChunkSize, vol::RectVolSize};
|
||||
use conrod_core::{
|
||||
color,
|
||||
image::Id,
|
||||
widget::{self, Button, Image, Rectangle, Text},
|
||||
widget_ids, Color, Colorable, Positionable, Sizeable, Widget, WidgetCommon,
|
||||
};
|
||||
@ -30,12 +33,13 @@ widget_ids! {
|
||||
pub struct Map<'a> {
|
||||
_show: &'a Show,
|
||||
client: &'a Client,
|
||||
world_map: (Id, Vec2<u32>),
|
||||
world_map: &'a (img_ids::Rotations, Vec2<u32>),
|
||||
imgs: &'a Imgs,
|
||||
rot_imgs: &'a ImgsRot,
|
||||
fonts: &'a Fonts,
|
||||
#[conrod(common_builder)]
|
||||
common: widget::CommonBuilder,
|
||||
pulse: f32,
|
||||
_pulse: f32,
|
||||
velocity: f32,
|
||||
}
|
||||
impl<'a> Map<'a> {
|
||||
@ -43,7 +47,8 @@ impl<'a> Map<'a> {
|
||||
show: &'a Show,
|
||||
client: &'a Client,
|
||||
imgs: &'a Imgs,
|
||||
world_map: (Id, Vec2<u32>),
|
||||
rot_imgs: &'a ImgsRot,
|
||||
world_map: &'a (img_ids::Rotations, Vec2<u32>),
|
||||
fonts: &'a Fonts,
|
||||
pulse: f32,
|
||||
velocity: f32,
|
||||
@ -51,11 +56,12 @@ impl<'a> Map<'a> {
|
||||
Self {
|
||||
_show: show,
|
||||
imgs,
|
||||
rot_imgs,
|
||||
world_map,
|
||||
client,
|
||||
fonts,
|
||||
common: widget::CommonBuilder::default(),
|
||||
pulse,
|
||||
_pulse: pulse,
|
||||
velocity,
|
||||
}
|
||||
}
|
||||
@ -160,9 +166,9 @@ impl<'a> Widget for Map<'a> {
|
||||
let (world_map, worldsize) = self.world_map;
|
||||
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)
|
||||
.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)
|
||||
.parent(state.ids.map_bg)
|
||||
.set(state.ids.grid, ui);
|
||||
@ -177,28 +183,15 @@ impl<'a> Widget for Map<'a> {
|
||||
|
||||
let x = player_pos.x as f64 / worldsize.x * 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 = 1.2;
|
||||
// Indicator
|
||||
Image::new(if indic_ani <= 0.3 {
|
||||
self.imgs.indicator_mmap
|
||||
} else if indic_ani <= 0.6 {
|
||||
self.imgs.indicator_mmap_2
|
||||
} else {
|
||||
self.imgs.indicator_mmap_3
|
||||
})
|
||||
.bottom_left_with_margins_on(state.ids.grid, y, x - (20.0 * 1.2) / 2.0)
|
||||
.w_h(
|
||||
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
|
||||
},
|
||||
let indic_scale = 0.6;
|
||||
Image::new(self.rot_imgs.indicator_mmap_small.target_north)
|
||||
.bottom_left_with_margins_on(
|
||||
state.ids.grid,
|
||||
y - 37.0 * indic_scale / 2.0,
|
||||
x - 32.0 * indic_scale / 2.0,
|
||||
)
|
||||
.color(Some(Color::Rgba(1.0, 1.0, 1.0, fade + 0.2)))
|
||||
.w_h(32.0 * indic_scale, 37.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);
|
||||
|
@ -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 common::{comp, terrain::TerrainChunkSize, vol::RectVolSize};
|
||||
use conrod_core::{
|
||||
color,
|
||||
image::Id,
|
||||
color, position,
|
||||
widget::{self, Button, Image, Rectangle, Text},
|
||||
widget_ids, Color, Colorable, Positionable, Sizeable, Widget, WidgetCommon,
|
||||
};
|
||||
@ -33,12 +36,11 @@ pub struct MiniMap<'a> {
|
||||
client: &'a Client,
|
||||
|
||||
imgs: &'a Imgs,
|
||||
world_map: (Id, Vec2<u32>),
|
||||
rot_imgs: &'a ImgsRot,
|
||||
world_map: &'a (img_ids::Rotations, Vec2<u32>),
|
||||
fonts: &'a Fonts,
|
||||
#[conrod(common_builder)]
|
||||
common: widget::CommonBuilder,
|
||||
pulse: f32,
|
||||
zoom: f32,
|
||||
}
|
||||
|
||||
impl<'a> MiniMap<'a> {
|
||||
@ -46,20 +48,18 @@ impl<'a> MiniMap<'a> {
|
||||
show: &'a Show,
|
||||
client: &'a Client,
|
||||
imgs: &'a Imgs,
|
||||
world_map: (Id, Vec2<u32>),
|
||||
rot_imgs: &'a ImgsRot,
|
||||
world_map: &'a (img_ids::Rotations, Vec2<u32>),
|
||||
fonts: &'a Fonts,
|
||||
pulse: f32,
|
||||
zoom: f32,
|
||||
) -> Self {
|
||||
Self {
|
||||
show,
|
||||
client,
|
||||
imgs,
|
||||
rot_imgs,
|
||||
world_map,
|
||||
fonts,
|
||||
common: widget::CommonBuilder::default(),
|
||||
pulse,
|
||||
zoom,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -69,6 +69,7 @@ pub struct State {
|
||||
|
||||
last_region_name: Option<String>,
|
||||
last_update: Instant,
|
||||
zoom: f64,
|
||||
}
|
||||
|
||||
pub enum Event {
|
||||
@ -86,6 +87,14 @@ impl<'a> Widget for MiniMap<'a> {
|
||||
|
||||
last_region_name: None,
|
||||
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 {
|
||||
let widget::UpdateArgs { state, ui, .. } = args;
|
||||
let zoom = self.zoom as f64;
|
||||
let zoom = state.zoom;
|
||||
if self.show.mini_map {
|
||||
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)
|
||||
.set(state.ids.mmap_frame, ui);
|
||||
|
||||
Rectangle::fill_with([92.0 * 4.0, 82.0 * 4.0], color::TRANSPARENT)
|
||||
.mid_top_with_margin_on(state.ids.mmap_frame, 13.0 * 4.0 + 4.0 * zoom)
|
||||
Rectangle::fill_with([92.0 * 3.0, 82.0 * 3.0], color::TRANSPARENT)
|
||||
.mid_top_with_margin_on(state.ids.mmap_frame, 13.0 * 3.0 + 3.0)
|
||||
.set(state.ids.mmap_frame_bg, ui);
|
||||
// Zoom Buttons
|
||||
// TODO: Add zoomable minimap
|
||||
|
||||
/*if Button::image(self.imgs.mmap_plus)
|
||||
.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
|
||||
// Map size
|
||||
let (world_map, worldsize) = self.world_map;
|
||||
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)
|
||||
.w_h(92.0 * 4.0 * zoom, 82.0 * 4.0 * zoom)
|
||||
.parent(state.ids.mmap_frame_bg)
|
||||
.set(state.ids.grid, ui);
|
||||
|
||||
// Zoom Buttons
|
||||
|
||||
// Pressing + multiplies, and - divides, zoom by ZOOM_FACTOR.
|
||||
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
|
||||
let player_pos = self
|
||||
.client
|
||||
@ -149,26 +179,32 @@ impl<'a> Widget for MiniMap<'a> {
|
||||
.get(self.client.entity())
|
||||
.map_or(Vec3::zero(), |pos| pos.0);
|
||||
|
||||
let x = player_pos.x as f64 / worldsize.x * 92.0 * 4.0;
|
||||
let y = player_pos.y as f64 / worldsize.y * 82.0 * 4.0;
|
||||
let indic_ani = (self.pulse * 6.0).cos() * 0.5 + 0.5; //Animation timer
|
||||
let indic_scale = 0.8;
|
||||
// Get map image source rectangle dimensons.
|
||||
let w_src = worldsize.x / TerrainChunkSize::RECT_SIZE.x as f64 / zoom;
|
||||
let h_src = worldsize.y / TerrainChunkSize::RECT_SIZE.y as f64 / zoom;
|
||||
|
||||
// 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
|
||||
Image::new(if indic_ani <= 0.5 {
|
||||
self.imgs.indicator_mmap
|
||||
} else {
|
||||
self.imgs.indicator_mmap_2
|
||||
})
|
||||
.bottom_left_with_margins_on(state.ids.grid, y, x - 5.0)
|
||||
.w_h(
|
||||
// Animation frames depening on timer value from 0.0 to 1.0
|
||||
22.0 * 0.8,
|
||||
if indic_ani <= 0.5 {
|
||||
18.0 * indic_scale
|
||||
} else {
|
||||
23.0 * indic_scale
|
||||
},
|
||||
)
|
||||
let ind_scale = 0.4;
|
||||
Image::new(self.rot_imgs.indicator_mmap_small.none)
|
||||
.middle_of(state.ids.grid)
|
||||
.w_h(32.0 * ind_scale, 37.0 * ind_scale)
|
||||
.color(Some(Color::Rgba(1.0, 1.0, 1.0, 1.0)))
|
||||
.floating(true)
|
||||
.parent(ui.window)
|
||||
@ -186,9 +222,9 @@ impl<'a> Widget for MiniMap<'a> {
|
||||
self.imgs.mmap_closed
|
||||
})
|
||||
.wh(if self.show.mini_map {
|
||||
[100.0 * 0.4; 2]
|
||||
[100.0 * 0.3; 2]
|
||||
} else {
|
||||
[100.0 * 0.2 * zoom; 2]
|
||||
[100.0 * 0.2; 2]
|
||||
})
|
||||
.hover_image(if self.show.mini_map {
|
||||
self.imgs.mmap_open_hover
|
||||
@ -267,7 +303,7 @@ impl<'a> Widget for MiniMap<'a> {
|
||||
state.ids.mmap_frame,
|
||||
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)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.mmap_location, ui),
|
||||
|
@ -13,7 +13,7 @@ mod skillbar;
|
||||
mod social;
|
||||
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;
|
||||
use std::time::Duration;
|
||||
|
||||
@ -46,7 +46,6 @@ use crate::{
|
||||
use client::{Client, Event as ClientEvent};
|
||||
use common::{assets::load_expect, comp, terrain::TerrainChunk, vol::RectRasterableVol};
|
||||
use conrod_core::{
|
||||
image::Id,
|
||||
text::cursor::Index,
|
||||
widget::{self, Button, Image, Rectangle, Text},
|
||||
widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, Widget,
|
||||
@ -307,7 +306,7 @@ impl Show {
|
||||
fn map(&mut self, open: bool) {
|
||||
self.map = open;
|
||||
self.bag = false;
|
||||
self.want_grab = !open;
|
||||
self.want_grab = true;
|
||||
}
|
||||
|
||||
fn character_window(&mut self, open: bool) {
|
||||
@ -431,7 +430,7 @@ impl Show {
|
||||
pub struct Hud {
|
||||
ui: Ui,
|
||||
ids: Ids,
|
||||
world_map: (Id, Vec2<u32>),
|
||||
world_map: (/* Id */ Rotations, Vec2<u32>),
|
||||
imgs: Imgs,
|
||||
item_imgs: ItemImgs,
|
||||
fonts: Fonts,
|
||||
@ -446,7 +445,6 @@ pub struct Hud {
|
||||
force_chat_input: Option<String>,
|
||||
force_chat_cursor: Option<Index>,
|
||||
pulse: f32,
|
||||
zoom: f32,
|
||||
velocity: f32,
|
||||
}
|
||||
|
||||
@ -461,7 +459,7 @@ impl Hud {
|
||||
let ids = Ids::new(ui.id_generator());
|
||||
// Load 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,
|
||||
);
|
||||
// Load images.
|
||||
@ -497,7 +495,7 @@ impl Hud {
|
||||
quest: false,
|
||||
spell: false,
|
||||
character_window: false,
|
||||
mini_map: false,
|
||||
mini_map: true,
|
||||
settings_tab: SettingsTab::Interface,
|
||||
social_tab: SocialTab::Online,
|
||||
want_grab: true,
|
||||
@ -509,7 +507,6 @@ impl Hud {
|
||||
force_chat_input: None,
|
||||
force_chat_cursor: None,
|
||||
pulse: 0.0,
|
||||
zoom: 1.0,
|
||||
velocity: 0.0,
|
||||
}
|
||||
}
|
||||
@ -1590,10 +1587,9 @@ impl Hud {
|
||||
&self.show,
|
||||
client,
|
||||
&self.imgs,
|
||||
self.world_map,
|
||||
&self.rot_imgs,
|
||||
&self.world_map,
|
||||
&self.fonts,
|
||||
self.pulse,
|
||||
self.zoom,
|
||||
)
|
||||
.set(self.ids.minimap, ui_widgets)
|
||||
{
|
||||
@ -1864,7 +1860,8 @@ impl Hud {
|
||||
&self.show,
|
||||
client,
|
||||
&self.imgs,
|
||||
self.world_map,
|
||||
&self.rot_imgs,
|
||||
&self.world_map,
|
||||
&self.fonts,
|
||||
self.pulse,
|
||||
self.velocity,
|
||||
|
@ -10,6 +10,7 @@ gfx_defines! {
|
||||
pos: [f32; 2] = "v_pos",
|
||||
uv: [f32; 2] = "v_uv",
|
||||
color: [f32; 4] = "v_color",
|
||||
center: [f32; 2] = "v_center",
|
||||
mode: u32 = "v_mode",
|
||||
}
|
||||
|
||||
@ -55,11 +56,23 @@ pub const MODE_TEXT: u32 = 0;
|
||||
pub const MODE_IMAGE: u32 = 1;
|
||||
/// Ignore `tex` and draw simple, colored 2D geometry.
|
||||
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 {
|
||||
Text,
|
||||
Image,
|
||||
Geometry,
|
||||
ImageSourceNorth,
|
||||
ImageTargetNorth,
|
||||
}
|
||||
|
||||
impl Mode {
|
||||
@ -68,6 +81,8 @@ impl Mode {
|
||||
Mode::Text => MODE_TEXT,
|
||||
Mode::Image => MODE_IMAGE,
|
||||
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>,
|
||||
mode: Mode,
|
||||
) -> 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 v = |pos, uv| Vertex {
|
||||
pos,
|
||||
uv,
|
||||
center,
|
||||
color: color.into_array(),
|
||||
mode: mode_val,
|
||||
};
|
||||
@ -118,10 +139,12 @@ pub fn create_tri(
|
||||
color: Rgba<f32>,
|
||||
mode: Mode,
|
||||
) -> Tri<UiPipeline> {
|
||||
let center = [0.0, 0.0];
|
||||
let mode_val = mode.value();
|
||||
let v = |pos, uv| Vertex {
|
||||
pos,
|
||||
uv,
|
||||
center,
|
||||
color: color.into_array(),
|
||||
mode: mode_val,
|
||||
};
|
||||
|
@ -190,7 +190,7 @@ impl 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.
|
||||
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 dot_vox::DotVoxData;
|
||||
use guillotiere::{size2, SimpleAtlasAllocator};
|
||||
use hashbrown::HashMap;
|
||||
use hashbrown::{hash_map::Entry, HashMap};
|
||||
use image::{DynamicImage, RgbaImage};
|
||||
use log::warn;
|
||||
use pixel_art::resize_pixel_art;
|
||||
@ -26,6 +26,14 @@ pub enum Rotation {
|
||||
Cw90,
|
||||
Cw180,
|
||||
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
|
||||
@ -41,7 +49,7 @@ pub struct Id(u32);
|
||||
#[derive(PartialEq, Eq, Hash, Copy, Clone)]
|
||||
pub struct TexId(usize);
|
||||
|
||||
type Parameters = (Id, Vec2<u16>, Aabr<u64>);
|
||||
type Parameters = (Id, Vec2<u16>);
|
||||
type GraphicMap = HashMap<Id, Graphic>;
|
||||
|
||||
enum CacheLoc {
|
||||
@ -130,6 +138,8 @@ impl GraphicCache {
|
||||
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(
|
||||
&mut self,
|
||||
renderer: &mut Renderer,
|
||||
@ -137,15 +147,18 @@ impl GraphicCache {
|
||||
dims: Vec2<u16>,
|
||||
source: Aabr<f64>,
|
||||
rotation: Rotation,
|
||||
) -> Option<(Aabr<u16>, TexId)> {
|
||||
) -> Option<(Aabr<f64>, TexId)> {
|
||||
let dims = match rotation {
|
||||
Rotation::Cw90 | Rotation::Cw270 => Vec2::new(dims.y, dims.x),
|
||||
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 {
|
||||
Rotation::None => Aabr { min, max },
|
||||
Rotation::None | Rotation::SourceNorth | Rotation::TargetNorth => Aabr { min, max },
|
||||
Rotation::Cw90 => Aabr {
|
||||
min: Vec2::new(min.x, max.y),
|
||||
max: Vec2::new(max.x, min.y),
|
||||
@ -156,8 +169,21 @@ impl GraphicCache {
|
||||
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) {
|
||||
Entry::Occupied(details) => {
|
||||
let details = details.get();
|
||||
let (idx, aabr) = match details.location {
|
||||
CacheLoc::Atlas {
|
||||
atlas_idx, aabr, ..
|
||||
@ -180,8 +206,11 @@ impl GraphicCache {
|
||||
upload_image(renderer, aabr, &self.textures[idx], &image);
|
||||
}
|
||||
|
||||
Some((rotated_aabr(aabr), TexId(idx)))
|
||||
} else {
|
||||
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)?;
|
||||
|
||||
@ -196,8 +225,7 @@ impl GraphicCache {
|
||||
// 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)))
|
||||
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 });
|
||||
@ -244,13 +272,12 @@ impl GraphicCache {
|
||||
// Upload
|
||||
upload_image(renderer, aabr, &self.textures[idx], &image);
|
||||
// Insert into cached map
|
||||
self.cache_map.insert(key, CachedDetails {
|
||||
details.insert(CachedDetails {
|
||||
location,
|
||||
valid: true,
|
||||
});
|
||||
|
||||
Some((rotated_aabr(aabr), TexId(idx)))
|
||||
}
|
||||
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 cw180: 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
|
||||
|
@ -28,6 +28,7 @@ use crate::{
|
||||
window::Window,
|
||||
Error,
|
||||
};
|
||||
use ::image::GenericImageView;
|
||||
use cache::Cache;
|
||||
use common::{assets, util::srgba_to_linear};
|
||||
use conrod_core::{
|
||||
@ -43,6 +44,7 @@ use conrod_core::{
|
||||
use graphic::{Rotation, TexId};
|
||||
use log::{error, warn};
|
||||
use std::{
|
||||
f32, f64,
|
||||
fs::File,
|
||||
io::{BufReader, Read},
|
||||
ops::Range,
|
||||
@ -172,6 +174,16 @@ impl Ui {
|
||||
cw90: self.image_map.insert((graphic_id, Rotation::Cw90)),
|
||||
cw180: self.image_map.insert((graphic_id, Rotation::Cw180)),
|
||||
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 {
|
||||
image_id,
|
||||
color,
|
||||
source_rect: _, // TODO: <-- use this
|
||||
source_rect,
|
||||
} => {
|
||||
let (graphic_id, rotation) = self
|
||||
.image_map
|
||||
.get(&image_id)
|
||||
.expect("Image does not exist in image map");
|
||||
let graphic_cache = self.cache.graphic_cache_mut();
|
||||
|
||||
let gl_aabr = gl_aabr(rect);
|
||||
let (source_aabr, gl_size) = {
|
||||
// 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 =
|
||||
srgba_to_linear(color.unwrap_or(conrod_core::color::WHITE).to_fsa().into());
|
||||
|
||||
let gl_aabr = gl_aabr(rect);
|
||||
let resolution = Vec2::new(
|
||||
(gl_aabr.size().w * half_res.x).round() as u16,
|
||||
(gl_aabr.size().h * half_res.y).round() as u16,
|
||||
(gl_size.w * half_res.x).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.
|
||||
let (uv_aabr, tex_id) = match graphic_cache.cache_res(
|
||||
@ -500,7 +554,13 @@ impl Ui {
|
||||
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 {
|
||||
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)) {
|
||||
(_, (false, _)) | (None, (_, true)) => {
|
||||
let (r, g, b) = (
|
||||
@ -251,7 +254,7 @@ impl MapConfig {
|
||||
0.0
|
||||
})
|
||||
.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_humidity {
|
||||
humidity as f64
|
||||
@ -272,17 +275,22 @@ impl MapConfig {
|
||||
},
|
||||
(Some(RiverKind::Ocean), _) => (
|
||||
0,
|
||||
((32.0 - water_depth * 32.0) * 1.0) as u8,
|
||||
((64.0 - water_depth * 64.0) * 1.0) as u8,
|
||||
((g_water - water_depth * g_water) * 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,
|
||||
),
|
||||
(Some(RiverKind::River { .. }), _) => {
|
||||
(0, 32 + (alt * 95.0) as u8, 64 + (alt * 191.0) as u8, 255)
|
||||
},
|
||||
(None, _) | (Some(RiverKind::Lake { .. }), _) => (
|
||||
0,
|
||||
(((32.0 + water_alt * 95.0) + (-water_depth * 32.0)) * 1.0) as u8,
|
||||
(((64.0 + water_alt * 191.0) + (-water_depth * 64.0)) * 1.0) as u8,
|
||||
(((g_water + water_alt * (127.0 - 32.0)) + (-water_depth * g_water)) * 1.0)
|
||||
as u8,
|
||||
(((b_water + water_alt * (255.0 - b_water)) + (-water_depth * b_water))
|
||||
* 1.0) as u8,
|
||||
255,
|
||||
),
|
||||
};
|
||||
|
@ -292,6 +292,9 @@ impl WorldFile {
|
||||
|
||||
pub struct WorldSim {
|
||||
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) locations: Vec<Location>,
|
||||
|
||||
@ -1288,6 +1291,7 @@ impl WorldSim {
|
||||
|
||||
let mut this = Self {
|
||||
seed,
|
||||
max_height: maxh as f32,
|
||||
chunks,
|
||||
locations: Vec::new(),
|
||||
gen_ctx,
|
||||
@ -1306,7 +1310,11 @@ impl WorldSim {
|
||||
pub fn get_map(&self) -> Vec<u32> {
|
||||
let mut v = vec![0u32; WORLD_SIZE.x * WORLD_SIZE.y];
|
||||
// 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
|
||||
|
Loading…
Reference in New Issue
Block a user