Compare commits

...

3 Commits
master ... dev

Author SHA1 Message Date
Arkitu
a9e711f3b9 forest button (functional) 2025-01-23 21:41:32 +01:00
Arkitu
7bd31de293 tree button (not yet clickable) 2025-01-23 19:42:39 +01:00
Arkitu
b448c40e54 start building ui + optimize build time for debug 2025-01-22 21:17:14 +01:00
6 changed files with 429 additions and 74 deletions

308
Cargo.lock generated
View File

@ -77,6 +77,12 @@ dependencies = [
"winit",
]
[[package]]
name = "adler2"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
[[package]]
name = "ahash"
version = "0.8.11"
@ -734,6 +740,7 @@ dependencies = [
"bevy_ecs",
"bevy_gizmos",
"bevy_hierarchy",
"bevy_image",
"bevy_input",
"bevy_log",
"bevy_math",
@ -1363,6 +1370,17 @@ version = "3.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
[[package]]
name = "buns"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75f1d46ab84e22a81b97efa9ee5f22a3f3508edf23a0203904f213b4faf32fe2"
dependencies = [
"deki_proc",
"extension-traits",
"maflow",
]
[[package]]
name = "bytemuck"
version = "1.20.0"
@ -1615,6 +1633,15 @@ dependencies = [
"const_soft_float",
]
[[package]]
name = "convert_case"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca"
dependencies = [
"unicode-segmentation",
]
[[package]]
name = "core-foundation"
version = "0.9.4"
@ -1731,6 +1758,15 @@ dependencies = [
"windows 0.54.0",
]
[[package]]
name = "crc32fast"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
dependencies = [
"cfg-if",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.14"
@ -1810,6 +1846,77 @@ version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2"
[[package]]
name = "deki"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d99371f8ebec1287967d7316c45cc22490db154e695c40dc697640f5ad07a221"
dependencies = [
"deki_core",
"deki_derive",
"deki_lerp",
"deki_macros",
"deki_proc",
]
[[package]]
name = "deki_core"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b95a4595bf7b9f83a550c7f3daee5fa03ab7113f8ac9db49cbe91f282089c3a"
dependencies = [
"buns",
"derive-new",
"derive_more",
"extension-traits",
"fastapprox",
"fastrand",
"maflow",
"type_cell",
]
[[package]]
name = "deki_derive"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7812924b99c75f34230c3cff26a07e0d4253f56b84865d5e3f3750ff0dcb1db6"
dependencies = [
"derive_preset",
]
[[package]]
name = "deki_lerp"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b64245eb17aca538ee0fb665909b324eb9219f6df57b029af5c1c53aaada0be5"
dependencies = [
"deki_core",
]
[[package]]
name = "deki_macros"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "058a36abf7e6c386334e058279c3aecc80bb8bd56f4254837d0f9c4eeafaaaa4"
dependencies = [
"deki_core",
"deki_proc",
]
[[package]]
name = "deki_proc"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47ae1da716b4b85978363cefa6963d63d0896ce9e4295b12c4a1636ad264dee3"
dependencies = [
"convert_case",
"extension-traits",
"maflow",
"proc-macro2",
"quote",
"syn 2.0.90",
]
[[package]]
name = "delaunator"
version = "1.0.2"
@ -1819,6 +1926,17 @@ dependencies = [
"robust",
]
[[package]]
name = "derive-new"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2cdc8d50f426189eef89dac62fabfa0abb27d5cc008f25bf4156a0203325becc"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.90",
]
[[package]]
name = "derive_more"
version = "1.0.0"
@ -1834,12 +1952,23 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22"
dependencies = [
"convert_case",
"proc-macro2",
"quote",
"syn 2.0.90",
"unicode-xid",
]
[[package]]
name = "derive_preset"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c676aecfc734fb672c8bf150b6984da6397d05a269a6bbe7308d6ddc91edf7e"
dependencies = [
"proc-macro2",
"quote",
]
[[package]]
name = "dispatch"
version = "0.2.0"
@ -2056,12 +2185,56 @@ dependencies = [
"pin-project-lite",
]
[[package]]
name = "ext-trait"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "703090345f7d5de48379b391c9dfe69967a3c1694730a3e53bf4c905f71069c0"
dependencies = [
"ext-trait-proc_macros",
]
[[package]]
name = "ext-trait-proc_macros"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd9f3f15f123dee4e8a6b14f033ba22904a48c5935505dc07225ce440e640d8b"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "extension-traits"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "360cbc11ebc403c8ebb731dfb4d3950835d40d3d9a20f0e89a27b17e991d0863"
dependencies = [
"ext-trait",
]
[[package]]
name = "fastapprox"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9dfa3c0fd35278e839805680f4c2f673ca71eb91068115b4a611e71429bc0c46"
[[package]]
name = "fastrand"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
[[package]]
name = "fdeflate"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c"
dependencies = [
"simd-adler32",
]
[[package]]
name = "fixedbitset"
version = "0.4.2"
@ -2074,6 +2247,16 @@ version = "0.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99"
[[package]]
name = "flate2"
version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c"
dependencies = [
"crc32fast",
"miniz_oxide",
]
[[package]]
name = "foldhash"
version = "0.1.4"
@ -2150,6 +2333,7 @@ dependencies = [
"console_log",
"getrandom",
"log",
"mevy",
"noise",
"rand",
"voronoice",
@ -2589,6 +2773,7 @@ dependencies = [
"bytemuck",
"byteorder-lite",
"num-traits",
"png",
]
[[package]]
@ -2759,6 +2944,12 @@ dependencies = [
"libc",
]
[[package]]
name = "maflow"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "102d5acb8c2bd7b07a6e5cd3b7f73bc5cd401a96d8f78df86464afa62b962fde"
[[package]]
name = "malloc_buf"
version = "0.0.6"
@ -2807,12 +2998,100 @@ dependencies = [
"paste",
]
[[package]]
name = "mevy"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8802cdd2c9767abb83234d4b016917ab08cdb7fdae97a3a3e0a28a5f80febbd5"
dependencies = [
"mevy_core",
"mevy_ecs",
"mevy_ui",
]
[[package]]
name = "mevy_core"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a388e5018afe90d85cd6e925a8c99a361e503b07aae760d70a432bdd1ab86172"
dependencies = [
"deki",
"mevy_core_syntax 0.1.1",
]
[[package]]
name = "mevy_core_syntax"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bece892cccb973e88cd8c4b686e2525a6f2a5e839e0870ac00e3d8fdd952e0e"
dependencies = [
"deki",
]
[[package]]
name = "mevy_core_syntax"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4915267a4ed798a3e9ef2fd1fff1b2cb5d1f356c5d131036e0ecddeae15ee267"
dependencies = [
"deki",
]
[[package]]
name = "mevy_ecs"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "407781ab6299ae18ebb9734a4db17ec6a865a31e196c2af926d16e552410f76f"
dependencies = [
"mevy_ecs_syntax",
]
[[package]]
name = "mevy_ecs_syntax"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be2b6d34fd01773ec549d05350d66141e8e2651f5123c41f8828306c8121f6e3"
dependencies = [
"deki",
"mevy_core_syntax 0.2.2",
]
[[package]]
name = "mevy_ui"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcea8c31c0895195aeb830b0edd650d7d0af71bec43721a9ace7723fed3b693c"
dependencies = [
"deki",
"mevy_ui_syntax",
]
[[package]]
name = "mevy_ui_syntax"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4cb9b2bb1c24ff7b13aecf3003849b6d6d3f4593b1ef321a8708ed431518d2a"
dependencies = [
"deki",
"mevy_core_syntax 0.2.2",
]
[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "miniz_oxide"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394"
dependencies = [
"adler2",
"simd-adler32",
]
[[package]]
name = "naga"
version = "22.1.0"
@ -3404,6 +3683,19 @@ version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
[[package]]
name = "png"
version = "0.17.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526"
dependencies = [
"bitflags 1.3.2",
"crc32fast",
"fdeflate",
"flate2",
"miniz_oxide",
]
[[package]]
name = "polling"
version = "3.7.3"
@ -3823,6 +4115,12 @@ version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "simd-adler32"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
[[package]]
name = "skrifa"
version = "0.22.3"
@ -4240,6 +4538,16 @@ version = "0.24.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5be21190ff5d38e8b4a2d3b6a3ae57f612cc39c96e83cedeaf7abc338a8bac4a"
[[package]]
name = "type_cell"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6d985656e9b8900f54ed89cce2fccf14f6c1e079f1a519635a3ba3c4a896e1e"
dependencies = [
"once_cell",
"paste",
]
[[package]]
name = "typeid"
version = "1.0.2"

View File

@ -7,9 +7,7 @@ edition = "2021"
name = "forestiles"
path = "src/lib.rs"
crate-type=[
"staticlib",
"cdylib",
"rlib"
"cdylib"
]
[[bin]]
@ -34,12 +32,14 @@ bevy = { version = "0.15", default-features = false, features = [
"sysinfo_plugin",
"webgl2",
"wayland",
"png"
]}
bevy-inspector-egui = { version = "0.28", default-features = false, features = [
"bevy_image",
"bevy_render",
"egui_open_url"
]}
mevy = "0.1"
log = "0.4"
rand = { version = "0.8", features = ["small_rng"] }
voronoice = "0.2"
@ -66,11 +66,11 @@ android_logger = "0.14"
opt-level = 1
# Enable a large amount of optimization in the dev profile for dependencies.
[profile.dev.package."*"]
opt-level = 3
# [profile.dev.package."*"]
# opt-level = 1
[package.metadata.android]
package = "org.forestiles.example"
package = "org.forestiles.game"
apk_name = "forestiles"
strip = "strip"
# see https://github.com/rust-mobile/cargo-apk

BIN
assets/ui/tree.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
assets/ui/tree_disabled.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -1,6 +1,6 @@
use std::time::Duration;
use bevy::{asset::RenderAssetUsages, picking::PickSet, prelude::*, render::mesh::{Indices, PrimitiveTopology}, utils::HashMap};
use bevy::{asset::RenderAssetUsages, picking::PickSet, prelude::*, render::mesh::{Indices, PrimitiveTopology}};
use noise::{Fbm, MultiFractal, NoiseFn, Perlin};
use rand::{thread_rng, Rng, SeedableRng};
use voronoice::{BoundingBox, Point, VoronoiBuilder};
@ -9,8 +9,9 @@ mod cells;
mod picking;
use picking::*;
use cells::*;
pub use cells::CellKind;
use crate::time::GameTime;
use crate::{time::GameTime, ui::CurrentAction};
pub struct Plugin;
impl bevy::prelude::Plugin for Plugin {
@ -154,23 +155,33 @@ fn setup(
mut cells: Query<&mut Cell>,
mut map_needs_update: Query<&mut MeshNeedsUpdate, With<MapMarker>>,
mut cmds: Commands,
gt: Res<GameTime>
ca: Res<CurrentAction>,
gt: Res<GameTime>,
| {
if trigger.duration > Duration::from_millis(200) {
return
}
let mut cell = cells.get_mut(trigger.target).unwrap();
match cell.kind {
CellKind::Dirt | CellKind::Grass => {
cmds.entity(trigger.target).insert((Wealth(0), Regeneration {
last_update: gt.current,
full_growth_duration: CellKind::Forest.regen_full_growth_duration()
}));
cell.kind = CellKind::Forest;
map_needs_update.single_mut().0 = true;
},
match *ca {
CurrentAction::ChangeCell(ck) => {
let mut cell = cells.get_mut(trigger.target).unwrap();
match ck {
CellKind::Forest => match cell.kind {
CellKind::Dirt | CellKind::Grass => {
cmds.entity(trigger.target).insert((Wealth(0), Regeneration {
last_update: gt.current,
full_growth_duration: CellKind::Forest.regen_full_growth_duration()
}));
cell.kind = CellKind::Forest;
map_needs_update.single_mut().0 = true;
},
_ => {}
},
_ => {}
}
}
_ => {}
}
});
cells_entities.push(cmd.id());
}

146
src/ui.rs
View File

@ -1,80 +1,116 @@
use std::collections::BTreeMap;
use mevy::*;
use bevy::{asset::embedded_asset, input::mouse::MouseWheel, math::{NormedVectorSpace, VectorSpace}, picking::{focus::HoverMap, pointer::PointerId}, prelude::*, utils::{dbg, HashMap}, window::PrimaryWindow};
use bevy::{input::mouse::MouseWheel, math::{NormedVectorSpace, VectorSpace}, picking::{focus::HoverMap, pointer::PointerId}, prelude::*, utils::HashMap, window::PrimaryWindow};
use crate::map::{self, MapMarker};
use crate::map::{self, CellKind, MapMarker};
pub struct Plugin;
impl bevy::prelude::Plugin for Plugin {
fn build(&self, app: &mut App) {
app.add_systems(Startup, setup)
app.init_resource::<CurrentAction>()
.add_systems(Startup, setup)
.add_systems(Update, zoom_with_scroll);
embedded_asset!(app, "../assets/ui/tree.png");
}
}
#[derive(Component)]
#[derive(Resource, Default)]
pub enum CurrentAction {
#[default]
None,
ChangeCell(CellKind)
}
#[derive(Component, Debug)]
struct PointersDragging(HashMap<PointerId, Vec2>);
#[derive(Component)]
pub struct MapUIComponent;
fn setup(
mut cmds: Commands
mut world: Commands,
asset_server: Res<AssetServer>
) {
cmds.spawn((
Node {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..default()
},
// Spawn all ui elements as children of this one
spawn!{
Node {width: 100%, height: 100%, display: Display::Flex, flex_direction: FlexDirection::Column, !};
PickingBehavior {
should_block_lower: false,
is_hoverable: true
},
MapUIComponent,
PointersDragging(HashMap::new())
)).observe(|trigger: Trigger<Pointer<DragStart>>, mut ptrs: Query<&mut PointersDragging>| {
let event = trigger.event();
// dbg!(event);
if event.button == PointerButton::Primary {
ptrs.get_mut(event.target).unwrap().0.insert(event.pointer_id, event.pointer_location.position);
}
}).observe(|trigger: Trigger<Pointer<DragEnd>>, mut ptrs: Query<&mut PointersDragging>| {
let event = trigger.event();
// dbg!(event);
if event.button == PointerButton::Primary {
ptrs.get_mut(event.target).unwrap().0.remove(&event.pointer_id);
}
}).observe(|
trigger: Trigger<Pointer<Drag>>,
mut ptrs: Query<&mut PointersDragging>,
mut cam: Query<&mut Transform, With<Camera2d>>,
| {
let event = trigger.event();
// dbg!(event);
if event.button == PointerButton::Primary {
let mut cam = cam.single_mut();
let mut ptrs = ptrs.get_mut(event.target).unwrap();
};
.observe(|trigger: Trigger<Pointer<DragEnd>>, mut ptrs: Query<&mut PointersDragging>| {
if trigger.button == PointerButton::Primary {
ptrs.single_mut().0.remove(&trigger.pointer_id);
}
});
.observe(|
trigger: Trigger<Pointer<Drag>>,
mut ptrs: Query<&mut PointersDragging>,
mut cam: Query<&mut Transform, With<Camera2d>>,
| {
if trigger.button == PointerButton::Primary {
let mut ptrs = ptrs.single_mut();
if !ptrs.0.contains_key(&trigger.pointer_id) {
return
}
let mut cam = cam.single_mut();
let old_midpoint = ptrs.0.values().fold(Vec2::ZERO, |acc, pos| acc + (pos/ptrs.0.len() as f32));
let old_d_to_midpoint = ptrs.0.values().fold(0., |acc, pos| acc + (old_midpoint-pos).norm());
ptrs.0.insert(trigger.pointer_id, trigger.pointer_location.position);
let new_midpoint = ptrs.0.values().fold(Vec2::ZERO, |acc, pos| acc + (pos/ptrs.0.len() as f32));
let new_d_to_midpoint = ptrs.0.values().fold(0., |acc, pos| acc + (new_midpoint-pos).norm());
// move camera
cam.translation.x -= (new_midpoint.x - old_midpoint.x)*cam.scale.x;
cam.translation.y += (new_midpoint.y - old_midpoint.y)*cam.scale.y;
let old_midpoint = ptrs.0.values().fold(Vec2::ZERO, |acc, pos| acc + (pos/ptrs.0.len() as f32));
let old_d_to_midpoint = ptrs.0.values().fold(0., |acc, pos| acc + (old_midpoint-pos).norm());
ptrs.0.insert(event.pointer_id, event.pointer_location.position);
let new_midpoint = ptrs.0.values().fold(Vec2::ZERO, |acc, pos| acc + (pos/ptrs.0.len() as f32));
let new_d_to_midpoint = ptrs.0.values().fold(0., |acc, pos| acc + (new_midpoint-pos).norm());
// move camera
cam.translation.x -= (new_midpoint.x - old_midpoint.x)*cam.scale.x;
cam.translation.y += (new_midpoint.y - old_midpoint.y)*cam.scale.y;
if ptrs.0.len() > 1 {
cam.scale *= old_d_to_midpoint/new_d_to_midpoint;
if ptrs.0.len() > 1 {
cam.scale *= old_d_to_midpoint/new_d_to_midpoint;
}
}
}
}
);
// Spawn all ui elements as children of this one
);
[map][
Node{
flex_grow: 1.,
!};
PointersDragging(HashMap::new());
MapUIComponent;
PickingBehavior {
should_block_lower: false,
is_hoverable: true
};
.observe(|trigger: Trigger<Pointer<DragStart>>, mut ptrs: Query<&mut PointersDragging>| {
if trigger.button == PointerButton::Primary {
if let Ok(mut ptrs) = ptrs.get_mut(trigger.target) {
ptrs.0.insert(trigger.pointer_id, trigger.pointer_location.position);
}
}
});
]
[
Node{
width: 100%,
height: 10vh,
align_self: AlignSelf::FlexEnd,
!};
Button;
BorderColor(#F00);
BackgroundColor(#77767b);
[
ImageNode::new(asset_server.load("embedded://forestiles/../assets/ui/tree.png"));
Node {
height: 80%,
margin: [>1vh],
!};
.observe(|trigger: Trigger<Pointer<Click>>, mut ca: ResMut<CurrentAction>| {
if trigger.button == PointerButton::Primary {
*ca = CurrentAction::ChangeCell(CellKind::Forest);
}
});
]
]
}
}
fn zoom_with_scroll(