Skip to content

Commit

Permalink
Merge pull request #39 from urholaukkarinen/new-subgizmos
Browse files Browse the repository at this point in the history
New subgizmos
  • Loading branch information
urholaukkarinen authored Feb 1, 2024
2 parents 26e1c4a + da3d0d3 commit c925688
Show file tree
Hide file tree
Showing 16 changed files with 683 additions and 324 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "egui-gizmo"
version = "0.14.1"
version = "0.15.0"
authors = ["Urho Laukkarinen <[email protected]>"]
edition = "2021"

Expand All @@ -18,7 +18,7 @@ members = ["demo"]

[dependencies]
egui = "0.25.0"
glam = { version = "0.24", features = ["mint"] }
glam = { version = "0.25.0", features = ["mint"] }
mint = "0.5"

[profile.release]
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

[Try it out in a web demo](https://urholaukkarinen.github.io/egui-gizmo/)

![Rotation](media/rotation.gif)
![Rotation](media/rotation.png)
![Translation](media/translation.png)
![Scale](media/scale.png)

Expand Down
4 changes: 4 additions & 0 deletions demo/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ egui-gizmo = { path = ".." }
[dependencies.bevy]
version = "0.12.1"

[dependencies.bevy_math]
version = "0.12.1"
features = ["mint"]

[dependencies.bevy_egui]
git = "https://github.com/urholaukkarinen/bevy_egui.git"
rev="bc3dd1559e24ca0178ed1d2dfef07cb784437505"
Expand Down
23 changes: 14 additions & 9 deletions demo/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -304,15 +304,20 @@ fn instructions_text(ui: &Ui) {
}

fn show_gizmo_status(ui: &Ui, response: GizmoResult) {
let length = Vec3::from(response.value).length();

let text = match response.mode {
GizmoMode::Rotate => format!("{:.1}°, {:.2} rad", length.to_degrees(), length),

GizmoMode::Translate | GizmoMode::Scale => format!(
"dX: {:.2}, dY: {:.2}, dZ: {:.2}",
response.value[0], response.value[1], response.value[2]
),
let text = if let Some(value) = response.value {
match response.mode {
GizmoMode::Rotate => {
let length = Vec3::from(value).length();
format!("{:.1}°, {:.2} rad", length.to_degrees(), length)
}

GizmoMode::Translate | GizmoMode::Scale => format!(
"dX: {:.2}, dY: {:.2}, dZ: {:.2}",
value[0], value[1], value[2]
),
}
} else {
String::new()
};

let rect = ui.clip_rect();
Expand Down
Binary file removed media/rotation.gif
Binary file not shown.
Binary file added media/rotation.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified media/scale.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified media/translation.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
159 changes: 110 additions & 49 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,14 @@ use std::hash::Hash;
use std::ops::Sub;

use crate::math::{screen_to_world, world_to_screen};
use egui::{Color32, Context, Id, PointerButton, Rect, Sense, Ui};
use egui::{Color32, Context, Id, PointerButton, Pos2, Rect, Sense, Ui};
use glam::{DMat4, DQuat, DVec3, Mat4, Quat, Vec3, Vec4Swizzles};

use crate::subgizmo::rotation::RotationParams;
use crate::subgizmo::scale::ScaleParams;
use crate::subgizmo::translation::TranslationParams;
use crate::subgizmo::{
RotationSubGizmo, ScaleSubGizmo, SubGizmo, TransformKind, TranslationSubGizmo,
ArcballSubGizmo, RotationSubGizmo, ScaleSubGizmo, SubGizmo, TransformKind, TranslationSubGizmo,
};

mod math;
Expand Down Expand Up @@ -136,7 +139,10 @@ impl Gizmo {

// Choose subgizmos based on the gizmo mode
match self.config.mode {
GizmoMode::Rotate => self.add_subgizmos(self.new_rotation()),
GizmoMode::Rotate => {
self.add_subgizmos(self.new_rotation());
self.add_subgizmos(self.new_arcball());
}
GizmoMode::Translate => self.add_subgizmos(self.new_translation()),
GizmoMode::Scale => self.add_subgizmos(self.new_scale()),
};
Expand Down Expand Up @@ -182,7 +188,7 @@ impl Gizmo {

if let Some((_, result)) = active_subgizmo.zip(result) {
self.config.translation = Vec3::from(result.translation).as_dvec3();
self.config.rotation = Quat::from(result.rotation).as_f64();
self.config.rotation = Quat::from(result.rotation).as_dquat();
self.config.scale = Vec3::from(result.scale).as_dvec3();
}

Expand All @@ -193,8 +199,8 @@ impl Gizmo {
result
}

fn draw_subgizmos(&self, ui: &mut Ui, state: &mut GizmoState) {
for subgizmo in &self.subgizmos {
fn draw_subgizmos(&mut self, ui: &mut Ui, state: &mut GizmoState) {
for subgizmo in &mut self.subgizmos {
if state.active_subgizmo_id.is_none() || subgizmo.is_active() {
subgizmo.draw(ui);
}
Expand All @@ -210,116 +216,165 @@ impl Gizmo {
.map(|(_, subgizmo)| subgizmo)
}

/// Create arcball subgizmo
fn new_arcball(&self) -> [ArcballSubGizmo; 1] {
[ArcballSubGizmo::new(self.id.with("arc"), self.config, ())]
}

/// Create subgizmos for rotation
fn new_rotation(&self) -> [RotationSubGizmo; 4] {
[
RotationSubGizmo::new(
self.id.with("rx"),
self.config,
GizmoDirection::X,
TransformKind::Axis,
RotationParams {
direction: GizmoDirection::X,
},
),
RotationSubGizmo::new(
self.id.with("ry"),
self.config,
GizmoDirection::Y,
TransformKind::Axis,
RotationParams {
direction: GizmoDirection::Y,
},
),
RotationSubGizmo::new(
self.id.with("rz"),
self.config,
GizmoDirection::Z,
TransformKind::Axis,
RotationParams {
direction: GizmoDirection::Z,
},
),
RotationSubGizmo::new(
self.id.with("rs"),
self.config,
GizmoDirection::Screen,
TransformKind::Axis,
RotationParams {
direction: GizmoDirection::View,
},
),
]
}

/// Create subgizmos for translation
fn new_translation(&self) -> [TranslationSubGizmo; 6] {
fn new_translation(&self) -> [TranslationSubGizmo; 7] {
[
TranslationSubGizmo::new(
self.id.with("txs"),
self.config,
TranslationParams {
direction: GizmoDirection::View,
transform_kind: TransformKind::Plane,
},
),
TranslationSubGizmo::new(
self.id.with("tx"),
self.config,
GizmoDirection::X,
TransformKind::Axis,
TranslationParams {
direction: GizmoDirection::X,
transform_kind: TransformKind::Axis,
},
),
TranslationSubGizmo::new(
self.id.with("ty"),
self.config,
GizmoDirection::Y,
TransformKind::Axis,
TranslationParams {
direction: GizmoDirection::Y,
transform_kind: TransformKind::Axis,
},
),
TranslationSubGizmo::new(
self.id.with("tz"),
self.config,
GizmoDirection::Z,
TransformKind::Axis,
TranslationParams {
direction: GizmoDirection::Z,
transform_kind: TransformKind::Axis,
},
),
TranslationSubGizmo::new(
self.id.with("tyz"),
self.config,
GizmoDirection::X,
TransformKind::Plane,
TranslationParams {
direction: GizmoDirection::X,
transform_kind: TransformKind::Plane,
},
),
TranslationSubGizmo::new(
self.id.with("txz"),
self.config,
GizmoDirection::Y,
TransformKind::Plane,
TranslationParams {
direction: GizmoDirection::Y,
transform_kind: TransformKind::Plane,
},
),
TranslationSubGizmo::new(
self.id.with("txy"),
self.config,
GizmoDirection::Z,
TransformKind::Plane,
TranslationParams {
direction: GizmoDirection::Z,
transform_kind: TransformKind::Plane,
},
),
]
}

/// Create subgizmos for scale
fn new_scale(&self) -> [ScaleSubGizmo; 6] {
fn new_scale(&self) -> [ScaleSubGizmo; 7] {
[
ScaleSubGizmo::new(
self.id.with("txs"),
self.config,
ScaleParams {
direction: GizmoDirection::View,
transform_kind: TransformKind::Plane,
},
),
ScaleSubGizmo::new(
self.id.with("sx"),
self.config,
GizmoDirection::X,
TransformKind::Axis,
ScaleParams {
direction: GizmoDirection::X,
transform_kind: TransformKind::Axis,
},
),
ScaleSubGizmo::new(
self.id.with("sy"),
self.config,
GizmoDirection::Y,
TransformKind::Axis,
ScaleParams {
direction: GizmoDirection::Y,
transform_kind: TransformKind::Axis,
},
),
ScaleSubGizmo::new(
self.id.with("sz"),
self.config,
GizmoDirection::Z,
TransformKind::Axis,
ScaleParams {
direction: GizmoDirection::Z,
transform_kind: TransformKind::Axis,
},
),
ScaleSubGizmo::new(
self.id.with("syz"),
self.config,
GizmoDirection::X,
TransformKind::Plane,
ScaleParams {
direction: GizmoDirection::X,
transform_kind: TransformKind::Plane,
},
),
ScaleSubGizmo::new(
self.id.with("sxz"),
self.config,
GizmoDirection::Y,
TransformKind::Plane,
ScaleParams {
direction: GizmoDirection::Y,
transform_kind: TransformKind::Plane,
},
),
ScaleSubGizmo::new(
self.id.with("sxy"),
self.config,
GizmoDirection::Z,
TransformKind::Plane,
ScaleParams {
direction: GizmoDirection::Z,
transform_kind: TransformKind::Plane,
},
),
]
}
Expand All @@ -333,15 +388,19 @@ impl Gizmo {

/// Calculate a world space ray from current mouse position
fn pointer_ray(&self, ui: &Ui) -> Option<Ray> {
let hover = ui.input(|i| i.pointer.hover_pos())?;
let screen_pos = ui.input(|i| i.pointer.hover_pos())?;

let mat = self.config.view_projection.inverse();
let origin = screen_to_world(self.config.viewport, mat, hover, -1.0);
let target = screen_to_world(self.config.viewport, mat, hover, 1.0);
let origin = screen_to_world(self.config.viewport, mat, screen_pos, -1.0);
let target = screen_to_world(self.config.viewport, mat, screen_pos, 1.0);

let direction = target.sub(origin).normalize();

Some(Ray { origin, direction })
Some(Ray {
screen_pos,
origin,
direction,
})
}
}

Expand All @@ -357,7 +416,7 @@ pub struct GizmoResult {
/// Mode of the active subgizmo
pub mode: GizmoMode,
/// Total scale, rotation or translation of the current gizmo activation, depending on mode
pub value: [f32; 3],
pub value: Option<[f32; 3]>,
}

impl GizmoResult {
Expand Down Expand Up @@ -400,8 +459,8 @@ pub enum GizmoDirection {
Y,
/// Gizmo points in the Z-direction
Z,
/// Gizmo points towards the screen
Screen,
/// Gizmo points in the view direction
View,
}

/// Controls the visual style of the gizmo
Expand All @@ -413,13 +472,13 @@ pub struct GizmoVisuals {
pub y_color: Color32,
/// Color of the z axis
pub z_color: Color32,
/// Color of the screen direction axis
/// Color of the forward axis
pub s_color: Color32,
/// Alpha of the gizmo color when inactive
pub inactive_alpha: f32,
/// Alpha of the gizmo color when highlighted/active
pub highlight_alpha: f32,
/// Color to use for highlighted and active axes. By default the axis color is used with `highlight_alpha`
/// Color to use for highlighted and active axes. By default, the axis color is used with `highlight_alpha`
pub highlight_color: Option<Color32>,
/// Width (thickness) of the gizmo strokes
pub stroke_width: f32,
Expand Down Expand Up @@ -556,12 +615,14 @@ impl GizmoConfig {

/// Whether local orientation is used
pub(crate) fn local_space(&self) -> bool {
// Scale mode only works in local space
self.orientation == GizmoOrientation::Local || self.mode == GizmoMode::Scale
}
}

#[derive(Debug, Copy, Clone)]
pub(crate) struct Ray {
screen_pos: Pos2,
origin: DVec3,
direction: DVec3,
}
Expand Down
Loading

0 comments on commit c925688

Please sign in to comment.