|
|
|
|
@ -7,12 +7,12 @@ impl Plugin for DicePlugin {
|
|
|
|
|
fn build(&self, app: &mut App) {
|
|
|
|
|
app.add_event::<DiceAction>();
|
|
|
|
|
app.add_systems(Startup, init_dice_ui);
|
|
|
|
|
app.add_systems(Startup, init_dice_cuboid.before(init_dice));
|
|
|
|
|
app.add_systems(Startup, init_dice);
|
|
|
|
|
app.add_systems(
|
|
|
|
|
Update,
|
|
|
|
|
button_emit_event::<DiceAction>.run_if(any_component_changed::<Interaction>),
|
|
|
|
|
);
|
|
|
|
|
app.add_systems(Update, draw_die.run_if(any_component_changed::<Die>));
|
|
|
|
|
app.add_systems(Update, roll_die.run_if(on_event::<DiceAction>()));
|
|
|
|
|
app.add_systems(Update, move_die.run_if(on_event::<KeyboardInput>()));
|
|
|
|
|
}
|
|
|
|
|
@ -23,6 +23,36 @@ enum DiceAction {
|
|
|
|
|
Roll,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[rustfmt::skip]
|
|
|
|
|
fn init_dice_cuboid(mut commands: Commands, mut meshes: ResMut<Assets<Mesh>>) {
|
|
|
|
|
// Store handle to mesh for later use
|
|
|
|
|
let cube_size = 1.0;
|
|
|
|
|
let a = 1.0 / 6.0;
|
|
|
|
|
let b = 2.0 * a;
|
|
|
|
|
let c = 3.0 * a;
|
|
|
|
|
let d = 4.0 * a;
|
|
|
|
|
let e = 5.0 * a;
|
|
|
|
|
let f = 1.0;
|
|
|
|
|
let cuboid = Mesh::from(Cuboid::new(cube_size, cube_size, cube_size)).with_inserted_attribute(
|
|
|
|
|
Mesh::ATTRIBUTE_UV_0,
|
|
|
|
|
vec![
|
|
|
|
|
// Top side
|
|
|
|
|
[1.0, 0.0], [0.0, 0.0], [0.0, a], [1.0, a],
|
|
|
|
|
// Bottom side
|
|
|
|
|
[1.0, a], [0.0, a], [0.0, b], [1.0, b],
|
|
|
|
|
// Right side
|
|
|
|
|
[1.0, b], [0.0, b], [0.0, c], [1.0, c],
|
|
|
|
|
// Left side
|
|
|
|
|
[1.0, c], [0.0, c], [0.0, d], [1.0, d],
|
|
|
|
|
// Back side
|
|
|
|
|
[1.0, d], [0.0, d], [0.0, e], [1.0, e],
|
|
|
|
|
// Front side
|
|
|
|
|
[1.0, e], [0.0, e], [0.0, f], [1.0, f],
|
|
|
|
|
],
|
|
|
|
|
);
|
|
|
|
|
commands.insert_resource(DiceCuboid { mesh: meshes.add(cuboid) });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Create UI for the Dice game at startup
|
|
|
|
|
fn init_dice_ui(mut commands: Commands) {
|
|
|
|
|
commands
|
|
|
|
|
@ -67,11 +97,7 @@ fn init_dice_ui(mut commands: Commands) {
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn init_dice(
|
|
|
|
|
mut meshes: ResMut<Assets<Mesh>>,
|
|
|
|
|
mut materials: ResMut<Assets<ColorMaterial>>,
|
|
|
|
|
mut commands: Commands,
|
|
|
|
|
) {
|
|
|
|
|
fn init_dice(mut commands: Commands) {
|
|
|
|
|
[
|
|
|
|
|
["a", "b", "c", "d", "e", "f"],
|
|
|
|
|
["g", "h", "i", "j", "k", "l"],
|
|
|
|
|
@ -79,46 +105,18 @@ fn init_dice(
|
|
|
|
|
]
|
|
|
|
|
.into_iter()
|
|
|
|
|
.enumerate()
|
|
|
|
|
.for_each(|(idx, set)| {
|
|
|
|
|
.for_each(|(_idx, set)| {
|
|
|
|
|
commands
|
|
|
|
|
.spawn((
|
|
|
|
|
GameChoice::Dice,
|
|
|
|
|
MenuState::Closed,
|
|
|
|
|
Die::new(set),
|
|
|
|
|
PickableBundle { ..default() },
|
|
|
|
|
On::<Pointer<Drag>>::target_component_mut::<Transform>(|m, transform| {
|
|
|
|
|
transform.translation.x += m.delta.x;
|
|
|
|
|
transform.translation.y -= m.delta.y;
|
|
|
|
|
}),
|
|
|
|
|
))
|
|
|
|
|
.insert(MaterialMesh2dBundle {
|
|
|
|
|
mesh: meshes
|
|
|
|
|
.add(Rectangle {
|
|
|
|
|
half_size: Vec2::splat(32.0),
|
|
|
|
|
})
|
|
|
|
|
.into(),
|
|
|
|
|
material: materials.add(Color::PINK),
|
|
|
|
|
..default()
|
|
|
|
|
})
|
|
|
|
|
.insert(Text2dBundle {
|
|
|
|
|
text: Text::from_section(
|
|
|
|
|
"",
|
|
|
|
|
TextStyle {
|
|
|
|
|
color: Color::BLACK,
|
|
|
|
|
font_size: 32.0,
|
|
|
|
|
..default()
|
|
|
|
|
},
|
|
|
|
|
),
|
|
|
|
|
..default()
|
|
|
|
|
})
|
|
|
|
|
.insert(Transform::from_xyz(idx as f32 * 100.0, 100.0, 0.0));
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn draw_die(mut q: Query<(&Die, &mut Text), Changed<Die>>) {
|
|
|
|
|
q.iter_mut().for_each(|(d, mut t)| {
|
|
|
|
|
info!("Dice currently reads {:?}", d.get());
|
|
|
|
|
t.sections[0].value.replace_range(.., d.get());
|
|
|
|
|
.add(Die::new(set));
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -159,7 +157,6 @@ fn move_die(
|
|
|
|
|
}
|
|
|
|
|
_ => (),
|
|
|
|
|
}
|
|
|
|
|
info!("Moved die {:?}", t.translation);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
_ => (),
|
|
|
|
|
@ -175,6 +172,123 @@ struct Die {
|
|
|
|
|
top: usize,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Resource)]
|
|
|
|
|
struct DiceCuboid {
|
|
|
|
|
mesh: Handle<Mesh>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl EntityCommand for Die {
|
|
|
|
|
fn apply(self, id: Entity, world: &mut World) {
|
|
|
|
|
info!("Applying entity command for die");
|
|
|
|
|
|
|
|
|
|
// Image we will render our texture to
|
|
|
|
|
let image = {
|
|
|
|
|
let size = Extent3d {
|
|
|
|
|
width: 256,
|
|
|
|
|
height: 256 * 6,
|
|
|
|
|
..default()
|
|
|
|
|
};
|
|
|
|
|
let mut image = Image {
|
|
|
|
|
texture_descriptor: TextureDescriptor {
|
|
|
|
|
label: None,
|
|
|
|
|
size,
|
|
|
|
|
dimension: TextureDimension::D2,
|
|
|
|
|
format: TextureFormat::Bgra8UnormSrgb,
|
|
|
|
|
mip_level_count: 1,
|
|
|
|
|
sample_count: 1,
|
|
|
|
|
usage: TextureUsages::TEXTURE_BINDING
|
|
|
|
|
| TextureUsages::COPY_DST
|
|
|
|
|
| TextureUsages::RENDER_ATTACHMENT,
|
|
|
|
|
view_formats: &[],
|
|
|
|
|
},
|
|
|
|
|
..default()
|
|
|
|
|
};
|
|
|
|
|
image.resize(size);
|
|
|
|
|
image
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Create image
|
|
|
|
|
let image_handle = world.resource_mut::<Assets<Image>>().add(image);
|
|
|
|
|
|
|
|
|
|
// Camera capturing a hidden scene rendered to a texture
|
|
|
|
|
let texture_camera = world
|
|
|
|
|
.spawn(Camera2dBundle {
|
|
|
|
|
camera: Camera {
|
|
|
|
|
order: -1,
|
|
|
|
|
target: RenderTarget::Image(image_handle.clone()),
|
|
|
|
|
..default()
|
|
|
|
|
},
|
|
|
|
|
..default()
|
|
|
|
|
})
|
|
|
|
|
.id();
|
|
|
|
|
|
|
|
|
|
// Scene being rendered to a texture
|
|
|
|
|
world
|
|
|
|
|
.spawn((
|
|
|
|
|
NodeBundle {
|
|
|
|
|
style: Style {
|
|
|
|
|
width: Val::Percent(100.0),
|
|
|
|
|
height: Val::Percent(100.0),
|
|
|
|
|
flex_direction: FlexDirection::Column,
|
|
|
|
|
justify_content: JustifyContent::Center,
|
|
|
|
|
align_items: AlignItems::Center,
|
|
|
|
|
..default()
|
|
|
|
|
},
|
|
|
|
|
background_color: BackgroundColor(Color::GOLD),
|
|
|
|
|
..default()
|
|
|
|
|
},
|
|
|
|
|
TargetCamera(texture_camera),
|
|
|
|
|
))
|
|
|
|
|
.with_children(|parent| {
|
|
|
|
|
self.sides.iter().for_each(|text| {
|
|
|
|
|
parent
|
|
|
|
|
.spawn(NodeBundle {
|
|
|
|
|
style: Style {
|
|
|
|
|
height: Val::Percent(100.0 / 6.0),
|
|
|
|
|
width: Val::Percent(100.0),
|
|
|
|
|
justify_content: JustifyContent::Center,
|
|
|
|
|
justify_items: JustifyItems::Center,
|
|
|
|
|
align_items: AlignItems::Center,
|
|
|
|
|
align_content: AlignContent::Center,
|
|
|
|
|
..default()
|
|
|
|
|
},
|
|
|
|
|
..default()
|
|
|
|
|
})
|
|
|
|
|
.with_children(|parent| {
|
|
|
|
|
parent.spawn(TextBundle {
|
|
|
|
|
text: Text::from_section(
|
|
|
|
|
*text,
|
|
|
|
|
TextStyle {
|
|
|
|
|
color: Color::BLACK,
|
|
|
|
|
font_size: 64.0,
|
|
|
|
|
..default()
|
|
|
|
|
},
|
|
|
|
|
),
|
|
|
|
|
..default()
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Material used for this object
|
|
|
|
|
let this_material =
|
|
|
|
|
world
|
|
|
|
|
.resource_mut::<Assets<StandardMaterial>>()
|
|
|
|
|
.add(StandardMaterial {
|
|
|
|
|
base_color_texture: Some(image_handle),
|
|
|
|
|
..default()
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
let pbr_bundle = PbrBundle {
|
|
|
|
|
mesh: world.resource::<DiceCuboid>().mesh.clone(),
|
|
|
|
|
material: this_material.clone(),
|
|
|
|
|
..default()
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
world.entity_mut(id).insert((self, pbr_bundle.clone()));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Die {
|
|
|
|
|
/// Initialize all dice values
|
|
|
|
|
fn new(sides: [&'static str; 6]) -> Die {
|
|
|
|
|
|