Skip to content

Commit

Permalink
Merge pull request #941 from AmbientRun/misc-fixes
Browse files Browse the repository at this point in the history
Misc fixes
  • Loading branch information
philpax authored Sep 22, 2023
2 parents 4a5e2b0 + cffb59b commit 857ce7e
Show file tree
Hide file tree
Showing 18 changed files with 185 additions and 46 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 19 additions & 5 deletions app/src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,16 @@ use ambient_element::{
consume_context, element_component, use_effect, use_ref_with, use_spawn, use_state,
use_state_with, Element, ElementComponentExt, Group, Hooks,
};
use ambient_native_std::{asset_cache::AssetCache, cb, friendly_id};
use ambient_native_std::{
asset_cache::{AssetCache, SyncAssetKeyExt},
cb,
};
use ambient_network::{
client::{client_network_stats, GameClientRenderTarget},
hooks::use_remote_resource,
native::client::{ClientView, ResolvedAddr},
};
use ambient_settings::SettingsKey;
use ambient_sys::time::Instant;
use ambient_ui_native::{Dock, WindowSized};
use glam::uvec2;
Expand All @@ -39,10 +43,20 @@ pub fn run(
golden_image_output_dir: Option<PathBuf>,
mixer: Option<AudioMixer>,
) -> ExitStatus {
let user_id = run
.user_id
.clone()
.unwrap_or_else(|| format!("user_{}", friendly_id()));
let settings = SettingsKey.get(&assets);

let user_id = match run.user_id.clone().or(settings.general.user_id) {
Some(user_id) => user_id,
None => {
let user_id = ambient_client_shared::util::random_username();
log::warn!(
"No `user_id` found in settings, using random username: {:?}",
user_id
);
user_id
}
};

let headless = if run.headless {
Some(uvec2(600, 600))
} else {
Expand Down
1 change: 1 addition & 0 deletions crates/client_shared/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ ambient_debugger = { path = "../debugger/" , version = "0.3.0-dev" }
ambient_ecs_editor = { path = "../ecs_editor/" , version = "0.3.0-dev" }

glam = { workspace = true }
rand = { workspace = true }
1 change: 1 addition & 0 deletions crates/client_shared/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
pub mod game_view;
pub mod player;
pub mod util;
56 changes: 56 additions & 0 deletions crates/client_shared/src/util.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
use rand::seq::SliceRandom;

/// Generates an adjective-animal username.
pub fn random_username() -> String {
const ADJECTIVES: &[&str] = &[
"Quirky",
"Sneaky",
"Witty",
"Curious",
"Grumpy",
"Silly",
"Mischievous",
"Goofy",
"Hasty",
"Awkward",
"Zany",
"Peculiar",
"Whimsical",
"Bumbling",
"Absurd",
"Oddball",
"Clumsy",
"Nutty",
"Haphazard",
"Eccentric",
];

const ANIMALS: &[&str] = &[
"Penguin",
"Platypus",
"Lemur",
"Armadillo",
"Sloth",
"Ostrich",
"Tapir",
"Narwhal",
"Chameleon",
"Aardvark",
"Quokka",
"Wombat",
"Kakapo",
"Capybara",
"Mandrill",
"Axolotl",
"Blobfish",
"Echidna",
"Wallaby",
];

let mut rng = rand::thread_rng();
format!(
"{}{}",
ADJECTIVES.choose(&mut rng).unwrap(),
ANIMALS.choose(&mut rng).unwrap()
)
}
1 change: 1 addition & 0 deletions crates/settings/src/general.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Clone, Default, Debug)]
pub struct GeneralSettings {
pub user_id: Option<String>,
pub api_token: Option<String>,
pub sentry: Sentry,
}
Expand Down
2 changes: 1 addition & 1 deletion docs/src/tutorials/game/6_ui.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Add the following to `client.rs`:
```rust
#[element_component]
fn PlayerPosition(hooks: &mut Hooks) -> Element {
let (pos, _) = use_entity_component(hooks, player::get_local(), translation());
let pos = use_entity_component(hooks, player::get_local(), translation());
Text::el(format!("Player position: {}", pos.unwrap_or_default()))
}
```
Expand Down
4 changes: 2 additions & 2 deletions guest/rust/packages/games/afps/core/fpsui/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub fn main() {

#[element_component]
pub fn App(hooks: &mut Hooks) -> Element {
let (player_name, _) = use_entity_component(hooks, player::get_local(), player_name());
let player_name = use_entity_component(hooks, player::get_local(), player_name());

if player_name.is_none() {
JoinScreen::el()
Expand Down Expand Up @@ -121,7 +121,7 @@ fn Crosshair(hooks: &mut Hooks) -> Element {

#[element_component]
fn Hud(hooks: &mut Hooks) -> Element {
let (local_health, _) = use_entity_component(hooks, player::get_local(), health());
let local_health = use_entity_component(hooks, player::get_local(), health());

WindowSized::el([Dock::el([Text::el(format!(
"health: {:?}",
Expand Down
3 changes: 1 addition & 2 deletions guest/rust/packages/games/tangent/core/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ fn handle_explosions() {

#[element_component]
fn CoreUI(_hooks: &mut Hooks) -> Element {
let vehicle_id = use_entity_component(_hooks, player::get_local(), pc::vehicle_ref()).0;
let vehicle_id = use_entity_component(_hooks, player::get_local(), pc::vehicle_ref());

if let Some(vehicle_id) = vehicle_id {
Crosshair::el(vehicle_id)
Expand All @@ -226,7 +226,6 @@ fn CoreUI(_hooks: &mut Hooks) -> Element {
fn Crosshair(hooks: &mut Hooks, vehicle_id: EntityId) -> Element {
let input_aim_direction =
use_entity_component(hooks, player::get_local(), pc::input_aim_direction())
.0
.unwrap_or_default();

let Some(active_camera_id) = camera::get_active(None) else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,7 @@ pub fn main() {

#[element_component]
pub fn App(hooks: &mut Hooks) -> Element {
let has_class = use_entity_component(hooks, player::get_local(), pc::vehicle_class())
.0
.is_some();
let has_class = use_entity_component(hooks, player::get_local(), pc::vehicle_class()).is_some();

let (toggle, set_toggle) = use_state(hooks, false);
use_keyboard_input(hooks, {
Expand Down Expand Up @@ -50,8 +48,7 @@ pub fn App(hooks: &mut Hooks) -> Element {

#[element_component]
pub fn ClassSelection(hooks: &mut Hooks, hide: Cb<dyn Fn() + Send + Sync>) -> Element {
let (player_class_id, _) =
use_entity_component(hooks, player::get_local(), pc::vehicle_class());
let player_class_id = use_entity_component(hooks, player::get_local(), pc::vehicle_class());

let mut classes = use_query(hooks, VehicleClass::as_query());
classes.sort_by_key(|(_, c)| c.name.clone());
Expand Down
11 changes: 3 additions & 8 deletions guest/rust/packages/games/tangent/mods/ui_holohud/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,19 @@ pub fn main() {

#[element_component]
fn Hud(hooks: &mut Hooks) -> Element {
let vehicle_id = use_entity_component(hooks, player::get_local(), pc::vehicle_ref()).0;
let vehicle_id = use_entity_component(hooks, player::get_local(), pc::vehicle_ref());
vehicle_id.map(VehicleHud::el).unwrap_or_default()
}

#[element_component]
fn VehicleHud(hooks: &mut Hooks, vehicle_id: EntityId) -> Element {
let health = use_entity_component(hooks, vehicle_id, vc::health())
.0
.unwrap_or_default();
let health = use_entity_component(hooks, vehicle_id, vc::health()).unwrap_or_default();

let max_health =
use_entity_component(hooks, vehicle_id, vdc::general::components::max_health())
.0
.unwrap_or_default();

let speed = use_entity_component(hooks, vehicle_id, vcc::speed_kph())
.0
.unwrap_or_default();
let speed = use_entity_component(hooks, vehicle_id, vcc::speed_kph()).unwrap_or_default();

let health_color = vec3(0.86, 0.08, 0.24)
.lerp(vec3(0.54, 0.72, 0.00), health / max_health)
Expand Down
13 changes: 6 additions & 7 deletions guest/rust/packages/tools/editor/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,8 @@ pub fn main() {

#[element_component]
pub fn App(hooks: &mut Hooks) -> Element {
let in_editor = use_entity_component(hooks, player::get_local(), in_editor())
.0
.unwrap_or_default();
let in_editor =
use_entity_component(hooks, player::get_local(), in_editor()).unwrap_or_default();

use_keyboard_input(hooks, move |_, keycode, modifiers, pressed| {
if modifiers == ModifiersState::empty() && keycode == Some(VirtualKeyCode::F5) && !pressed {
Expand Down Expand Up @@ -232,8 +231,8 @@ fn MenuBar(_hooks: &mut Hooks, menu_bar_items: HashSet<(EntityId, String)>) -> E
#[element_component]
fn MouseoverDisplay(hooks: &mut Hooks) -> Element {
let player_id = player::get_local();
let (mouseover_position, _) = use_entity_component(hooks, player_id, mouseover_position());
let (camera_id, _) = use_entity_component(hooks, player_id, editor_camera());
let mouseover_position = use_entity_component(hooks, player_id, mouseover_position());
let camera_id = use_entity_component(hooks, player_id, editor_camera());

let Some(mouseover_position) = mouseover_position else {
return Element::new();
Expand All @@ -253,8 +252,8 @@ fn MouseoverDisplay(hooks: &mut Hooks) -> Element {
#[element_component]
fn SelectedDisplay(hooks: &mut Hooks) -> Element {
let player_id = player::get_local();
let (selected_entity, _) = use_entity_component(hooks, player_id, selected_entity());
let (camera_id, _) = use_entity_component(hooks, player_id, editor_camera());
let selected_entity = use_entity_component(hooks, player_id, selected_entity());
let camera_id = use_entity_component(hooks, player_id, editor_camera());

// TODO: is there a better way to force this element to re-render every frame?
let rerender = use_rerender_signal(hooks);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ pub fn PackageManager(hooks: &mut Hooks) -> Element {
hooks,
packages::this::entity(),
packages::this::components::mod_manager_for(),
)
.0;
);

let title = if mod_manager_for.is_some() {
"Mod Manager".to_string()
Expand Down
15 changes: 7 additions & 8 deletions shared_crates/element/src/hooks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -582,10 +582,9 @@ pub fn use_query<
}

#[cfg(feature = "guest")]
/// Use a component from an entity in the ECS, and update its state if required.
/// Use a component from an entity in the ECS.
///
/// If the entity or component does not exist, this will return `None`.
/// The setter will add the component if it does not exist.
pub fn use_entity_component<
T: ambient_guest_bridge::api::ecs::SupportedValue
+ Clone
Expand All @@ -598,7 +597,7 @@ pub fn use_entity_component<
hooks: &mut Hooks,
id: EntityId,
component: ambient_guest_bridge::api::ecs::Component<T>,
) -> (Option<T>, Setter<T>) {
) -> Option<T> {
use ambient_guest_bridge::api::prelude::{change_query, entity};

let refresh = use_rerender_signal(hooks);
Expand All @@ -612,10 +611,7 @@ pub fn use_entity_component<
}
});

(
entity::get_component(id, component),
cb(move |value| entity::add_component(id, component, value)),
)
entity::get_component(id, component)
}

#[cfg(feature = "guest")]
Expand All @@ -637,7 +633,10 @@ pub fn use_resource<
) -> (Option<T>, Setter<T>) {
use ambient_guest_bridge::api::entity;

use_entity_component(hooks, entity::resources(), component)
(
use_entity_component(hooks, entity::resources(), component),
cb(move |value| entity::add_component(entity::resources(), component, value)),
)
}

#[cfg(feature = "guest")]
Expand Down
57 changes: 56 additions & 1 deletion shared_crates/ui/src/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use ambient_guest_bridge::core::{
hierarchy::components::children,
transform::components::{local_to_parent, local_to_world, translation},
};
use glam::{vec2, vec3, Mat4, Vec2, Vec3};
use glam::{vec2, vec3, Mat4, Vec2, Vec3, Vec3Swizzles};
use itertools::Itertools;

pub use ambient_guest_bridge::core::layout::{
Expand Down Expand Up @@ -231,6 +231,61 @@ pub fn MeasureAbsolutePosition(
inner.on_spawned(move |_, id, _| set_id(Some(id)))
}

/// Sets the `translation` of `inner` to offset its size in the selected axes.
/// Note that you will have to use another mechanism to move the inner element as a result.
///
/// Consider using layout centering where possible.
#[element_component]
pub fn LayoutFreeCenter(
hooks: &mut Hooks,
/// The element to center. Must have the corresponding size component(s) set (`width`, `height`).
inner: Element,
/// Whether or not to center on the X axis.
center_x: bool,
/// Whether or not to center on the Y axis.
center_y: bool,
) -> Element {
#[derive(Default, Clone, PartialEq, Debug)]
struct State {
width: f32,
height: f32,
scale: Vec2,
}

let (id, set_id) = use_state(hooks, None);
let (current, set_current) = use_state(hooks, State::default());

let mut offset = Vec3::ZERO;
if center_x {
offset.x -= (current.width / 2.0) * current.scale.x;
}
if center_y {
offset.y -= (current.height / 2.0) * current.scale.y;
}

use_frame(hooks, move |world| {
if let Some(id) = id {
let width = world.get(id, width()).unwrap_or(0.);
let height = world.get(id, height()).unwrap_or(0.);
let ltw = world.get(id, local_to_world()).unwrap_or_default();
let (scale, _, _) = ltw.to_scale_rotation_translation();

let state = State {
width,
height,
scale: scale.xy(),
};

if current != state {
set_current(state);
}
}
});
inner
.on_spawned(move |_, id, _| set_id(Some(id)))
.with(translation(), offset)
}

#[element_component]
/// A simple separator, similar to `<hr>` in HTML.
pub fn Separator(
Expand Down
Loading

0 comments on commit 857ce7e

Please sign in to comment.