input tested thoroughly, prepped for only raycasting and ecs work to make bare minimum

This commit is contained in:
Lillian Vixe 2024-04-11 03:22:48 -07:00
parent 5678a94cb8
commit 04acadd160
6 changed files with 409 additions and 111 deletions

View file

@ -1,15 +1,8 @@
use bevy::app::*;
mod vvedit;
mod vvlib;
use vvedit::editor_ui;
fn main() {
editor_ui::register_edit_ui(
// ^ constructs editor UI
vvedit::setup(
// ^ setup the window itself
&mut App::new(),
),
)
.run();
// pass in to editor
vvedit::setup(&mut App::new()).run();
}

View file

@ -4,7 +4,7 @@ use bevy::{diagnostic::FrameTimeDiagnosticsPlugin, prelude::*, window::WindowRes
use crate::vvlib::oct_asset::{self, OctAssetMarker, OctTreeAsset};
mod editor_bevy_shim;
mod editor_bevy_input_shim;
pub mod editor_ui;
mod orbit_camera;
@ -17,6 +17,8 @@ pub fn setup(app: &mut App) -> &mut App {
}),
..default()
}))
.add_plugins(oct_asset::OctAssetPlugin)
.init_asset::<oct_asset::OctTreeAsset>()
.add_systems(Startup, crate::vvlib::fps_display::setup_fps_counter)
.add_systems(
Update,
@ -25,10 +27,9 @@ pub fn setup(app: &mut App) -> &mut App {
crate::vvlib::fps_display::fps_counter_showhide,
),
)
.add_plugins(oct_asset::OctAssetPlugin)
.init_asset::<oct_asset::OctTreeAsset>()
.add_plugins(FrameTimeDiagnosticsPlugin::default())
.add_systems(Startup, startup)
.add_systems(Startup, startup);
editor_ui::register_edit_ui(app)
}
pub fn startup(
@ -57,8 +58,7 @@ pub fn startup(
))
.id();
commands.entity(parent).add_child(child);
let camera_and_light_transform =
Transform::from_xyz(1.8, 1.8, 1.8).looking_at(Vec3::ZERO, Vec3::Y);
let light_transform = Transform::from_xyz(1.8, 1.8, 1.8).looking_at(Vec3::ZERO, Vec3::Y);
commands.spawn(PointLightBundle {
point_light: PointLight {
@ -66,7 +66,7 @@ pub fn startup(
range: 100.0,
..default()
},
transform: camera_and_light_transform,
transform: light_transform,
..default()
});
}

View file

@ -0,0 +1,37 @@
use crate::vvlib::inputs::{BinaryInputBinding, BinaryInputID, InputRegister, InputRegisterPlugin};
use bevy::prelude::*;
pub fn setup_inputs(app: &mut bevy::app::App) -> &mut bevy::app::App {
app.add_plugins(InputRegisterPlugin);
app.add_systems(Startup, initiate_default_or_load_controls)
}
pub mod keybind_codes {
pub const INSERT_VOXEL: &str = "INSERT_VOXEL";
pub const REMOVE_VOXEL: &str = "REMOVE_VOXEL";
pub const PAINT_VOXEL: &str = "PAINT_VOXEL";
}
pub fn initiate_default_or_load_controls(
// system that will setup default keybinds until i implement loading and saving settings from file
mut input_data: ResMut<InputRegister>,
) {
input_data.set_binary_input(
&keybind_codes::INSERT_VOXEL.into(),
BinaryInputBinding::create_binding(BinaryInputID::MouseButton(MouseButton::Left)),
);
input_data.set_binary_input(
&keybind_codes::REMOVE_VOXEL.into(),
BinaryInputBinding::create_binding_2(
BinaryInputID::MouseButton(MouseButton::Left),
BinaryInputID::KeyCode(KeyCode::KeyR),
),
);
input_data.set_binary_input(
&keybind_codes::PAINT_VOXEL.into(),
BinaryInputBinding::create_binding_2(
BinaryInputID::MouseButton(MouseButton::Left),
BinaryInputID::KeyCode(KeyCode::KeyE),
),
);
}

View file

@ -1,44 +0,0 @@
use crate::vvlib::inputs::{BinaryInputData, DualAxis};
use bevy::math::Vec2;
pub enum EventData {
// clicks
ActionAddVoxel,
ActionPaintVoxel,
ActionRemoveVoxel,
// movement
ActionRotate(Vec2),
ActionZoom(Vec2), // either direction positive is zoom in, negative is zoom out
ActionPan(Vec2),
}
pub struct InputConfig {
add_voxel: BinaryInputData,
paint_voxel: BinaryInputData,
remove_voxel: BinaryInputData,
drag_rotate_binding: BinaryInputData,
drag_rotate_axis: DualAxis,
drag_zoom_binding: BinaryInputData,
drag_zoom_axis: DualAxis,
drag_pan_binding: BinaryInputData,
drag_pan_axis: DualAxis,
}
impl Default for InputConfig {
fn default() -> Self {
Self {
add_voxel: Default::default(),
paint_voxel: Default::default(),
remove_voxel: Default::default(),
drag_rotate_binding: Default::default(),
drag_rotate_axis: Default::default(),
drag_zoom_binding: Default::default(),
drag_zoom_axis: Default::default(),
drag_pan_binding: Default::default(),
drag_pan_axis: Default::default(),
}
}
}

View file

@ -7,16 +7,26 @@ use bevy::{
};
use bevy_egui::{egui, EguiContexts, EguiPlugin};
use crate::vvlib::oct_asset::{MeshingOctTreePairs, OctTreeAsset};
use crate::{
vvedit::editor_bevy_input_shim::keybind_codes::REMOVE_VOXEL, vvlib::inputs::InputRegister,
};
use crate::{
vvedit::editor_bevy_input_shim::keybind_codes::{INSERT_VOXEL, PAINT_VOXEL},
vvlib::oct_asset::{MeshingOctTreePairs, OctTreeAsset},
};
use super::orbit_camera::orbit_camera::{pan_orbit_camera, spawn_camera};
use super::{
editor_bevy_input_shim::setup_inputs,
orbit_camera::orbit_camera::{pan_orbit_camera, spawn_camera},
};
pub fn register_edit_ui(app: &mut bevy::prelude::App) -> &mut bevy::prelude::App {
app.insert_resource(EditWindowUIState {});
app.add_plugins(EguiPlugin);
app.add_systems(Startup, startup_system_edit_ui);
app.add_systems(Update, edit_window_ui);
app.insert_resource(EditWindowUIState {});
app.add_systems(Update, pan_orbit_camera);
setup_inputs(app);
app
}
@ -32,9 +42,18 @@ pub fn edit_window_ui(
mut contexts: EguiContexts,
mut oct_assets: ResMut<Assets<OctTreeAsset>>,
mut pairs: ResMut<MeshingOctTreePairs>,
input_data: ResMut<InputRegister>,
) {
egui::Window::new("VVEdit").show(contexts.ctx_mut(), |ui| {
if ui.button("add voxels").clicked() {
let mut label = String::from("Pre-Alpha");
use std::fmt::Write;
writeln!(label, " Controls:").ok();
writeln!(label, "click adds a voxel:").ok();
writeln!(label, "R+click removes a voxel:").ok();
writeln!(label, "E+click paints (edits) a voxel:").ok();
ui.label(label);
if ui.button("Add Origin Voxel").clicked() {
//
for pair in &mut pairs.handles {
let id = pair.oct_handle.clone();
@ -42,10 +61,23 @@ pub fn edit_window_ui(
if tree.is_some() {
//
let tree = tree.unwrap();
tree.model
.set_voxel_at_location(Vec3::splat(-2.), Color::BLUE);
tree.model.set_voxel_at_location(Vec3::ZERO, Color::BLUE);
}
}
}
// click processing
let paint = input_data.get_binary_input(&PAINT_VOXEL.into());
let remove = input_data.get_binary_input(&REMOVE_VOXEL.into());
let insert = input_data.get_binary_input(&INSERT_VOXEL.into());
if let Some(_input) = paint.filter(|input| input.pressed()) {
//
println!("paint input!");
} else if let Some(_input) = remove.filter(|input| input.pressed()) {
//
println!("remove input!");
} else if let Some(_input) = insert.filter(|input| input.pressed()) {
//
println!("insert input!");
}
});
}

View file

@ -1,11 +1,115 @@
#![allow(dead_code)]
use std::collections::VecDeque;
use std::collections::{HashMap, VecDeque};
use bevy::input::{gamepad::*, keyboard::KeyCode, mouse::MouseButton};
use bevy::prelude::*;
pub struct InputRegisterPlugin;
impl Plugin for InputRegisterPlugin {
fn build(&self, app: &mut App) {
app.insert_resource(InputRegister::default());
app.add_systems(First, poll_bindings);
}
}
#[derive(Default)]
pub fn poll_bindings(
// register where we store inputs
mut input_data: ResMut<InputRegister>,
// required bevy stuff\
mut cursor_moved_events: EventReader<CursorMoved>,
gamepad_button_inputs: Res<ButtonInput<GamepadButton>>,
mouse_button_inputs: Res<ButtonInput<MouseButton>>,
key_button_inputs: Res<ButtonInput<KeyCode>>,
axes: Res<Axis<GamepadAxis>>,
) {
let mut mouse_movement_delta = None;
for event in cursor_moved_events.read() {
mouse_movement_delta = event.delta;
}
for (_, twin_axis) in &mut input_data.twin_axes {
let mut vert: Option<f32> = None;
let mut hori: Option<f32> = None;
match twin_axis.binding.vert {
AxisInputID::GamepadAxis(v_axis) => {
vert = axes.get(v_axis);
}
AxisInputID::MouseMotionX => {
if mouse_movement_delta.is_some() {
vert = Some(mouse_movement_delta.clone().unwrap().x);
}
}
AxisInputID::MouseMotionY => {
if mouse_movement_delta.is_some() {
vert = Some(mouse_movement_delta.clone().unwrap().y);
}
}
_ => {}
}
match twin_axis.binding.hori {
AxisInputID::GamepadAxis(v_axis) => {
hori = axes.get(v_axis);
}
AxisInputID::MouseMotionX => {
if mouse_movement_delta.is_some() {
hori = Some(mouse_movement_delta.clone().unwrap().x);
}
}
AxisInputID::MouseMotionY => {
if mouse_movement_delta.is_some() {
hori = Some(mouse_movement_delta.clone().unwrap().y);
}
}
_ => {}
}
if hori.is_none() {
hori = Some(0.);
}
if vert.is_none() {
vert = Some(0.);
}
let vec2 = Vec2::new(hori.unwrap(), vert.unwrap());
twin_axis.poll(vec2);
}
for (_, axis) in &mut input_data.axes {
match axis.binding {
AxisInputID::MouseMotionX => {
//
if mouse_movement_delta.is_some() {
axis.poll(mouse_movement_delta.unwrap().x)
} else {
axis.poll(0.);
}
}
AxisInputID::MouseMotionY => {
//
if mouse_movement_delta.is_some() {
axis.poll(mouse_movement_delta.unwrap().y)
} else {
axis.poll(0.);
}
}
AxisInputID::GamepadAxis(v_axis) => {
let val = axes.get(v_axis);
if val.is_some() {
axis.poll(val.unwrap().clone());
}
}
AxisInputID::Unbound => {} // no op - nothing is bound, so we ignore it
}
}
for (_, binding) in &mut input_data.binaries {
let active = binding.binding.is_activated(
&key_button_inputs,
&mouse_button_inputs,
&gamepad_button_inputs,
);
binding.history.poll(active);
}
}
#[derive(Default, Clone)]
pub enum BinaryInputID {
#[default]
Unbound,
@ -14,25 +118,34 @@ pub enum BinaryInputID {
GamepadButton(GamepadButton, Gamepad),
}
#[derive(Default)]
pub enum BinaryInputState {
#[default]
Inactive,
JustActivated,
Activated,
JustDeactivated,
impl From<KeyCode> for BinaryInputID {
fn from(value: KeyCode) -> Self {
Self::KeyCode(value)
}
}
#[derive(Default)]
impl From<MouseButton> for BinaryInputID {
fn from(value: MouseButton) -> Self {
Self::MouseButton(value)
}
}
impl From<(GamepadButton, Gamepad)> for BinaryInputID {
fn from(value: (GamepadButton, Gamepad)) -> Self {
Self::GamepadButton(value.0, value.1)
}
}
#[derive(Default, Clone)]
pub struct BinaryInputBinding {
inputs: [BinaryInputID; 5],
}
impl BinaryInputBinding {
pub fn is_activated(
&self,
keycode_buttons: Res<ButtonInput<KeyCode>>,
mouse_buttons: Res<ButtonInput<MouseButton>>,
gamepad_buttons: Res<ButtonInput<GamepadButton>>,
keycode_buttons: &Res<ButtonInput<KeyCode>>,
mouse_buttons: &Res<ButtonInput<MouseButton>>,
gamepad_buttons: &Res<ButtonInput<GamepadButton>>,
) -> bool {
let mut total_unbound = 0;
@ -130,33 +243,15 @@ impl BinaryInputBinding {
}
}
#[derive(Default)]
pub enum AxisInputID {
#[default]
Unbound,
MouseMotionX,
MouseMotionY,
GamepadAxis(GamepadAxis, Gamepad),
}
#[derive(Default)]
pub struct DualAxis {
vert: AxisInputID,
hori: AxisInputID,
}
pub struct BinaryInputHistory {
input: BinaryInputID,
history: VecDeque<(bool, usize)>,
dispose_after_duration: usize,
pub history: VecDeque<(bool, usize)>,
pub dispose_after_duration: usize,
}
impl BinaryInputHistory {
//
pub fn poll(&mut self, is_activated: bool) {
//
if is_activated {
let last = self.history.get_mut(self.history.len());
let last = self.history.back_mut();
if last.is_some() {
let last = last.unwrap();
if last.0 {
@ -165,12 +260,14 @@ impl BinaryInputHistory {
} else {
last.1 += 1;
}
} else {
self.history.push_back((true, 1));
}
} else {
self.history.push_back((true, 1));
}
} else {
let last = self.history.get_mut(self.history.len());
let last = self.history.back_mut();
if last.is_some() {
let last = last.unwrap();
if !last.0 {
@ -179,6 +276,8 @@ impl BinaryInputHistory {
} else {
last.1 += 1;
}
} else {
self.history.push_back((false, 1));
}
} else {
self.history.push_back((false, 1));
@ -187,11 +286,11 @@ impl BinaryInputHistory {
// dispose settings time
let mut count: usize = 0;
let mut num_to_pop: usize = 0;
for each in self.history.iter().rev() {
for each in self.history.clone().iter().rev() {
if count >= self.dispose_after_duration {
num_to_pop += 1;
} else {
if usize::MAX - each.1 > count {
if usize::MAX - each.1 < count {
count = usize::MAX;
} else {
count += each.1;
@ -205,7 +304,7 @@ impl BinaryInputHistory {
}
pub fn pressed(&self) -> bool {
let last = self.history.get(self.history.len());
let last = self.history.back();
if last.is_some() {
let last = last.unwrap();
if last.1 == 1 {
@ -216,7 +315,7 @@ impl BinaryInputHistory {
false
}
pub fn active(&self) -> bool {
let last = self.history.get(self.history.len());
let last = self.history.back();
if last.is_some() {
let last = last.unwrap();
// if the value is set, then the value currently set is whether or not it is active. otherwise it was never activated, and is thus false.
@ -226,10 +325,9 @@ impl BinaryInputHistory {
}
pub fn current_duration(&self) -> usize {
let last = self.history.get(self.history.len());
let last = self.history.back();
if last.is_some() {
let last = last.unwrap();
// if the value is set, then the value currently set is whether or not it is active. otherwise it was never activated, and is thus false.
return last.1;
}
@ -240,15 +338,197 @@ impl BinaryInputHistory {
impl Default for BinaryInputHistory {
fn default() -> Self {
BinaryInputHistory {
input: Default::default(),
history: VecDeque::new(),
dispose_after_duration: 1024,
dispose_after_duration: 256,
}
}
}
#[derive(Default)]
pub struct BinaryInputData {
input_binding: BinaryInputBinding,
input_state: BinaryInputHistory,
pub binding: BinaryInputBinding,
pub history: BinaryInputHistory,
}
#[derive(Default, Clone)]
pub enum AxisInputID {
#[default]
Unbound,
MouseMotionX,
MouseMotionY,
GamepadAxis(GamepadAxis),
}
#[derive(Default, Clone)]
pub struct TwinAxisInputID {
pub vert: AxisInputID,
pub hori: AxisInputID,
}
pub struct AxisInputHistory {
pub history: VecDeque<f32>,
pub dispose_after_duration: usize,
}
pub struct TwinAxisInputHistory {
pub history: VecDeque<Vec2>,
pub dispose_after_duration: usize,
}
impl Default for AxisInputHistory {
fn default() -> Self {
AxisInputHistory {
history: VecDeque::new(),
dispose_after_duration: 64,
}
}
}
impl Default for TwinAxisInputHistory {
fn default() -> Self {
TwinAxisInputHistory {
history: VecDeque::new(),
dispose_after_duration: 64,
}
}
}
#[derive(Default)]
pub struct AxisInputData {
pub binding: AxisInputID,
pub history: AxisInputHistory,
}
impl AxisInputData {
pub fn poll(&mut self, value: f32) {
self.history.history.push_back(value);
if self.history.history.len() > self.history.dispose_after_duration {
self.history.history.pop_front();
}
}
}
#[derive(Default)]
pub struct TwinAxisInputData {
pub binding: TwinAxisInputID,
pub history: TwinAxisInputHistory,
}
impl TwinAxisInputData {
pub fn poll(&mut self, value: Vec2) {
self.history.history.push_back(value);
if self.history.history.len() > self.history.dispose_after_duration {
self.history.history.pop_front();
}
}
}
#[derive(Resource)]
pub struct InputRegister {
//
pub binaries: HashMap<String, BinaryInputData>,
pub axes: HashMap<String, AxisInputData>,
pub twin_axes: HashMap<String, TwinAxisInputData>,
}
impl Default for InputRegister {
fn default() -> Self {
Self {
binaries: HashMap::new(),
axes: HashMap::new(),
twin_axes: HashMap::new(),
}
}
}
impl InputRegister {
// binding getters
pub fn get_binary_binding(&self, key: &String) -> Option<BinaryInputBinding> {
let getter = self.binaries.get(key);
if getter.is_some() {
return Some(getter.unwrap().binding.clone());
}
None
}
pub fn get_axis_binding(&self, key: &String) -> Option<AxisInputID> {
let getter = self.axes.get(key);
if getter.is_some() {
return Some(getter.unwrap().binding.clone());
}
None
}
pub fn get_twinaxis_binding(&self, key: &String) -> Option<TwinAxisInputID> {
let getter = self.twin_axes.get(key);
if getter.is_some() {
return Some(getter.unwrap().binding.clone());
}
None
}
// input getters
pub fn get_binary_input(&self, key: &String) -> Option<&BinaryInputHistory> {
if self.binaries.contains_key(key) {
return Some(&self.binaries.get(key).unwrap().history);
}
None
}
pub fn get_axis_input(&self, key: &String) -> Option<&AxisInputHistory> {
if self.axes.contains_key(key) {
return Some(&self.axes.get(key).unwrap().history);
}
None
}
pub fn get_twinaxis_input(&self, key: &String) -> Option<&TwinAxisInputHistory> {
if self.twin_axes.contains_key(key) {
return Some(&self.twin_axes.get(key).unwrap().history);
}
None
}
//setters
pub fn set_binary_input(&mut self, key: &String, bind: BinaryInputBinding) {
if self.binaries.contains_key(key) {
let value = self.binaries.get_mut(key);
if value.is_some() {
let value = value.unwrap();
value.binding = bind;
}
} else {
self.binaries.insert(
key.clone(),
BinaryInputData {
binding: bind,
..default()
},
);
}
}
pub fn set_axis_input(&mut self, key: &String, bind: AxisInputID) {
if self.axes.contains_key(key) {
let value = self.axes.get_mut(key);
if value.is_some() {
let value = value.unwrap();
value.binding = bind;
}
} else {
self.axes.insert(
key.clone(),
AxisInputData {
binding: bind,
..default()
},
);
}
}
pub fn set_twinaxis_input(&mut self, key: &String, bind: TwinAxisInputID) {
if self.twin_axes.contains_key(key) {
let value = self.twin_axes.get_mut(key);
if value.is_some() {
let value = value.unwrap();
value.binding = bind;
}
} else {
self.twin_axes.insert(
key.clone(),
TwinAxisInputData {
binding: bind,
..default()
},
);
}
}
}