use crate::editor::{ACTIONLIST, RUSTERIX};
use crate::prelude::*;
use rusterix::prelude::*;
use theframework::prelude::*;
#[derive(PartialEq, Clone, Copy, Debug)]
pub enum HudMode {
Selection,
Vertex,
Linedef,
Sector,
Effects,
Dungeon,
Rect,
Terrain,
Entity,
}
pub struct Hud {
mode: HudMode,
icon_rects: Vec<TheDim>,
pub selected_icon_index: i32,
subdiv_rects: Vec<TheDim>,
mouse_pos: Vec2<i32>,
light_icon: Option<TheRGBABuffer>,
plane_picker_rects: Vec<TheDim>,
edit_mode_rects: Vec<TheDim>,
}
impl Hud {
fn active_action_material_slots(
&self,
map: &Map,
ctx: &mut TheContext,
server_ctx: &mut ServerContext,
) -> Option<Vec<ActionMaterialSlot>> {
if server_ctx.get_map_context() != MapContext::Region {
return None;
}
if let Some(action_id) = server_ctx.curr_action_id
&& let Some(action) = ACTIONLIST.read().unwrap().get_action_by_id(action_id)
&& action.is_applicable(map, ctx, server_ctx)
&& let Some(slots) = action.hud_material_slots(map, server_ctx)
{
return Some(slots);
}
None
}
fn active_builder_item_slots(
&self,
map: &Map,
_ctx: &mut TheContext,
server_ctx: &mut ServerContext,
) -> Option<Vec<ActionItemSlot>> {
if !server_ctx.builder_tool_active {
return None;
}
match server_ctx.curr_map_tool_type {
MapToolType::Sector => crate::actions::builder_hud_item_slots_for_selected_sector(map),
MapToolType::Linedef => {
crate::actions::builder_hud_item_slots_for_selected_linedef(map)
}
MapToolType::Vertex => crate::actions::builder_hud_item_slots_for_selected_vertex(map),
_ => None,
}
}
fn active_palette_material_slots(
&self,
map: &Map,
_ctx: &mut TheContext,
server_ctx: &mut ServerContext,
) -> Option<Vec<ActionMaterialSlot>> {
if !server_ctx.palette_tool_active {
return None;
}
match server_ctx.curr_map_tool_type {
MapToolType::Sector => {
crate::actions::builder_hud_material_slots_for_selected_sector(map)
}
MapToolType::Linedef => {
crate::actions::builder_hud_material_slots_for_selected_linedef(map)
}
MapToolType::Vertex => {
crate::actions::builder_hud_material_slots_for_selected_vertex(map)
}
_ => None,
}
}
fn clean_coord(v: f32) -> f32 {
if v.abs() < 0.0005 { 0.0 } else { v }
}
pub fn new(mode: HudMode) -> Self {
Self {
mode,
icon_rects: vec![],
selected_icon_index: 0,
subdiv_rects: vec![],
mouse_pos: Vec2::zero(),
light_icon: None,
plane_picker_rects: vec![],
edit_mode_rects: vec![],
}
}
pub fn draw(
&mut self,
buffer: &mut TheRGBABuffer,
map: &mut Map,
ctx: &mut TheContext,
server_ctx: &mut ServerContext,
id: Option<u32>,
_assets: &Assets,
) {
if (self.mode == HudMode::Linedef || self.mode == HudMode::Sector)
&& self.light_icon.is_none()
{
if let Some(li) = ctx.ui.icon("light_small") {
self.light_icon = Some(li.clone());
}
}
let width = buffer.dim().width as usize;
let height = buffer.dim().height as usize;
let stride = buffer.stride();
let info_height = 20;
let bg_color = [48, 48, 50, 235];
let panel_color = [34, 34, 36, 240];
let text_color = [168, 168, 172, 255];
let sel_text_color = [240, 240, 242, 255];
let accent_color = [210, 176, 92, 255];
let geom_accent = [98, 150, 120, 255];
let detail_accent = [176, 124, 92, 255];
self.subdiv_rects = vec![];
ctx.draw.rect(
buffer.pixels_mut(),
&(0, 0, width, info_height),
stride,
&bg_color,
);
ctx.draw.rect(
buffer.pixels_mut(),
&(0, info_height - 1, width, 1),
stride,
&[96, 96, 100, 255],
);
if server_ctx.editor_view_mode == EditorViewMode::D2 {
if let Some(v) = server_ctx.hover_cursor {
ctx.draw
.rect(buffer.pixels_mut(), &(8, 2, 150, 16), stride, &panel_color);
ctx.draw.text(
buffer.pixels_mut(),
&(10, 2),
stride,
&format!("{:.2}, {:.2}", v.x, v.y),
TheFontSettings {
size: 13.0,
..Default::default()
},
&text_color,
&bg_color,
);
}
} else if let Some(v) = server_ctx.hover_cursor_3d {
let snapped = server_ctx.snap_world_point_for_edit(map, v);
ctx.draw
.rect(buffer.pixels_mut(), &(8, 2, 175, 16), stride, &panel_color);
ctx.draw.text(
buffer.pixels_mut(),
&(10, 2),
stride,
&format!(
"{:.2}, {:.2}, {:.2}",
Self::clean_coord(snapped.x),
Self::clean_coord(snapped.y),
Self::clean_coord(snapped.z)
),
TheFontSettings {
size: 13.0,
..Default::default()
},
&text_color,
&bg_color,
);
}
if let Some(v) = &server_ctx.background_progress {
ctx.draw.text(
buffer.pixels_mut(),
&(550, 2),
stride,
v,
TheFontSettings {
size: 13.0,
..Default::default()
},
&text_color,
&bg_color,
);
}
let icon_size = 40;
let mut icons = 0;
let action_item_slots = self.active_builder_item_slots(map, ctx, server_ctx);
let action_material_slots = if action_item_slots.is_none() {
self.active_palette_material_slots(map, ctx, server_ctx)
.or_else(|| self.active_action_material_slots(map, ctx, server_ctx))
} else {
None
};
if server_ctx.get_map_context() == MapContext::Region {
icons = if let Some(slots) = &action_item_slots {
slots.len() as i32
} else if let Some(slots) = &action_material_slots {
slots.len() as i32
} else if self.mode == HudMode::Vertex {
0
} else if self.mode == HudMode::Linedef {
0
} else {
1
};
} else if server_ctx.get_map_context() == MapContext::Screen {
icons = if self.mode == HudMode::Sector { 2 } else { 0 };
}
if self.mode == HudMode::Effects
|| self.mode == HudMode::Dungeon
|| self.mode == HudMode::Rect
|| self.mode == HudMode::Terrain
{
icons = 0;
}
self.icon_rects.clear();
let x = width as i32 - (icon_size * icons) - 1;
for i in 0..icons {
let rect = TheDim::rect(x + (i * icon_size), 20, icon_size, icon_size);
ctx.draw.rect(
buffer.pixels_mut(),
&rect.to_buffer_utuple(),
stride,
&bg_color,
);
let r = rect.to_buffer_utuple();
ctx.draw.text_rect(
buffer.pixels_mut(),
&(r.0, 1, r.2, 19),
stride,
&self.get_icon_text(
i,
server_ctx,
action_item_slots.as_deref(),
action_material_slots.as_deref(),
),
TheFontSettings {
size: 10.0,
..Default::default()
},
&text_color,
&bg_color,
TheHorizontalAlign::Center,
TheVerticalAlign::Center,
);
let r = &rect.to_buffer_utuple();
ctx.draw.rect(
buffer.pixels_mut(),
&(r.0 + 1, r.1 + 1, r.2 - 2, r.3 - 2),
stride,
&[30, 30, 30, 255],
);
if let Some(id) = id {
let (tile, has_light) = self.get_icon(
i,
map,
id,
icon_size as usize,
action_item_slots.as_deref(),
action_material_slots.as_deref(),
);
if let Some(tile) = tile {
let texture = tile.textures[0].resized(icon_size as usize, icon_size as usize);
ctx.draw.blend_slice(
buffer.pixels_mut(),
&texture.data,
&rect.to_buffer_utuple(),
stride,
);
}
if has_light {
if let Some(light_icon) = &self.light_icon {
ctx.draw.blend_slice(
buffer.pixels_mut(),
light_icon.pixels(),
&(
rect.x as usize + 1,
rect.y as usize + 1,
light_icon.dim().width as usize,
light_icon.dim().height as usize,
),
stride,
);
}
}
}
if i == self.selected_icon_index {
ctx.draw.rect_outline(
buffer.pixels_mut(),
&rect.to_buffer_utuple(),
stride,
&sel_text_color,
);
}
self.icon_rects.push(rect);
}
if (map.camera == MapCamera::TwoD
|| server_ctx.get_map_context() == MapContext::Screen
|| server_ctx.editor_view_mode != EditorViewMode::D2)
&& self.mode != HudMode::Terrain
&& self.mode != HudMode::Dungeon
&& self.mode != HudMode::Rect
{
let x = 170;
let size = 20;
for i in 0..10 {
let rect = TheDim::rect(x + (i * size), 0, size, size);
let active = (i + 1) as f32 == map.subdivisions;
let hovered = rect.contains(self.mouse_pos);
let inner = if active {
[68, 68, 72, 255]
} else if hovered {
[54, 54, 58, 255]
} else {
panel_color
};
ctx.draw.rect(
buffer.pixels_mut(),
&rect.to_buffer_utuple(),
stride,
&bg_color,
);
ctx.draw.rect(
buffer.pixels_mut(),
&(
rect.x as usize + 1,
rect.y as usize + 2,
rect.width as usize - 2,
rect.height as usize - 4,
),
stride,
&inner,
);
if active {
ctx.draw.rect(
buffer.pixels_mut(),
&(
rect.x as usize + 3,
rect.y as usize + 16,
rect.width as usize - 6,
2,
),
stride,
&accent_color,
);
}
let r = rect.to_buffer_utuple();
ctx.draw.text_rect(
buffer.pixels_mut(),
&(r.0, 1, r.2, 19),
stride,
&(i + 1).to_string(),
TheFontSettings {
size: 12.5,
..Default::default()
},
&if active || hovered {
sel_text_color
} else {
text_color
},
&bg_color,
TheHorizontalAlign::Center,
TheVerticalAlign::Center,
);
self.subdiv_rects.push(rect);
}
}
if server_ctx.editor_view_mode != EditorViewMode::D2 && self.mode != HudMode::Rect {
self.edit_mode_rects.clear();
let labels = ["GEOM", "DETAIL"];
let modes = [GeometryEditMode::Geometry, GeometryEditMode::Detail];
let start_x = 390;
let button_w = 52;
for i in 0..2 {
let rect = TheDim::rect(start_x + (i as i32 * (button_w + 4)), 0, button_w, 20);
let active = server_ctx.geometry_edit_mode == modes[i];
let fg = if active { sel_text_color } else { text_color };
let inner = if active {
[60, 60, 64, 255]
} else {
panel_color
};
let accent = if i == 0 { geom_accent } else { detail_accent };
ctx.draw.rect(
buffer.pixels_mut(),
&rect.to_buffer_utuple(),
stride,
&bg_color,
);
ctx.draw.rect(
buffer.pixels_mut(),
&(
rect.x as usize + 1,
rect.y as usize + 2,
rect.width as usize - 2,
rect.height as usize - 4,
),
stride,
&inner,
);
ctx.draw.text_rect(
buffer.pixels_mut(),
&rect.to_buffer_utuple(),
stride,
labels[i],
TheFontSettings {
size: 11.0,
..Default::default()
},
&fg,
&inner,
TheHorizontalAlign::Center,
TheVerticalAlign::Center,
);
if active {
ctx.draw.rect_outline(
buffer.pixels_mut(),
&rect.to_buffer_utuple(),
stride,
&sel_text_color,
);
ctx.draw.rect(
buffer.pixels_mut(),
&(
rect.x as usize + 4,
rect.y as usize + 16,
rect.width as usize - 8,
2,
),
stride,
&accent,
);
}
self.edit_mode_rects.push(rect);
}
} else {
self.edit_mode_rects.clear();
}
if self.mode == HudMode::Terrain {
if let Some(v) = server_ctx.hover_height {
ctx.draw.text(
buffer.pixels_mut(),
&(150, 2),
stride,
&format!("Elevation {v:.2}"),
TheFontSettings {
size: 13.0,
..Default::default()
},
&text_color,
&bg_color,
);
}
}
if server_ctx.get_map_context() == MapContext::Character
|| server_ctx.get_map_context() == MapContext::Item
{
if let Some(Value::Texture(texture)) = map.properties.get("shape") {
let w = texture.width as i32;
let h = texture.height as i32;
let preview_rect = TheDim::rect(width as i32 - w - 1, height as i32 - h - 1, w, h);
ctx.draw.blend_slice(
buffer.pixels_mut(),
&texture.data,
&preview_rect.to_buffer_utuple(),
stride,
);
}
} else if server_ctx.get_map_context() == MapContext::Screen {
}
if server_ctx.editor_view_mode != EditorViewMode::D2
&& server_ctx.show_editing_geometry
&& server_ctx.geometry_edit_mode != GeometryEditMode::Detail
{
self.draw_plane_picker(buffer, ctx, server_ctx, width, height, stride);
} else {
self.plane_picker_rects.clear();
}
}
fn draw_plane_picker(
&mut self,
buffer: &mut TheRGBABuffer,
_ctx: &mut TheContext,
server_ctx: &ServerContext,
width: usize,
height: usize,
stride: usize,
) {
self.plane_picker_rects.clear();
let widget_size = 80;
let widget_margin = 8;
let shadow_color = [0, 0, 0, 110];
let x = width as i32 - widget_size - widget_margin;
let y = height as i32 - widget_size - widget_margin;
let cx = x + widget_size / 2;
let cy = y + widget_size / 2 + 18;
let size = 15;
let iso_x = |ix: i32, iy: i32, _iz: i32| cx + (ix - iy) * size;
let iso_y = |ix: i32, iy: i32, iz: i32| cy + (ix + iy) * size / 2 - iz * size;
let p = [
(iso_x(-1, -1, 0), iso_y(-1, -1, 0)), (iso_x(1, -1, 0), iso_y(1, -1, 0)), (iso_x(1, 1, 0), iso_y(1, 1, 0)), (iso_x(-1, 1, 0), iso_y(-1, 1, 0)), (iso_x(-1, -1, 2), iso_y(-1, -1, 2)), (iso_x(1, -1, 2), iso_y(1, -1, 2)), (iso_x(1, 1, 2), iso_y(1, 1, 2)), (iso_x(-1, 1, 2), iso_y(-1, 1, 2)), ];
let xz_color = if server_ctx.gizmo_mode == GizmoMode::XZ {
[132, 212, 148, 248]
} else {
[102, 112, 108, 96]
};
let xy_color = if server_ctx.gizmo_mode == GizmoMode::XY {
[126, 144, 220, 248]
} else {
[104, 108, 122, 96]
};
let yz_color = if server_ctx.gizmo_mode == GizmoMode::YZ {
[224, 146, 122, 248]
} else {
[122, 108, 102, 96]
};
let widget_bounds = (x, y, x + widget_size, y + widget_size);
let fill_quad = |buffer: &mut [u8],
p0: (i32, i32),
p1: (i32, i32),
p2: (i32, i32),
p3: (i32, i32),
color: [u8; 4]| {
let points = [p0, p1, p2, p3];
let min_y = points.iter().map(|p| p.1).min().unwrap();
let max_y = points.iter().map(|p| p.1).max().unwrap();
for scan_y in min_y..=max_y {
if scan_y < widget_bounds.1 || scan_y >= widget_bounds.3 {
continue;
}
let mut x_intersects = Vec::new();
for i in 0..4 {
let a = points[i];
let b = points[(i + 1) % 4];
if (a.1 <= scan_y && b.1 > scan_y) || (b.1 <= scan_y && a.1 > scan_y) {
let t = (scan_y - a.1) as f32 / (b.1 - a.1) as f32;
let x = a.0 as f32 + t * (b.0 - a.0) as f32;
x_intersects.push(x as i32);
}
}
x_intersects.sort();
for i in (0..x_intersects.len()).step_by(2) {
if i + 1 < x_intersects.len() {
for px in x_intersects[i]..=x_intersects[i + 1] {
if px >= widget_bounds.0
&& px < widget_bounds.2
&& scan_y >= widget_bounds.1
&& scan_y < widget_bounds.3
&& px >= 0
&& scan_y >= 0
&& (px as usize) < width
&& (scan_y as usize) < height
{
let offset = scan_y as usize * stride * 4 + px as usize * 4;
if offset + 3 < buffer.len() {
buffer[offset] = color[0];
buffer[offset + 1] = color[1];
buffer[offset + 2] = color[2];
buffer[offset + 3] = color[3];
}
}
}
}
}
}
};
fill_quad(
buffer.pixels_mut(),
(p[4].0 + 3, p[4].1 + 3),
(p[5].0 + 3, p[5].1 + 3),
(p[6].0 + 3, p[6].1 + 3),
(p[7].0 + 3, p[7].1 + 3),
shadow_color,
);
fill_quad(
buffer.pixels_mut(),
(p[3].0 + 3, p[3].1 + 3),
(p[7].0 + 3, p[7].1 + 3),
(p[6].0 + 3, p[6].1 + 3),
(p[2].0 + 3, p[2].1 + 3),
shadow_color,
);
fill_quad(
buffer.pixels_mut(),
(p[1].0 + 3, p[1].1 + 3),
(p[5].0 + 3, p[5].1 + 3),
(p[6].0 + 3, p[6].1 + 3),
(p[2].0 + 3, p[2].1 + 3),
shadow_color,
);
fill_quad(buffer.pixels_mut(), p[4], p[5], p[6], p[7], xz_color);
fill_quad(buffer.pixels_mut(), p[3], p[7], p[6], p[2], yz_color);
fill_quad(buffer.pixels_mut(), p[1], p[5], p[6], p[2], xy_color);
let edge_color = [196, 196, 200, 220];
let draw_edge = |buf: &mut [u8], p0: (i32, i32), p1: (i32, i32)| {
let mut x0 = p0.0;
let mut y0 = p0.1;
let x1 = p1.0;
let y1 = p1.1;
let dx = (x1 - x0).abs();
let dy = (y1 - y0).abs();
let sx = if x0 < x1 { 1 } else { -1 };
let sy = if y0 < y1 { 1 } else { -1 };
let mut err = dx - dy;
loop {
if x0 >= widget_bounds.0
&& x0 < widget_bounds.2
&& y0 >= widget_bounds.1
&& y0 < widget_bounds.3
&& x0 >= 0
&& y0 >= 0
&& (x0 as usize) < width
&& (y0 as usize) < height
{
let offset = y0 as usize * stride * 4 + x0 as usize * 4;
if offset + 3 < buf.len() {
buf[offset] = edge_color[0];
buf[offset + 1] = edge_color[1];
buf[offset + 2] = edge_color[2];
buf[offset + 3] = edge_color[3];
}
}
if x0 == x1 && y0 == y1 {
break;
}
let e2 = 2 * err;
if e2 > -dy {
err -= dy;
x0 += sx;
}
if e2 < dx {
err += dx;
y0 += sy;
}
}
};
let buf = buffer.pixels_mut();
draw_edge(buf, p[4], p[5]);
draw_edge(buf, p[5], p[6]);
draw_edge(buf, p[6], p[7]);
draw_edge(buf, p[7], p[4]);
draw_edge(buf, p[1], p[5]);
draw_edge(buf, p[2], p[6]);
draw_edge(buf, p[3], p[7]);
draw_edge(buf, p[1], p[2]);
draw_edge(buf, p[2], p[3]);
let active_edge = match server_ctx.gizmo_mode {
GizmoMode::XZ => [248, 255, 250, 255],
GizmoMode::YZ => [255, 244, 236, 255],
GizmoMode::XY => [238, 244, 255, 255],
};
let active_face = match server_ctx.gizmo_mode {
GizmoMode::XZ => [p[4], p[5], p[6], p[7]],
GizmoMode::YZ => [p[3], p[7], p[6], p[2]],
GizmoMode::XY => [p[1], p[5], p[6], p[2]],
};
draw_edge(buf, active_face[0], active_face[1]);
draw_edge(buf, active_face[1], active_face[2]);
draw_edge(buf, active_face[2], active_face[3]);
draw_edge(buf, active_face[3], active_face[0]);
draw_edge(buf, active_face[0], active_face[1]);
draw_edge(buf, active_face[1], active_face[2]);
draw_edge(buf, active_face[2], active_face[3]);
draw_edge(buf, active_face[3], active_face[0]);
let draw_highlight_edge = |buf: &mut [u8], p0: (i32, i32), p1: (i32, i32)| {
let mut x0 = p0.0;
let mut y0 = p0.1;
let x1 = p1.0;
let y1 = p1.1;
let dx = (x1 - x0).abs();
let dy = (y1 - y0).abs();
let sx = if x0 < x1 { 1 } else { -1 };
let sy = if y0 < y1 { 1 } else { -1 };
let mut err = dx - dy;
loop {
if x0 >= widget_bounds.0
&& x0 < widget_bounds.2
&& y0 >= widget_bounds.1
&& y0 < widget_bounds.3
&& x0 >= 0
&& y0 >= 0
&& (x0 as usize) < width
&& (y0 as usize) < height
{
let offset = y0 as usize * stride * 4 + x0 as usize * 4;
if offset + 3 < buf.len() {
buf[offset] = active_edge[0];
buf[offset + 1] = active_edge[1];
buf[offset + 2] = active_edge[2];
buf[offset + 3] = active_edge[3];
}
}
if x0 == x1 && y0 == y1 {
break;
}
let e2 = 2 * err;
if e2 > -dy {
err -= dy;
x0 += sx;
}
if e2 < dx {
err += dx;
y0 += sy;
}
}
};
draw_highlight_edge(buf, active_face[0], active_face[1]);
draw_highlight_edge(buf, active_face[1], active_face[2]);
draw_highlight_edge(buf, active_face[2], active_face[3]);
draw_highlight_edge(buf, active_face[3], active_face[0]);
self.plane_picker_rects.push(TheDim::rect(
p[4].0.min(p[5].0).min(p[6].0).min(p[7].0),
p[4].1.min(p[5].1).min(p[6].1).min(p[7].1),
p[4].0.max(p[5].0).max(p[6].0).max(p[7].0) - p[4].0.min(p[5].0).min(p[6].0).min(p[7].0),
p[4].1.max(p[5].1).max(p[6].1).max(p[7].1) - p[4].1.min(p[5].1).min(p[6].1).min(p[7].1),
));
self.plane_picker_rects.push(TheDim::rect(
p[3].0.min(p[7].0).min(p[6].0).min(p[2].0),
p[3].1.min(p[7].1).min(p[6].1).min(p[2].1),
p[3].0.max(p[7].0).max(p[6].0).max(p[2].0) - p[3].0.min(p[7].0).min(p[6].0).min(p[2].0),
p[3].1.max(p[7].1).max(p[6].1).max(p[2].1) - p[3].1.min(p[7].1).min(p[6].1).min(p[2].1),
));
self.plane_picker_rects.push(TheDim::rect(
p[1].0.min(p[5].0).min(p[6].0).min(p[2].0),
p[1].1.min(p[5].1).min(p[6].1).min(p[2].1),
p[1].0.max(p[5].0).max(p[6].0).max(p[2].0) - p[1].0.min(p[5].0).min(p[6].0).min(p[2].0),
p[1].1.max(p[5].1).max(p[6].1).max(p[2].1) - p[1].1.min(p[5].1).min(p[6].1).min(p[2].1),
));
}
pub fn clicked(
&mut self,
x: i32,
y: i32,
map: &mut Map,
_ui: &mut TheUI,
ctx: &mut TheContext,
server_ctx: &mut ServerContext,
) -> bool {
if server_ctx.get_map_context() != MapContext::Region
&& server_ctx.get_map_context() != MapContext::Screen
&& server_ctx.get_map_context() != MapContext::Character
&& server_ctx.get_map_context() != MapContext::Item
{
return false;
}
for (i, rect) in self.icon_rects.iter().enumerate() {
if rect.contains(Vec2::new(x, y)) {
self.selected_icon_index = i as i32;
server_ctx.selected_hud_icon_index = i as i32;
if self.mode == HudMode::Linedef {
server_ctx.selected_wall_row = Some(i as i32);
ctx.ui.send(TheEvent::Custom(
TheId::named("Map Selection Changed"),
TheValue::Empty,
));
}
return true;
}
}
if self.mode != HudMode::Rect {
for (i, rect) in self.subdiv_rects.iter().enumerate() {
if rect.contains(Vec2::new(x, y)) {
map.subdivisions = (i + 1) as f32;
return true;
}
}
}
if server_ctx.editor_view_mode != EditorViewMode::D2 {
for (i, rect) in self.edit_mode_rects.iter().enumerate() {
if rect.contains(Vec2::new(x, y)) {
server_ctx.geometry_edit_mode = if i == 0 {
GeometryEditMode::Geometry
} else {
GeometryEditMode::Detail
};
return true;
}
}
}
if server_ctx.editor_view_mode != EditorViewMode::D2
&& server_ctx.show_editing_geometry
&& server_ctx.geometry_edit_mode != GeometryEditMode::Detail
{
for (i, rect) in self.plane_picker_rects.iter().enumerate() {
if rect.contains(Vec2::new(x, y)) {
server_ctx.gizmo_mode = match i {
0 => {
println!("Plane picker: XZ plane selected");
GizmoMode::XZ
}
1 => {
println!("Plane picker: YZ plane selected");
GizmoMode::YZ
}
2 => {
println!("Plane picker: XY plane selected");
GizmoMode::XY
}
_ => server_ctx.gizmo_mode,
};
return true;
}
}
}
if map.camera == MapCamera::TwoD && y < 20 {
return true;
}
false
}
pub fn dragged(
&mut self,
_x: i32,
_y: i32,
_map: &mut Map,
_ui: &mut TheUI,
_ctx: &mut TheContext,
_server_ctx: &mut ServerContext,
) -> bool {
false
}
pub fn hovered(
&mut self,
x: i32,
y: i32,
_map: &mut Map,
_ui: &mut TheUI,
_ctx: &mut TheContext,
_server_ctx: &mut ServerContext,
) -> bool {
self.mouse_pos = Vec2::new(x, y);
false
}
#[allow(clippy::collapsible_if)]
pub fn get_icon_text(
&self,
index: i32,
server_ctx: &mut ServerContext,
action_item_slots: Option<&[ActionItemSlot]>,
action_material_slots: Option<&[ActionMaterialSlot]>,
) -> String {
let mut text: String = "".into();
if let Some(slots) = action_item_slots
&& let Some(slot) = slots.get(index as usize)
{
return slot.label.clone();
}
if let Some(slots) = action_material_slots {
if let Some(slot) = slots.get(index as usize) {
return slot.label.clone();
}
}
if server_ctx.get_map_context() == MapContext::Region {
if self.mode == HudMode::Sector {
if index == 0 {
text = "TILE".into();
}
}
} else if server_ctx.get_map_context() == MapContext::Screen {
if index == 0 {
text = "NORM".into();
} else if index == 1 {
text = "ACTIVE".into();
}
}
text
}
#[allow(clippy::collapsible_if)]
pub fn get_icon(
&self,
index: i32,
map: &Map,
id: u32,
icon_size: usize,
action_item_slots: Option<&[ActionItemSlot]>,
action_material_slots: Option<&[ActionMaterialSlot]>,
) -> (Option<rusterix::Tile>, bool) {
if let Some(slots) = action_item_slots
&& slots.get(index as usize).is_some()
{
return (None, false);
}
if let Some(slots) = action_material_slots
&& let Some(slot) = slots.get(index as usize)
{
if let Some(pixelsource) = &slot.source {
let props = ValueContainer::default();
if let Some(tile) =
pixelsource.to_tile(&RUSTERIX.read().unwrap().assets, icon_size, &props, map)
{
return (Some(tile), false);
}
}
return (None, false);
}
if self.mode == HudMode::Sector {
if let Some(sector) = map.find_sector(id) {
if index == 0 {
let has_light = sector.properties.get("floor_light").is_some();
if let Some(pixelsource) = sector.properties.get_default_source() {
if let Some(tile) = pixelsource.to_tile(
&RUSTERIX.read().unwrap().assets,
icon_size,
§or.properties,
map,
) {
return (Some(tile), has_light);
}
}
return (None, has_light);
} else if index == 1 {
let has_light = sector.properties.get("ceiling_light").is_some();
if let Some(Value::Source(pixelsource)) =
§or.properties.get("ceiling_source")
{
if let Some(tile) = pixelsource.to_tile(
&RUSTERIX.read().unwrap().assets,
icon_size,
§or.properties,
map,
) {
return (Some(tile), has_light);
}
}
return (None, has_light);
}
}
}
(None, false)
}
}