Skip to content

Commit

Permalink
add local origin option
Browse files Browse the repository at this point in the history
  • Loading branch information
seabassjh committed Sep 23, 2023
1 parent b9a93f6 commit aec0422
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 31 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ members = ["demo"]

[workspace.package]
edition = "2021"
version = "0.3.3"
version = "0.3.4"
license = "MIT OR Apache-2.0"
repository = "https://github.com/vectorgameexperts/bevy-vello"

Expand Down
20 changes: 12 additions & 8 deletions demo/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use bevy::{asset::ChangeWatcher, prelude::*};
use bevy_vello::{
BevyVelloPlugin, ColorPaletteSwap, VelloText, VelloTextBundle, VelloVector, VelloVectorBundle,
BevyVelloPlugin, ColorPaletteSwap, Origin, VelloText, VelloTextBundle, VelloVector,
VelloVectorBundle,
};
use std::time::Duration;

Expand All @@ -26,6 +27,7 @@ fn setup_vector_graphics(mut commands: Commands, asset_server: ResMut<AssetServe
commands
.spawn(VelloVectorBundle {
layer: bevy_vello::Layer::Background,
origin: bevy_vello::Origin::Center,
// Can only load *.json (Lottie animations) and *.svg (static vector graphics)
vector: asset_server.load("../assets/squid.json"),
debug_visualizations: bevy_vello::DebugVisualizations::Visible,
Expand All @@ -47,16 +49,16 @@ fn setup_vector_graphics(mut commands: Commands, asset_server: ResMut<AssetServe
commands.spawn(VelloTextBundle {
font: asset_server.load("../assets/Rubik-Medium.vttf"),
text: VelloText {
content: "squid".to_string(),
size: 320.0,
content: "hello vello".to_string(),
size: 100.0,
},
..default()
});
}

/// Transform the camera to the center of the vector graphic apply zooming
fn camera_system(
mut query: Query<(&Transform, &mut Handle<VelloVector>)>,
mut query: Query<(&GlobalTransform, &mut Handle<VelloVector>, &Origin)>,
mut query_cam: Query<&mut Transform, (With<Camera>, Without<Handle<VelloVector>>)>,
vectors: ResMut<Assets<VelloVector>>,
mut q: Query<&mut OrthographicProjection, With<Camera>>,
Expand All @@ -68,16 +70,18 @@ fn camera_system(
let Ok(mut camera_transform) = query_cam.get_single_mut() else {
return;
};
let Ok((&(mut target_transform), vector)) = query.get_single_mut() else {
let Ok((target_transform, vector, origin)) = query.get_single_mut() else {
return;
};

// Zoom in & out to demonstrate scalability and show the vector graphic's viewbox/anchor point
projection.scale = 2.0 * time.elapsed_seconds().cos();
projection.scale = 2.0 * time.elapsed_seconds().sin().clamp(0.2, 0.8);

// Set the camera position to the center point of the vector
if let Some(vector) = vectors.get(&vector) {
target_transform.translation.y += vector.height * target_transform.scale.y / 2.0;
camera_transform.translation = target_transform.translation;
camera_transform.translation = vector
.center_in_world(target_transform, origin)
.extend(camera_transform.translation.z);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/assets/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ fn compute_local_transform(width: f32, height: f32) -> Transform {
fn compute_local_transform_center(width: f32, height: f32) -> Transform {
let mut transform = Transform::default();
transform.translation.x = width / 2.0;
transform.translation.y = height / 2.0;
transform.translation.y = -height / 2.0;

transform
}
37 changes: 28 additions & 9 deletions src/assets/vector.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::metadata::Metadata;
use crate::{metadata::Metadata, Origin};
use bevy::{
math::{Vec3A, Vec4Swizzles},
math::{Vec3A, Vec3Swizzles, Vec4Swizzles},
prelude::*,
reflect::{TypePath, TypeUuid},
};
Expand All @@ -24,19 +24,38 @@ pub struct VelloVector {
}

impl VelloVector {
pub fn center_in_world(&self, transform: &GlobalTransform, origin: &Origin) -> Vec2 {
let world_transform = transform.compute_matrix();
let local_transform = match origin {
Origin::BottomCenter => self
.local_transform_bottom_center
.compute_matrix()
.inverse(),
Origin::Center => return transform.translation().xy(),
};

let local_center_point = Vec3A::new(self.width / 2.0, -self.height / 2.0, 0.0);

(world_transform * local_transform * local_center_point.extend(1.0)).xy()
}

/// Returns the 4 corner points of this vector's bounding box in world space
pub fn bb_in_world(&self, transform: &GlobalTransform) -> [Vec2; 4] {
pub fn bb_in_world(&self, transform: &GlobalTransform, origin: &Origin) -> [Vec2; 4] {
let min = Vec3A::ZERO;
let x_axis = Vec3A::new(self.width, 0.0, 0.0);

let max = Vec3A::new(self.width, -self.height, 0.0);
let y_axis = Vec3A::new(0.0, -self.height, 0.0);

let world_transform = transform.compute_matrix();
let local_transform = self
.local_transform_bottom_center
.compute_matrix()
.inverse();
let local_transform = match origin {
Origin::BottomCenter => self
.local_transform_bottom_center
.compute_matrix()
.inverse(),
Origin::Center => self.local_transform_center.compute_matrix().inverse(),
};

let min = (world_transform * local_transform * min.extend(1.0)).xy();
let x_axis = (world_transform * local_transform * x_axis.extend(1.0)).xy();
let max = (world_transform * local_transform * max.extend(1.0)).xy();
Expand All @@ -53,8 +72,8 @@ impl VelloVector {
let y_axis = Vec3A::new(0.0, -self.height, 0.0);

let world_transform = transform.compute_matrix();
let mut local_transform = self.local_transform_center.compute_matrix().inverse();
local_transform.y_axis *= -1.0;
let local_transform = self.local_transform_center.compute_matrix().inverse();

let min = (world_transform * local_transform * min.extend(1.0)).xy();
let x_axis = (world_transform * local_transform * x_axis.extend(1.0)).xy();
let max = (world_transform * local_transform * max.extend(1.0)).xy();
Expand Down
22 changes: 14 additions & 8 deletions src/debug.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use bevy::prelude::*;
use bevy::{math::Vec3Swizzles, prelude::*};

use crate::VelloVector;
use crate::{Origin, VelloVector};

pub struct DebugVisualizationsPlugin;

Expand All @@ -20,7 +20,12 @@ pub enum DebugVisualizations {

fn draw_viewbox(
query_world: Query<
(&Handle<VelloVector>, &GlobalTransform, &DebugVisualizations),
(
&Handle<VelloVector>,
&GlobalTransform,
Option<&Origin>,
&DebugVisualizations,
),
Without<Node>,
>,
query_ui: Query<(&Handle<VelloVector>, &GlobalTransform, &DebugVisualizations), With<Node>>,
Expand All @@ -35,19 +40,20 @@ fn draw_viewbox(
const RED_X_SIZE: f32 = 8.0;

// Show world-space vectors
for (vector, transform, _) in query_world
for (vector, transform, origin, _) in query_world
.iter()
.filter(|(_, _, d)| **d == DebugVisualizations::Visible)
.filter(|(_, _, _, d)| **d == DebugVisualizations::Visible)
{
if let Some(vector) = vectors.get(vector) {
let [min, x_axis, max, y_axis] = vector.bb_in_world(transform);
let [min, x_axis, max, y_axis] =
vector.bb_in_world(transform, origin.unwrap_or(&Origin::default()));

gizmos.line_2d(min, x_axis, Color::WHITE);
gizmos.line_2d(min, y_axis, Color::WHITE);
gizmos.line_2d(x_axis, max, Color::WHITE);
gizmos.line_2d(y_axis, max, Color::WHITE);

let red_x_origin = Vec2::new((y_axis.x + max.x) / 2.0, (y_axis.y + max.y) / 2.0);
let red_x_origin = transform.translation().xy();
let from = red_x_origin + RED_X_SIZE * Vec2::splat(1.0) * projection.scale;
let to = red_x_origin + RED_X_SIZE * Vec2::splat(-1.0) * projection.scale;

Expand Down Expand Up @@ -81,7 +87,7 @@ fn draw_viewbox(
gizmos.line_2d(x_axis, max, Color::WHITE);
gizmos.line_2d(y_axis, max, Color::WHITE);

let red_x_origin = Vec2::new(y_axis.x, x_axis.y);
let red_x_origin = Vec2::new((y_axis.x + max.x) / 2.0, (y_axis.y + min.y) / 2.0);
let from = red_x_origin + RED_X_SIZE * Vec2::splat(1.0) * projection.scale;
let to = red_x_origin + RED_X_SIZE * Vec2::splat(-1.0) * projection.scale;

Expand Down
11 changes: 11 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,14 @@ pub enum Layer {
UI,
}

#[derive(PartialEq, Component, Default, Copy, Clone, Debug, Reflect)]
#[reflect(Component)]
pub enum Origin {
#[default]
BottomCenter,
Center,
}

#[derive(PartialEq, Component, Default, Clone, Debug, Reflect)]
#[reflect(Component)]
/// Add this component to a `VelloVectorBundle` entity to enable runtime color editing.
Expand Down Expand Up @@ -118,7 +126,10 @@ impl ColorPaletteSwap {
#[derive(Bundle, Default)]
pub struct VelloVectorBundle {
pub vector: Handle<VelloVector>,
/// Configures the draw order within the vello canvas
pub layer: Layer,
/// This object's transform local origin. Enable debug visualizations to visualize (red X)
pub origin: Origin,
pub transform: Transform,
pub global_transform: GlobalTransform,
/// User indication of whether an entity is visible
Expand Down
7 changes: 5 additions & 2 deletions src/renderer/extract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ use bevy::{
window::PrimaryWindow,
};

use crate::{font::VelloFont, ColorPaletteSwap, Layer, VelloText, VelloVector};
use crate::{font::VelloFont, ColorPaletteSwap, Layer, Origin, VelloText, VelloVector};

#[derive(Component, Clone)]
pub struct ExtractedRenderVector {
pub vector_handle: Handle<VelloVector>,
pub render_data: VelloVector,
pub transform: GlobalTransform,
pub layer: Layer,
pub origin: Origin,
pub color_pallette_swap: Option<ColorPaletteSwap>,
pub ui_node: Option<Node>,
}
Expand All @@ -22,6 +23,7 @@ pub fn vector_instances(
Query<(
&Handle<VelloVector>,
&Layer,
Option<&Origin>,
&GlobalTransform,
Option<&ColorPaletteSwap>,
Option<&Node>,
Expand All @@ -30,7 +32,7 @@ pub fn vector_instances(
>,
assets: Extract<Res<Assets<VelloVector>>>,
) {
for (vello_vector_handle, layer, transform, color_pallette_swap, ui_node, visibility) in
for (vello_vector_handle, layer, origin, transform, color_pallette_swap, ui_node, visibility) in
query_vectors.iter()
{
if let Some(asset_data) = assets.get(vello_vector_handle) {
Expand All @@ -40,6 +42,7 @@ pub fn vector_instances(
render_data: asset_data.to_owned(),
transform: *transform,
layer: *layer,
origin: origin.copied().unwrap_or_default(),
color_pallette_swap: color_pallette_swap.cloned(),
ui_node: ui_node.cloned(),
});
Expand Down
10 changes: 8 additions & 2 deletions src/renderer/prepare.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,17 @@ pub fn prepare_vector_affines(
model_matrix.y_axis.y *= fill_scale.y;
}

let mut local_center_matrix = local_center_matrix;
local_center_matrix.w_axis.y *= -1.0;
model_matrix * local_center_matrix
}
_ => {
let mut model_matrix =
world_transform.compute_matrix() * local_bottom_center_matrix;
let local_matrix = match render_vector.origin {
crate::Origin::BottomCenter => local_bottom_center_matrix,
crate::Origin::Center => local_center_matrix,
};

let mut model_matrix = world_transform.compute_matrix() * local_matrix;
model_matrix.w_axis.y *= -1.0;

let (projection_mat, view_mat) = {
Expand Down

0 comments on commit aec0422

Please sign in to comment.