|
|
|
@ -17,6 +17,8 @@ fn main() {
|
|
|
|
})
|
|
|
|
})
|
|
|
|
.add_plugins(MonologueAssetsPlugin)
|
|
|
|
.add_plugins(MonologueAssetsPlugin)
|
|
|
|
.add_event::<DialogEvent>()
|
|
|
|
.add_event::<DialogEvent>()
|
|
|
|
|
|
|
|
.add_event::<PlantTree>()
|
|
|
|
|
|
|
|
.add_event::<AssignMonologue>()
|
|
|
|
.init_state::<DialogState>()
|
|
|
|
.init_state::<DialogState>()
|
|
|
|
.insert_resource(ClearColor(WHITE.into()))
|
|
|
|
.insert_resource(ClearColor(WHITE.into()))
|
|
|
|
.add_systems(
|
|
|
|
.add_systems(
|
|
|
|
@ -43,6 +45,8 @@ fn main() {
|
|
|
|
.run_if(in_state(DialogState::Idle))
|
|
|
|
.run_if(in_state(DialogState::Idle))
|
|
|
|
.run_if(on_event::<Pointer<Click>>),
|
|
|
|
.run_if(on_event::<Pointer<Click>>),
|
|
|
|
spawn_debug_buttons.run_if(on_event::<AssetEvent<Monologue>>),
|
|
|
|
spawn_debug_buttons.run_if(on_event::<AssetEvent<Monologue>>),
|
|
|
|
|
|
|
|
handle_plant_tree.run_if(on_event::<PlantTree>),
|
|
|
|
|
|
|
|
assign_monologue_to_tree.run_if(on_event::<AssignMonologue>),
|
|
|
|
dialog_engine.run_if(on_event::<DialogEvent>),
|
|
|
|
dialog_engine.run_if(on_event::<DialogEvent>),
|
|
|
|
auto_scroll.run_if(any_component_added::<DialogOption>),
|
|
|
|
auto_scroll.run_if(any_component_added::<DialogOption>),
|
|
|
|
dialog_box_visibility.run_if(state_changed::<DialogState>),
|
|
|
|
dialog_box_visibility.run_if(state_changed::<DialogState>),
|
|
|
|
@ -57,7 +61,6 @@ fn main() {
|
|
|
|
.add_observer(add_dialog_option)
|
|
|
|
.add_observer(add_dialog_option)
|
|
|
|
.add_observer(add_tree_monologue)
|
|
|
|
.add_observer(add_tree_monologue)
|
|
|
|
.add_observer(remove_tree_monologue)
|
|
|
|
.add_observer(remove_tree_monologue)
|
|
|
|
.add_observer(populate_tree)
|
|
|
|
|
|
|
|
.add_observer(show_monologue_list)
|
|
|
|
.add_observer(show_monologue_list)
|
|
|
|
.add_observer(hide_monologue_list)
|
|
|
|
.add_observer(hide_monologue_list)
|
|
|
|
.run();
|
|
|
|
.run();
|
|
|
|
@ -119,13 +122,29 @@ struct MonologuePreview;
|
|
|
|
|
|
|
|
|
|
|
|
/// Panel for selecting which monologue tree to spawn
|
|
|
|
/// Panel for selecting which monologue tree to spawn
|
|
|
|
fn init_debug_ui(mut commands: Commands) {
|
|
|
|
fn init_debug_ui(mut commands: Commands) {
|
|
|
|
let button = commands
|
|
|
|
commands.spawn((
|
|
|
|
|
|
|
|
Name::new("Tree Planter"),
|
|
|
|
|
|
|
|
Text::new("+Tree"),
|
|
|
|
|
|
|
|
Node {
|
|
|
|
|
|
|
|
top: Val::Px(0.0),
|
|
|
|
|
|
|
|
left: Val::Px(0.0),
|
|
|
|
|
|
|
|
min_width: Val::Px(25.0),
|
|
|
|
|
|
|
|
min_height: Val::Px(25.0),
|
|
|
|
|
|
|
|
..default()
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
BackgroundColor(RED.into()),
|
|
|
|
|
|
|
|
DebuggingState::On,
|
|
|
|
|
|
|
|
MonologuesContainer,
|
|
|
|
|
|
|
|
Button,
|
|
|
|
|
|
|
|
)).observe(spawn_tree);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let monologue_button = commands
|
|
|
|
.spawn((
|
|
|
|
.spawn((
|
|
|
|
Name::new("Monologue Assignment Menu"),
|
|
|
|
Name::new("Monologue Assignment Menu"),
|
|
|
|
Text::new("+Monologue"),
|
|
|
|
Text::new("+Monologue"),
|
|
|
|
Node {
|
|
|
|
Node {
|
|
|
|
align_self: AlignSelf::Start,
|
|
|
|
top: Val::Px(25.0),
|
|
|
|
justify_self: JustifySelf::Start,
|
|
|
|
left: Val::Px(0.0),
|
|
|
|
min_width: Val::Px(25.0),
|
|
|
|
min_width: Val::Px(25.0),
|
|
|
|
min_height: Val::Px(25.0),
|
|
|
|
min_height: Val::Px(25.0),
|
|
|
|
..default()
|
|
|
|
..default()
|
|
|
|
@ -137,12 +156,12 @@ fn init_debug_ui(mut commands: Commands) {
|
|
|
|
.id();
|
|
|
|
.id();
|
|
|
|
commands
|
|
|
|
commands
|
|
|
|
.spawn((
|
|
|
|
.spawn((
|
|
|
|
NavParent(button),
|
|
|
|
NavParent(monologue_button),
|
|
|
|
NavState::default(),
|
|
|
|
NavState::default(),
|
|
|
|
Name::new("Container"),
|
|
|
|
Name::new("Container"),
|
|
|
|
Node {
|
|
|
|
Node {
|
|
|
|
flex_direction: FlexDirection::Row,
|
|
|
|
flex_direction: FlexDirection::Row,
|
|
|
|
top: Val::Px(25.0),
|
|
|
|
top: Val::Px(50.0),
|
|
|
|
height: Val::Percent(90.0),
|
|
|
|
height: Val::Percent(90.0),
|
|
|
|
width: Val::Percent(80.0),
|
|
|
|
width: Val::Percent(80.0),
|
|
|
|
..default()
|
|
|
|
..default()
|
|
|
|
@ -166,7 +185,7 @@ fn init_debug_ui(mut commands: Commands) {
|
|
|
|
parent.spawn((
|
|
|
|
parent.spawn((
|
|
|
|
Name::new("Preview"),
|
|
|
|
Name::new("Preview"),
|
|
|
|
MonologuePreview,
|
|
|
|
MonologuePreview,
|
|
|
|
NavParent(button),
|
|
|
|
NavParent(monologue_button),
|
|
|
|
NavState::default(),
|
|
|
|
NavState::default(),
|
|
|
|
Node {
|
|
|
|
Node {
|
|
|
|
flex_direction: FlexDirection::Column,
|
|
|
|
flex_direction: FlexDirection::Column,
|
|
|
|
@ -452,24 +471,30 @@ fn monologue_asset_tooltip(
|
|
|
|
mut over_events: EventReader<Pointer<Over>>,
|
|
|
|
mut over_events: EventReader<Pointer<Over>>,
|
|
|
|
mut out_events: EventReader<Pointer<Out>>,
|
|
|
|
mut out_events: EventReader<Pointer<Out>>,
|
|
|
|
mut tooltip: ResMut<ToolTip>,
|
|
|
|
mut tooltip: ResMut<ToolTip>,
|
|
|
|
scripts: Query<&TreeMonologue>,
|
|
|
|
trees: Query<(&Tree, Option<&TreeMonologue>)>,
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
out_events
|
|
|
|
out_events
|
|
|
|
.read()
|
|
|
|
.read()
|
|
|
|
.filter_map(|Pointer { target, .. }| scripts.contains(*target).then_some(*target))
|
|
|
|
.filter_map(|Pointer { target, .. }| trees.contains(*target).then_some(*target))
|
|
|
|
.for_each(|_| {
|
|
|
|
.for_each(|_| {
|
|
|
|
tooltip.remove("Script");
|
|
|
|
tooltip.remove("Script");
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
over_events
|
|
|
|
over_events
|
|
|
|
.read()
|
|
|
|
.read()
|
|
|
|
.filter_map(|Pointer { target, .. }| scripts.contains(*target).then_some(*target))
|
|
|
|
.filter_map(|Pointer { target, .. }| trees.contains(*target).then_some(*target))
|
|
|
|
.for_each(|e| {
|
|
|
|
.for_each(|e| {
|
|
|
|
if let Ok(TreeMonologue(handle)) = scripts.get(e) {
|
|
|
|
match trees.get(e) {
|
|
|
|
|
|
|
|
Ok((_tree, Some(TreeMonologue(handle)))) => {
|
|
|
|
match handle.path() {
|
|
|
|
match handle.path() {
|
|
|
|
Some(p) => tooltip.insert("Script", format!("{p}")),
|
|
|
|
Some(p) => tooltip.insert("Script", format!("{p}")),
|
|
|
|
None => tooltip.insert("Script", "???".into()),
|
|
|
|
None => tooltip.insert("Script", "A".into()),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
Ok((_tree, None)) => {
|
|
|
|
|
|
|
|
tooltip.insert("Script", "N/A".into());
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
_ => ()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -576,7 +601,6 @@ fn spawn_debug_buttons(
|
|
|
|
BackgroundColor(PINK.into()),
|
|
|
|
BackgroundColor(PINK.into()),
|
|
|
|
))
|
|
|
|
))
|
|
|
|
.observe(preview_monologue)
|
|
|
|
.observe(preview_monologue)
|
|
|
|
.observe(spawn_monologue_tree)
|
|
|
|
|
|
|
|
.observe(toggle_debug_button_color_over)
|
|
|
|
.observe(toggle_debug_button_color_over)
|
|
|
|
.observe(toggle_debug_button_color_out);
|
|
|
|
.observe(toggle_debug_button_color_out);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
@ -665,30 +689,21 @@ fn hide_monologue_list(
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn spawn_monologue_tree(
|
|
|
|
#[derive(Event)]
|
|
|
|
trigger: Trigger<Pointer<Click>>,
|
|
|
|
struct PlantTree;
|
|
|
|
tree_monologues: Query<&TreeMonologue, With<Button>>,
|
|
|
|
|
|
|
|
mut commands: Commands,
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
let tree_monologue = tree_monologues.get(trigger.target()).unwrap();
|
|
|
|
|
|
|
|
info!("Spawning monologuing tree");
|
|
|
|
|
|
|
|
commands.spawn((Tree, tree_monologue.clone()));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// When a monologuing tree is added, give it a mesh, a material, and a position in space
|
|
|
|
/// Plan a tree in the world
|
|
|
|
///
|
|
|
|
/// Handles random placement, 3d model, materials, and observers
|
|
|
|
/// TODO: This can be an `on_add` hook intead, just a little more clunky
|
|
|
|
fn handle_plant_tree(
|
|
|
|
fn populate_tree(
|
|
|
|
mut events: EventReader<PlantTree>,
|
|
|
|
trigger: Trigger<OnAdd, TreeMonologue>,
|
|
|
|
|
|
|
|
trees: Query<Entity, With<Tree>>,
|
|
|
|
trees: Query<Entity, With<Tree>>,
|
|
|
|
server: Res<AssetServer>,
|
|
|
|
server: Res<AssetServer>,
|
|
|
|
mut commands: Commands,
|
|
|
|
mut commands: Commands,
|
|
|
|
mut meshes: ResMut<Assets<Mesh>>,
|
|
|
|
mut meshes: ResMut<Assets<Mesh>>,
|
|
|
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
|
|
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
if !trees.contains(trigger.target()) {
|
|
|
|
events.read().for_each(|_event| {
|
|
|
|
return;
|
|
|
|
let mut tree = commands.spawn(Tree);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Generate "random" X and Y Coordinates for this tree
|
|
|
|
// Generate "random" X and Y Coordinates for this tree
|
|
|
|
// 1. Take the top 2 bytes
|
|
|
|
// 1. Take the top 2 bytes
|
|
|
|
@ -696,7 +711,7 @@ fn populate_tree(
|
|
|
|
// 3. Re-interpret as i8s
|
|
|
|
// 3. Re-interpret as i8s
|
|
|
|
// 4. Cast to f32
|
|
|
|
// 4. Cast to f32
|
|
|
|
let transform = {
|
|
|
|
let transform = {
|
|
|
|
let n = RandomState::default().hash_one(trigger.target());
|
|
|
|
let n = RandomState::default().hash_one(tree.id());
|
|
|
|
let [a, b, ..] = n.to_be_bytes();
|
|
|
|
let [a, b, ..] = n.to_be_bytes();
|
|
|
|
|
|
|
|
|
|
|
|
let x: f32 = a.cast_signed().wrapping_div(4).into();
|
|
|
|
let x: f32 = a.cast_signed().wrapping_div(4).into();
|
|
|
|
@ -709,20 +724,36 @@ fn populate_tree(
|
|
|
|
|
|
|
|
|
|
|
|
let material = MeshMaterial3d(materials.add(StandardMaterial {
|
|
|
|
let material = MeshMaterial3d(materials.add(StandardMaterial {
|
|
|
|
base_color_texture: Some(server.load("trees/placeholder/tree.png")),
|
|
|
|
base_color_texture: Some(server.load("trees/placeholder/tree.png")),
|
|
|
|
base_color: WHITE.into(),
|
|
|
|
base_color: WHITE.with_alpha(0.9).into(),
|
|
|
|
alpha_mode: AlphaMode::Blend,
|
|
|
|
alpha_mode: AlphaMode::Blend,
|
|
|
|
..default()
|
|
|
|
..default()
|
|
|
|
}));
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
let mesh = Mesh3d(meshes.add(Plane3d::new(Vec3::Y, Vec2::splat(1.0))));
|
|
|
|
let mesh = Mesh3d(meshes.add(Plane3d::new(Vec3::Y, Vec2::splat(1.0))));
|
|
|
|
|
|
|
|
|
|
|
|
debug!("Fleshing out monologuing tree");
|
|
|
|
tree.insert((mesh, material, transform))
|
|
|
|
|
|
|
|
|
|
|
|
commands
|
|
|
|
|
|
|
|
.entity(trigger.target())
|
|
|
|
|
|
|
|
.insert((mesh, material, transform))
|
|
|
|
|
|
|
|
.observe(delete_tree)
|
|
|
|
.observe(delete_tree)
|
|
|
|
.observe(drag_tree);
|
|
|
|
.observe(drag_tree);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Event)]
|
|
|
|
|
|
|
|
struct AssignMonologue(Handle<Monologue>);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Assign the given monologue to a tree
|
|
|
|
|
|
|
|
fn assign_monologue_to_tree(
|
|
|
|
|
|
|
|
mut events: EventReader<AssignMonologue>,
|
|
|
|
|
|
|
|
query: Query<Entity, (With<Tree>, Without<TreeMonologue>)>,
|
|
|
|
|
|
|
|
mut commands: Commands,
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
events.read().for_each(|event| {
|
|
|
|
|
|
|
|
// Get a valid tree to assign an entity to
|
|
|
|
|
|
|
|
let tree = query.iter().next().unwrap();
|
|
|
|
|
|
|
|
// Create the TreeMonologue component
|
|
|
|
|
|
|
|
let monologue = TreeMonologue(event.0.clone());
|
|
|
|
|
|
|
|
// Insert the component to the entity
|
|
|
|
|
|
|
|
commands.entity(tree).insert(monologue);
|
|
|
|
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn drag_tree(
|
|
|
|
fn drag_tree(
|
|
|
|
@ -823,3 +854,11 @@ fn control_menu(
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Observer for the "Plant a new tree" button in the debug UI
|
|
|
|
|
|
|
|
fn spawn_tree(
|
|
|
|
|
|
|
|
_trigger: Trigger<Pointer<Click>>,
|
|
|
|
|
|
|
|
mut events: EventWriter<PlantTree>,
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
events.write(PlantTree);
|
|
|
|
|
|
|
|
}
|
|
|
|
|