use mittens_engine::{engine, utils};
use mittens_engine::engine::ecs::component::{
AmbientLightComponent, BackgroundColorComponent, BackgroundComponent, Camera3DComponent,
CameraXRComponent, ColorComponent, InputComponent, InputTransformModeComponent,
InputXRComponent, PointerComponent, RaycastableComponent, TextComponent, TextShadowComponent,
TextureComponent, TextureFilteringComponent, TransformComponent, TransparentCutoutComponent,
};
#[path = "example_util/mod.rs"]
mod example_util;
fn main() {
mittens_engine::example_support::ensure_model_assets();
utils::logger::init();
let world = engine::ecs::World::default();
let mut universe = engine::Universe::new(world);
let background = universe
.world
.add_component(BackgroundColorComponent::new());
let background_c = universe
.world
.add_component(ColorComponent::rgba(0.20, 0.2, 0.20, 1.0));
let _ = universe.world.add_child(background, background_c);
universe.add(background);
let ambient = universe
.world
.add_component(AmbientLightComponent::rgb(0.50, 0.50, 0.50));
universe.add(ambient);
let directional_tx = universe
.world
.add_component(TransformComponent::new().with_position(0.0, 0.5, 1.0));
let directional_light = universe.world.add_component(
engine::ecs::component::DirectionalLightComponent::new()
.with_color(1.0, 1.0, 1.0)
.with_intensity(0.8),
);
let _ = universe.attach(directional_tx, directional_light);
universe.add(directional_tx);
let bg_root = universe
.world
.add_component(BackgroundComponent::new().with_occlusion_and_lighting());
universe.add(bg_root);
let mut bg_cloud_params = example_util::CloudRingParams::default();
bg_cloud_params.cloud_count = 6;
bg_cloud_params.seed = 0xF0_17_C10u32;
example_util::spawn_cloud_ring(&mut universe, bg_root, bg_cloud_params);
let input = universe
.world
.add_component(InputComponent::new().with_speed(2.0));
let input_mode = universe
.world
.add_component(InputTransformModeComponent::forward_z().with_roll_axis_y());
let _ = universe.attach(input, input_mode);
let rig_transform = universe
.world
.add_component(TransformComponent::new().with_position(1.8, -0.5, 2.5));
let _ = universe.attach(input, rig_transform);
let camera = universe.world.add_component(Camera3DComponent::new());
let _ = universe.attach(rig_transform, camera);
let pointer = universe.world.add_component(PointerComponent::new());
let _ = universe.attach(camera, pointer);
example_util::spawn_desktop_camera_controls_hint(&mut universe, rig_transform);
universe.add(input);
let fg_cloud_root = universe
.world
.add_component(TransformComponent::new().with_position(0.0, -6.0, -10.0));
universe.add(fg_cloud_root);
let mut fg_cloud_params = example_util::CloudRingParams::default();
fg_cloud_params.cloud_count = 4;
fg_cloud_params.radius = 9.0;
fg_cloud_params.center_y = 1.0;
fg_cloud_params.puffs_per_cloud = 22;
fg_cloud_params.angle_jitter = 0.35;
fg_cloud_params.high_y_probability = 0.35;
fg_cloud_params.high_y_multiplier = 1.4;
fg_cloud_params.seed = 0xF0_17_C102u32;
example_util::spawn_cloud_ring(&mut universe, fg_cloud_root, fg_cloud_params);
fn estimate_text_height_world(text: &str, scale: f32) -> f32 {
let line_count = text.lines().count().max(1) as f32;
let pad_lines = 1.25;
(line_count + pad_lines) * scale
}
fn spawn_text_block(
universe: &mut engine::Universe,
position: (f32, f32, f32),
scale: f32,
text: &str,
font_texture_uri: Option<&str>,
text_color_rgba: Option<[f32; 4]>,
shadow: Option<TextShadowComponent>,
filtering: TextureFilteringComponent,
) -> f32 {
let text_root = universe.world.add_component(
TransformComponent::new().with_position(position.0, position.1, position.2),
);
let text_scale = universe
.world
.add_component(TransformComponent::new().with_scale(scale, scale, 1.0));
let _ = universe.attach(text_root, text_scale);
let text_parent = if let Some([r, g, b, a]) = text_color_rgba {
let color = universe
.world
.add_component(ColorComponent::rgba(r, g, b, a));
let _ = universe.attach(text_scale, color);
color
} else {
text_scale
};
let text_c = universe.world.add_component(TextComponent::new(text));
let _ = universe.attach(text_parent, text_c);
let raycastable = universe
.world
.add_component(RaycastableComponent::enabled());
let _ = universe.attach(text_c, raycastable);
let cutout = universe
.world
.add_component(TransparentCutoutComponent::new());
let _ = universe.attach(text_c, cutout);
if let Some(shadow) = shadow {
let shadow_id = universe.world.add_component(shadow);
let _ = universe.attach(text_c, shadow_id);
}
if let Some(uri) = font_texture_uri {
let tex = universe
.world
.add_component(TextureComponent::with_uri(uri));
let _ = universe.attach(text_c, tex);
}
let filtering_id = universe.world.add_component(filtering);
let _ = universe.attach(text_c, filtering_id);
universe.add(text_root);
estimate_text_height_world(text, scale)
}
const TEXT_BIG: &str = "CAT ENGINE\nfont example\nBIG TEXT";
const TEXT_MED: &str = "multi-line\ntext block\nmedium";
const TEXT_SMALL: &str = "small\ntext";
const TEXT_TINY: &str = "tiny\ntext\n(zoom in)";
let x = -1.2;
let z = -2.0;
let mut y = 1.2;
let gap = 0.15;
let shadow_crisp = Some(
TextShadowComponent::new()
.with_scale(1.35)
.with_offset([0.06, -0.06, 0.0015]),
);
y -= spawn_text_block(
&mut universe,
(x, y, z),
0.55,
TEXT_BIG,
None,
Some([1.0, 1.0, 1.0, 1.0]),
shadow_crisp,
TextureFilteringComponent::nearest_magnification(),
) + gap;
y -= spawn_text_block(
&mut universe,
(x, y, z),
0.25,
TEXT_MED,
None,
Some([0.60, 0.95, 1.00, 1.0]),
Some(
TextShadowComponent::new()
.with_rgba([0.0, 0.0, 0.15, 1.0])
.with_scale(1.20)
.with_offset([0.05, -0.04, 0.0015]),
),
TextureFilteringComponent::linear(),
) + gap;
y -= spawn_text_block(
&mut universe,
(x, y, z),
0.14,
TEXT_SMALL,
None,
Some([1.0, 0.88, 0.35, 1.0]),
Some(
TextShadowComponent::new()
.with_rgba([0.15, 0.0, 0.0, 1.0])
.with_scale(1.55)
.with_offset([0.08, -0.08, 0.0015]),
),
TextureFilteringComponent::nearest(),
) + gap;
let _ = spawn_text_block(
&mut universe,
(x, y, z),
0.08,
TEXT_TINY,
None,
Some([0.90, 1.0, 0.70, 1.0]),
shadow_crisp,
TextureFilteringComponent::nearest_magnification(),
);
const TEXT_LEFT: &str = "even though there's hexes\nto the solar plexus in my lexus\ni'm feelin' reckless,\nwhen i'm eating breakfast";
let _ = spawn_text_block(
&mut universe,
(x - 8.1, 1.1, z),
0.22,
TEXT_LEFT,
Some("assets/textures/font_system.dds"),
Some([0.95, 0.95, 0.95, 1.0]),
Some(
TextShadowComponent::new()
.with_scale(1.25)
.with_offset([0.05, -0.05, 0.0015]),
),
TextureFilteringComponent::nearest_magnification(),
);
let alt_atlas = Some("assets/textures/font_system.0.0.dds");
let alt_z = z - 0.05;
let alt_grey = Some([0.25, 0.25, 0.25, 1.0]);
let mut y_alt = 1.2;
y_alt -= spawn_text_block(
&mut universe,
(x, y_alt, alt_z),
0.55,
TEXT_BIG,
alt_atlas,
alt_grey,
Some(
TextShadowComponent::new()
.with_rgba([0.0, 0.0, 0.0, 1.0])
.with_scale(1.15)
.with_offset([0.03, -0.03, 0.0015]),
),
TextureFilteringComponent::linear(),
) + gap;
y_alt -= spawn_text_block(
&mut universe,
(x, y_alt, alt_z),
0.25,
TEXT_MED,
alt_atlas,
alt_grey,
Some(
TextShadowComponent::new()
.with_rgba([0.0, 0.0, 0.0, 1.0])
.with_scale(1.15)
.with_offset([0.03, -0.03, 0.0015]),
),
TextureFilteringComponent::linear(),
) + gap;
y_alt -= spawn_text_block(
&mut universe,
(x, y_alt, alt_z),
0.14,
TEXT_SMALL,
alt_atlas,
alt_grey,
Some(
TextShadowComponent::new()
.with_rgba([0.0, 0.0, 0.0, 1.0])
.with_scale(1.15)
.with_offset([0.03, -0.03, 0.0015]),
),
TextureFilteringComponent::linear(),
) + gap;
let _ = spawn_text_block(
&mut universe,
(x, y_alt, alt_z),
0.08,
TEXT_TINY,
alt_atlas,
alt_grey,
Some(
TextShadowComponent::new()
.with_rgba([0.0, 0.0, 0.0, 1.0])
.with_scale(1.15)
.with_offset([0.03, -0.03, 0.0015]),
),
TextureFilteringComponent::linear(),
);
universe.enable_repl();
let xr_input = universe.world.add_component(InputXRComponent::on());
let xr_gamepad = universe
.world
.add_component(engine::ecs::component::InputXRGamepadComponent::new().speed(1.5));
let xr_head = universe.world.add_component(TransformComponent::new());
let xr_camera = universe.world.add_component(CameraXRComponent::on());
let _ = universe.attach(xr_input, xr_head);
let _ = universe.attach(xr_input, xr_gamepad);
let _ = universe.attach(xr_head, xr_camera);
universe.add(xr_input);
let xr_root = universe
.world
.add_component(engine::ecs::component::XrComponent::on());
universe.add(xr_root);
universe.systems.process_commands(
&mut universe.world,
&mut universe.visuals,
&mut universe.render_assets,
&mut universe.command_queue,
);
engine::Windowing::run_app(universe).expect("Windowing failed");
}