Skip to content

Commit f105839

Browse files
committed
rectilinear grid work
1 parent 1b0ef1b commit f105839

File tree

3 files changed

+46
-52
lines changed

3 files changed

+46
-52
lines changed

editor/src/messages/portfolio/document/overlays/grid_overlays.rs

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::messages::layout::utility_types::widget_prelude::*;
22
use crate::messages::portfolio::document::overlays::utility_types::OverlayContext;
33
use crate::messages::portfolio::document::utility_types::misc::{GridSnapping, GridType};
44
use crate::messages::prelude::*;
5-
use glam::DVec2;
5+
use glam::{DVec2,UVec2};
66
use graphene_std::raster::color::Color;
77
use graphene_std::renderer::Quad;
88
use graphene_std::vector::style::FillChoice;
@@ -11,9 +11,10 @@ fn grid_overlay_rectangular(document: &DocumentMessageHandler, overlay_context:
1111
let origin = document.snapping_state.grid.origin;
1212
let grid_color = "#".to_string() + &document.snapping_state.grid.grid_color.to_rgba_hex_srgb();
1313
let grid_color_minor = "#".to_string() + &document.snapping_state.grid.grid_color_minor.to_rgba_hex_srgb();
14-
let Some(spacing) = GridSnapping::compute_rectangle_spacing(spacing, &document.document_ptz) else {
14+
let Some(scaled_spacing) = GridSnapping::compute_rectangle_spacing(spacing, &document.snapping_state.grid.rectangular_major_interval, &document.document_ptz) else {
1515
return;
1616
};
17+
let scale_is_adjusted = scaled_spacing != spacing;
1718
let document_to_viewport = document.navigation_handler.calculate_offset_transform(overlay_context.size / 2., &document.document_ptz);
1819

1920
let bounds = document_to_viewport.inverse() * Quad::from_box([DVec2::ZERO, overlay_context.size]);
@@ -24,17 +25,17 @@ fn grid_overlay_rectangular(document: &DocumentMessageHandler, overlay_context:
2425
let max = bounds.0.iter().map(|&corner| corner[secondary]).max_by(|a, b| a.partial_cmp(b).unwrap()).unwrap_or_default();
2526
let primary_start = bounds.0.iter().map(|&corner| corner[primary]).min_by(|a, b| a.partial_cmp(b).unwrap()).unwrap_or_default();
2627
let primary_end = bounds.0.iter().map(|&corner| corner[primary]).max_by(|a, b| a.partial_cmp(b).unwrap()).unwrap_or_default();
27-
let spacing = spacing[secondary];
28+
let spacing = scaled_spacing[secondary];
2829
let first_index = ((min - origin[secondary]) / spacing).ceil() as i32;
2930
for line_index in 0..=((max - min) / spacing).ceil() as i32 {
3031
let is_major = is_major_line(
3132
line_index + first_index,
3233
if primary == 1 {
33-
document.snapping_state.grid.rectangular_major_interval_along_x
34+
document.snapping_state.grid.rectangular_major_interval.x
3435
} else {
35-
document.snapping_state.grid.rectangular_major_interval_along_y
36+
document.snapping_state.grid.rectangular_major_interval.y
3637
},
37-
);
38+
) || scale_is_adjusted;
3839
let secondary_pos = (((min - origin[secondary]) / spacing).ceil() + line_index as f64) * spacing + origin[secondary];
3940
let start = if primary == 0 {
4041
DVec2::new(primary_start, secondary_pos)
@@ -47,7 +48,7 @@ fn grid_overlay_rectangular(document: &DocumentMessageHandler, overlay_context:
4748
DVec2::new(secondary_pos, primary_end)
4849
};
4950
overlay_context.line(
50-
document_to_viewport.transform_point2(start),
51+
document_to_viewport.transform_point2(start),
5152
document_to_viewport.transform_point2(end),
5253
if is_major {
5354
Some(&grid_color)
@@ -73,7 +74,7 @@ fn grid_overlay_rectangular_dot(document: &DocumentMessageHandler, overlay_conte
7374
let origin = document.snapping_state.grid.origin;
7475
let grid_color = "#".to_string() + &document.snapping_state.grid.grid_color.to_rgba_hex_srgb();
7576
let grid_color_minor = "#".to_string() + &document.snapping_state.grid.grid_color_minor.to_rgba_hex_srgb();
76-
let Some(spacing) = GridSnapping::compute_rectangle_spacing(spacing, &document.document_ptz) else {
77+
let Some(spacing) = GridSnapping::compute_rectangle_spacing(spacing, &document.snapping_state.grid.rectangular_major_interval, &document.document_ptz) else {
7778
return;
7879
};
7980
let document_to_viewport = document.navigation_handler.calculate_offset_transform(overlay_context.size / 2., &document.document_ptz);
@@ -202,10 +203,6 @@ fn is_major_line(line_index: i32, major_interval: u32) -> bool {
202203
line_index % major_interval as i32 == 0
203204
}
204205

205-
fn line_is_thick(line_index: i32, major_interval: u32, major_is_thick: bool) -> bool {
206-
major_is_thick && is_major_line(line_index, major_interval)
207-
}
208-
209206
pub fn grid_overlay(document: &DocumentMessageHandler, overlay_context: &mut OverlayContext) {
210207
match document.snapping_state.grid.grid_type {
211208
GridType::Rectangular { spacing, .. } => {
@@ -388,26 +385,26 @@ pub fn overlay_options(grid: &GridSnapping) -> Vec<LayoutGroup> {
388385
widgets: vec![
389386
TextLabel::new("Mark Every").table_align(true).widget_holder(),
390387
Separator::new(SeparatorType::Unrelated).widget_holder(),
391-
NumberInput::new(Some(grid.rectangular_major_interval_along_x as f64))
388+
NumberInput::new(Some(grid.rectangular_major_interval.x as f64))
392389
.unit(" col")
393390
.int()
394391
.min(1.)
395392
.min_width(98)
396393
.on_update(update_val(grid, |grid, val: &NumberInput| {
397394
if let Some(val) = val.value {
398-
grid.rectangular_major_interval_along_x = val as u32;
395+
grid.rectangular_major_interval.x = val as u32;
399396
}
400397
}))
401398
.widget_holder(),
402399
Separator::new(SeparatorType::Related).widget_holder(),
403-
NumberInput::new(Some(grid.rectangular_major_interval_along_y as f64))
400+
NumberInput::new(Some(grid.rectangular_major_interval.y as f64))
404401
.unit(" row")
405402
.int()
406403
.min(1.)
407404
.min_width(98)
408405
.on_update(update_val(grid, |grid, val: &NumberInput| {
409406
if let Some(val) = val.value {
410-
grid.rectangular_major_interval_along_y = val as u32;
407+
grid.rectangular_major_interval.y = val as u32;
411408
}
412409
}))
413410
.widget_holder(),
@@ -450,26 +447,26 @@ pub fn overlay_options(grid: &GridSnapping) -> Vec<LayoutGroup> {
450447
widgets: vec![
451448
TextLabel::new("Mark Every").table_align(true).widget_holder(),
452449
Separator::new(SeparatorType::Unrelated).widget_holder(),
453-
NumberInput::new(Some(grid.isometric_major_interval_along_a as f64))
450+
NumberInput::new(Some(grid.isometric_major_interval.z as f64))
454451
.label("A")
455452
.int()
456453
.min(1.)
457454
.min_width(98)
458455
.on_update(update_val(grid, |grid, val: &NumberInput| {
459456
if let Some(val) = val.value {
460-
grid.isometric_major_interval_along_a = val as u32;
457+
grid.isometric_major_interval.z = val as u32;
461458
}
462459
}))
463460
.widget_holder(),
464461
Separator::new(SeparatorType::Related).widget_holder(),
465-
NumberInput::new(Some(grid.isometric_major_interval_along_b as f64))
462+
NumberInput::new(Some(grid.isometric_major_interval.y as f64))
466463
.label("B")
467464
.int()
468465
.min(1.)
469466
.min_width(98)
470467
.on_update(update_val(grid, |grid, val: &NumberInput| {
471468
if let Some(val) = val.value {
472-
grid.isometric_major_interval_along_b = val as u32;
469+
grid.isometric_major_interval.y = val as u32;
473470
}
474471
}))
475472
.widget_holder(),
@@ -479,14 +476,14 @@ pub fn overlay_options(grid: &GridSnapping) -> Vec<LayoutGroup> {
479476
widgets: vec![
480477
TextLabel::new("").table_align(true).widget_holder(),
481478
Separator::new(SeparatorType::Unrelated).widget_holder(),
482-
NumberInput::new(Some(grid.isometric_major_interval_along_x as f64))
479+
NumberInput::new(Some(grid.isometric_major_interval.x as f64))
483480
.label("X")
484481
.int()
485482
.min(1.)
486483
.min_width(200)
487484
.on_update(update_val(grid, |grid, val: &NumberInput| {
488485
if let Some(val) = val.value {
489-
grid.isometric_major_interval_along_x = val as u32;
486+
grid.isometric_major_interval.x = val as u32;
490487
}
491488
}))
492489
.widget_holder(),

editor/src/messages/portfolio/document/utility_types/misc.rs

Lines changed: 25 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::consts::COLOR_OVERLAY_GRAY_DARK;
2-
use glam::DVec2;
2+
use glam::{DVec2,UVec2, UVec3};
33
use graphene_std::raster::Color;
44
use std::fmt;
55

@@ -213,17 +213,12 @@ pub struct GridSnapping {
213213
pub origin: DVec2,
214214
pub grid_type: GridType,
215215
pub rectangular_spacing: DVec2,
216-
pub rectangular_major_interval_along_x: u32,
217-
pub rectangular_major_interval_along_y: u32,
216+
pub rectangular_major_interval: UVec2,
218217
pub isometric_y_spacing: f64,
219218
pub isometric_angle_a: f64,
220219
pub isometric_angle_b: f64,
221-
/// Interval between major y-axis lines
222-
pub isometric_major_interval_along_x: u32,
223-
/// Interval between major angle a lines
224-
pub isometric_major_interval_along_b: u32,
225-
/// Interval between major angle b lines
226-
pub isometric_major_interval_along_a: u32,
220+
/// X is the major interval along the X axis, Y is the major interval along the B axis, Z is the major interval along the A axis.
221+
pub isometric_major_interval: UVec3,
227222
pub grid_color: Color,
228223
pub grid_color_minor: Color,
229224
pub major_is_thick: bool,
@@ -236,14 +231,11 @@ impl Default for GridSnapping {
236231
origin: DVec2::ZERO,
237232
grid_type: Default::default(),
238233
rectangular_spacing: DVec2::ONE,
239-
rectangular_major_interval_along_x: 1,
240-
rectangular_major_interval_along_y: 1,
234+
rectangular_major_interval: UVec2::ONE,
241235
isometric_y_spacing: 1.,
242236
isometric_angle_a: 30.,
243237
isometric_angle_b: 30.,
244-
isometric_major_interval_along_x: 1,
245-
isometric_major_interval_along_b: 1,
246-
isometric_major_interval_along_a: 1,
238+
isometric_major_interval: UVec3::ONE,
247239
grid_color: Color::from_rgb_str(COLOR_OVERLAY_GRAY_DARK.strip_prefix('#').unwrap()).unwrap().with_alpha(0.4),
248240
grid_color_minor: Color::from_rgb_str(COLOR_OVERLAY_GRAY_DARK.strip_prefix('#').unwrap()).unwrap().with_alpha(0.2),
249241
major_is_thick: false,
@@ -254,18 +246,23 @@ impl Default for GridSnapping {
254246

255247
impl GridSnapping {
256248
// Double grid size until it takes up at least 10px.
257-
pub fn compute_rectangle_spacing(mut size: DVec2, navigation: &PTZ) -> Option<DVec2> {
258-
let mut iterations = 0;
259-
size = size.abs();
260-
while (size * navigation.zoom()).cmplt(DVec2::splat(10.)).any() {
261-
if iterations > 100 {
262-
return None;
249+
pub fn compute_rectangle_spacing(mut size: DVec2, major_interval: &UVec2, navigation: &PTZ) -> Option<DVec2> {
250+
let mut iterations = 0;
251+
size = size.abs();
252+
while (size.x * navigation.zoom() < 10.) || (size.y * navigation.zoom() < 10.) {
253+
if iterations > 100 {
254+
return None;
255+
}
256+
if size.x * navigation.zoom() < 10. {
257+
size.x *= if major_interval.x != 1 {major_interval.x as f64} else {2.};
258+
}
259+
if size.y * navigation.zoom() < 10. {
260+
size.y *= if major_interval.y != 1 {major_interval.y as f64} else {2.};
261+
}
262+
iterations += 1;
263263
}
264-
size *= 2.;
265-
iterations += 1;
264+
Some(size)
266265
}
267-
Some(size)
268-
}
269266

270267
// Double grid size until it takes up at least 10px.
271268
pub fn compute_isometric_multiplier(length: f64, divisor: f64, navigation: &PTZ) -> Option<f64> {
@@ -283,11 +280,11 @@ impl GridSnapping {
283280
}
284281

285282
pub fn has_minor_lines(&self) -> bool {
286-
match self.grid_type {
287-
GridType::Rectangular { .. } => self.rectangular_major_interval_along_x > 1 || self.rectangular_major_interval_along_y > 1,
288-
GridType::Isometric { .. } => self.isometric_major_interval_along_x > 1 || self.isometric_major_interval_along_a > 1 || self.isometric_major_interval_along_b > 1,
283+
match self.grid_type {
284+
GridType::Rectangular { .. } => self.rectangular_major_interval.x > 1 || self.rectangular_major_interval.y > 1,
285+
GridType::Isometric { .. } => self.isometric_major_interval.x > 1 || self.isometric_major_interval.z > 1 || self.isometric_major_interval.y > 1,
286+
}
289287
}
290-
}
291288
}
292289

293290
#[derive(Debug, Clone, Copy, PartialEq, Eq)]

editor/src/messages/tool/common_functionality/snapping/grid_snapper.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use super::*;
22
use crate::messages::portfolio::document::utility_types::misc::{GridSnapTarget, GridSnapping, GridType, SnapTarget};
3-
use glam::DVec2;
3+
use glam::{DVec2,UVec2};
44
use graphene_std::renderer::Quad;
55

66
struct Line {
@@ -18,7 +18,7 @@ impl GridSnapper {
1818
let document = snap_data.document;
1919
let mut lines = Vec::new();
2020

21-
let Some(spacing) = GridSnapping::compute_rectangle_spacing(spacing, &document.document_ptz) else {
21+
let Some(spacing) = GridSnapping::compute_rectangle_spacing(spacing, &UVec2::ONE, &document.document_ptz) else {
2222
return lines;
2323
};
2424
let origin = document.snapping_state.grid.origin;

0 commit comments

Comments
 (0)