Skip to content

Commit

Permalink
better terraforming UI
Browse files Browse the repository at this point in the history
  • Loading branch information
Uriopass committed Dec 17, 2023
1 parent 7fbecc8 commit 1afb714
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 32 deletions.
2 changes: 1 addition & 1 deletion geom/src/heightmap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,7 @@ mod erosion {
for _ in 0..n_particles {
// Create water droplet at random point in bounds, in a circle

let d = randgen().powf(0.8) * (bounds.size() / 2.0).mag();
let d = randgen().powf(0.8) * bounds.w() * 0.5;
let angle = Radians(randgen() * std::f32::consts::TAU);
let pos = bounds.center() + angle.vec2() * d;

Expand Down
119 changes: 107 additions & 12 deletions native_app/src/gui/terraforming.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,59 +3,154 @@ use crate::inputmap::{InputAction, InputMap};
use crate::rendering::immediate::ImmediateDraw;
use crate::uiworld::UiWorld;
use egui_inspect::Inspect;
use geom::Vec3;
use geom::{Vec2, Vec3, OBB};
use simulation::map::TerraformKind;
use simulation::world_command::WorldCommand;
use simulation::Simulation;

#[derive(Inspect)]
pub struct TerraformingResource {
#[inspect(skip)]
pub kind: TerraformKind,
pub radius: f32,
pub amount: f32,
#[inspect(skip)]
pub level: f32,
level: Option<f32>,
#[inspect(skip)]
slope_start: Option<Vec3>,
#[inspect(skip)]
pub slope: Option<(Vec3, Vec3)>,
slope_end: Option<Vec3>,
}

/// Lot brush tool
/// Allows to build houses on lots
pub fn terraforming(sim: &Simulation, uiworld: &mut UiWorld) {
profiling::scope!("gui::terraforming");
let res = uiworld.write::<TerraformingResource>();
let mut res = uiworld.write::<TerraformingResource>();
let tool = *uiworld.read::<Tool>();
let inp = uiworld.read::<InputMap>();
let _draw = uiworld.write::<ImmediateDraw>();
let mut draw = uiworld.write::<ImmediateDraw>();
let _map = sim.map();
let commands = &mut *uiworld.commands();

if !matches!(tool, Tool::Terraforming) {
res.slope_start = None;
res.slope_end = None;
return;
}

if inp.act.contains(&InputAction::SizeUp) {
res.radius *= 1.1;
}
if inp.act.contains(&InputAction::SizeDown) {
res.radius /= 1.1;
}

let mpos = unwrap_ret!(inp.unprojected);

if inp.act.contains(&InputAction::Select) {
let mut amount_multiplier = 1.0;

// handle actions
match res.kind {
TerraformKind::Elevation => {
if inp.act.contains(&InputAction::SecondarySelect) {
amount_multiplier = -1.0;
}
}
TerraformKind::Smooth => {}
TerraformKind::Level => {
// set level on first click
if res.level == None && inp.just_act.contains(&InputAction::Select) {
res.level = Some(mpos.z);
}

// when hold is released, reset level
if !inp.act.contains(&InputAction::Select) {
res.level = None;
}
}
TerraformKind::Slope => {
// Set the end slope (second click)
if res.slope_start != None
&& res.slope_end == None
&& inp.just_act.contains(&InputAction::Select)
{
if !res.slope_start.unwrap().is_close(mpos, 5.0) {
res.slope_end = Some(mpos);
}
}

// Set the start slope (first click)
if res.slope_start == None && inp.just_act.contains(&InputAction::Select) {
res.slope_start = Some(mpos);
}

if inp.just_act.contains(&InputAction::Close) {
res.slope_start = None;
res.slope_end = None;
}
}
TerraformKind::Erode => {}
}

if inp.act.contains(&InputAction::Select) || inp.act.contains(&InputAction::SecondarySelect) {
if res.kind == TerraformKind::Level && res.level.is_none() {
return;
}
if res.kind == TerraformKind::Slope && res.slope_end.is_none() {
return;
}
commands.push(WorldCommand::Terraform {
center: mpos.xy(),
radius: res.radius,
amount: res.amount,
level: res.level,
amount: res.amount * amount_multiplier,
level: res.level.unwrap_or(0.0),
kind: res.kind,
slope: res.slope,
slope: res.slope_start.zip(res.slope_end),
})
}

// Draw the state
match res.kind {
TerraformKind::Elevation => {}
TerraformKind::Smooth => {}
TerraformKind::Level => {
if !inp.act.contains(&InputAction::Select) {
draw.obb(
OBB::new(
mpos.xy(),
Vec2::X,
res.radius * std::f32::consts::FRAC_1_SQRT_2,
res.radius * std::f32::consts::FRAC_1_SQRT_2,
),
res.level.unwrap_or(mpos.z) - 0.5,
)
.color(simulation::config().gui_primary.a(0.2));
}
}
TerraformKind::Slope => {
if res.slope_start.is_none() {
draw.circle(mpos, res.radius * 0.7)
} else if res.slope_end.is_none() {
draw.line(res.slope_start.unwrap(), mpos, res.radius)
} else {
draw.line(res.slope_start.unwrap(), res.slope_end.unwrap(), res.radius)
}
.color(simulation::config().gui_primary.a(0.2));
}
TerraformKind::Erode => {}
}
}

impl Default for TerraformingResource {
fn default() -> Self {
Self {
kind: TerraformKind::Erode,
radius: 1000.0,
radius: 200.0,
amount: 200.0,
level: 50.0,
slope: None,
level: None,
slope_start: None,
slope_end: None,
}
}
}
22 changes: 6 additions & 16 deletions native_app/src/gui/topgui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,7 @@ impl Gui {
}

if matches!(*uiworld.read::<Tab>(), Tab::Terraforming) {
let lbw = 120.0;
let lbw = 150.0;
Window::new("Terraforming")
.min_width(lbw)
.auto_sized()
Expand All @@ -537,21 +537,11 @@ impl Gui {
},
);

if ui.button("Lift").clicked() {
state.kind = TerraformKind::Elevation;
}
if ui.button("Smooth").clicked() {
state.kind = TerraformKind::Smooth;
}
if ui.button("Level").clicked() {
state.kind = TerraformKind::Level;
}
if ui.button("Slope").clicked() {
state.kind = TerraformKind::Slope;
}
if ui.button("Erode").clicked() {
state.kind = TerraformKind::Erode;
}
ui.radio_value(&mut state.kind, TerraformKind::Elevation, "Raise/Lower");
ui.radio_value(&mut state.kind, TerraformKind::Smooth, "Smooth");
ui.radio_value(&mut state.kind, TerraformKind::Level, "Level");
ui.radio_value(&mut state.kind, TerraformKind::Slope, "Slope");
ui.radio_value(&mut state.kind, TerraformKind::Erode, "Erode");
});
}

Expand Down
9 changes: 9 additions & 0 deletions native_app/src/inputmap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,11 @@ pub enum InputAction {
Zoom,
Dezoom,
Rotate,
SizeUp,
SizeDown,
Close,
Select,
SecondarySelect,
NoSnapping,
HideInterface,
UpElevation,
Expand Down Expand Up @@ -90,8 +93,11 @@ const DEFAULT_BINDINGS: &[(InputAction, &[&[UnitInput]])] = &[
(Zoom, &[&[Key(K::Plus)], &[WheelUp]]),
(Dezoom, &[&[Key(K::Minus)], &[WheelDown]]),
(Rotate, &[&[Key(K::LControl), WheelUp], &[Key(K::LControl), WheelDown]]),
(SizeUp, &[&[Key(K::LControl), WheelUp]]),
(SizeDown, &[&[Key(K::LControl), WheelDown]]),
(Close, &[&[Key(K::Escape)]]),
(Select, &[&[Mouse(Left)]]),
(SecondarySelect, &[&[Key(K::LControl), Mouse(Left)]]),
(NoSnapping, &[&[Key(K::LControl)]]),
(HideInterface, &[&[Key(K::H)]]),
(UpElevation, &[&[Key(K::LControl), WheelUp]]),
Expand Down Expand Up @@ -325,13 +331,16 @@ impl Display for InputAction {
Rotate => "Rotate",
Close => "Close",
Select => "Select",
SecondarySelect => "Secondary Select",
HideInterface => "Hide interface",
NoSnapping => "No Snapping",
UpElevation => "Up Elevation",
DownElevation => "Down Elevation",
OpenEconomyMenu => "Economy Menu",
PausePlay => "Pause/Play",
OpenChat => "Interact with Chat",
SizeUp => "Size Up",
SizeDown => "Size Down",
}
)
}
Expand Down
4 changes: 1 addition & 3 deletions simulation/src/map/terrain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub struct Terrain {
pub trees: Grid<Tree, Vec2>,
}

#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum TerraformKind {
Elevation,
Smooth,
Expand All @@ -43,8 +43,6 @@ pub enum TerraformKind {
Erode,
}

debug_inspect_impl!(TerraformKind);

defer_serialize!(Terrain, SerializedTerrain);

impl Default for Terrain {
Expand Down

0 comments on commit 1afb714

Please sign in to comment.